mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-05 18:32:41 +09:00
Compare commits
208 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
447fa6715c | ||
|
|
2398a23562 | ||
|
|
93c7611c32 | ||
|
|
607801ec41 | ||
|
|
16d2cf05ab | ||
|
|
d562b419b6 | ||
|
|
5482602ba8 | ||
|
|
37d3e0ec33 | ||
|
|
29724f31c5 | ||
|
|
580da8f353 | ||
|
|
8644993699 | ||
|
|
f55fe989a4 | ||
|
|
27dbe97542 | ||
|
|
abf0386e2e | ||
|
|
2b10eebed8 | ||
|
|
695738fb31 | ||
|
|
cfde557e23 | ||
|
|
3dbc63777f | ||
|
|
4aabd8e823 | ||
|
|
6a5b8eb7b6 | ||
|
|
a00e473341 | ||
|
|
4019a6d4b2 | ||
|
|
0487e39f82 | ||
|
|
3a7cb1a83b | ||
|
|
f317186aa6 | ||
|
|
5b7df68555 | ||
|
|
833a4b1775 | ||
|
|
1b8ecd179b | ||
|
|
085b56302c | ||
|
|
5066b208de | ||
|
|
ac658bb92c | ||
|
|
001d3fb820 | ||
|
|
8092251133 | ||
|
|
55239cbab7 | ||
|
|
df74ee0376 | ||
|
|
8d88f148d7 | ||
|
|
7bfab90a8f | ||
|
|
1a8da2e08f | ||
|
|
7c180ff8eb | ||
|
|
c34f7cdb1a | ||
|
|
fd0baf637d | ||
|
|
dff3ce089d | ||
|
|
9836b7db7b | ||
|
|
d752f0d7d0 | ||
|
|
669c76c0fd | ||
|
|
ac57ec5c47 | ||
|
|
f6dab64412 | ||
|
|
847f0bb9f3 | ||
|
|
1886bd6a01 | ||
|
|
7e07f5c4dc | ||
|
|
799536db46 | ||
|
|
c68650a7fb | ||
|
|
fe7caa05cc | ||
|
|
026167f854 | ||
|
|
8abfbe2165 | ||
|
|
16bfe983c2 | ||
|
|
503af4b807 | ||
|
|
8b3dd7de5d | ||
|
|
a04535e212 | ||
|
|
a1460333dc | ||
|
|
d15f20b2d2 | ||
|
|
863da7d5a1 | ||
|
|
1cad923b36 | ||
|
|
edb6ba28f1 | ||
|
|
494721cc90 | ||
|
|
d27e693ecf | ||
|
|
81a995cd84 | ||
|
|
d977e7ec10 | ||
|
|
b73d1ac1eb | ||
|
|
428d26d4a8 | ||
|
|
a254c26df9 | ||
|
|
1fed0e1adc | ||
|
|
88a652fa92 | ||
|
|
35039b8563 | ||
|
|
62afc0a727 | ||
|
|
b6a2323981 | ||
|
|
f23b587fe7 | ||
|
|
305cac291d | ||
|
|
6705b215db | ||
|
|
a9b4aa4cc4 | ||
|
|
1faa39b44c | ||
|
|
780f71c4ca | ||
|
|
484cb22f14 | ||
|
|
2a70473af7 | ||
|
|
a28863bff7 | ||
|
|
162f2841d0 | ||
|
|
e7a5429d7a | ||
|
|
622d21691c | ||
|
|
774b37b9f8 | ||
|
|
9dfdfe2389 | ||
|
|
4439a68911 | ||
|
|
782c376c8b | ||
|
|
a3b917151c | ||
|
|
0732ba32ee | ||
|
|
726d6a5077 | ||
|
|
b33cae7a3a | ||
|
|
854fcb1434 | ||
|
|
4730ed18f1 | ||
|
|
937996c74c | ||
|
|
3f253b3f5a | ||
|
|
f5a98b0f5b | ||
|
|
1a97a84023 | ||
|
|
420d015b76 | ||
|
|
22911a1ece | ||
|
|
4b763d8d37 | ||
|
|
1254fc668a | ||
|
|
09824025f7 | ||
|
|
bd1a915bdb | ||
|
|
cab7044772 | ||
|
|
68c9f1abd8 | ||
|
|
301de3ab6b | ||
|
|
8f8bd3c0cb | ||
|
|
23a6fa9421 | ||
|
|
b7c2f48ebf | ||
|
|
70e31b4aa0 | ||
|
|
d73846f0b4 | ||
|
|
527bbf67e8 | ||
|
|
5feb31f219 | ||
|
|
31efbafbe3 | ||
|
|
28af02eea0 | ||
|
|
c698a6fc5d | ||
|
|
e5a51eca45 | ||
|
|
8536dc4b73 | ||
|
|
0a0f46f299 | ||
|
|
1543ac9c8d | ||
|
|
c3c0710412 | ||
|
|
fa33919e24 | ||
|
|
b1162495af | ||
|
|
41655ee878 | ||
|
|
0d9b44c0e3 | ||
|
|
e87f36e885 | ||
|
|
b301cb17a3 | ||
|
|
e259daeff8 | ||
|
|
edb618c136 | ||
|
|
43cf04c031 | ||
|
|
e9991b1f06 | ||
|
|
975785dd42 | ||
|
|
e269e8901f | ||
|
|
87c31c2ffe | ||
|
|
54c674c936 | ||
|
|
2ba58fab22 | ||
|
|
cd7bd8568c | ||
|
|
cf80f829b4 | ||
|
|
ed25e094ab | ||
|
|
10df304b2f | ||
|
|
ecae62837c | ||
|
|
e8e871b44e | ||
|
|
6be6c19daf | ||
|
|
61f91bdc7e | ||
|
|
8ab50be000 | ||
|
|
dfab6e2d1c | ||
|
|
2f7bbdf8c9 | ||
|
|
af4767df5c | ||
|
|
233a399706 | ||
|
|
dcf1717793 | ||
|
|
b1e68f39e7 | ||
|
|
ee3d9330a8 | ||
|
|
d1d15306d1 | ||
|
|
e3b1ebbbfe | ||
|
|
17ae7e335e | ||
|
|
1edb57eda9 | ||
|
|
a2a9b0f977 | ||
|
|
ff96f804b6 | ||
|
|
a926994bfe | ||
|
|
83903535e3 | ||
|
|
8142408d3a | ||
|
|
a4158d1904 | ||
|
|
781019216c | ||
|
|
1322cd7a58 | ||
|
|
464bbd747e | ||
|
|
574182e1eb | ||
|
|
ef8209a953 | ||
|
|
9309098eab | ||
|
|
790a79b04c | ||
|
|
f8a40dafb9 | ||
|
|
9843a0b741 | ||
|
|
085a4debd5 | ||
|
|
4c1e24864f | ||
|
|
5d5f907e7f | ||
|
|
39178b5756 | ||
|
|
3d8412dd51 | ||
|
|
ff7057a46d | ||
|
|
bb8ef28913 | ||
|
|
13918ad344 | ||
|
|
7528ce60e7 | ||
|
|
6c6a7e7d97 | ||
|
|
111c509287 | ||
|
|
9d7ef0ad63 | ||
|
|
9aae54c81f | ||
|
|
1bc4ffc337 | ||
|
|
27879bc45e | ||
|
|
a3694b6989 | ||
|
|
28625fba5b | ||
|
|
7c3196ceac | ||
|
|
80c1264f4b | ||
|
|
f0340c28f1 | ||
|
|
5beb29ad35 | ||
|
|
27e307142b | ||
|
|
e02e752f68 | ||
|
|
5ddf67a9c2 | ||
|
|
4d3e2b23b8 | ||
|
|
ddf61373f6 | ||
|
|
b4ed3f07e4 | ||
|
|
ced94f2e0d | ||
|
|
aff432b197 | ||
|
|
0ac3be1482 | ||
|
|
75eaf99076 | ||
|
|
e67d60d336 |
@@ -2,12 +2,9 @@ root = "."
|
|||||||
tmp_dir = ".air"
|
tmp_dir = ".air"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
cmd = "make --no-print-directory backend"
|
cmd = "make backend"
|
||||||
bin = "gitea"
|
bin = "gitea"
|
||||||
delay = 1000
|
|
||||||
include_ext = ["go", "tmpl"]
|
include_ext = ["go", "tmpl"]
|
||||||
include_file = ["main.go"]
|
|
||||||
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
|
||||||
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
|
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
|
||||||
|
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
||||||
exclude_regex = ["_test.go$", "_gen.go$"]
|
exclude_regex = ["_test.go$", "_gen.go$"]
|
||||||
stop_on_error = true
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ cpu.out
|
|||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
/npm-debug.log*
|
/npm-debug.log*
|
||||||
/public/js
|
/public/js
|
||||||
|
/public/serviceworker.js
|
||||||
/public/css
|
/public/css
|
||||||
/public/fonts
|
/public/fonts
|
||||||
/public/img/webpack
|
/public/img/webpack
|
||||||
|
|||||||
1343
.drone.yml
1343
.drone.yml
File diff suppressed because it is too large
Load Diff
252
.eslintrc.yaml
252
.eslintrc.yaml
@@ -9,17 +9,10 @@ parserOptions:
|
|||||||
ecmaVersion: latest
|
ecmaVersion: latest
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- "@eslint-community/eslint-plugin-eslint-comments"
|
- eslint-plugin-unicorn
|
||||||
- eslint-plugin-array-func
|
|
||||||
- eslint-plugin-custom-elements
|
|
||||||
- eslint-plugin-import
|
- eslint-plugin-import
|
||||||
- eslint-plugin-jquery
|
- eslint-plugin-jquery
|
||||||
- eslint-plugin-no-jquery
|
|
||||||
- eslint-plugin-no-use-extend-native
|
|
||||||
- eslint-plugin-regexp
|
|
||||||
- eslint-plugin-sonarjs
|
- eslint-plugin-sonarjs
|
||||||
- eslint-plugin-unicorn
|
|
||||||
- eslint-plugin-wc
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
es2022: true
|
es2022: true
|
||||||
@@ -29,11 +22,11 @@ globals:
|
|||||||
__webpack_public_path__: true
|
__webpack_public_path__: true
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
- files: ["web_src/**/*", "docs/**/*"]
|
- files: ["web_src/**/*.js", "docs/**/*.js"]
|
||||||
env:
|
env:
|
||||||
browser: true
|
browser: true
|
||||||
node: false
|
node: false
|
||||||
- files: ["web_src/**/*worker.*"]
|
- files: ["web_src/**/*worker.js"]
|
||||||
env:
|
env:
|
||||||
worker: true
|
worker: true
|
||||||
rules:
|
rules:
|
||||||
@@ -42,31 +35,16 @@ overrides:
|
|||||||
rules:
|
rules:
|
||||||
import/no-unresolved: [0]
|
import/no-unresolved: [0]
|
||||||
import/no-extraneous-dependencies: [0]
|
import/no-extraneous-dependencies: [0]
|
||||||
- files: ["*.config.*"]
|
- files: ["*.config.js"]
|
||||||
rules:
|
rules:
|
||||||
import/no-unused-modules: [0]
|
import/no-unused-modules: [0]
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
"@eslint-community/eslint-comments/disable-enable-pair": [2]
|
|
||||||
"@eslint-community/eslint-comments/no-aggregating-enable": [2]
|
|
||||||
"@eslint-community/eslint-comments/no-duplicate-disable": [2]
|
|
||||||
"@eslint-community/eslint-comments/no-restricted-disable": [0]
|
|
||||||
"@eslint-community/eslint-comments/no-unlimited-disable": [2]
|
|
||||||
"@eslint-community/eslint-comments/no-unused-disable": [2]
|
|
||||||
"@eslint-community/eslint-comments/no-unused-enable": [2]
|
|
||||||
"@eslint-community/eslint-comments/no-use": [0]
|
|
||||||
"@eslint-community/eslint-comments/require-description": [0]
|
|
||||||
accessor-pairs: [2]
|
accessor-pairs: [2]
|
||||||
array-bracket-newline: [0]
|
array-bracket-newline: [0]
|
||||||
array-bracket-spacing: [2, never]
|
array-bracket-spacing: [2, never]
|
||||||
array-callback-return: [2, {checkForEach: true}]
|
array-callback-return: [2, {checkForEach: true}]
|
||||||
array-element-newline: [0]
|
array-element-newline: [0]
|
||||||
array-func/avoid-reverse: [2]
|
|
||||||
array-func/from-map: [2]
|
|
||||||
array-func/no-unnecessary-this-arg: [2]
|
|
||||||
array-func/prefer-array-from: [2]
|
|
||||||
array-func/prefer-flat-map: [0] # handled by unicorn/prefer-array-flat-map
|
|
||||||
array-func/prefer-flat: [0] # handled by unicorn/prefer-array-flat
|
|
||||||
arrow-body-style: [0]
|
arrow-body-style: [0]
|
||||||
arrow-parens: [2, always]
|
arrow-parens: [2, always]
|
||||||
arrow-spacing: [2, {before: true, after: true}]
|
arrow-spacing: [2, {before: true, after: true}]
|
||||||
@@ -84,19 +62,6 @@ rules:
|
|||||||
consistent-this: [0]
|
consistent-this: [0]
|
||||||
constructor-super: [2]
|
constructor-super: [2]
|
||||||
curly: [0]
|
curly: [0]
|
||||||
custom-elements/expose-class-on-global: [0]
|
|
||||||
custom-elements/extends-correct-class: [2]
|
|
||||||
custom-elements/file-name-matches-element: [2]
|
|
||||||
custom-elements/no-constructor: [2]
|
|
||||||
custom-elements/no-customized-built-in-elements: [2]
|
|
||||||
custom-elements/no-dom-traversal-in-attributechangedcallback: [2]
|
|
||||||
custom-elements/no-dom-traversal-in-connectedcallback: [2]
|
|
||||||
custom-elements/no-exports-with-element: [2]
|
|
||||||
custom-elements/no-method-prefixed-with-on: [2]
|
|
||||||
custom-elements/no-unchecked-define: [0]
|
|
||||||
custom-elements/one-element-per-file: [0]
|
|
||||||
custom-elements/tag-name-matches-class: [2]
|
|
||||||
custom-elements/valid-tag-name: [2]
|
|
||||||
default-case-last: [2]
|
default-case-last: [2]
|
||||||
default-case: [0]
|
default-case: [0]
|
||||||
default-param-last: [0]
|
default-param-last: [0]
|
||||||
@@ -132,9 +97,9 @@ rules:
|
|||||||
import/namespace: [0]
|
import/namespace: [0]
|
||||||
import/newline-after-import: [0]
|
import/newline-after-import: [0]
|
||||||
import/no-absolute-path: [0]
|
import/no-absolute-path: [0]
|
||||||
import/no-amd: [2]
|
import/no-amd: [0]
|
||||||
import/no-anonymous-default-export: [0]
|
import/no-anonymous-default-export: [0]
|
||||||
import/no-commonjs: [2]
|
import/no-commonjs: [0]
|
||||||
import/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
|
import/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
|
||||||
import/no-default-export: [0]
|
import/no-default-export: [0]
|
||||||
import/no-deprecated: [0]
|
import/no-deprecated: [0]
|
||||||
@@ -199,7 +164,7 @@ rules:
|
|||||||
jquery/no-parse-html: [2]
|
jquery/no-parse-html: [2]
|
||||||
jquery/no-prop: [0]
|
jquery/no-prop: [0]
|
||||||
jquery/no-proxy: [2]
|
jquery/no-proxy: [2]
|
||||||
jquery/no-ready: [2]
|
jquery/no-ready: [0]
|
||||||
jquery/no-serialize: [2]
|
jquery/no-serialize: [2]
|
||||||
jquery/no-show: [2]
|
jquery/no-show: [2]
|
||||||
jquery/no-size: [2]
|
jquery/no-size: [2]
|
||||||
@@ -291,99 +256,6 @@ rules:
|
|||||||
no-invalid-this: [0]
|
no-invalid-this: [0]
|
||||||
no-irregular-whitespace: [2]
|
no-irregular-whitespace: [2]
|
||||||
no-iterator: [2]
|
no-iterator: [2]
|
||||||
no-jquery/no-ajax-events: [2]
|
|
||||||
no-jquery/no-ajax: [0]
|
|
||||||
no-jquery/no-and-self: [2]
|
|
||||||
no-jquery/no-animate-toggle: [2]
|
|
||||||
no-jquery/no-animate: [2]
|
|
||||||
no-jquery/no-append-html: [0]
|
|
||||||
no-jquery/no-attr: [0]
|
|
||||||
no-jquery/no-bind: [2]
|
|
||||||
no-jquery/no-box-model: [2]
|
|
||||||
no-jquery/no-browser: [2]
|
|
||||||
no-jquery/no-camel-case: [2]
|
|
||||||
no-jquery/no-class-state: [0]
|
|
||||||
no-jquery/no-class: [0]
|
|
||||||
no-jquery/no-clone: [2]
|
|
||||||
no-jquery/no-closest: [0]
|
|
||||||
no-jquery/no-constructor-attributes: [2]
|
|
||||||
no-jquery/no-contains: [2]
|
|
||||||
no-jquery/no-context-prop: [2]
|
|
||||||
no-jquery/no-css: [0]
|
|
||||||
no-jquery/no-data: [0]
|
|
||||||
no-jquery/no-deferred: [2]
|
|
||||||
no-jquery/no-delegate: [2]
|
|
||||||
no-jquery/no-each-collection: [0]
|
|
||||||
no-jquery/no-each-util: [0]
|
|
||||||
no-jquery/no-each: [0]
|
|
||||||
no-jquery/no-error-shorthand: [2]
|
|
||||||
no-jquery/no-error: [2]
|
|
||||||
no-jquery/no-escape-selector: [2]
|
|
||||||
no-jquery/no-event-shorthand: [2]
|
|
||||||
no-jquery/no-extend: [2]
|
|
||||||
no-jquery/no-fade: [2]
|
|
||||||
no-jquery/no-filter: [0]
|
|
||||||
no-jquery/no-find-collection: [0]
|
|
||||||
no-jquery/no-find-util: [2]
|
|
||||||
no-jquery/no-find: [0]
|
|
||||||
no-jquery/no-fx-interval: [2]
|
|
||||||
no-jquery/no-global-eval: [2]
|
|
||||||
no-jquery/no-global-selector: [0]
|
|
||||||
no-jquery/no-grep: [2]
|
|
||||||
no-jquery/no-has: [2]
|
|
||||||
no-jquery/no-hold-ready: [2]
|
|
||||||
no-jquery/no-html: [0]
|
|
||||||
no-jquery/no-in-array: [2]
|
|
||||||
no-jquery/no-is-array: [2]
|
|
||||||
no-jquery/no-is-empty-object: [2]
|
|
||||||
no-jquery/no-is-function: [2]
|
|
||||||
no-jquery/no-is-numeric: [2]
|
|
||||||
no-jquery/no-is-plain-object: [2]
|
|
||||||
no-jquery/no-is-window: [2]
|
|
||||||
no-jquery/no-is: [0]
|
|
||||||
no-jquery/no-jquery-constructor: [0]
|
|
||||||
no-jquery/no-live: [2]
|
|
||||||
no-jquery/no-load-shorthand: [2]
|
|
||||||
no-jquery/no-load: [2]
|
|
||||||
no-jquery/no-map-collection: [0]
|
|
||||||
no-jquery/no-map-util: [2]
|
|
||||||
no-jquery/no-map: [0]
|
|
||||||
no-jquery/no-merge: [2]
|
|
||||||
no-jquery/no-node-name: [2]
|
|
||||||
no-jquery/no-noop: [2]
|
|
||||||
no-jquery/no-now: [2]
|
|
||||||
no-jquery/no-on-ready: [2]
|
|
||||||
no-jquery/no-other-methods: [0]
|
|
||||||
no-jquery/no-other-utils: [2]
|
|
||||||
no-jquery/no-param: [2]
|
|
||||||
no-jquery/no-parent: [0]
|
|
||||||
no-jquery/no-parents: [0]
|
|
||||||
no-jquery/no-parse-html-literal: [0]
|
|
||||||
no-jquery/no-parse-html: [2]
|
|
||||||
no-jquery/no-parse-json: [2]
|
|
||||||
no-jquery/no-parse-xml: [2]
|
|
||||||
no-jquery/no-prop: [0]
|
|
||||||
no-jquery/no-proxy: [2]
|
|
||||||
no-jquery/no-ready-shorthand: [2]
|
|
||||||
no-jquery/no-ready: [2]
|
|
||||||
no-jquery/no-selector-prop: [2]
|
|
||||||
no-jquery/no-serialize: [2]
|
|
||||||
no-jquery/no-size: [2]
|
|
||||||
no-jquery/no-sizzle: [0]
|
|
||||||
no-jquery/no-slide: [2]
|
|
||||||
no-jquery/no-sub: [2]
|
|
||||||
no-jquery/no-support: [2]
|
|
||||||
no-jquery/no-text: [0]
|
|
||||||
no-jquery/no-trigger: [0]
|
|
||||||
no-jquery/no-trim: [2]
|
|
||||||
no-jquery/no-type: [2]
|
|
||||||
no-jquery/no-unique: [2]
|
|
||||||
no-jquery/no-unload-shorthand: [2]
|
|
||||||
no-jquery/no-val: [0]
|
|
||||||
no-jquery/no-visibility: [2]
|
|
||||||
no-jquery/no-when: [2]
|
|
||||||
no-jquery/no-wrap: [2]
|
|
||||||
no-jquery/variable-pattern: [0]
|
|
||||||
no-label-var: [2]
|
no-label-var: [2]
|
||||||
no-labels: [0] # handled by no-restricted-syntax
|
no-labels: [0] # handled by no-restricted-syntax
|
||||||
no-lone-blocks: [2]
|
no-lone-blocks: [2]
|
||||||
@@ -452,7 +324,6 @@ rules:
|
|||||||
no-unused-private-class-members: [2]
|
no-unused-private-class-members: [2]
|
||||||
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}]
|
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}]
|
||||||
no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}]
|
no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}]
|
||||||
no-use-extend-native/no-use-extend-native: [2]
|
|
||||||
no-useless-backreference: [2]
|
no-useless-backreference: [2]
|
||||||
no-useless-call: [2]
|
no-useless-call: [2]
|
||||||
no-useless-catch: [2]
|
no-useless-catch: [2]
|
||||||
@@ -493,80 +364,6 @@ rules:
|
|||||||
quote-props: [0]
|
quote-props: [0]
|
||||||
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
||||||
radix: [2, as-needed]
|
radix: [2, as-needed]
|
||||||
regexp/confusing-quantifier: [2]
|
|
||||||
regexp/control-character-escape: [2]
|
|
||||||
regexp/hexadecimal-escape: [0]
|
|
||||||
regexp/letter-case: [0]
|
|
||||||
regexp/match-any: [2]
|
|
||||||
regexp/negation: [2]
|
|
||||||
regexp/no-contradiction-with-assertion: [0]
|
|
||||||
regexp/no-control-character: [0]
|
|
||||||
regexp/no-dupe-characters-character-class: [2]
|
|
||||||
regexp/no-dupe-disjunctions: [2]
|
|
||||||
regexp/no-empty-alternative: [2]
|
|
||||||
regexp/no-empty-capturing-group: [2]
|
|
||||||
regexp/no-empty-character-class: [0]
|
|
||||||
regexp/no-empty-group: [2]
|
|
||||||
regexp/no-empty-lookarounds-assertion: [2]
|
|
||||||
regexp/no-escape-backspace: [2]
|
|
||||||
regexp/no-extra-lookaround-assertions: [0]
|
|
||||||
regexp/no-invalid-regexp: [2]
|
|
||||||
regexp/no-invisible-character: [2]
|
|
||||||
regexp/no-lazy-ends: [2]
|
|
||||||
regexp/no-legacy-features: [2]
|
|
||||||
regexp/no-misleading-capturing-group: [0]
|
|
||||||
regexp/no-misleading-unicode-character: [0]
|
|
||||||
regexp/no-missing-g-flag: [2]
|
|
||||||
regexp/no-non-standard-flag: [2]
|
|
||||||
regexp/no-obscure-range: [2]
|
|
||||||
regexp/no-octal: [2]
|
|
||||||
regexp/no-optional-assertion: [2]
|
|
||||||
regexp/no-potentially-useless-backreference: [2]
|
|
||||||
regexp/no-standalone-backslash: [2]
|
|
||||||
regexp/no-super-linear-backtracking: [0]
|
|
||||||
regexp/no-super-linear-move: [0]
|
|
||||||
regexp/no-trivially-nested-assertion: [2]
|
|
||||||
regexp/no-trivially-nested-quantifier: [2]
|
|
||||||
regexp/no-unused-capturing-group: [0]
|
|
||||||
regexp/no-useless-assertions: [2]
|
|
||||||
regexp/no-useless-backreference: [2]
|
|
||||||
regexp/no-useless-character-class: [2]
|
|
||||||
regexp/no-useless-dollar-replacements: [2]
|
|
||||||
regexp/no-useless-escape: [2]
|
|
||||||
regexp/no-useless-flag: [2]
|
|
||||||
regexp/no-useless-lazy: [2]
|
|
||||||
regexp/no-useless-non-capturing-group: [2]
|
|
||||||
regexp/no-useless-quantifier: [2]
|
|
||||||
regexp/no-useless-range: [2]
|
|
||||||
regexp/no-useless-two-nums-quantifier: [2]
|
|
||||||
regexp/no-zero-quantifier: [2]
|
|
||||||
regexp/optimal-lookaround-quantifier: [2]
|
|
||||||
regexp/optimal-quantifier-concatenation: [0]
|
|
||||||
regexp/prefer-character-class: [0]
|
|
||||||
regexp/prefer-d: [0]
|
|
||||||
regexp/prefer-escape-replacement-dollar-char: [0]
|
|
||||||
regexp/prefer-lookaround: [0]
|
|
||||||
regexp/prefer-named-backreference: [0]
|
|
||||||
regexp/prefer-named-capture-group: [0]
|
|
||||||
regexp/prefer-named-replacement: [0]
|
|
||||||
regexp/prefer-plus-quantifier: [2]
|
|
||||||
regexp/prefer-predefined-assertion: [2]
|
|
||||||
regexp/prefer-quantifier: [0]
|
|
||||||
regexp/prefer-question-quantifier: [2]
|
|
||||||
regexp/prefer-range: [2]
|
|
||||||
regexp/prefer-regexp-exec: [2]
|
|
||||||
regexp/prefer-regexp-test: [2]
|
|
||||||
regexp/prefer-result-array-groups: [0]
|
|
||||||
regexp/prefer-star-quantifier: [2]
|
|
||||||
regexp/prefer-unicode-codepoint-escapes: [2]
|
|
||||||
regexp/prefer-w: [0]
|
|
||||||
regexp/require-unicode-regexp: [0]
|
|
||||||
regexp/sort-alternatives: [0]
|
|
||||||
regexp/sort-character-class-elements: [0]
|
|
||||||
regexp/sort-flags: [0]
|
|
||||||
regexp/strict: [2]
|
|
||||||
regexp/unicode-escape: [0]
|
|
||||||
regexp/use-ignore-case: [0]
|
|
||||||
require-atomic-updates: [0]
|
require-atomic-updates: [0]
|
||||||
require-await: [0]
|
require-await: [0]
|
||||||
require-unicode-regexp: [0]
|
require-unicode-regexp: [0]
|
||||||
@@ -596,7 +393,7 @@ rules:
|
|||||||
sonarjs/no-nested-template-literals: [0]
|
sonarjs/no-nested-template-literals: [0]
|
||||||
sonarjs/no-one-iteration-loop: [2]
|
sonarjs/no-one-iteration-loop: [2]
|
||||||
sonarjs/no-redundant-boolean: [2]
|
sonarjs/no-redundant-boolean: [2]
|
||||||
sonarjs/no-redundant-jump: [2]
|
sonarjs/no-redundant-jump: [0]
|
||||||
sonarjs/no-same-line-conditional: [2]
|
sonarjs/no-same-line-conditional: [2]
|
||||||
sonarjs/no-small-switch: [0]
|
sonarjs/no-small-switch: [0]
|
||||||
sonarjs/no-unused-collection: [2]
|
sonarjs/no-unused-collection: [2]
|
||||||
@@ -636,18 +433,17 @@ rules:
|
|||||||
unicorn/import-style: [0]
|
unicorn/import-style: [0]
|
||||||
unicorn/new-for-builtins: [2]
|
unicorn/new-for-builtins: [2]
|
||||||
unicorn/no-abusive-eslint-disable: [0]
|
unicorn/no-abusive-eslint-disable: [0]
|
||||||
unicorn/no-array-callback-reference: [0]
|
|
||||||
unicorn/no-array-for-each: [2]
|
unicorn/no-array-for-each: [2]
|
||||||
|
unicorn/no-array-instanceof: [0]
|
||||||
unicorn/no-array-method-this-argument: [2]
|
unicorn/no-array-method-this-argument: [2]
|
||||||
unicorn/no-array-push-push: [2]
|
unicorn/no-array-push-push: [2]
|
||||||
unicorn/no-array-reduce: [2]
|
|
||||||
unicorn/no-await-expression-member: [0]
|
unicorn/no-await-expression-member: [0]
|
||||||
unicorn/no-console-spaces: [0]
|
unicorn/no-console-spaces: [0]
|
||||||
unicorn/no-document-cookie: [2]
|
unicorn/no-document-cookie: [2]
|
||||||
unicorn/no-empty-file: [2]
|
unicorn/no-empty-file: [2]
|
||||||
|
unicorn/no-fn-reference-in-iterator: [0]
|
||||||
unicorn/no-for-loop: [0]
|
unicorn/no-for-loop: [0]
|
||||||
unicorn/no-hex-escape: [0]
|
unicorn/no-hex-escape: [0]
|
||||||
unicorn/no-instanceof-array: [0]
|
|
||||||
unicorn/no-invalid-remove-event-listener: [2]
|
unicorn/no-invalid-remove-event-listener: [2]
|
||||||
unicorn/no-keyword-prefix: [0]
|
unicorn/no-keyword-prefix: [0]
|
||||||
unicorn/no-lonely-if: [2]
|
unicorn/no-lonely-if: [2]
|
||||||
@@ -658,6 +454,7 @@ rules:
|
|||||||
unicorn/no-null: [0]
|
unicorn/no-null: [0]
|
||||||
unicorn/no-object-as-default-parameter: [0]
|
unicorn/no-object-as-default-parameter: [0]
|
||||||
unicorn/no-process-exit: [0]
|
unicorn/no-process-exit: [0]
|
||||||
|
unicorn/no-reduce: [2]
|
||||||
unicorn/no-static-only-class: [2]
|
unicorn/no-static-only-class: [2]
|
||||||
unicorn/no-thenable: [2]
|
unicorn/no-thenable: [2]
|
||||||
unicorn/no-this-assignment: [2]
|
unicorn/no-this-assignment: [2]
|
||||||
@@ -683,19 +480,15 @@ rules:
|
|||||||
unicorn/prefer-array-index-of: [2]
|
unicorn/prefer-array-index-of: [2]
|
||||||
unicorn/prefer-array-some: [2]
|
unicorn/prefer-array-some: [2]
|
||||||
unicorn/prefer-at: [0]
|
unicorn/prefer-at: [0]
|
||||||
unicorn/prefer-blob-reading-methods: [2]
|
|
||||||
unicorn/prefer-code-point: [0]
|
unicorn/prefer-code-point: [0]
|
||||||
|
unicorn/prefer-dataset: [2]
|
||||||
unicorn/prefer-date-now: [2]
|
unicorn/prefer-date-now: [2]
|
||||||
unicorn/prefer-default-parameters: [0]
|
unicorn/prefer-default-parameters: [0]
|
||||||
unicorn/prefer-dom-node-append: [2]
|
unicorn/prefer-event-key: [2]
|
||||||
unicorn/prefer-dom-node-dataset: [0]
|
|
||||||
unicorn/prefer-dom-node-remove: [2]
|
|
||||||
unicorn/prefer-dom-node-text-content: [2]
|
|
||||||
unicorn/prefer-event-target: [2]
|
unicorn/prefer-event-target: [2]
|
||||||
unicorn/prefer-export-from: [2, {ignoreUsedVariables: true}]
|
unicorn/prefer-export-from: [2]
|
||||||
unicorn/prefer-includes: [2]
|
unicorn/prefer-includes: [2]
|
||||||
unicorn/prefer-json-parse-buffer: [0]
|
unicorn/prefer-json-parse-buffer: [0]
|
||||||
unicorn/prefer-keyboard-event-key: [2]
|
|
||||||
unicorn/prefer-logical-operator-over-ternary: [2]
|
unicorn/prefer-logical-operator-over-ternary: [2]
|
||||||
unicorn/prefer-math-trunc: [2]
|
unicorn/prefer-math-trunc: [2]
|
||||||
unicorn/prefer-modern-dom-apis: [0]
|
unicorn/prefer-modern-dom-apis: [0]
|
||||||
@@ -703,7 +496,9 @@ rules:
|
|||||||
unicorn/prefer-module: [2]
|
unicorn/prefer-module: [2]
|
||||||
unicorn/prefer-native-coercion-functions: [2]
|
unicorn/prefer-native-coercion-functions: [2]
|
||||||
unicorn/prefer-negative-index: [2]
|
unicorn/prefer-negative-index: [2]
|
||||||
|
unicorn/prefer-node-append: [0]
|
||||||
unicorn/prefer-node-protocol: [2]
|
unicorn/prefer-node-protocol: [2]
|
||||||
|
unicorn/prefer-node-remove: [0]
|
||||||
unicorn/prefer-number-properties: [0]
|
unicorn/prefer-number-properties: [0]
|
||||||
unicorn/prefer-object-from-entries: [2]
|
unicorn/prefer-object-from-entries: [2]
|
||||||
unicorn/prefer-object-has-own: [0]
|
unicorn/prefer-object-has-own: [0]
|
||||||
@@ -712,17 +507,17 @@ rules:
|
|||||||
unicorn/prefer-query-selector: [0]
|
unicorn/prefer-query-selector: [0]
|
||||||
unicorn/prefer-reflect-apply: [0]
|
unicorn/prefer-reflect-apply: [0]
|
||||||
unicorn/prefer-regexp-test: [2]
|
unicorn/prefer-regexp-test: [2]
|
||||||
|
unicorn/prefer-replace-all: [0]
|
||||||
unicorn/prefer-set-has: [0]
|
unicorn/prefer-set-has: [0]
|
||||||
unicorn/prefer-set-size: [2]
|
unicorn/prefer-set-size: [2]
|
||||||
unicorn/prefer-spread: [0]
|
unicorn/prefer-spread: [0]
|
||||||
unicorn/prefer-string-replace-all: [0]
|
unicorn/prefer-starts-ends-with: [2]
|
||||||
unicorn/prefer-string-slice: [0]
|
unicorn/prefer-string-slice: [0]
|
||||||
unicorn/prefer-string-starts-ends-with: [2]
|
|
||||||
unicorn/prefer-string-trim-start-end: [2]
|
|
||||||
unicorn/prefer-switch: [0]
|
unicorn/prefer-switch: [0]
|
||||||
unicorn/prefer-ternary: [0]
|
unicorn/prefer-ternary: [0]
|
||||||
unicorn/prefer-text-content: [2]
|
unicorn/prefer-text-content: [2]
|
||||||
unicorn/prefer-top-level-await: [0]
|
unicorn/prefer-top-level-await: [0]
|
||||||
|
unicorn/prefer-trim-start-end: [2]
|
||||||
unicorn/prefer-type-error: [0]
|
unicorn/prefer-type-error: [0]
|
||||||
unicorn/prevent-abbreviations: [0]
|
unicorn/prevent-abbreviations: [0]
|
||||||
unicorn/relative-url-style: [2]
|
unicorn/relative-url-style: [2]
|
||||||
@@ -737,15 +532,6 @@ rules:
|
|||||||
use-isnan: [2]
|
use-isnan: [2]
|
||||||
valid-typeof: [2, {requireStringLiterals: true}]
|
valid-typeof: [2, {requireStringLiterals: true}]
|
||||||
vars-on-top: [0]
|
vars-on-top: [0]
|
||||||
wc/attach-shadow-constructor: [2]
|
|
||||||
wc/guard-super-call: [2]
|
|
||||||
wc/no-closed-shadow-root: [2]
|
|
||||||
wc/no-constructor-attributes: [2]
|
|
||||||
wc/no-constructor-params: [2]
|
|
||||||
wc/no-invalid-element-name: [0] # covered by custom-elements/valid-tag-name
|
|
||||||
wc/no-self-class: [2]
|
|
||||||
wc/no-typos: [2]
|
|
||||||
wc/require-listener-teardown: [2]
|
|
||||||
wrap-iife: [2, inside]
|
wrap-iife: [2, inside]
|
||||||
wrap-regex: [0]
|
wrap-regex: [0]
|
||||||
yield-star-spacing: [2, after]
|
yield-star-spacing: [2, after]
|
||||||
|
|||||||
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -1,10 +1,8 @@
|
|||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
*.tmpl linguist-language=Handlebars
|
*.tmpl linguist-language=Handlebars
|
||||||
/assets/*.json linguist-generated
|
/assets/*.json linguist-generated
|
||||||
/public/img/svg/*.svg linguist-generated
|
/public/vendor/** -text -eol linguist-vendored
|
||||||
/templates/swagger/v1_json.tmpl linguist-generated
|
|
||||||
/vendor/** -text -eol linguist-vendored
|
/vendor/** -text -eol linguist-vendored
|
||||||
/web_src/fomantic/build/** linguist-generated
|
/web_src/fomantic/build/** linguist-generated
|
||||||
/web_src/fomantic/_site/globals/site.variables linguist-language=Less
|
|
||||||
/web_src/js/vendor/** -text -eol linguist-vendored
|
/web_src/js/vendor/** -text -eol linguist-vendored
|
||||||
Dockerfile.* linguist-language=Dockerfile
|
Dockerfile.* linguist-language=Dockerfile
|
||||||
|
|||||||
23
.github/lock.yml
vendored
Normal file
23
.github/lock.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Configuration for Lock Threads - https://github.com/dessant/lock-threads-app
|
||||||
|
|
||||||
|
# Number of days of inactivity before a closed issue or pull request is locked
|
||||||
|
daysUntilLock: 60
|
||||||
|
|
||||||
|
# Skip issues and pull requests created before a given timestamp. Timestamp must
|
||||||
|
# follow ISO 8601 (`YYYY-MM-DD`). `false` is disabled
|
||||||
|
skipCreatedBefore: false
|
||||||
|
|
||||||
|
# Issues and pull requests with these labels will be ignored.
|
||||||
|
exemptLabels: []
|
||||||
|
|
||||||
|
# Label to add before locking, such as `outdated`. `false` is disabled
|
||||||
|
lockLabel: false
|
||||||
|
|
||||||
|
# Comment to post before locking.
|
||||||
|
lockComment: >
|
||||||
|
This thread has been automatically locked since there has not been
|
||||||
|
any recent activity after it was closed. Please open a new issue for
|
||||||
|
related bugs and link to relevant comments in this thread.
|
||||||
|
|
||||||
|
# Assign `resolved` as the reason for locking. Set to `false` to disable
|
||||||
|
setLockReason: true
|
||||||
28
.github/workflows/cron-licenses.yml
vendored
28
.github/workflows/cron-licenses.yml
vendored
@@ -1,28 +0,0 @@
|
|||||||
name: cron-licenses
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "7 0 * * 1" # every Monday at 00:07 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cron-licenses:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.1"
|
|
||||||
- run: make generate-license generate-gitignore
|
|
||||||
timeout-minutes: 40
|
|
||||||
- name: push translations to repo
|
|
||||||
uses: appleboy/git-push-action@v0.0.2
|
|
||||||
with:
|
|
||||||
author_email: "teabot@gitea.io"
|
|
||||||
author_name: GiteaBot
|
|
||||||
branch: main
|
|
||||||
commit: true
|
|
||||||
commit_message: "[skip ci] Updated licenses and gitignores"
|
|
||||||
remote: "git@github.com:go-gitea/gitea.git"
|
|
||||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
|
||||||
22
.github/workflows/cron-lock.yml
vendored
22
.github/workflows/cron-lock.yml
vendored
@@ -1,22 +0,0 @@
|
|||||||
name: cron-lock
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *" # every day at 00:00 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: lock
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
action:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: dessant/lock-threads@v4
|
|
||||||
with:
|
|
||||||
issue-inactive-days: 45
|
|
||||||
49
.github/workflows/cron-translations.yml
vendored
49
.github/workflows/cron-translations.yml
vendored
@@ -1,49 +0,0 @@
|
|||||||
name: cron-translations
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "7 0 * * *" # every day at 00:07 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
crowdin-pull:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: download from crowdin
|
|
||||||
uses: docker://jonasfranz/crowdin
|
|
||||||
env:
|
|
||||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
|
||||||
PLUGIN_DOWNLOAD: true
|
|
||||||
PLUGIN_EXPORT_DIR: options/locale/
|
|
||||||
PLUGIN_IGNORE_BRANCH: true
|
|
||||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
|
||||||
- name: update locales
|
|
||||||
run: ./build/update-locales.sh
|
|
||||||
- name: push translations to repo
|
|
||||||
uses: appleboy/git-push-action@v0.0.2
|
|
||||||
with:
|
|
||||||
author_email: "teabot@gitea.io"
|
|
||||||
author_name: GiteaBot
|
|
||||||
branch: main
|
|
||||||
commit: true
|
|
||||||
commit_message: "[skip ci] Updated translations via Crowdin"
|
|
||||||
remote: "git@github.com:go-gitea/gitea.git"
|
|
||||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
|
||||||
crowdin-push:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: push translations to crowdin
|
|
||||||
uses: docker://jonasfranz/crowdin
|
|
||||||
env:
|
|
||||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
|
||||||
PLUGIN_UPLOAD: true
|
|
||||||
PLUGIN_EXPORT_DIR: options/locale/
|
|
||||||
PLUGIN_IGNORE_BRANCH: true
|
|
||||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
|
||||||
PLUGIN_FILES: |
|
|
||||||
locale_en-US.ini: options/locale/locale_en-US.ini
|
|
||||||
PLUGIN_BRANCH: main
|
|
||||||
53
.github/workflows/files-changed.yml
vendored
53
.github/workflows/files-changed.yml
vendored
@@ -1,53 +0,0 @@
|
|||||||
name: files-changed
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
outputs:
|
|
||||||
backend:
|
|
||||||
description: "whether backend files changed"
|
|
||||||
value: ${{ jobs.detect.outputs.backend }}
|
|
||||||
frontend:
|
|
||||||
description: "whether frontend files changed"
|
|
||||||
value: ${{ jobs.detect.outputs.frontend }}
|
|
||||||
docs:
|
|
||||||
description: "whether docs files changed"
|
|
||||||
value: ${{ jobs.detect.outputs.docs }}
|
|
||||||
actions:
|
|
||||||
description: "whether actions files changed"
|
|
||||||
value: ${{ jobs.detect.outputs.actions }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
detect:
|
|
||||||
name: detect which files changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 3
|
|
||||||
# Map a step output to a job output
|
|
||||||
outputs:
|
|
||||||
backend: ${{ steps.changes.outputs.backend }}
|
|
||||||
frontend: ${{ steps.changes.outputs.frontend }}
|
|
||||||
docs: ${{ steps.changes.outputs.docs }}
|
|
||||||
actions: ${{ steps.changes.outputs.actions }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dorny/paths-filter@v2
|
|
||||||
id: changes
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
backend:
|
|
||||||
- "**/*.go"
|
|
||||||
- "**/*.tmpl"
|
|
||||||
- "go.mod"
|
|
||||||
- "go.sum"
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
- "**/*.js"
|
|
||||||
- "web_src/**"
|
|
||||||
- "package.json"
|
|
||||||
- "package-lock.json"
|
|
||||||
|
|
||||||
docs:
|
|
||||||
- "**/*.md"
|
|
||||||
- "docs/**"
|
|
||||||
|
|
||||||
actions:
|
|
||||||
- ".github/workflows/*"
|
|
||||||
140
.github/workflows/pull-compliance.yml
vendored
140
.github/workflows/pull-compliance.yml
vendored
@@ -1,140 +0,0 @@
|
|||||||
name: compliance
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
lint-backend:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make lint-backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
|
|
||||||
lint-go-windows:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make lint-go-windows lint-go-vet
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
GOOS: windows
|
|
||||||
GOARCH: amd64
|
|
||||||
|
|
||||||
lint-go-gogit:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make lint-go
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
|
||||||
|
|
||||||
checks-backend:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
if: needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend
|
|
||||||
- run: make lint-frontend
|
|
||||||
- run: make checks-frontend
|
|
||||||
- run: make frontend
|
|
||||||
|
|
||||||
backend:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
# no frontend build here as backend should be able to build
|
|
||||||
# even without any frontend files
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
|
||||||
- name: build-backend-arm64
|
|
||||||
run: make backend # test cross compile
|
|
||||||
env:
|
|
||||||
GOOS: linux
|
|
||||||
GOARCH: arm64
|
|
||||||
TAGS: bindata gogit
|
|
||||||
- name: build-backend-windows
|
|
||||||
run: go build -o gitea_windows
|
|
||||||
env:
|
|
||||||
GOOS: windows
|
|
||||||
GOARCH: amd64
|
|
||||||
TAGS: bindata gogit
|
|
||||||
- name: build-backend-386
|
|
||||||
run: go build -o gitea_linux_386 # test if compatible with 32 bit
|
|
||||||
env:
|
|
||||||
GOOS: linux
|
|
||||||
GOARCH: 386
|
|
||||||
|
|
||||||
docs:
|
|
||||||
if: needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend
|
|
||||||
- run: make lint-md
|
|
||||||
- run: make docs # test if build could succeed
|
|
||||||
|
|
||||||
actions:
|
|
||||||
if: needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
- run: make lint-actions
|
|
||||||
247
.github/workflows/pull-db-tests.yml
vendored
247
.github/workflows/pull-db-tests.yml
vendored
@@ -1,247 +0,0 @@
|
|||||||
name: db-tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
test-pgsql:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
pgsql:
|
|
||||||
image: postgres:15
|
|
||||||
env:
|
|
||||||
POSTGRES_DB: test
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
ldap:
|
|
||||||
image: gitea/test-openldap:latest
|
|
||||||
ports:
|
|
||||||
- "389:389"
|
|
||||||
- "636:636"
|
|
||||||
minio:
|
|
||||||
# as github actions doesn't support "entrypoint", we need to use a non-official image
|
|
||||||
# that has a custom entrypoint set to "minio server /data"
|
|
||||||
image: bitnami/minio:2021.3.17
|
|
||||||
env:
|
|
||||||
MINIO_ACCESS_KEY: 123456
|
|
||||||
MINIO_SECRET_KEY: 12345678
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.0"
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: make test-pgsql-migration test-pgsql
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit
|
|
||||||
RACE_ENABLED: true
|
|
||||||
TEST_TAGS: gogit
|
|
||||||
TEST_LDAP: 1
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-sqlite:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.0"
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
|
||||||
- run: make test-sqlite-migration test-sqlite
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
|
||||||
RACE_ENABLED: true
|
|
||||||
TEST_TAGS: gogit sqlite sqlite_unlock_notify
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-unit:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mysql:
|
|
||||||
image: mysql:5.7
|
|
||||||
env:
|
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
|
||||||
MYSQL_DATABASE: test
|
|
||||||
ports:
|
|
||||||
- "3306:3306"
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:7.5.0
|
|
||||||
env:
|
|
||||||
discovery.type: single-node
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
smtpimap:
|
|
||||||
image: tabascoterrier/docker-imap-devel:latest
|
|
||||||
ports:
|
|
||||||
- "25:25"
|
|
||||||
- "143:143"
|
|
||||||
- "587:587"
|
|
||||||
- "993:993"
|
|
||||||
redis:
|
|
||||||
image: redis
|
|
||||||
options: >- # wait until redis has started
|
|
||||||
--health-cmd "redis-cli ping"
|
|
||||||
--health-interval 5s
|
|
||||||
--health-timeout 3s
|
|
||||||
--health-retries 10
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
minio:
|
|
||||||
image: bitnami/minio:2021.3.17
|
|
||||||
env:
|
|
||||||
MINIO_ACCESS_KEY: 123456
|
|
||||||
MINIO_SECRET_KEY: 12345678
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.0"
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- name: unit-tests
|
|
||||||
run: make unit-test-coverage test-check
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
RACE_ENABLED: true
|
|
||||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
|
||||||
- name: unit-tests-gogit
|
|
||||||
run: make unit-test-coverage test-check
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit
|
|
||||||
RACE_ENABLED: true
|
|
||||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
|
||||||
|
|
||||||
test-mysql5:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mysql:
|
|
||||||
image: mysql:5.7
|
|
||||||
env:
|
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
|
||||||
MYSQL_DATABASE: test
|
|
||||||
ports:
|
|
||||||
- "3306:3306"
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:7.5.0
|
|
||||||
env:
|
|
||||||
discovery.type: single-node
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
smtpimap:
|
|
||||||
image: tabascoterrier/docker-imap-devel:latest
|
|
||||||
ports:
|
|
||||||
- "25:25"
|
|
||||||
- "143:143"
|
|
||||||
- "587:587"
|
|
||||||
- "993:993"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.0"
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- name: run tests
|
|
||||||
run: make test-mysql-migration integration-test-coverage
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
RACE_ENABLED: true
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
|
|
||||||
|
|
||||||
test-mysql8:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mysql8:
|
|
||||||
image: mysql:8
|
|
||||||
env:
|
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
|
||||||
MYSQL_DATABASE: testgitea
|
|
||||||
ports:
|
|
||||||
- "3306:3306"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.0"
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql8" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: make test-mysql8-migration test-mysql8
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-mssql:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mssql:
|
|
||||||
image: mcr.microsoft.com/mssql/server:latest
|
|
||||||
env:
|
|
||||||
ACCEPT_EULA: Y
|
|
||||||
MSSQL_PID: Standard
|
|
||||||
SA_PASSWORD: MwantsaSecurePassword1
|
|
||||||
ports:
|
|
||||||
- "1433:1433"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20.0"
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mssql" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: make test-mssql-migration test-mssql
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
23
.github/workflows/pull-docker-dryrun.yml
vendored
23
.github/workflows/pull-docker-dryrun.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: docker-dryrun
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
docker-dryrun:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: docker/setup-buildx-action@v2
|
|
||||||
- uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
push: false
|
|
||||||
tags: gitea/gitea:linux-amd64
|
|
||||||
32
.github/workflows/pull-e2e-tests.yml
vendored
32
.github/workflows/pull-e2e-tests.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
name: e2e-tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
test-e2e:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend frontend deps-backend
|
|
||||||
- run: npx playwright install --with-deps
|
|
||||||
- run: make test-e2e-sqlite
|
|
||||||
timeout-minutes: 40
|
|
||||||
env:
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
92
.github/workflows/release-nightly.yml
vendored
92
.github/workflows/release-nightly.yml
vendored
@@ -1,92 +0,0 @@
|
|||||||
name: release-nightly-assets
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ main, release/v* ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
nightly-binary:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ">=1.20"
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend deps-backend
|
|
||||||
# xgo build
|
|
||||||
- run: make release
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
- name: import gpg key
|
|
||||||
id: import_gpg
|
|
||||||
uses: crazy-max/ghaction-import-gpg@v5
|
|
||||||
with:
|
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
|
||||||
- name: sign binaries
|
|
||||||
run: |
|
|
||||||
for f in dist/release/*; do
|
|
||||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
|
||||||
done
|
|
||||||
# clean branch name to get the folder name in S3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
|
||||||
echo "Cleaned name is ${REF_NAME}"
|
|
||||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: upload binaries to s3
|
|
||||||
uses: jakejarvis/s3-sync-action@master
|
|
||||||
env:
|
|
||||||
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
AWS_REGION: ${{ secrets.AWS_REGION }}
|
|
||||||
SOURCE_DIR: dist/release
|
|
||||||
DEST_DIR: gitea/${{ steps.clean_name.outputs.branch }}
|
|
||||||
nightly-docker:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: docker/setup-qemu-action@v2
|
|
||||||
- uses: docker/setup-buildx-action@v2
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
# if main then say nightly otherwise cleanup name
|
|
||||||
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
|
||||||
echo "branch=nightly" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
|
||||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
|
||||||
- name: build rootless docker image
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
file: Dockerfile.rootless
|
|
||||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -16,6 +16,10 @@ _test
|
|||||||
.vscode
|
.vscode
|
||||||
__debug_bin
|
__debug_bin
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
*.cgo1.go
|
*.cgo1.go
|
||||||
*.cgo2.c
|
*.cgo2.c
|
||||||
_cgo_defun.c
|
_cgo_defun.c
|
||||||
@@ -43,7 +47,6 @@ cpu.out
|
|||||||
|
|
||||||
*.db
|
*.db
|
||||||
*.log
|
*.log
|
||||||
*.log.*.gz
|
|
||||||
|
|
||||||
/gitea
|
/gitea
|
||||||
/gitea-vet
|
/gitea-vet
|
||||||
@@ -53,6 +56,8 @@ cpu.out
|
|||||||
/bin
|
/bin
|
||||||
/dist
|
/dist
|
||||||
/custom/*
|
/custom/*
|
||||||
|
!/custom/conf
|
||||||
|
/custom/conf/*
|
||||||
!/custom/conf/app.example.ini
|
!/custom/conf/app.example.ini
|
||||||
/data
|
/data
|
||||||
/indexers
|
/indexers
|
||||||
@@ -66,12 +71,12 @@ cpu.out
|
|||||||
/tests/e2e/test-artifacts
|
/tests/e2e/test-artifacts
|
||||||
/tests/e2e/test-snapshots
|
/tests/e2e/test-snapshots
|
||||||
/tests/*.ini
|
/tests/*.ini
|
||||||
/tests/**/*.git/**/*.sample
|
|
||||||
/node_modules
|
/node_modules
|
||||||
/yarn.lock
|
/yarn.lock
|
||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
/npm-debug.log*
|
/npm-debug.log*
|
||||||
/public/js
|
/public/js
|
||||||
|
/public/serviceworker.js
|
||||||
/public/css
|
/public/css
|
||||||
/public/fonts
|
/public/fonts
|
||||||
/public/img/webpack
|
/public/img/webpack
|
||||||
|
|||||||
11
.gitpod.yml
11
.gitpod.yml
@@ -10,12 +10,9 @@ tasks:
|
|||||||
- name: Run backend
|
- name: Run backend
|
||||||
command: |
|
command: |
|
||||||
gp sync-await setup
|
gp sync-await setup
|
||||||
if [ ! -f custom/conf/app.ini ]
|
|
||||||
then
|
|
||||||
mkdir -p custom/conf/
|
mkdir -p custom/conf/
|
||||||
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
|
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
|
||||||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
||||||
fi
|
|
||||||
export TAGS="sqlite sqlite_unlock_notify"
|
export TAGS="sqlite sqlite_unlock_notify"
|
||||||
make watch-backend
|
make watch-backend
|
||||||
- name: Run frontend
|
- name: Run frontend
|
||||||
@@ -23,6 +20,10 @@ tasks:
|
|||||||
gp sync-await setup
|
gp sync-await setup
|
||||||
make watch-frontend
|
make watch-frontend
|
||||||
openMode: split-right
|
openMode: split-right
|
||||||
|
- name: Run docs
|
||||||
|
before: sudo bash -c "$(grep 'https://github.com/gohugoio/hugo/releases/download' Makefile | tr -d '\')" # install hugo
|
||||||
|
command: cd docs && make clean update && hugo server -D -F --baseUrl $(gp url 1313) --liveReloadPort=443 --appendPort=false --bind=0.0.0.0
|
||||||
|
openMode: split-right
|
||||||
|
|
||||||
vscode:
|
vscode:
|
||||||
extensions:
|
extensions:
|
||||||
@@ -31,7 +32,7 @@ vscode:
|
|||||||
- golang.go
|
- golang.go
|
||||||
- stylelint.vscode-stylelint
|
- stylelint.vscode-stylelint
|
||||||
- DavidAnson.vscode-markdownlint
|
- DavidAnson.vscode-markdownlint
|
||||||
- Vue.volar
|
- johnsoncodehk.volar
|
||||||
- ms-azuretools.vscode-docker
|
- ms-azuretools.vscode-docker
|
||||||
- zixuanchen.vitest-explorer
|
- zixuanchen.vitest-explorer
|
||||||
- alexcvzz.vscode-sqlite
|
- alexcvzz.vscode-sqlite
|
||||||
@@ -39,3 +40,5 @@ vscode:
|
|||||||
ports:
|
ports:
|
||||||
- name: Gitea
|
- name: Gitea
|
||||||
port: 3000
|
port: 3000
|
||||||
|
- name: Docs
|
||||||
|
port: 1313
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ linters:
|
|||||||
- depguard
|
- depguard
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
- errcheck
|
||||||
- forbidigo
|
|
||||||
- gocritic
|
- gocritic
|
||||||
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
||||||
- gofmt
|
- gofmt
|
||||||
@@ -23,7 +22,7 @@ linters:
|
|||||||
- unconvert
|
- unconvert
|
||||||
- unused
|
- unused
|
||||||
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||||
- wastedassign
|
# - wastedassign # disabled - https://github.com/golangci/golangci-lint/issues/2649
|
||||||
enable-all: false
|
enable-all: false
|
||||||
disable-all: true
|
disable-all: true
|
||||||
fast: false
|
fast: false
|
||||||
@@ -86,7 +85,6 @@ linters-settings:
|
|||||||
- io/ioutil: "use os or io instead"
|
- io/ioutil: "use os or io instead"
|
||||||
- golang.org/x/exp: "it's experimental and unreliable."
|
- golang.org/x/exp: "it's experimental and unreliable."
|
||||||
- code.gitea.io/gitea/modules/git/internal: "do not use the internal package, use AddXxx function instead"
|
- code.gitea.io/gitea/modules/git/internal: "do not use the internal package, use AddXxx function instead"
|
||||||
- gopkg.in/ini.v1: "do not use the ini package, use gitea's config system instead"
|
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
max-issues-per-linter: 0
|
max-issues-per-linter: 0
|
||||||
@@ -107,25 +105,73 @@ issues:
|
|||||||
- errcheck
|
- errcheck
|
||||||
- dupl
|
- dupl
|
||||||
- gosec
|
- gosec
|
||||||
- path: cmd
|
|
||||||
linters:
|
|
||||||
- forbidigo
|
|
||||||
- linters:
|
- linters:
|
||||||
- dupl
|
- dupl
|
||||||
text: "webhook"
|
text: "webhook"
|
||||||
- linters:
|
- linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
text: "`ID' should not be capitalized"
|
text: "`ID' should not be capitalized"
|
||||||
|
- path: modules/templates/helper.go
|
||||||
|
linters:
|
||||||
|
- gocritic
|
||||||
- linters:
|
- linters:
|
||||||
- unused
|
- unused
|
||||||
- deadcode
|
- deadcode
|
||||||
text: "swagger"
|
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/api/v1/repo/issue_subscription.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
- path: routers/repo/view.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
- path: models/migrations/
|
||||||
|
linters:
|
||||||
|
- unused
|
||||||
- linters:
|
- linters:
|
||||||
- staticcheck
|
- staticcheck
|
||||||
text: "argument x is overwritten before first use"
|
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
|
||||||
|
- path: models/update.go
|
||||||
|
linters:
|
||||||
|
- unused
|
||||||
|
- path: cmd/dump.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
- path: services/webhook/webhook.go
|
||||||
|
linters:
|
||||||
|
- structcheck
|
||||||
- text: "commentFormatting: put a space between `//` and comment text"
|
- text: "commentFormatting: put a space between `//` and comment text"
|
||||||
linters:
|
linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
- text: "exitAfterDefer:"
|
- text: "exitAfterDefer:"
|
||||||
linters:
|
linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
|
- path: modules/graceful/manager_windows.go
|
||||||
|
linters:
|
||||||
|
- staticcheck
|
||||||
|
text: "svc.IsAnInteractiveSession is deprecated: Use IsWindowsService instead."
|
||||||
|
- path: models/user/openid.go
|
||||||
|
linters:
|
||||||
|
- golint
|
||||||
|
- path: models/user/badge.go
|
||||||
|
linters:
|
||||||
|
- revive
|
||||||
|
text: "exported: type name will be used as user.UserBadge by other packages, and that stutters; consider calling this Badge"
|
||||||
|
|||||||
2
.ignore
2
.ignore
@@ -1,8 +1,8 @@
|
|||||||
*.min.css
|
*.min.css
|
||||||
*.min.js
|
*.min.js
|
||||||
/assets/*.json
|
|
||||||
/modules/options/bindata.go
|
/modules/options/bindata.go
|
||||||
/modules/public/bindata.go
|
/modules/public/bindata.go
|
||||||
/modules/templates/bindata.go
|
/modules/templates/bindata.go
|
||||||
|
/public/vendor/plugins
|
||||||
/vendor
|
/vendor
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
3
.lgtm
Normal file
3
.lgtm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pattern = "(?)LGTM"
|
||||||
|
self_approval_off = true
|
||||||
|
ignore_maintainers_file = true
|
||||||
1
.npmrc
1
.npmrc
@@ -3,4 +3,3 @@ fund=false
|
|||||||
update-notifier=false
|
update-notifier=false
|
||||||
package-lock=true
|
package-lock=true
|
||||||
save-exact=true
|
save-exact=true
|
||||||
lockfile-version=3
|
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ ignoreFiles:
|
|||||||
- "**/*.go"
|
- "**/*.go"
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"]
|
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"]
|
||||||
rules:
|
rules:
|
||||||
scale-unlimited/declaration-strict-value: null
|
scale-unlimited/declaration-strict-value: null
|
||||||
- files: ["**/chroma/*", "**/codemirror/*"]
|
- files: ["**/chroma/*", "**/codemirror/*"]
|
||||||
rules:
|
rules:
|
||||||
block-no-empty: null
|
block-no-empty: null
|
||||||
- files: ["**/*.vue"]
|
|
||||||
customSyntax: postcss-html
|
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
alpha-value-notation: null
|
alpha-value-notation: null
|
||||||
@@ -80,7 +78,6 @@ rules:
|
|||||||
media-feature-name-no-vendor-prefix: true
|
media-feature-name-no-vendor-prefix: true
|
||||||
media-feature-name-unit-allowed-list: null
|
media-feature-name-unit-allowed-list: null
|
||||||
media-feature-name-value-allowed-list: null
|
media-feature-name-value-allowed-list: null
|
||||||
media-feature-name-value-no-unknown: true
|
|
||||||
media-feature-range-notation: null
|
media-feature-range-notation: null
|
||||||
named-grid-areas-no-invalid: true
|
named-grid-areas-no-invalid: true
|
||||||
no-descending-specificity: null
|
no-descending-specificity: null
|
||||||
@@ -91,7 +88,6 @@ rules:
|
|||||||
no-invalid-position-at-import-rule: null
|
no-invalid-position-at-import-rule: null
|
||||||
no-irregular-whitespace: true
|
no-irregular-whitespace: true
|
||||||
no-unknown-animations: null
|
no-unknown-animations: null
|
||||||
no-unknown-custom-properties: null
|
|
||||||
number-max-precision: null
|
number-max-precision: null
|
||||||
property-allowed-list: null
|
property-allowed-list: null
|
||||||
property-disallowed-list: null
|
property-disallowed-list: null
|
||||||
@@ -99,7 +95,7 @@ rules:
|
|||||||
property-no-vendor-prefix: null
|
property-no-vendor-prefix: null
|
||||||
rule-empty-line-before: null
|
rule-empty-line-before: null
|
||||||
rule-selector-property-disallowed-list: null
|
rule-selector-property-disallowed-list: null
|
||||||
scale-unlimited/declaration-strict-value: [[color, background-color, border-color, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true}]
|
scale-unlimited/declaration-strict-value: [color, {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor)$/}]
|
||||||
selector-attribute-name-disallowed-list: null
|
selector-attribute-name-disallowed-list: null
|
||||||
selector-attribute-operator-allowed-list: null
|
selector-attribute-operator-allowed-list: null
|
||||||
selector-attribute-operator-disallowed-list: null
|
selector-attribute-operator-disallowed-list: null
|
||||||
|
|||||||
27
BSDmakefile
27
BSDmakefile
@@ -1,7 +1,6 @@
|
|||||||
# GNU makefile proxy script for BSD make
|
# GNU makefile proxy script for BSD make
|
||||||
#
|
|
||||||
# Written and maintained by Mahmoud Al-Qudsi <mqudsi@neosmart.net>
|
# Written and maintained by Mahmoud Al-Qudsi <mqudsi@neosmart.net>
|
||||||
# Copyright NeoSmart Technologies <https://neosmart.net/> 2014-2019
|
# Copyright NeoSmart Technologies <https://neosmart.net/> 2014-2018
|
||||||
# Obtain updates from <https://github.com/neosmart/gmake-proxy>
|
# Obtain updates from <https://github.com/neosmart/gmake-proxy>
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@@ -29,30 +28,24 @@ JARG =
|
|||||||
GMAKE = "gmake"
|
GMAKE = "gmake"
|
||||||
#When gmake is called from another make instance, -w is automatically added
|
#When gmake is called from another make instance, -w is automatically added
|
||||||
#which causes extraneous messages about directory changes to be emitted.
|
#which causes extraneous messages about directory changes to be emitted.
|
||||||
# Running with --no-print-directory silences these messages.
|
#--no-print-directory silences these messages.
|
||||||
GARGS = "--no-print-directory"
|
GARGS = "--no-print-directory"
|
||||||
|
|
||||||
.if "$(.MAKE.JOBS)" != ""
|
.if "$(.MAKE.JOBS)" != ""
|
||||||
JARG = -j$(.MAKE.JOBS)
|
JARG = -j$(.MAKE.JOBS)
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# bmake prefers out-of-source builds and tries to cd into ./obj (among others)
|
#by default bmake will cd into ./obj first
|
||||||
# where possible. GNU Make doesn't, so override that value.
|
|
||||||
.OBJDIR: ./
|
.OBJDIR: ./
|
||||||
|
|
||||||
# The GNU convention is to use the lowercased `prefix` variable/macro to
|
|
||||||
# specify the installation directory. Humor them.
|
|
||||||
GPREFIX = ""
|
|
||||||
.if defined(PREFIX) && ! defined(prefix)
|
|
||||||
GPREFIX = 'prefix = "$(PREFIX)"'
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.BEGIN: .SILENT
|
|
||||||
which $(GMAKE) || printf "Error: GNU Make is required!\n\n" 1>&2 && false
|
|
||||||
|
|
||||||
.PHONY: FRC
|
.PHONY: FRC
|
||||||
$(.TARGETS): FRC
|
$(.TARGETS): FRC
|
||||||
$(GMAKE) $(GPREFIX) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||||
|
|
||||||
.DONE .DEFAULT: .SILENT
|
.DONE .DEFAULT: .SILENT
|
||||||
$(GMAKE) $(GPREFIX) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||||
|
|
||||||
|
.ERROR: .SILENT
|
||||||
|
if ! which $(GMAKE) > /dev/null; then \
|
||||||
|
echo "GNU Make is required!"; \
|
||||||
|
fi
|
||||||
|
|||||||
1252
CHANGELOG.md
1252
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -1,96 +0,0 @@
|
|||||||
# Gitea Community Code of Conduct
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
Online communities include people from many different backgrounds. The Gitea contributors are committed to providing a friendly, safe and welcoming environment for all, regardless of gender identity and expression, sexual orientation, disabilities, neurodiversity, physical appearance, body size, ethnicity, nationality, race, age, religion, or similar personal characteristics.
|
|
||||||
|
|
||||||
The first goal of the Code of Conduct is to specify a baseline standard of behavior so that people with different social values and communication styles can talk about Gitea effectively, productively, and respectfully.
|
|
||||||
|
|
||||||
The second goal is to provide a mechanism for resolving conflicts in the community when they arise.
|
|
||||||
|
|
||||||
The third goal of the Code of Conduct is to make our community welcoming to people from different backgrounds. Diversity is critical to the project; for Gitea to be successful, it needs contributors and users from all backgrounds.
|
|
||||||
|
|
||||||
We believe that healthy debate and disagreement are essential to a healthy project and community. However, it is never ok to be disrespectful. We value diverse opinions, but we value respectful behavior more.
|
|
||||||
|
|
||||||
## Community values
|
|
||||||
|
|
||||||
These are the values to which people in the Gitea community should aspire.
|
|
||||||
|
|
||||||
- **Be friendly and welcoming.**
|
|
||||||
- **Be patient.**
|
|
||||||
- Remember that people have varying communication styles and that not everyone is using their native language. (Meaning and tone can be lost in translation.)
|
|
||||||
- **Be thoughtful.**
|
|
||||||
- Productive communication requires effort. Think about how your words will be interpreted.
|
|
||||||
- Remember that sometimes it is best to refrain entirely from commenting.
|
|
||||||
- **Be respectful.**
|
|
||||||
- In particular, respect differences of opinion.
|
|
||||||
- **Be charitable.**
|
|
||||||
- Interpret the arguments of others in good faith, do not seek to disagree.
|
|
||||||
- When we do disagree, try to understand why.
|
|
||||||
- **Be constructive.**
|
|
||||||
- Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation.
|
|
||||||
- Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved.
|
|
||||||
- Avoid snarking (pithy, unproductive, sniping comments)
|
|
||||||
- Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict.
|
|
||||||
- Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group).
|
|
||||||
- **Be responsible.**
|
|
||||||
- What you say and do matters. Take responsibility for your words and actions, including their consequences, whether intended or otherwise.
|
|
||||||
|
|
||||||
People are complicated. You should expect to be misunderstood and to misunderstand others; when this inevitably occurs, resist the urge to be defensive or assign blame. Try not to take offense where no offense was intended. Give people the benefit of the doubt. Even if the intent was to provoke, do not rise to it. It is the responsibility of all parties to de-escalate conflict when it arises.
|
|
||||||
|
|
||||||
## Code of Conduct
|
|
||||||
|
|
||||||
### Our Pledge
|
|
||||||
|
|
||||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
||||||
|
|
||||||
### Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment include:
|
|
||||||
|
|
||||||
- Using welcoming and inclusive language
|
|
||||||
- Being respectful of differing viewpoints and experiences
|
|
||||||
- Gracefully accepting constructive criticism
|
|
||||||
- Focusing on what is best for the community
|
|
||||||
- Showing empathy towards other community members
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
|
||||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
|
||||||
- Public or private harassment
|
|
||||||
- Publishing others’ private information, such as a physical or electronic address, without explicit permission
|
|
||||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
||||||
|
|
||||||
### Our Responsibilities
|
|
||||||
|
|
||||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or reject: comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, as well as to ban (temporarily or permanently) any contributor for behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
|
||||||
|
|
||||||
### Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
|
||||||
|
|
||||||
This Code of Conduct also applies outside the project spaces when the Project Stewards have a reasonable belief that an individual’s behavior may have a negative impact on the project or its community.
|
|
||||||
|
|
||||||
### Conflict Resolution
|
|
||||||
|
|
||||||
We do not believe that all conflict is bad; healthy debate and disagreement often yield positive results. However, it is never okay to be disrespectful or to engage in behavior that violates the project’s code of conduct.
|
|
||||||
|
|
||||||
If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe.
|
|
||||||
|
|
||||||
Reports should be directed to the Gitea Project Stewards at conduct@gitea.com. It is the Project Stewards’ duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the technical-oversight-committee.
|
|
||||||
|
|
||||||
We will investigate every complaint, but you may not receive a direct response. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the project and project-sponsored spaces. Under normal circumstances, we will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. If there is a consensus between maintainers that such an endeavor would be useless (i.e. in case of an obvious spammer), we reserve the right to take action without notifying the accused first. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone’s safety, we may take action without notice.
|
|
||||||
|
|
||||||
### Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
- Treat everyone with respect and kindness.
|
|
||||||
- Be thoughtful in how you communicate.
|
|
||||||
- Don’t be destructive or inflammatory.
|
|
||||||
- If you encounter an issue, please mail conduct@gitea.com.
|
|
||||||
654
CONTRIBUTING.md
654
CONTRIBUTING.md
@@ -1,157 +1,75 @@
|
|||||||
# Contribution Guidelines
|
# Contribution Guidelines
|
||||||
|
|
||||||
<details><summary>Table of Contents</summary>
|
## Table of Contents
|
||||||
|
|
||||||
- [Contribution Guidelines](#contribution-guidelines)
|
- [Contribution Guidelines](#contribution-guidelines)
|
||||||
|
- [Table of Contents](#table-of-contents)
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
- [Issues](#issues)
|
- [Bug reports](#bug-reports)
|
||||||
- [How to report issues](#how-to-report-issues)
|
- [Discuss your design](#discuss-your-design)
|
||||||
- [Types of issues](#types-of-issues)
|
- [Testing redux](#testing-redux)
|
||||||
- [Discuss your design before the implementation](#discuss-your-design-before-the-implementation)
|
- [Vendoring](#vendoring)
|
||||||
- [Building Gitea](#building-gitea)
|
|
||||||
- [Dependencies](#dependencies)
|
|
||||||
- [Backend](#backend)
|
|
||||||
- [Frontend](#frontend)
|
|
||||||
- [Design guideline](#design-guideline)
|
|
||||||
- [Styleguide](#styleguide)
|
|
||||||
- [Copyright](#copyright)
|
|
||||||
- [Testing](#testing)
|
|
||||||
- [Translation](#translation)
|
- [Translation](#translation)
|
||||||
|
- [Building Gitea](#building-gitea)
|
||||||
- [Code review](#code-review)
|
- [Code review](#code-review)
|
||||||
- [Pull request format](#pull-request-format)
|
- [Styleguide](#styleguide)
|
||||||
- [PR title and summary](#pr-title-and-summary)
|
- [Design guideline](#design-guideline)
|
||||||
- [Milestone](#milestone)
|
|
||||||
- [Labels](#labels)
|
|
||||||
- [Breaking PRs](#breaking-prs)
|
|
||||||
- [What is a breaking PR?](#what-is-a-breaking-pr)
|
|
||||||
- [How to handle breaking PRs?](#how-to-handle-breaking-prs)
|
|
||||||
- [Maintaining open PRs](#maintaining-open-prs)
|
|
||||||
- [Getting PRs merged](#getting-prs-merged)
|
|
||||||
- [Final call](#final-call)
|
|
||||||
- [Commit messages](#commit-messages)
|
|
||||||
- [PR Co-authors](#pr-co-authors)
|
|
||||||
- [PRs targeting `main`](#prs-targeting-main)
|
|
||||||
- [Backport PRs](#backport-prs)
|
|
||||||
- [Documentation](#documentation)
|
|
||||||
- [API v1](#api-v1)
|
- [API v1](#api-v1)
|
||||||
- [GitHub API compatability](#github-api-compatability)
|
|
||||||
- [Adding/Maintaining API routes](#addingmaintaining-api-routes)
|
|
||||||
- [When to use what HTTP method](#when-to-use-what-http-method)
|
|
||||||
- [Requirements for API routes](#requirements-for-api-routes)
|
|
||||||
- [Backports and Frontports](#backports-and-frontports)
|
|
||||||
- [What is backported?](#what-is-backported)
|
|
||||||
- [How to backport?](#how-to-backport)
|
|
||||||
- [Format of backport PRs](#format-of-backport-prs)
|
|
||||||
- [Frontports](#frontports)
|
|
||||||
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
|
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
|
||||||
- [Release Cycle](#release-cycle)
|
- [Release Cycle](#release-cycle)
|
||||||
- [Maintainers](#maintainers)
|
- [Maintainers](#maintainers)
|
||||||
- [Technical Oversight Committee (TOC)](#technical-oversight-committee-toc)
|
- [Owners](#owners)
|
||||||
- [Current TOC members](#current-toc-members)
|
|
||||||
- [Previous TOC/owners members](#previous-tocowners-members)
|
|
||||||
- [Governance Compensation](#governance-compensation)
|
|
||||||
- [TOC \& Working groups](#toc--working-groups)
|
|
||||||
- [Roadmap](#roadmap)
|
|
||||||
- [Versions](#versions)
|
- [Versions](#versions)
|
||||||
- [Releasing Gitea](#releasing-gitea)
|
- [Releasing Gitea](#releasing-gitea)
|
||||||
|
- [Copyright](#copyright)
|
||||||
</details>
|
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
This document explains how to contribute changes to the Gitea project. \
|
This document explains how to contribute changes to the Gitea project.
|
||||||
It assumes you have followed the [installation instructions](https://docs.gitea.io/en-us/). \
|
It assumes you have followed the
|
||||||
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
|
[installation instructions](https://docs.gitea.io/en-us/).
|
||||||
|
Sensitive security-related issues should be reported to
|
||||||
|
[security@gitea.io](mailto:security@gitea.io).
|
||||||
|
|
||||||
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
|
For configuring IDE or code editor to develop Gitea see [IDE and code editor configuration](contrib/ide/)
|
||||||
|
|
||||||
## Issues
|
## Bug reports
|
||||||
|
|
||||||
### How to report issues
|
Please search the issues on the issue tracker with a variety of keywords
|
||||||
|
to ensure your bug is not already reported.
|
||||||
|
|
||||||
Please search the issues on the issue tracker with a variety of related keywords to ensure that your issue has not already been reported.
|
If unique, [open an issue](https://github.com/go-gitea/gitea/issues/new)
|
||||||
|
and answer the questions so we can understand and reproduce the
|
||||||
|
problematic behavior.
|
||||||
|
|
||||||
If your issue has not been reported yet, [open an issue](https://github.com/go-gitea/gitea/issues/new)
|
To show us that the issue you are having is in Gitea itself, please
|
||||||
and answer the questions so we can understand and reproduce the problematic behavior. \
|
write clear, concise instructions so we can reproduce the behavior—
|
||||||
Please write clear and concise instructions so that we can reproduce the behavior — even if it seems obvious. \
|
even if it seems obvious. The more detailed and specific you are,
|
||||||
The more detailed and specific you are, the faster we can fix the issue. \
|
the faster we can fix the issue. Check out [How to Report Bugs
|
||||||
It is really helpful if you can reproduce your problem on a site running on the latest commits, i.e. <https://try.gitea.io>, as perhaps your problem has already been fixed on a current version. \
|
Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html).
|
||||||
Please follow the guidelines described in [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html) for your report.
|
|
||||||
|
|
||||||
Please be kind, remember that Gitea comes at no cost to you, and you're getting free help.
|
Please be kind, remember that Gitea comes at no cost to you, and you're
|
||||||
|
getting free help.
|
||||||
|
|
||||||
### Types of issues
|
## Discuss your design
|
||||||
|
|
||||||
Typically, issues fall in one of the following categories:
|
The project welcomes submissions. If you want to change or add something,
|
||||||
|
please let everyone know what you're working on—[file an issue](https://github.com/go-gitea/gitea/issues/new)!
|
||||||
|
Significant changes must go through the change proposal process
|
||||||
|
before they can be accepted. To create a proposal, file an issue with
|
||||||
|
your proposed changes documented, and make sure to note in the title
|
||||||
|
of the issue that it is a proposal.
|
||||||
|
|
||||||
- `bug`: Something in the frontend or backend behaves unexpectedly
|
This process gives everyone a chance to validate the design, helps
|
||||||
- `security issue`: bug that has serious implications such as leaking another users data. Please do not file such issues on the public tracker and send a mail to security@gitea.io instead
|
prevent duplication of effort, and ensures that the idea fits inside
|
||||||
- `feature`: Completely new functionality. You should describe this feature in enough detail that anyone who reads the issue can understand how it is supposed to be implemented
|
the goals for the project and tools. It also checks that the design is
|
||||||
- `enhancement`: An existing feature should get an upgrade
|
sound before code is written; the code review tool is not the place for
|
||||||
- `refactoring`: Parts of the code base don't conform with other parts and should be changed to improve Gitea's maintainability
|
high-level discussions.
|
||||||
|
|
||||||
### Discuss your design before the implementation
|
## Testing redux
|
||||||
|
|
||||||
We welcome submissions. \
|
Before submitting a pull request, run all the tests for the whole tree
|
||||||
If you want to change or add something, please let everyone know what you're working on — [file an issue](https://github.com/go-gitea/gitea/issues/new) or comment on an existing one before starting your work!
|
to make sure your changes don't cause regression elsewhere.
|
||||||
|
|
||||||
Significant changes such as new features must go through the change proposal process before they can be accepted. \
|
|
||||||
This is mainly to save yourself the trouble of implementing it, only to find out that your proposed implementation has some potential problems. \
|
|
||||||
Furthermore, this process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside
|
|
||||||
the goals for the project and tools.
|
|
||||||
|
|
||||||
Pull requests should not be the place for architecture discussions.
|
|
||||||
|
|
||||||
## Building Gitea
|
|
||||||
|
|
||||||
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
|
|
||||||
Go dependencies are managed using [Go Modules](https://golang.org/cmd/go/#hdr-Module_maintenance). \
|
|
||||||
You can find more details in the [go mod documentation](https://go.dev/ref/mod) and the [Go Modules Wiki](https://github.com/golang/go/wiki/Modules).
|
|
||||||
|
|
||||||
Pull requests should only modify `go.mod` and `go.sum` where it is related to your change, be it a bugfix or a new feature. \
|
|
||||||
Apart from that, these files should only be modified by Pull Requests whose only purpose is to update dependencies.
|
|
||||||
|
|
||||||
The `go.mod`, `go.sum` 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.
|
|
||||||
|
|
||||||
### Frontend
|
|
||||||
|
|
||||||
For the frontend, we use [npm](https://www.npmjs.com/).
|
|
||||||
|
|
||||||
The same restrictions apply for frontend dependencies as for backend dependencies, with the exceptions that the files for it are `package.json` and `package-lock.json`, and that new versions must always reference an existing version.
|
|
||||||
|
|
||||||
## Design guideline
|
|
||||||
|
|
||||||
Depending on your change, please read the
|
|
||||||
|
|
||||||
- [backend development guideline](https://docs.gitea.com/contributing/guidelines-backend)
|
|
||||||
- [frontend development guideline](https://docs.gitea.com/contributing/guidelines-frontend)
|
|
||||||
- [refactoring guideline](https://docs.gitea.com/contributing/guidelines-refactoring)
|
|
||||||
|
|
||||||
## Styleguide
|
|
||||||
|
|
||||||
You should always run `make fmt` before committing to conform to Gitea's styleguide.
|
|
||||||
|
|
||||||
## Copyright
|
|
||||||
|
|
||||||
New code files that you contribute should use the standard copyright header:
|
|
||||||
|
|
||||||
```
|
|
||||||
// Copyright <current year> The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
```
|
|
||||||
|
|
||||||
Afterwards, copyright should only be modified when the copyright author changes.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
Before submitting a pull request, run all tests to make sure your changes don't cause a regression elsewhere.
|
|
||||||
|
|
||||||
Here's how to run the test suite:
|
Here's how to run the test suite:
|
||||||
|
|
||||||
@@ -159,304 +77,257 @@ Here's how to run the test suite:
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
| :-------------------- | :---------------------------------------------------------------- |
|
| :-------------------- | :---------------------------------------------------------------- |
|
||||||
|``make lint`` | lint everything (not needed if you only change the front- **or** backend) |
|
|``make lint`` | lint everything (not suggest if you only change one type code) |
|
||||||
|``make lint-frontend`` | lint frontend files |
|
|``make lint-frontend`` | lint frontend files |
|
||||||
|``make lint-backend`` | lint backend files |
|
|``make lint-backend`` | lint backend files |
|
||||||
|
|
||||||
- run tests (we suggest running them on Linux)
|
- run test code (Suggest run in Linux)
|
||||||
|
|
||||||
| Command | Action | |
|
| | |
|
||||||
| :------------------------------------- | :----------------------------------------------- | ------------ |
|
| :------------------------------------- | :----------------------------------------------- |
|
||||||
|``make test[\#SpecificTestName]`` | run unit test(s) |
|
|``make test[\#TestSpecificName]`` | run unit test |
|
||||||
|``make test-sqlite[\#SpecificTestName]``| run [integration](tests/integration) test(s) for SQLite |[More details](tests/integration/README.md) |
|
|``make test-sqlite[\#TestSpecificName]``| run [integration](tests/integration) test for SQLite |
|
||||||
|``make test-e2e-sqlite[\#SpecificTestName]``| run [end-to-end](tests/e2e) test(s) for SQLite |[More details](tests/e2e/README.md) |
|
|[More details about integration tests](tests/integration/README.md) |
|
||||||
|
|``make test-e2e-sqlite[\#TestSpecificFileName]``| run [end-to-end](tests/e2e) test for SQLite |
|
||||||
|
|[More details about e2e tests](tests/e2e/README.md) |
|
||||||
|
|
||||||
|
## Vendoring
|
||||||
|
|
||||||
|
We manage dependencies via [Go Modules](https://golang.org/cmd/go/#hdr-Module_maintenance), more details: [go mod](https://go.dev/ref/mod).
|
||||||
|
|
||||||
|
Pull requests should only include `go.mod`, `go.sum` updates if they are part of
|
||||||
|
the same change, be it a bugfix or a feature addition.
|
||||||
|
|
||||||
|
The `go.mod`, `go.sum` update needs to be justified as part of the PR description,
|
||||||
|
and must be verified by the reviewers and/or merger to always reference
|
||||||
|
an existing upstream commit.
|
||||||
|
|
||||||
|
You can find more information on how to get started with it on the [Modules Wiki](https://github.com/golang/go/wiki/Modules).
|
||||||
|
|
||||||
## Translation
|
## Translation
|
||||||
|
|
||||||
All translation work happens on [Crowdin](https://crowdin.com/project/gitea).
|
We do all translation work inside [Crowdin](https://crowdin.com/project/gitea).
|
||||||
The only translation that is maintained in this repository is [the English translation](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.ini).
|
The only translation that is maintained in this Git repository is
|
||||||
It is synced regularly with Crowdin. \
|
[`en_US.ini`](https://github.com/go-gitea/gitea/blob/master/options/locale/locale_en-US.ini)
|
||||||
Other locales on main branch **should not** be updated manually as they will be overwritten with each sync. \
|
and is synced regularly to Crowdin. Once a translation has reached
|
||||||
Once a language has reached a **satisfactory percentage** of translated keys (~25%), it will be synced back into this repo and included in the next released version.
|
A SATISFACTORY PERCENTAGE it will be synced back into this repo and
|
||||||
|
included in the next released version.
|
||||||
|
|
||||||
The tool `go run build/backport-locale.go` can be used to backport locales from the main branch to release branches that were missed.
|
## Building Gitea
|
||||||
|
|
||||||
|
See the [hacking instructions](https://docs.gitea.io/en-us/hacking-on-gitea/).
|
||||||
|
|
||||||
## Code review
|
## Code review
|
||||||
|
|
||||||
### Pull request format
|
Changes to Gitea must be reviewed before they are accepted—no matter who
|
||||||
|
makes the change, even if they are an owner or a maintainer. We use GitHub's
|
||||||
|
pull request workflow to do that. And, we also use [LGTM](http://lgtm.co)
|
||||||
|
to ensure every PR is reviewed by at least 2 maintainers.
|
||||||
|
|
||||||
Please try to make your pull request easy to review for us. \
|
Please try to make your pull request easy to review for us. And, please read
|
||||||
For that, please read the [*Best Practices for Faster Reviews*](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) guide. \
|
the *[How to get faster PR reviews](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews)* guide;
|
||||||
It has lots of useful tips for any project you may want to contribute to. \
|
it has lots of useful tips for any project you may want to contribute.
|
||||||
Some of the key points:
|
Some of the key points:
|
||||||
|
|
||||||
- Make small pull requests. \
|
- Make small pull requests. The smaller, the faster to review and the
|
||||||
The smaller, the faster to review and the more likely it will be merged soon.
|
more likely it will be merged soon.
|
||||||
- Don't make changes unrelated to your PR. \
|
- Don't make changes unrelated to your PR. Maybe there are typos on
|
||||||
Maybe there are typos on some comments, maybe refactoring would be welcome on a function... \
|
some comments, maybe refactoring would be welcome on a function... but
|
||||||
but if that is not related to your PR, please make *another* PR for that.
|
if that is not related to your PR, please make *another* PR for that.
|
||||||
- Split big pull requests into multiple small ones. \
|
- Split big pull requests into multiple small ones. An incremental change
|
||||||
An incremental change will be faster to review than a huge PR.
|
will be faster to review than a huge PR.
|
||||||
- Allow edits by maintainers. This way, the maintainers will take care of merging the PR later on instead of you.
|
- Use the first comment as a summary explainer of your PR and you should keep this up-to-date as the PR evolves.
|
||||||
|
|
||||||
### PR title and summary
|
If your PR could cause a breaking change you must add a BREAKING section to this comment e.g.:
|
||||||
|
|
||||||
In the PR title, describe the problem you are fixing, not how you are fixing it. \
|
|
||||||
Use the first comment as a summary of your PR. \
|
|
||||||
In the PR summary, you can describe exactly how you are fixing this problem. \
|
|
||||||
Keep this summary up-to-date as the PR evolves. \
|
|
||||||
If your PR changes the UI, you must add **after** screenshots in the PR summary. \
|
|
||||||
If you are not implementing a new feature, you should also post **before** screenshots for comparison. \
|
|
||||||
If your PR closes some issues, you must note that in a way that both GitHub and Gitea understand, i.e. by appending a paragraph like
|
|
||||||
|
|
||||||
```text
|
|
||||||
Fixes/Closes/Resolves #<ISSUE_NR_X>.
|
|
||||||
Fixes/Closes/Resolves #<ISSUE_NR_Y>.
|
|
||||||
```
|
|
||||||
|
|
||||||
to your summary. \
|
|
||||||
Each issue that will be closed must stand on a separate line.
|
|
||||||
|
|
||||||
### Milestone
|
|
||||||
|
|
||||||
A PR should only be assigned to a milestone if it will likely be merged into the given version. \
|
|
||||||
As a rule of thumb, assume that a PR will stay open for an additional month for every 100 added lines. \
|
|
||||||
PRs without a milestone may not be merged.
|
|
||||||
|
|
||||||
### Labels
|
|
||||||
|
|
||||||
Every PR should be labeled correctly with every label that applies. \
|
|
||||||
This includes especially the distinction between `bug` (fixing existing functionality), `feature` (new functionality), `enhancement` (upgrades for existing functionality), and `refactoring` (improving the internal code structure without changing the output (much)). \
|
|
||||||
Furthermore,
|
|
||||||
|
|
||||||
- the amount of pending required approvals
|
|
||||||
- whether this PR is `blocked`, a `backport` or `breaking`
|
|
||||||
- if it targets the `ui` or `api`
|
|
||||||
- if it increases the application `speed`
|
|
||||||
- reduces `memory usage`
|
|
||||||
|
|
||||||
are oftentimes notable labels.
|
|
||||||
|
|
||||||
### Breaking PRs
|
|
||||||
|
|
||||||
#### What is a breaking PR?
|
|
||||||
|
|
||||||
A PR is breaking if it meets one of the following criteria:
|
|
||||||
|
|
||||||
- It changes API output in an incompatible way for existing users
|
|
||||||
- It removes a setting that an admin could previously set (i.e. via `app.ini`)
|
|
||||||
- An admin must do something manually to restore the old behavior
|
|
||||||
|
|
||||||
In particular, this means that adding new settings is not breaking.\
|
|
||||||
Changing the default value of a setting or replacing the setting with another one is breaking, however.
|
|
||||||
|
|
||||||
#### How to handle breaking PRs?
|
|
||||||
|
|
||||||
If your PR has a breaking change, you must add a `BREAKING` section to your PR summary, e.g.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
## :warning: BREAKING :warning:
|
## :warning: BREAKING :warning:
|
||||||
```
|
```
|
||||||
|
|
||||||
To explain how this will affect users and how to mitigate these changes.
|
To explain how this could affect users and how to mitigate these changes.
|
||||||
|
|
||||||
### Maintaining open PRs
|
Once code review starts on your PR, do not rebase nor squash your branch as it makes it
|
||||||
|
difficult to review the new changes. Only if there is a need, sync your branch by merging
|
||||||
|
the base branch into yours. Don't worry about merge commits messing up your tree as
|
||||||
|
the final merge process squashes all commits into one, with the visible commit message (first
|
||||||
|
line) being the PR title + PR index and description being the PR's first comment.
|
||||||
|
|
||||||
The moment you create a non-draft PR or the moment you convert a draft PR to a non-draft PR is the moment code review starts for it. \
|
Once your PR gets the `lgtm/done` label, don't worry about keeping it up-to-date or breaking
|
||||||
Once that happens, do not rebase or squash your branch anymore as it makes it difficult to review the new changes. \
|
builds (unless there's a merge conflict or a request is made by a maintainer to make
|
||||||
Merge the base branch into your branch only when you really need to, i.e. because of conflicting changes in the mean time. \
|
modifications). It is the maintainer team's responsibility from this point to get it merged.
|
||||||
This reduces unnecessary CI runs. \
|
|
||||||
Don't worry about merge commits messing up your commit history as every PR will be squash merged. \
|
|
||||||
This means that all changes are joined into a single new commit whose message is as described below.
|
|
||||||
|
|
||||||
### Getting PRs merged
|
## Styleguide
|
||||||
|
|
||||||
Changes to Gitea must be reviewed before they are accepted — no matter who
|
For imports you should use the following format (*without* the comments)
|
||||||
makes the change, even if they are an owner or a maintainer. \
|
|
||||||
The only exception are critical bugs that prevent Gitea from being compiled or started. \
|
|
||||||
Specifically, we require two approvals from maintainers for every PR. \
|
|
||||||
Once this criteria has been met, your PR receives the `lgtm/done` label. \
|
|
||||||
From this point on, your only responsibility is to fix merge conflicts or respond to/implement requests by maintainers. \
|
|
||||||
It is the responsibility of the maintainers from this point to get your PR merged.
|
|
||||||
|
|
||||||
If a PR has the `lgtm/done` label and there are no open discussions or merge conflicts anymore, any maintainer can add the `reviewed/wait-merge` label. \
|
```go
|
||||||
This label means that the PR is part of the merge queue and will be merged as soon as possible. \
|
import (
|
||||||
The merge queue will be cleared in the order of the list below:
|
// stdlib
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
<https://github.com/go-gitea/gitea/pulls?q=is%3Apr+label%3Areviewed%2Fwait-merge+sort%3Acreated-asc+is%3Aopen>
|
// local packages
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/sdk/gitea"
|
||||||
|
|
||||||
Gitea uses it's own tool, the <https://github.com/GiteaBot/gitea-backporter> to automate parts of the review process. \
|
// external packages
|
||||||
This tool does the things listed below automatically:
|
"github.com/foo/bar"
|
||||||
|
"gopkg.io/baz.v1"
|
||||||
- create a backport PR if needed once the initial PR was merged
|
)
|
||||||
- remove the PR from the merge queue after the PR merged
|
|
||||||
- keep the oldest branch in the merge queue up to date with merges
|
|
||||||
|
|
||||||
### Final call
|
|
||||||
|
|
||||||
If a PR has been ignored for more than 7 days with no comments or reviews, and the author or any maintainer believes it will not survive a long wait (such as a refactoring PR), they can send "final call" to the TOC by mentioning them in a comment.
|
|
||||||
|
|
||||||
After another 7 days, if there is still zero approval, this is considered a polite refusal, and the PR will be closed to avoid wasting further time. Therefore, the "final call" has a cost, and should be used cautiously.
|
|
||||||
|
|
||||||
However, if there are no objections from maintainers, the PR can be merged with only one approval from the TOC (not the author).
|
|
||||||
|
|
||||||
### Commit messages
|
|
||||||
|
|
||||||
Mergers are able and required to rewrite the PR title and summary (the first comment of a PR) so that it can produce an easily understandable commit message if necessary. \
|
|
||||||
The final commit message should no longer contain any uncertainty such as `hopefully, <x> won't happen anymore`. Replace uncertainty with certainty.
|
|
||||||
|
|
||||||
#### PR Co-authors
|
|
||||||
|
|
||||||
A person counts as a PR co-author the moment they (co-)authored a commit that is not simply a `Merge base branch into branch` commit. \
|
|
||||||
Mergers are required to remove such "false-positive" co-authors when writing the commit message. \
|
|
||||||
The true co-authors must remain in the commit message.
|
|
||||||
|
|
||||||
#### PRs targeting `main`
|
|
||||||
|
|
||||||
The commit message of PRs targeting `main` is always
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$PR_TITLE ($PR_INDEX)
|
|
||||||
|
|
||||||
$REWRITTEN_PR_SUMMARY
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Backport PRs
|
## Design guideline
|
||||||
|
|
||||||
The commit message of backport PRs is always
|
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:
|
||||||
|
|
||||||
```bash
|
- **models:** Contains the data structures used by xorm to construct database tables. It also contains supporting functions to query and update the database. Dependencies to other code in Gitea should be avoided although some modules might be needed (for example for logging).
|
||||||
$PR_TITLE ($INITIAL_PR_INDEX) ($BACKPORT_PR_INDEX)
|
- **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.
|
||||||
$REWRITTEN_PR_SUMMARY
|
- **modules:** Different modules to handle specific functionality in Gitea. Shall only depend on other modules but not other packages (models, services).
|
||||||
```
|
- **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.
|
||||||
|
- **tests/e2e:** End to end tests
|
||||||
|
- **tests/integration:** Integration tests
|
||||||
|
- **tests/gitea-repositories-meta:** Sample repos used in integration tests. Adding a new repo requires editing `models/fixtures/repositories.yml` and `models/fixtures/repo_unit.yml` to match.
|
||||||
|
- **tests/gitea-lfs-meta:** Sample LFS objects used in integration tests. Adding a new object requires editing `models/fixtures/lfs_meta_object.yml` to match.
|
||||||
|
- **vendor:** External code that Gitea depends on.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated in the same PR.
|
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated.
|
||||||
|
|
||||||
## API v1
|
## API v1
|
||||||
|
|
||||||
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
|
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [GitHub API v3](https://developer.github.com/v3/).
|
||||||
|
|
||||||
### GitHub API compatability
|
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.
|
||||||
|
|
||||||
Gitea's API should use the same endpoints and fields as the GitHub 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).
|
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).
|
||||||
|
|
||||||
### Adding/Maintaining API routes
|
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 expected results (errors, success, fail messages) must 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 [modules/structs/](modules/structs/)
|
||||||
All JSON input types must be defined as a struct in [modules/structs/](modules/structs/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L76-L91)) \
|
([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). \
|
and referenced in
|
||||||
They can then be used like [this example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L318). \
|
[routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go).
|
||||||
All JSON responses must be defined as a struct in [modules/structs/](modules/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/](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 [this example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L277-L279).
|
|
||||||
|
|
||||||
### When to use what HTTP method
|
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 [modules/structs/](modules/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/](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:
|
In general, HTTP methods are chosen as follows:
|
||||||
|
|
||||||
- **GET** endpoints return the requested object(s) and status **OK (200)**
|
- **GET** endpoints return requested object and status **OK (200)**
|
||||||
- **DELETE** endpoints return the status **No Content (204)** and no content either
|
- **DELETE** endpoints return status **No Content (204)**
|
||||||
- **POST** endpoints are used to **create** new objects (e.g. a User) and return the status **Created (201)** and the created object
|
- **POST** endpoints return status **Created (201)**, used to **create** new objects (e.g. a User)
|
||||||
- **PUT** endpoints are used to **add/assign** existing Objects (e.g. a user to a team) and return the status **No Content (204)** and no content either
|
- **PUT** endpoints return status **No Content (204)**, used to **add/assign** existing Objects (e.g. User) to something (e.g. Org-Team)
|
||||||
- **PATCH** endpoints are used to **edit/change** an existing object and return the changed object and the status **OK (200)**
|
- **PATCH** endpoints return changed object and status **OK (200)**, used to **edit/change** an existing object
|
||||||
|
|
||||||
### Requirements for API routes
|
An endpoint which changes/edits an object expects all fields to be optional (except ones to identify the object, which are required).
|
||||||
|
|
||||||
All parameters of endpoints changing/editing an object must be optional (except the ones to identify the object, which are required).
|
### Endpoints returning lists should
|
||||||
|
|
||||||
Endpoints returning lists must
|
|
||||||
|
|
||||||
- support pagination (`page` & `limit` options in query)
|
- support pagination (`page` & `limit` options in query)
|
||||||
- set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
|
- set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
|
||||||
|
|
||||||
## Backports and Frontports
|
## Backports and Frontports
|
||||||
|
|
||||||
### What is backported?
|
Occasionally backports of PRs are required.
|
||||||
|
|
||||||
We backport PRs given the following circumstances:
|
The backported PR title should be:
|
||||||
|
|
||||||
1. Feature freeze is active, but `<version>-rc0` has not been released yet. Here, we backport as much as possible. <!-- TODO: Is that our definition with the new backport bot? -->
|
|
||||||
2. `rc0` has been released. Here, we only backport bug- and security-fixes, and small enhancements. Large PRs such as refactors are not backported anymore. <!-- TODO: Is that our definition with the new backport bot? -->
|
|
||||||
3. We never backport new features.
|
|
||||||
4. We never backport breaking changes except when
|
|
||||||
1. The breaking change has no effect on the vast majority of users
|
|
||||||
2. The component triggering the breaking change is marked as experimental
|
|
||||||
|
|
||||||
### How to backport?
|
|
||||||
|
|
||||||
In the past, it was necessary to manually backport your PRs. \
|
|
||||||
Now, that's not a requirement anymore as our [backport bot](https://github.com/GiteaBot) tries to create backports automatically once the PR is merged when the PR
|
|
||||||
|
|
||||||
- does not have the label `backport/manual`
|
|
||||||
- has the label `backport/<version>`
|
|
||||||
|
|
||||||
The `backport/manual` label signifies either that you want to backport the change yourself, or that there were conflicts when backporting, thus you **must** do it yourself.
|
|
||||||
|
|
||||||
### Format of backport PRs
|
|
||||||
|
|
||||||
The title of backport PRs should be
|
|
||||||
|
|
||||||
```
|
```
|
||||||
<original PR title> (#<original pr number>)
|
Title of backported PR (#ORIGINAL_PR_NUMBER)
|
||||||
```
|
```
|
||||||
|
|
||||||
The first two lines of the summary of the backporting PR should be
|
The first two lines of the summary of the backporting PR should be:
|
||||||
|
|
||||||
```
|
```
|
||||||
Backport #<original pr number>
|
Backport #ORIGINAL_PR_NUMBER
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
with the rest of the summary and labels matching the original PR.
|
with the rest of the summary matching the original PR. Similarly for frontports
|
||||||
|
|
||||||
### Frontports
|
---
|
||||||
|
|
||||||
Frontports behave exactly as described above for backports.
|
A command to help create backports can be found in `contrib/backport` and can be installed (from inside the gitea repo root directory) using:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go install contrib/backport/backport.go
|
||||||
|
```
|
||||||
|
|
||||||
## Developer Certificate of Origin (DCO)
|
## 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). \
|
We consider the act of contributing to the code by submitting a Pull
|
||||||
No further action is required. \
|
Request as the "Sign off" or agreement to the certifications and terms
|
||||||
You can also decide to sign off your commits by adding the following line at the end of your commit messages:
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
Signed-off-by: Joe Smith <joe.smith@email.com>
|
Signed-off-by: Joe Smith <joe.smith@email.com>
|
||||||
```
|
```
|
||||||
|
|
||||||
If you set the `user.name` and `user.email` Git config options, you can add the line to the end of your commits automatically with `git commit -s`.
|
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.
|
We assume in good faith that the information you provide is legally binding.
|
||||||
|
|
||||||
## Release Cycle
|
## Release Cycle
|
||||||
|
|
||||||
We adopted a release schedule to streamline the process of working on, finishing, and issuing releases. \
|
We adopted a release schedule to streamline the process of working
|
||||||
The overall goal is to make a major release every three or four months, which breaks down into two or three months of general development followed by one month of testing and polishing known as the release freeze. \
|
on, finishing, and issuing releases. The overall goal is to make a
|
||||||
All the feature pull requests should be
|
minor release every three or four months, which breaks down into two or three months of
|
||||||
|
general development followed by one month of testing and polishing
|
||||||
|
known as the release freeze. All the feature pull requests should be
|
||||||
merged before feature freeze. And, during the frozen period, a corresponding
|
merged before feature freeze. And, during the frozen period, a corresponding
|
||||||
release branch is open for fixes backported from main branch. Release candidates
|
release branch is open for fixes backported from main branch. Release candidates
|
||||||
are made during this period for user testing to
|
are made during this period for user testing to
|
||||||
obtain a final version that is maintained in this branch.
|
obtain a final version that is maintained in this branch.
|
||||||
|
|
||||||
|
Major release cycles are seasonal. They always begin on the 25th and end on
|
||||||
|
the 24th (i.e., the 25th of December to March 24th).
|
||||||
|
|
||||||
During a development cycle, we may also publish any necessary minor releases
|
During a development cycle, we may also publish any necessary minor releases
|
||||||
for the previous version. For example, if the latest, published release is
|
for the previous version. For example, if the latest, published release is
|
||||||
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
|
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
|
||||||
still possible.
|
still possible.
|
||||||
|
|
||||||
|
The previous release gets fixes for:
|
||||||
|
|
||||||
|
- Security issues
|
||||||
|
- Critical bugs
|
||||||
|
- Regressions
|
||||||
|
- Build issues
|
||||||
|
- Necessary enhancements (including necessary UI/UX fixes)
|
||||||
|
|
||||||
|
The backported fixes should avoid breaking downgrade between minor releases as much as possible.
|
||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
|
|
||||||
To make sure every PR is checked, we have [maintainers](MAINTAINERS). \
|
To make sure every PR is checked, we have [team
|
||||||
Every PR **must** be reviewed by at least two maintainers (or owners) before it can get merged. \
|
maintainers](MAINTAINERS). Every PR **MUST** be reviewed by at least
|
||||||
For refactoring PRs after a week and documentation only PRs, the approval of only one maintainer is enough. \
|
two maintainers (or owners) before it can get merged. A maintainer
|
||||||
A maintainer should be a contributor of Gitea and contributed at least
|
should be a contributor of Gitea (or Gogs) and contributed at least
|
||||||
4 accepted PRs. A contributor should apply as a maintainer in the
|
4 accepted PRs. A contributor should apply as a maintainer in the
|
||||||
[Discord](https://discord.gg/Gitea) `#develop` channel. The team maintainers may invite the contributor. A maintainer
|
[Discord](https://discord.gg/NsatcWJ) #develop channel. The owners
|
||||||
|
or the team maintainers may invite the contributor. A maintainer
|
||||||
should spend some time on code reviews. If a maintainer has no
|
should spend some time on code reviews. If a maintainer has no
|
||||||
time to do that, they should apply to leave the maintainers team
|
time to do that, they should apply to leave the maintainers team
|
||||||
and we will give them the honor of being a member of the [advisors
|
and we will give them the honor of being a member of the [advisors
|
||||||
@@ -470,74 +341,69 @@ if possible provide GPG signed commits.
|
|||||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||||
https://help.github.com/articles/signing-commits-with-gpg/
|
https://help.github.com/articles/signing-commits-with-gpg/
|
||||||
|
|
||||||
## Technical Oversight Committee (TOC)
|
## Owners
|
||||||
|
|
||||||
At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions would be elected as it has been over the past years, and the other three would consist of appointed members from the Gitea company.
|
Since Gitea is a pure community organization without any company support,
|
||||||
https://blog.gitea.io/2023/02/gitea-quarterly-report-23q1/
|
to keep the development healthy we will elect three owners every year. All
|
||||||
|
contributors may vote to elect up to three candidates, one of which will
|
||||||
When the new community members have been elected, the old members will give up ownership to the newly elected members. For security reasons, TOC members or any account with write access (like a bot) must use 2FA.
|
be the main owner, and the other two the assistant owners. When the new
|
||||||
|
owners have been elected, the old owners will give up ownership to the
|
||||||
|
newly elected owners. If an owner is unable to do so, the other owners
|
||||||
|
will assist in ceding ownership to the newly elected owners.
|
||||||
|
For security reasons, Owners or any account with write access (like a bot)
|
||||||
|
must use 2FA.
|
||||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||||
|
|
||||||
### Current TOC members
|
After the election, the new owners should proactively agree
|
||||||
|
with our [CONTRIBUTING](CONTRIBUTING.md) requirements in the
|
||||||
|
[Discord](https://discord.gg/NsatcWJ) #general channel. Below are the
|
||||||
|
words to speak:
|
||||||
|
|
||||||
- 2023-01-01 ~ 2023-12-31 - https://blog.gitea.io/2023/02/gitea-quarterly-report-23q1/
|
```
|
||||||
- Company
|
I'm honored to having been elected an owner of Gitea, I agree with
|
||||||
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
|
[CONTRIBUTING](CONTRIBUTING.md). I will spend part of my time on Gitea
|
||||||
|
and lead the development of Gitea.
|
||||||
|
```
|
||||||
|
|
||||||
|
To honor the past owners, here's the history of the owners and the time
|
||||||
|
they served:
|
||||||
|
|
||||||
|
- 2022-01-01 ~ 2022-12-31 - https://github.com/go-gitea/gitea/issues/17872
|
||||||
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||||
- Community
|
|
||||||
- [6543](https://gitea.com/6543) <6543@obermui.de>
|
|
||||||
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
|
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
|
||||||
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com>
|
|
||||||
|
|
||||||
### Previous TOC/owners members
|
- 2021-01-01 ~ 2021-12-31 - https://github.com/go-gitea/gitea/issues/13801
|
||||||
|
- [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>
|
||||||
|
|
||||||
Here's the history of the owners and the time they served:
|
- 2020-01-01 ~ 2020-12-31 - https://github.com/go-gitea/gitea/issues/9230
|
||||||
|
- [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>
|
||||||
|
|
||||||
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
- 2019-01-01 ~ 2019-12-31 - https://github.com/go-gitea/gitea/issues/5572
|
||||||
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
|
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||||
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
|
- [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||||
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
|
- [Matti Ranta](https://github.com/techknowlogick) <techknowlogick@gitea.io>
|
||||||
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
|
||||||
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
|
||||||
|
|
||||||
## Governance Compensation
|
- 2018-01-01 ~ 2018-12-31 - https://github.com/go-gitea/gitea/issues/3255
|
||||||
|
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||||
|
- [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||||
|
- [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||||
|
|
||||||
Each member of the community elected TOC will be granted $500 each month as compensation for their work.
|
- 2016-11-04 ~ 2017-12-31
|
||||||
|
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||||
Furthermore, any community release manager for a specific release or LTS will be compensated $500 for the delivery of said release.
|
- [Thomas Boerger](https://github.com/tboerger) <thomas@webhippie.de>
|
||||||
|
- [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||||
These funds will come from community sources like the OpenCollective rather than directly from the company.
|
|
||||||
Only non-company members are eligible for this compensation, and if a member of the community TOC takes the responsibility of release manager, they would only be compensated for their TOC duties.
|
|
||||||
Gitea Ltd employees are not eligible to receive any funds from the OpenCollective unless it is reimbursement for a purchase made for the Gitea project itself.
|
|
||||||
|
|
||||||
## TOC & Working groups
|
|
||||||
|
|
||||||
With Gitea covering many projects outside of the main repository, several groups will be created to help focus on specific areas instead of requiring maintainers to be a jack-of-all-trades. Maintainers are of course more than welcome to be part of multiple groups should they wish to contribute in multiple places.
|
|
||||||
|
|
||||||
The currently proposed groups are:
|
|
||||||
|
|
||||||
- **Core Group**: maintain the primary Gitea repository
|
|
||||||
- **Integration Group**: maintain the Gitea ecosystem's related tools, including go-sdk/tea/changelog/bots etc.
|
|
||||||
- **Documentation Group**: maintain related documents and repositories
|
|
||||||
- **Translation Group**: coordinate with translators and maintain translations
|
|
||||||
- **Security Group**: managed by TOC directly, members are decided by TOC, maintains security patches/responsible for security items
|
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
Each year a roadmap will be discussed with the entire Gitea maintainers team, and feedback will be solicited from various stakeholders.
|
|
||||||
TOC members need to review the roadmap every year and work together on the direction of the project.
|
|
||||||
|
|
||||||
When a vote is required for a proposal or other change, the vote of community elected TOC members count slightly more than the vote of company elected TOC members. With this approach, we both avoid ties and ensure that changes align with the mission statement and community opinion.
|
|
||||||
|
|
||||||
You can visit our roadmap on the wiki.
|
|
||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
Gitea has the `main` branch as a tip branch and has version branches
|
Gitea has the `main` branch as a tip branch and has version branches
|
||||||
such as `release/v1.19`. `release/v1.19` is a release branch and we will
|
such as `release/v0.9`. `release/v0.9` is a release branch and we will
|
||||||
tag `v1.19.0` for binary download. If `v1.19.0` has bugs, we will accept
|
tag `v0.9.0` for binary download. If `v0.9.0` has bugs, we will accept
|
||||||
pull requests on the `release/v1.19` branch and publish a `v1.19.1` tag,
|
pull requests on the `release/v0.9` branch and publish a `v0.9.1` tag,
|
||||||
after bringing the bug fix also to the main branch.
|
after bringing the bug fix also to the main branch.
|
||||||
|
|
||||||
Since the `main` branch is a tip version, if you wish to use Gitea
|
Since the `main` branch is a tip version, if you wish to use Gitea
|
||||||
@@ -557,7 +423,21 @@ be reviewed by two maintainers and must pass the automatic tests.
|
|||||||
- And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
|
- And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
|
||||||
- If needed send a frontport PR for the changelog to branch `main` and update the version in `docs/config.yaml` to refer to the new version.
|
- If needed send a frontport PR for the changelog to branch `main` and update the version in `docs/config.yaml` to refer to the new version.
|
||||||
- Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
|
- Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
|
||||||
- Verify all release assets were correctly published through CI on dl.gitea.com and GitHub releases. Once ACKed:
|
- Verify all release assets were correctly published through CI on dl.gitea.io and GitHub releases. Once ACKed:
|
||||||
- bump the version of https://dl.gitea.com/gitea/version.json
|
- bump the version of https://dl.gitea.io/gitea/version.json
|
||||||
- merge the blog post PR
|
- merge the blog post PR
|
||||||
- announce the release in discord `#announcements`
|
- announce the release in discord `#announcements`
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
Code that you contribute should use the standard copyright header:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Copyright <year> The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Files in the repository contain copyright from the year they are added
|
||||||
|
to the year they are last changed. If the copyright author is changed,
|
||||||
|
just paste the header below the old one.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Build stage
|
#Build stage
|
||||||
FROM docker.io/library/golang:1.20-alpine3.18 AS build-env
|
FROM docker.io/library/golang:1.20-alpine3.17 AS build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY ${GOPROXY:-direct}
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
@@ -23,7 +23,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
|||||||
# Begin env-to-ini build
|
# Begin env-to-ini build
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.18
|
FROM docker.io/library/alpine:3.17
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
LABEL maintainer="maintainers@gitea.io"
|
||||||
|
|
||||||
EXPOSE 22 3000
|
EXPOSE 22 3000
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Build stage
|
#Build stage
|
||||||
FROM docker.io/library/golang:1.20-alpine3.18 AS build-env
|
FROM docker.io/library/golang:1.20-alpine3.17 AS build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY ${GOPROXY:-direct}
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
@@ -23,7 +23,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
|||||||
# Begin env-to-ini build
|
# Begin env-to-ini build
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.18
|
FROM docker.io/library/alpine:3.17
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
LABEL maintainer="maintainers@gitea.io"
|
||||||
|
|
||||||
EXPOSE 2222 3000
|
EXPOSE 2222 3000
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Kees de Vries <bouwko@gmail.com> (@Bwko)
|
|||||||
Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
||||||
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
||||||
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
||||||
|
Matthias Loibl <mail@matthiasloibl.com> (@metalmatze)
|
||||||
Rachid Zarouali <nobody@nobody.tld> (@xinity)
|
Rachid Zarouali <nobody@nobody.tld> (@xinity)
|
||||||
Rémy Boulanouar <admin@dblk.org> (@DblK)
|
Rémy Boulanouar <admin@dblk.org> (@DblK)
|
||||||
Sandro Santilli <strk@kbt.io> (@strk)
|
Sandro Santilli <strk@kbt.io> (@strk)
|
||||||
@@ -43,12 +44,9 @@ Steven Kriegler <sk.bunsenbrenner@gmail.com> (@justusbunsi)
|
|||||||
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
|
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
|
||||||
Leon Hofmeister <dev.lh@web.de> (@delvh)
|
Leon Hofmeister <dev.lh@web.de> (@delvh)
|
||||||
Wim <wim@42.be> (@42wim)
|
Wim <wim@42.be> (@42wim)
|
||||||
|
Xinyu Zhou <i@sourcehut.net> (@xin-u)
|
||||||
Jason Song <i@wolfogre.com> (@wolfogre)
|
Jason Song <i@wolfogre.com> (@wolfogre)
|
||||||
Yarden Shoham <git@yardenshoham.com> (@yardenshoham)
|
Yarden Shoham <hrsi88@gmail.com> (@yardenshoham)
|
||||||
Yu Tian <zettat123@gmail.com> (@Zettat123)
|
Yu Tian <zettat123@gmail.com> (@Zettat123)
|
||||||
Eddie Yang <576951401@qq.com> (@yp05327)
|
Eddie Yang <576951401@qq.com> (@yp05327)
|
||||||
Dong Ge <gedong_1994@163.com> (@sillyguodong)
|
Dong Ge <gedong_1994@163.com> (@sillyguodong)
|
||||||
Xinyi Gong <hestergong@gmail.com> (@HesterG)
|
|
||||||
wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
|
|
||||||
Gary Moon <gary@garymoon.net> (@garymoon)
|
|
||||||
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
|
|
||||||
|
|||||||
214
Makefile
214
Makefile
@@ -20,28 +20,28 @@ IMPORT := code.gitea.io/gitea
|
|||||||
|
|
||||||
GO ?= go
|
GO ?= go
|
||||||
SHASUM ?= shasum -a 256
|
SHASUM ?= shasum -a 256
|
||||||
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
|
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||||
COMMA := ,
|
COMMA := ,
|
||||||
|
|
||||||
XGO_VERSION := go-1.20.x
|
XGO_VERSION := go-1.20.x
|
||||||
|
|
||||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.43.0
|
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.40.4
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.6.0
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
|
ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.2
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2
|
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.4.0
|
||||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0
|
||||||
|
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
||||||
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
||||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.4
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.3
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
|
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.5.0
|
||||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@latest
|
|
||||||
|
|
||||||
DOCKER_IMAGE ?= gitea/gitea
|
DOCKER_IMAGE ?= gitea/gitea
|
||||||
DOCKER_TAG ?= latest
|
DOCKER_TAG ?= latest
|
||||||
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
ifeq ($(HAS_GO), GO)
|
||||||
GOPATH ?= $(shell $(GO) env GOPATH)
|
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||||
export PATH := $(GOPATH)/bin:$(PATH)
|
export PATH := $(GOPATH)/bin:$(PATH)
|
||||||
|
|
||||||
@@ -79,21 +79,12 @@ endif
|
|||||||
STORED_VERSION_FILE := VERSION
|
STORED_VERSION_FILE := VERSION
|
||||||
HUGO_VERSION ?= 0.111.3
|
HUGO_VERSION ?= 0.111.3
|
||||||
|
|
||||||
GITHUB_REF_TYPE ?= branch
|
|
||||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
|
||||||
|
|
||||||
# backwards compatible to build with Drone
|
|
||||||
ifneq ($(DRONE_TAG),)
|
ifneq ($(DRONE_TAG),)
|
||||||
GITHUB_REF_TYPE := tag
|
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||||
GITHUB_REF_NAME := $(DRONE_TAG)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(GITHUB_REF_TYPE),branch)
|
|
||||||
VERSION ?= $(subst v,,$(GITHUB_REF_NAME))
|
|
||||||
GITEA_VERSION ?= $(VERSION)
|
GITEA_VERSION ?= $(VERSION)
|
||||||
else
|
else
|
||||||
ifneq ($(GITHUB_REF_NAME),)
|
ifneq ($(DRONE_BRANCH),)
|
||||||
VERSION ?= $(subst release/v,,$(GITHUB_REF_NAME))
|
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||||
else
|
else
|
||||||
VERSION ?= main
|
VERSION ?= main
|
||||||
endif
|
endif
|
||||||
@@ -106,11 +97,6 @@ else
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# if version = "main" then update version to "nightly"
|
|
||||||
ifeq ($(VERSION),main)
|
|
||||||
VERSION := main-nightly
|
|
||||||
endif
|
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||||
@@ -123,7 +109,7 @@ FOMANTIC_WORK_DIR := web_src/fomantic
|
|||||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
||||||
WEBPACK_CONFIGS := webpack.config.js
|
WEBPACK_CONFIGS := webpack.config.js
|
||||||
WEBPACK_DEST := public/js/index.js public/css/index.css
|
WEBPACK_DEST := public/js/index.js public/css/index.css
|
||||||
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack
|
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack public/serviceworker.js
|
||||||
|
|
||||||
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
||||||
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
||||||
@@ -145,11 +131,11 @@ TEST_TAGS ?= sqlite sqlite_unlock_notify
|
|||||||
|
|
||||||
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
||||||
|
|
||||||
GO_DIRS := build cmd models modules routers services tests
|
GO_DIRS := cmd tests models modules routers build services tools
|
||||||
WEB_DIRS := web_src/js web_src/css
|
WEB_DIRS := web_src/js web_src/css
|
||||||
|
|
||||||
GO_SOURCES := $(wildcard *.go)
|
GO_SOURCES := $(wildcard *.go)
|
||||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" -not -path modules/options/bindata.go -not -path modules/public/bindata.go -not -path modules/templates/bindata.go)
|
||||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||||
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
||||||
|
|
||||||
@@ -203,26 +189,11 @@ help:
|
|||||||
@echo " - clean delete backend and integration files"
|
@echo " - clean delete backend and integration files"
|
||||||
@echo " - clean-all delete backend, frontend and integration files"
|
@echo " - clean-all delete backend, frontend and integration files"
|
||||||
@echo " - deps install dependencies"
|
@echo " - deps install dependencies"
|
||||||
@echo " - deps-docs install docs dependencies"
|
|
||||||
@echo " - deps-frontend install frontend dependencies"
|
@echo " - deps-frontend install frontend dependencies"
|
||||||
@echo " - deps-backend install backend dependencies"
|
@echo " - deps-backend install backend dependencies"
|
||||||
@echo " - deps-tools install tool dependencies"
|
|
||||||
@echo " - lint lint everything"
|
@echo " - lint lint everything"
|
||||||
@echo " - lint-fix lint everything and fix issues"
|
|
||||||
@echo " - lint-actions lint action workflow files"
|
|
||||||
@echo " - lint-frontend lint frontend files"
|
@echo " - lint-frontend lint frontend files"
|
||||||
@echo " - lint-frontend-fix lint frontend files and fix issues"
|
|
||||||
@echo " - lint-backend lint backend files"
|
@echo " - lint-backend lint backend files"
|
||||||
@echo " - lint-backend-fix lint backend files and fix issues"
|
|
||||||
@echo " - lint-go lint go files"
|
|
||||||
@echo " - lint-go-fix lint go files and fix issues"
|
|
||||||
@echo " - lint-go-vet lint go files with vet"
|
|
||||||
@echo " - lint-js lint js files"
|
|
||||||
@echo " - lint-js-fix lint js files and fix issues"
|
|
||||||
@echo " - lint-css lint css files"
|
|
||||||
@echo " - lint-css-fix lint css files and fix issues"
|
|
||||||
@echo " - lint-md lint markdown files"
|
|
||||||
@echo " - lint-swagger lint swagger files"
|
|
||||||
@echo " - checks run various consistency checks"
|
@echo " - checks run various consistency checks"
|
||||||
@echo " - checks-frontend check frontend files"
|
@echo " - checks-frontend check frontend files"
|
||||||
@echo " - checks-backend check backend files"
|
@echo " - checks-backend check backend files"
|
||||||
@@ -240,10 +211,13 @@ help:
|
|||||||
@echo " - generate-manpage generate manpage"
|
@echo " - generate-manpage generate manpage"
|
||||||
@echo " - generate-swagger generate the swagger spec from code comments"
|
@echo " - generate-swagger generate the swagger spec from code comments"
|
||||||
@echo " - swagger-validate check if the swagger spec is valid"
|
@echo " - swagger-validate check if the swagger spec is valid"
|
||||||
|
@echo " - golangci-lint run golangci-lint linter"
|
||||||
@echo " - go-licenses regenerate go licenses"
|
@echo " - go-licenses regenerate go licenses"
|
||||||
|
@echo " - vet examines Go source code and reports suspicious constructs"
|
||||||
@echo " - tidy run go mod tidy"
|
@echo " - tidy run go mod tidy"
|
||||||
@echo " - test[\#TestSpecificName] run unit test"
|
@echo " - test[\#TestSpecificName] run unit test"
|
||||||
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
||||||
|
@echo " - pr#<index> build and start gitea from a PR with integration test data loaded"
|
||||||
|
|
||||||
.PHONY: go-check
|
.PHONY: go-check
|
||||||
go-check:
|
go-check:
|
||||||
@@ -294,16 +268,12 @@ clean:
|
|||||||
fmt:
|
fmt:
|
||||||
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
@# strip whitespace after '{{' and before `}}` unless there is only whitespace before it
|
||||||
@# whitespace before it
|
@$(SED_INPLACE) -e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' $(TEMPLATES)
|
||||||
@$(SED_INPLACE) \
|
|
||||||
-e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' \
|
|
||||||
-e 's/([ ]\{1,\}/(/g' -e '/^[ ]\{1,\})/! s/[ ]\{1,\})/)/g' \
|
|
||||||
$(TEMPLATES)
|
|
||||||
|
|
||||||
.PHONY: fmt-check
|
.PHONY: fmt-check
|
||||||
fmt-check: fmt
|
fmt-check: fmt
|
||||||
@diff=$$(git diff --color=always $(GO_SOURCES) templates $(WEB_DIRS)); \
|
@diff=$$(git diff $(GO_SOURCES) templates $(WEB_DIRS)); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
echo "Please run 'make fmt' and commit the result:"; \
|
echo "Please run 'make fmt' and commit the result:"; \
|
||||||
echo "$${diff}"; \
|
echo "$${diff}"; \
|
||||||
@@ -314,6 +284,12 @@ fmt-check: fmt
|
|||||||
misspell-check:
|
misspell-check:
|
||||||
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
|
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
|
||||||
|
|
||||||
|
.PHONY: vet
|
||||||
|
vet:
|
||||||
|
@echo "Running go vet..."
|
||||||
|
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
||||||
|
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
|
||||||
|
|
||||||
.PHONY: $(TAGS_EVIDENCE)
|
.PHONY: $(TAGS_EVIDENCE)
|
||||||
$(TAGS_EVIDENCE):
|
$(TAGS_EVIDENCE):
|
||||||
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
||||||
@@ -333,7 +309,7 @@ $(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA)
|
|||||||
|
|
||||||
.PHONY: swagger-check
|
.PHONY: swagger-check
|
||||||
swagger-check: generate-swagger
|
swagger-check: generate-swagger
|
||||||
@diff=$$(git diff --color=always '$(SWAGGER_SPEC)'); \
|
@diff=$$(git diff '$(SWAGGER_SPEC)'); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
echo "Please run 'make generate-swagger' and commit the result:"; \
|
echo "Please run 'make generate-swagger' and commit the result:"; \
|
||||||
echo "$${diff}"; \
|
echo "$${diff}"; \
|
||||||
@@ -346,6 +322,11 @@ swagger-validate:
|
|||||||
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
|
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||||
|
|
||||||
|
.PHONY: errcheck
|
||||||
|
errcheck:
|
||||||
|
@echo "Running errcheck..."
|
||||||
|
$(GO) run $(ERRCHECK_PACKAGE) $(GO_PACKAGES)
|
||||||
|
|
||||||
.PHONY: checks
|
.PHONY: checks
|
||||||
checks: checks-frontend checks-backend
|
checks: checks-frontend checks-backend
|
||||||
|
|
||||||
@@ -358,81 +339,23 @@ checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-valida
|
|||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: lint-frontend lint-backend
|
lint: lint-frontend lint-backend
|
||||||
|
|
||||||
.PHONY: lint-fix
|
|
||||||
lint-fix: lint-frontend-fix lint-backend-fix
|
|
||||||
|
|
||||||
.PHONY: lint-frontend
|
.PHONY: lint-frontend
|
||||||
lint-frontend: lint-js lint-css lint-md lint-swagger
|
lint-frontend: node_modules
|
||||||
|
|
||||||
.PHONY: lint-frontend-fix
|
|
||||||
lint-frontend-fix: lint-js-fix lint-css-fix lint-md lint-swagger
|
|
||||||
|
|
||||||
.PHONY: lint-backend
|
|
||||||
lint-backend: lint-go lint-go-vet lint-editorconfig
|
|
||||||
|
|
||||||
.PHONY: lint-backend-fix
|
|
||||||
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
|
||||||
|
|
||||||
.PHONY: lint-js
|
|
||||||
lint-js: node_modules
|
|
||||||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e
|
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e
|
||||||
|
npx stylelint --color --max-warnings=0 web_src/css
|
||||||
.PHONY: lint-js-fix
|
|
||||||
lint-js-fix: node_modules
|
|
||||||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e --fix
|
|
||||||
|
|
||||||
.PHONY: lint-css
|
|
||||||
lint-css: node_modules
|
|
||||||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue
|
|
||||||
|
|
||||||
.PHONY: lint-css-fix
|
|
||||||
lint-css-fix: node_modules
|
|
||||||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue --fix
|
|
||||||
|
|
||||||
.PHONY: lint-swagger
|
|
||||||
lint-swagger: node_modules
|
|
||||||
npx spectral lint -q -F hint $(SWAGGER_SPEC)
|
npx spectral lint -q -F hint $(SWAGGER_SPEC)
|
||||||
|
|
||||||
.PHONY: lint-md
|
|
||||||
lint-md: node_modules
|
|
||||||
npx markdownlint docs *.md
|
npx markdownlint docs *.md
|
||||||
|
|
||||||
.PHONY: lint-go
|
.PHONY: lint-backend
|
||||||
lint-go:
|
lint-backend: golangci-lint vet editorconfig-checker
|
||||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
|
||||||
|
|
||||||
.PHONY: lint-go-fix
|
|
||||||
lint-go-fix:
|
|
||||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --fix
|
|
||||||
|
|
||||||
# workaround step for the lint-go-windows CI task because 'go run' can not
|
|
||||||
# have distinct GOOS/GOARCH for its build and run steps
|
|
||||||
.PHONY: lint-go-windows
|
|
||||||
lint-go-windows:
|
|
||||||
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
|
|
||||||
golangci-lint run
|
|
||||||
|
|
||||||
.PHONY: lint-go-vet
|
|
||||||
lint-go-vet:
|
|
||||||
@echo "Running go vet..."
|
|
||||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
|
||||||
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
|
|
||||||
|
|
||||||
.PHONY: lint-editorconfig
|
|
||||||
lint-editorconfig:
|
|
||||||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .github/workflows
|
|
||||||
|
|
||||||
.PHONY: lint-actions
|
|
||||||
lint-actions:
|
|
||||||
$(GO) run $(ACTIONLINT_PACKAGE)
|
|
||||||
|
|
||||||
.PHONY: watch
|
.PHONY: watch
|
||||||
watch:
|
watch:
|
||||||
@bash build/watch.sh
|
bash tools/watch.sh
|
||||||
|
|
||||||
.PHONY: watch-frontend
|
.PHONY: watch-frontend
|
||||||
watch-frontend: node-check node_modules
|
watch-frontend: node-check node_modules
|
||||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||||
NODE_ENV=development npx webpack --watch --progress
|
NODE_ENV=development npx webpack --watch --progress
|
||||||
|
|
||||||
.PHONY: watch-backend
|
.PHONY: watch-backend
|
||||||
@@ -491,7 +414,7 @@ vendor: go.mod go.sum
|
|||||||
|
|
||||||
.PHONY: tidy-check
|
.PHONY: tidy-check
|
||||||
tidy-check: tidy
|
tidy-check: tidy
|
||||||
@diff=$$(git diff --color=always go.mod go.sum $(GO_LICENSE_FILE)); \
|
@diff=$$(git diff go.mod go.sum $(GO_LICENSE_FILE)); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
echo "Please run 'make tidy' and commit the result:"; \
|
echo "Please run 'make tidy' and commit the result:"; \
|
||||||
echo "$${diff}"; \
|
echo "$${diff}"; \
|
||||||
@@ -823,7 +746,7 @@ generate-go: $(TAGS_PREREQ)
|
|||||||
|
|
||||||
.PHONY: security-check
|
.PHONY: security-check
|
||||||
security-check:
|
security-check:
|
||||||
go run $(GOVULNCHECK_PACKAGE) ./...
|
go run $(GOVULNCHECK_PACKAGE) -v ./...
|
||||||
|
|
||||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||||
@@ -840,28 +763,28 @@ release-windows: | $(DIST_DIRS)
|
|||||||
ifeq (,$(findstring gogit,$(TAGS)))
|
ifeq (,$(findstring gogit,$(TAGS)))
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
||||||
endif
|
endif
|
||||||
ifneq ($(DRONE_TAG),)
|
ifeq ($(CI),true)
|
||||||
cp /build/* $(DIST)/binaries
|
cp /build/* $(DIST)/binaries
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: release-linux
|
.PHONY: release-linux
|
||||||
release-linux: | $(DIST_DIRS)
|
release-linux: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
|
||||||
ifneq ($(DRONE_TAG),)
|
ifeq ($(CI),true)
|
||||||
cp /build/* $(DIST)/binaries
|
cp /build/* $(DIST)/binaries
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: release-darwin
|
.PHONY: release-darwin
|
||||||
release-darwin: | $(DIST_DIRS)
|
release-darwin: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
|
||||||
ifneq ($(DRONE_TAG),)
|
ifeq ($(CI),true)
|
||||||
cp /build/* $(DIST)/binaries
|
cp /build/* $(DIST)/binaries
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: release-freebsd
|
.PHONY: release-freebsd
|
||||||
release-freebsd: | $(DIST_DIRS)
|
release-freebsd: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'freebsd/amd64' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'freebsd/amd64' -out gitea-$(VERSION) .
|
||||||
ifneq ($(DRONE_TAG),)
|
ifeq ($(CI),true)
|
||||||
cp /build/* $(DIST)/binaries
|
cp /build/* $(DIST)/binaries
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -892,17 +815,14 @@ release-docs: | $(DIST_DIRS) docs
|
|||||||
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs/public .
|
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs/public .
|
||||||
|
|
||||||
.PHONY: docs
|
.PHONY: docs
|
||||||
docs: deps-docs
|
docs:
|
||||||
|
@hash hugo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||||
|
curl -sL https://github.com/gohugoio/hugo/releases/download/v$(HUGO_VERSION)/hugo_$(HUGO_VERSION)_Linux-64bit.tar.gz | tar zxf - -C /tmp && mv /tmp/hugo /usr/bin/hugo && chmod +x /usr/bin/hugo; \
|
||||||
|
fi
|
||||||
cd docs; make trans-copy clean build-offline;
|
cd docs; make trans-copy clean build-offline;
|
||||||
|
|
||||||
.PHONY: deps-docs
|
|
||||||
deps-docs:
|
|
||||||
@hash hugo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
|
||||||
curl -sL https://github.com/gohugoio/hugo/releases/download/v$(HUGO_VERSION)/hugo_$(HUGO_VERSION)_Linux-64bit.tar.gz | tar zxf - -C /tmp && mkdir -p ~/go/bin && mv /tmp/hugo ~/go/bin/hugo && chmod +x ~/go/bin/hugo; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: deps
|
.PHONY: deps
|
||||||
deps: deps-frontend deps-backend deps-tools deps-docs
|
deps: deps-frontend deps-backend
|
||||||
|
|
||||||
.PHONY: deps-frontend
|
.PHONY: deps-frontend
|
||||||
deps-frontend: node_modules
|
deps-frontend: node_modules
|
||||||
@@ -910,11 +830,9 @@ deps-frontend: node_modules
|
|||||||
.PHONY: deps-backend
|
.PHONY: deps-backend
|
||||||
deps-backend:
|
deps-backend:
|
||||||
$(GO) mod download
|
$(GO) mod download
|
||||||
|
|
||||||
.PHONY: deps-tools
|
|
||||||
deps-tools:
|
|
||||||
$(GO) install $(AIR_PACKAGE)
|
$(GO) install $(AIR_PACKAGE)
|
||||||
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
|
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
|
||||||
|
$(GO) install $(ERRCHECK_PACKAGE)
|
||||||
$(GO) install $(GOFUMPT_PACKAGE)
|
$(GO) install $(GOFUMPT_PACKAGE)
|
||||||
$(GO) install $(GOLANGCI_LINT_PACKAGE)
|
$(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||||
$(GO) install $(GXZ_PAGAGE)
|
$(GO) install $(GXZ_PAGAGE)
|
||||||
@@ -923,7 +841,6 @@ deps-tools:
|
|||||||
$(GO) install $(XGO_PACKAGE)
|
$(GO) install $(XGO_PACKAGE)
|
||||||
$(GO) install $(GO_LICENSES_PACKAGE)
|
$(GO) install $(GO_LICENSES_PACKAGE)
|
||||||
$(GO) install $(GOVULNCHECK_PACKAGE)
|
$(GO) install $(GOVULNCHECK_PACKAGE)
|
||||||
$(GO) install $(ACTIONLINT_PACKAGE)
|
|
||||||
|
|
||||||
node_modules: package-lock.json
|
node_modules: package-lock.json
|
||||||
npm install --no-save
|
npm install --no-save
|
||||||
@@ -965,7 +882,7 @@ svg: node-check | node_modules
|
|||||||
.PHONY: svg-check
|
.PHONY: svg-check
|
||||||
svg-check: svg
|
svg-check: svg
|
||||||
@git add $(SVG_DEST_DIR)
|
@git add $(SVG_DEST_DIR)
|
||||||
@diff=$$(git diff --color=always --cached $(SVG_DEST_DIR)); \
|
@diff=$$(git diff --cached $(SVG_DEST_DIR)); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
echo "Please run 'make svg' and 'git add $(SVG_DEST_DIR)' and commit the result:"; \
|
echo "Please run 'make svg' and 'git add $(SVG_DEST_DIR)' and commit the result:"; \
|
||||||
echo "$${diff}"; \
|
echo "$${diff}"; \
|
||||||
@@ -975,7 +892,7 @@ svg-check: svg
|
|||||||
.PHONY: lockfile-check
|
.PHONY: lockfile-check
|
||||||
lockfile-check:
|
lockfile-check:
|
||||||
npm install --package-lock-only
|
npm install --package-lock-only
|
||||||
@diff=$$(git diff --color=always package-lock.json); \
|
@diff=$$(git diff package-lock.json); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
echo "package-lock.json is inconsistent with package.json"; \
|
echo "package-lock.json is inconsistent with package.json"; \
|
||||||
echo "Please run 'npm install --package-lock-only' and commit the result:"; \
|
echo "Please run 'npm install --package-lock-only' and commit the result:"; \
|
||||||
@@ -1014,10 +931,33 @@ generate-manpage:
|
|||||||
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
||||||
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
||||||
|
|
||||||
|
.PHONY: pr\#%
|
||||||
|
pr\#%: clean-all
|
||||||
|
$(GO) run contrib/pr/checkout.go $*
|
||||||
|
|
||||||
|
.PHONY: golangci-lint
|
||||||
|
golangci-lint:
|
||||||
|
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||||
|
|
||||||
|
# workaround step for the lint-backend-windows CI task because 'go run' can not
|
||||||
|
# have distinct GOOS/GOARCH for its build and run steps
|
||||||
|
.PHONY: golangci-lint-windows
|
||||||
|
golangci-lint-windows:
|
||||||
|
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||||
|
golangci-lint run
|
||||||
|
|
||||||
|
.PHONY: editorconfig-checker
|
||||||
|
editorconfig-checker:
|
||||||
|
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates
|
||||||
|
|
||||||
.PHONY: docker
|
.PHONY: docker
|
||||||
docker:
|
docker:
|
||||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
||||||
|
|
||||||
|
.PHONY: docker-build
|
||||||
|
docker-build:
|
||||||
|
docker run -ti --rm -v "$(CURDIR):/srv/app/src/code.gitea.io/gitea" -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" CGO_EXTRA_CFLAGS="$(CGO_EXTRA_CFLAGS)" webhippie/golang:edge make clean build
|
||||||
|
|
||||||
# This endif closes the if at the top of the file
|
# This endif closes the if at the top of the file
|
||||||
endif
|
endif
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -110,7 +110,7 @@ Translations are done through Crowdin. If you want to translate to a new languag
|
|||||||
|
|
||||||
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
|
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
|
||||||
|
|
||||||
https://docs.gitea.io/en-us/contributing/translation-guidelines/
|
https://docs.gitea.io/en-us/translation-guidelines/
|
||||||
|
|
||||||
[](https://crowdin.com/project/gitea)
|
[](https://crowdin.com/project/gitea)
|
||||||
|
|
||||||
@@ -173,8 +173,8 @@ for the full license text.
|
|||||||
|
|
||||||
Looking for an overview of the interface? Check it out!
|
Looking for an overview of the interface? Check it out!
|
||||||
|
|
||||||
||||
|
||||
|
||||||
|:---:|:---:|:---:|
|
|:---:|:---:|:---:|
|
||||||
||||
|
||||
|
||||||
|||
|
|||
|
||||||
|||
|
|||
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ Fork -> Patch -> Push -> Pull Request
|
|||||||
|
|
||||||
## 截图
|
## 截图
|
||||||
|
|
||||||
||||
|
||||
|
||||||
|:---:|:---:|:---:|
|
|:---:|:---:|:---:|
|
||||||
||||
|
||||
|
||||||
|||
|
|||
|
||||||
|||
|
|||
|
||||||
|
|||||||
110
assets/go-licenses.json
generated
110
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
@@ -1,114 +0,0 @@
|
|||||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
//go:build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
println("usage: backport-locales <to-ref>")
|
|
||||||
println("eg: backport-locales release/v1.19")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
mustNoErr := func(err error) {
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
collectInis := func(ref string) map[string]setting.ConfigProvider {
|
|
||||||
inis := map[string]setting.ConfigProvider{}
|
|
||||||
err := filepath.WalkDir("options/locale", func(path string, d os.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if d.IsDir() || !strings.HasSuffix(d.Name(), ".ini") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
cfg, err := setting.NewConfigProviderForLocale(path)
|
|
||||||
mustNoErr(err)
|
|
||||||
inis[path] = cfg
|
|
||||||
fmt.Printf("collecting: %s @ %s\n", path, ref)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
mustNoErr(err)
|
|
||||||
return inis
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect new locales from current working directory
|
|
||||||
inisNew := collectInis("HEAD")
|
|
||||||
|
|
||||||
// switch to the target ref, and collect the old locales
|
|
||||||
cmd := exec.Command("git", "checkout", os.Args[1])
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
mustNoErr(cmd.Run())
|
|
||||||
inisOld := collectInis(os.Args[1])
|
|
||||||
|
|
||||||
// use old en-US as the base, and copy the new translations to the old locales
|
|
||||||
enUsOld := inisOld["options/locale/locale_en-US.ini"]
|
|
||||||
brokenWarned := map[string]bool{}
|
|
||||||
for path, iniOld := range inisOld {
|
|
||||||
if iniOld == enUsOld {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
iniNew := inisNew[path]
|
|
||||||
if iniNew == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, secEnUS := range enUsOld.Sections() {
|
|
||||||
secOld := iniOld.Section(secEnUS.Name())
|
|
||||||
secNew := iniNew.Section(secEnUS.Name())
|
|
||||||
for _, keyEnUs := range secEnUS.Keys() {
|
|
||||||
if secNew.HasKey(keyEnUs.Name()) {
|
|
||||||
oldStr := secOld.Key(keyEnUs.Name()).String()
|
|
||||||
newStr := secNew.Key(keyEnUs.Name()).String()
|
|
||||||
broken := oldStr != "" && strings.Count(oldStr, "%") != strings.Count(newStr, "%")
|
|
||||||
broken = broken || strings.Contains(oldStr, "\n") || strings.Contains(oldStr, "\n")
|
|
||||||
if broken {
|
|
||||||
brokenWarned[secOld.Name()+"."+keyEnUs.Name()] = true
|
|
||||||
fmt.Println("----")
|
|
||||||
fmt.Printf("WARNING: skip broken locale: %s , [%s] %s\n", path, secEnUS.Name(), keyEnUs.Name())
|
|
||||||
fmt.Printf("\told: %s\n", strings.ReplaceAll(oldStr, "\n", "\\n"))
|
|
||||||
fmt.Printf("\tnew: %s\n", strings.ReplaceAll(newStr, "\n", "\\n"))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
secOld.Key(keyEnUs.Name()).SetValue(newStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mustNoErr(iniOld.SaveTo(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("========")
|
|
||||||
|
|
||||||
for path, iniNew := range inisNew {
|
|
||||||
for _, sec := range iniNew.Sections() {
|
|
||||||
for _, key := range sec.Keys() {
|
|
||||||
str := sec.Key(key.Name()).String()
|
|
||||||
broken := strings.Contains(str, "\n")
|
|
||||||
broken = broken || strings.HasPrefix(str, "`") != strings.HasSuffix(str, "`")
|
|
||||||
broken = broken || strings.HasPrefix(str, "\"`")
|
|
||||||
broken = broken || strings.HasPrefix(str, "`\"")
|
|
||||||
broken = broken || strings.Count(str, `"`)%2 == 1
|
|
||||||
broken = broken || strings.Count(str, "`")%2 == 1
|
|
||||||
if broken && !brokenWarned[sec.Name()+"."+key.Name()] {
|
|
||||||
fmt.Printf("WARNING: found broken locale: %s , [%s] %s\n", path, sec.Name(), key.Name())
|
|
||||||
fmt.Printf("\tstr: %s\n", strings.ReplaceAll(str, "\n", "\\n"))
|
|
||||||
fmt.Println("----")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
|
|
||||||
var optionLogVerbose bool
|
var optionLogVerbose bool
|
||||||
|
|
||||||
func logVerbose(msg string, args ...any) {
|
func logVerbose(msg string, args ...interface{}) {
|
||||||
if optionLogVerbose {
|
if optionLogVerbose {
|
||||||
log.Printf(msg, args...)
|
log.Printf(msg, args...)
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,7 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
|
|||||||
"modules",
|
"modules",
|
||||||
"routers",
|
"routers",
|
||||||
"services",
|
"services",
|
||||||
|
"tools",
|
||||||
}
|
}
|
||||||
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
||||||
|
|
||||||
|
|||||||
@@ -60,13 +60,13 @@ func main() {
|
|||||||
// generate data
|
// generate data
|
||||||
buf, err := generate()
|
buf, err := generate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("generate err: %v", err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// write
|
// write
|
||||||
err = os.WriteFile(*flagOut, buf, 0o644)
|
err = os.WriteFile(*flagOut, buf, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("WriteFile err: %v", err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
goPath "path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -28,47 +27,14 @@ type LicenseEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) != 3 {
|
|
||||||
fmt.Println("usage: go run generate-go-licenses.go <base-dir> <out-json-file>")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
base, out := os.Args[1], os.Args[2]
|
base, out := os.Args[1], os.Args[2]
|
||||||
|
|
||||||
// Add ext for excluded files because license_test.go will be included for some reason.
|
paths := []string{}
|
||||||
// And there are more files that should be excluded, check with:
|
|
||||||
//
|
|
||||||
// go run github.com/google/go-licenses@v1.6.0 save . --force --save_path=.go-licenses 2>/dev/null
|
|
||||||
// find .go-licenses -type f | while read FILE; do echo "${$(basename $FILE)##*.}"; done | sort -u
|
|
||||||
// AUTHORS
|
|
||||||
// COPYING
|
|
||||||
// LICENSE
|
|
||||||
// Makefile
|
|
||||||
// NOTICE
|
|
||||||
// gitignore
|
|
||||||
// go
|
|
||||||
// md
|
|
||||||
// mod
|
|
||||||
// sum
|
|
||||||
// toml
|
|
||||||
// txt
|
|
||||||
// yml
|
|
||||||
//
|
|
||||||
// It could be removed once we have a better regex.
|
|
||||||
excludedExt := map[string]bool{
|
|
||||||
".gitignore": true,
|
|
||||||
".go": true,
|
|
||||||
".mod": true,
|
|
||||||
".sum": true,
|
|
||||||
".toml": true,
|
|
||||||
".yml": true,
|
|
||||||
}
|
|
||||||
var paths []string
|
|
||||||
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
|
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) || excludedExt[filepath.Ext(entry.Name())] {
|
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
paths = append(paths, path)
|
paths = append(paths, path)
|
||||||
@@ -80,27 +46,28 @@ func main() {
|
|||||||
|
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
var entries []LicenseEntry
|
entries := []LicenseEntry{}
|
||||||
for _, filePath := range paths {
|
for _, path := range paths {
|
||||||
licenseText, err := os.ReadFile(filePath)
|
path := filepath.ToSlash(path)
|
||||||
|
|
||||||
|
licenseText, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgPath := filepath.ToSlash(filePath)
|
path = strings.Replace(path, base+"/", "", 1)
|
||||||
pkgPath = strings.TrimPrefix(pkgPath, base+"/")
|
name := goPath.Dir(path)
|
||||||
pkgName := path.Dir(pkgPath)
|
|
||||||
|
|
||||||
// There might be a bug somewhere in go-licenses that sometimes interprets the
|
// There might be a bug somewhere in go-licenses that sometimes interprets the
|
||||||
// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
|
// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
|
||||||
// removing both of them for the sake of stable output.
|
// removing both of them for the sake of stable output.
|
||||||
if pkgName == "." || pkgName == "code.gitea.io/gitea" {
|
if name == "." || name == "code.gitea.io/gitea" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entries = append(entries, LicenseEntry{
|
entries = append(entries, LicenseEntry{
|
||||||
Name: pkgName,
|
Name: name,
|
||||||
Path: pkgPath,
|
Path: path,
|
||||||
LicenseText: string(licenseText),
|
LicenseText: string(licenseText),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -110,11 +77,6 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure file has a final newline
|
|
||||||
if jsonBytes[len(jsonBytes)-1] != '\n' {
|
|
||||||
jsonBytes = append(jsonBytes, '\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.WriteFile(out, jsonBytes, 0o644)
|
err = os.WriteFile(out, jsonBytes, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -25,22 +25,14 @@ async function processFile(file, {prefix, fullName} = {}) {
|
|||||||
if (prefix === 'octicon') name = name.replace(/-[0-9]+$/, ''); // chop of '-16' on octicons
|
if (prefix === 'octicon') name = name.replace(/-[0-9]+$/, ''); // chop of '-16' on octicons
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the `xmlns` attribute so that the files are displayable in standalone documents
|
|
||||||
// The svg backend module will strip the attribute during startup for inline display
|
|
||||||
const {data} = optimize(await readFile(file, 'utf8'), {
|
const {data} = optimize(await readFile(file, 'utf8'), {
|
||||||
plugins: [
|
plugins: [
|
||||||
{name: 'preset-default'},
|
{name: 'preset-default'},
|
||||||
|
{name: 'removeXMLNS'},
|
||||||
{name: 'removeDimensions'},
|
{name: 'removeDimensions'},
|
||||||
{name: 'prefixIds', params: {prefix: () => name}},
|
{name: 'prefixIds', params: {prefix: () => name}},
|
||||||
{name: 'addClassesToSVGElement', params: {classNames: ['svg', name]}},
|
{name: 'addClassesToSVGElement', params: {classNames: ['svg', name]}},
|
||||||
{
|
{name: 'addAttributesToSVGElement', params: {attributes: [{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'}]}},
|
||||||
name: 'addAttributesToSVGElement', params: {
|
|
||||||
attributes: [
|
|
||||||
{'xmlns': 'http://www.w3.org/2000/svg'},
|
|
||||||
{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
//go:build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
_, err := io.Copy(os.Stdout, os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +1,14 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# this script runs in alpine image which only has `sh` shell
|
|
||||||
|
|
||||||
set +e
|
|
||||||
if sed --version 2>/dev/null | grep -q GNU; then
|
|
||||||
SED_INPLACE="sed -i"
|
|
||||||
else
|
|
||||||
SED_INPLACE="sed -i ''"
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ ! -f ./options/locale/locale_en-US.ini ]; then
|
|
||||||
echo "please run this script in the root directory of the project"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv ./options/locale/locale_en-US.ini ./options/
|
mv ./options/locale/locale_en-US.ini ./options/
|
||||||
|
|
||||||
# the "ini" library for locale has many quirks, its behavior is different from Crowdin.
|
# Make sure to only change lines that have the translation enclosed between quotes
|
||||||
# see i18n_test.go for more details
|
sed -i -r -e '/^[a-zA-Z0-9_.-]+[ ]*=[ ]*".*"$/ {
|
||||||
|
s/^([a-zA-Z0-9_.-]+)[ ]*="/\1=/
|
||||||
# this script helps to unquote the Crowdin outputs for the quirky ini library
|
|
||||||
# * find all `key="...\"..."` lines
|
|
||||||
# * remove the leading quote
|
|
||||||
# * remove the trailing quote
|
|
||||||
# * unescape the quotes
|
|
||||||
# * eg: key="...\"..." => key=..."...
|
|
||||||
$SED_INPLACE -r -e '/^[-.A-Za-z0-9_]+[ ]*=[ ]*".*"$/ {
|
|
||||||
s/^([-.A-Za-z0-9_]+)[ ]*=[ ]*"/\1=/
|
|
||||||
s/"$//
|
|
||||||
s/\\"/"/g
|
s/\\"/"/g
|
||||||
|
s/"$//
|
||||||
}' ./options/locale/*.ini
|
}' ./options/locale/*.ini
|
||||||
|
|
||||||
# * if the escaped line is incomplete like `key="...` or `key=..."`, quote it with backticks
|
|
||||||
# * eg: key="... => key=`"...`
|
|
||||||
# * eg: key=..." => key=`..."`
|
|
||||||
$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*(".*[^"])$/\1=`\2`/' ./options/locale/*.ini
|
|
||||||
$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*([^"].*")$/\1=`\2`/' ./options/locale/*.ini
|
|
||||||
|
|
||||||
# Remove translation under 25% of en_us
|
# Remove translation under 25% of en_us
|
||||||
baselines=$(wc -l "./options/locale_en-US.ini" | cut -d" " -f1)
|
baselines=$(wc -l "./options/locale_en-US.ini" | cut -d" " -f1)
|
||||||
baselines=$((baselines / 4))
|
baselines=$((baselines / 4))
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
make --no-print-directory watch-frontend &
|
|
||||||
make --no-print-directory watch-backend &
|
|
||||||
|
|
||||||
trap 'kill $(jobs -p)' EXIT
|
|
||||||
wait
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/private"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// CmdActions represents the available actions sub-commands.
|
|
||||||
CmdActions = cli.Command{
|
|
||||||
Name: "actions",
|
|
||||||
Usage: "",
|
|
||||||
Description: "Commands for managing Gitea Actions",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
subcmdActionsGenRunnerToken,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
subcmdActionsGenRunnerToken = cli.Command{
|
|
||||||
Name: "generate-runner-token",
|
|
||||||
Usage: "Generate a new token for a runner to use to register with the server",
|
|
||||||
Action: runGenerateActionsRunnerToken,
|
|
||||||
Aliases: []string{"grt"},
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "scope, s",
|
|
||||||
Value: "",
|
|
||||||
Usage: "{owner}[/{repo}] - leave empty for a global runner",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func runGenerateActionsRunnerToken(c *cli.Context) error {
|
|
||||||
ctx, cancel := installSignals()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
setting.MustInstalled()
|
|
||||||
|
|
||||||
scope := c.String("scope")
|
|
||||||
|
|
||||||
respText, extra := private.GenerateActionsRunnerToken(ctx, scope)
|
|
||||||
if extra.HasError() {
|
|
||||||
return handleCliResponseExtra(extra)
|
|
||||||
}
|
|
||||||
_, _ = fmt.Printf("%s\n", respText)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -63,7 +63,7 @@ Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicKey(priv any) any {
|
func publicKey(priv interface{}) interface{} {
|
||||||
switch k := priv.(type) {
|
switch k := priv.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
return &k.PublicKey
|
return &k.PublicKey
|
||||||
@@ -74,7 +74,7 @@ func publicKey(priv any) any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pemBlockForKey(priv any) *pem.Block {
|
func pemBlockForKey(priv interface{}) *pem.Block {
|
||||||
switch k := priv.(type) {
|
switch k := priv.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
|
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
|
||||||
@@ -94,7 +94,7 @@ func runCert(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var priv any
|
var priv interface{}
|
||||||
var err error
|
var err error
|
||||||
switch c.String("ecdsa-curve") {
|
switch c.String("ecdsa-curve") {
|
||||||
case "":
|
case "":
|
||||||
|
|||||||
36
cmd/cmd.go
36
cmd/cmd.go
@@ -9,7 +9,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -58,9 +57,10 @@ func confirm() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initDB(ctx context.Context) error {
|
func initDB(ctx context.Context) error {
|
||||||
setting.MustInstalled()
|
setting.InitProviderFromExistingFile()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
setting.LoadDBSetting()
|
setting.LoadDBSetting()
|
||||||
setting.InitSQLLoggersForCli(log.INFO)
|
setting.InitSQLLog(false)
|
||||||
|
|
||||||
if setting.Database.Type == "" {
|
if setting.Database.Type == "" {
|
||||||
log.Fatal(`Database settings are missing from the configuration file: %q.
|
log.Fatal(`Database settings are missing from the configuration file: %q.
|
||||||
@@ -94,33 +94,3 @@ func installSignals() (context.Context, context.CancelFunc) {
|
|||||||
|
|
||||||
return ctx, cancel
|
return ctx, cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {
|
|
||||||
if out != os.Stdout && out != os.Stderr {
|
|
||||||
panic("setupConsoleLogger can only be used with os.Stdout or os.Stderr")
|
|
||||||
}
|
|
||||||
|
|
||||||
writeMode := log.WriterMode{
|
|
||||||
Level: level,
|
|
||||||
Colorize: colorize,
|
|
||||||
WriterOption: log.WriterConsoleOption{Stderr: out == os.Stderr},
|
|
||||||
}
|
|
||||||
writer := log.NewEventWriterConsole("console-default", writeMode)
|
|
||||||
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareConsoleLoggerLevel by default, use INFO level for console logger, but some sub-commands (for git/ssh protocol) shouldn't output any log to stdout.
|
|
||||||
// Any log appears in git stdout pipe will break the git protocol, eg: client can't push and hangs forever.
|
|
||||||
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error {
|
|
||||||
return func(c *cli.Context) error {
|
|
||||||
level := defaultLevel
|
|
||||||
if c.Bool("quiet") || c.GlobalBoolT("quiet") {
|
|
||||||
level = log.FATAL
|
|
||||||
}
|
|
||||||
if c.Bool("debug") || c.GlobalBool("debug") || c.Bool("verbose") || c.GlobalBool("verbose") {
|
|
||||||
level = log.TRACE
|
|
||||||
}
|
|
||||||
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
var CmdConvert = cli.Command{
|
var CmdConvert = cli.Command{
|
||||||
Name: "convert",
|
Name: "convert",
|
||||||
Usage: "Convert the database",
|
Usage: "Convert the database",
|
||||||
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4",
|
||||||
Action: runConvert,
|
Action: runConvert,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,22 +35,17 @@ func runConvert(ctx *cli.Context) error {
|
|||||||
log.Info("Log path: %s", setting.Log.RootPath)
|
log.Info("Log path: %s", setting.Log.RootPath)
|
||||||
log.Info("Configuration file: %s", setting.CustomConf)
|
log.Info("Configuration file: %s", setting.CustomConf)
|
||||||
|
|
||||||
switch {
|
if !setting.Database.Type.IsMySQL() {
|
||||||
case setting.Database.Type.IsMySQL():
|
fmt.Println("This command can only be used with a MySQL database")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if err := db.ConvertUtf8ToUtf8mb4(); err != nil {
|
if err := db.ConvertUtf8ToUtf8mb4(); err != nil {
|
||||||
log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err)
|
log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
||||||
case setting.Database.Type.IsMSSQL():
|
|
||||||
if err := db.ConvertVarcharToNVarchar(); err != nil {
|
|
||||||
log.Fatal("Failed to convert database from varchar to nvarchar: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("Converted successfully, please confirm your database's all columns character is NVARCHAR now")
|
|
||||||
default:
|
|
||||||
fmt.Println("This command can only be used with a MySQL or MSSQL database")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
golog "log"
|
golog "log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
@@ -82,25 +82,24 @@ You should back-up your database before doing this and ensure that your database
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runRecreateTable(ctx *cli.Context) error {
|
func runRecreateTable(ctx *cli.Context) error {
|
||||||
stdCtx, cancel := installSignals()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// Redirect the default golog to here
|
// Redirect the default golog to here
|
||||||
golog.SetFlags(0)
|
golog.SetFlags(0)
|
||||||
golog.SetPrefix("")
|
golog.SetPrefix("")
|
||||||
golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info))
|
golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
|
||||||
|
|
||||||
debug := ctx.Bool("debug")
|
setting.InitProviderFromExistingFile()
|
||||||
setting.MustInstalled()
|
setting.LoadCommonSettings()
|
||||||
setting.LoadDBSetting()
|
setting.LoadDBSetting()
|
||||||
|
|
||||||
if debug {
|
setting.Log.EnableXORMLog = ctx.Bool("debug")
|
||||||
setting.InitSQLLoggersForCli(log.DEBUG)
|
setting.Database.LogSQL = ctx.Bool("debug")
|
||||||
} else {
|
// FIXME: don't use CfgProvider directly
|
||||||
setting.InitSQLLoggersForCli(log.INFO)
|
setting.CfgProvider.Section("log").Key("XORM").SetValue(",")
|
||||||
}
|
|
||||||
|
setting.InitSQLLog(!ctx.Bool("debug"))
|
||||||
|
stdCtx, cancel := installSignals()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
setting.Database.LogSQL = debug
|
|
||||||
if err := db.InitEngine(stdCtx); err != nil {
|
if err := db.InitEngine(stdCtx); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
fmt.Println("Check if you are using the right config file. You can use a --config directive to specify one.")
|
fmt.Println("Check if you are using the right config file. You can use a --config directive to specify one.")
|
||||||
@@ -127,31 +126,44 @@ func runRecreateTable(ctx *cli.Context) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
|
func setDoctorLogger(ctx *cli.Context) {
|
||||||
// Silence the default loggers
|
|
||||||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
|
||||||
|
|
||||||
logFile := ctx.String("log-file")
|
logFile := ctx.String("log-file")
|
||||||
if !ctx.IsSet("log-file") {
|
if !ctx.IsSet("log-file") {
|
||||||
logFile = "doctor.log"
|
logFile = "doctor.log"
|
||||||
}
|
}
|
||||||
|
colorize := log.CanColorStdout
|
||||||
|
if ctx.IsSet("color") {
|
||||||
|
colorize = ctx.Bool("color")
|
||||||
|
}
|
||||||
|
|
||||||
if len(logFile) == 0 {
|
if len(logFile) == 0 {
|
||||||
// if no doctor log-file is set, do not show any log from default logger
|
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"NONE","stacktracelevel":"NONE","colorize":%t}`, colorize))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if logFile == "-" {
|
defer func() {
|
||||||
setupConsoleLogger(log.TRACE, colorize, os.Stdout)
|
recovered := recover()
|
||||||
} else {
|
if recovered == nil {
|
||||||
logFile, _ = filepath.Abs(logFile)
|
|
||||||
writeMode := log.WriterMode{Level: log.TRACE, WriterOption: log.WriterFileOption{FileName: logFile}}
|
|
||||||
writer, err := log.NewEventWriter("console-to-file", "file", writeMode)
|
|
||||||
if err != nil {
|
|
||||||
log.FallbackErrorf("unable to create file log writer: %v", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
|
||||||
|
err, ok := recovered.(error)
|
||||||
|
if !ok {
|
||||||
|
panic(recovered)
|
||||||
|
}
|
||||||
|
if errors.Is(err, os.ErrPermission) {
|
||||||
|
fmt.Fprintf(os.Stderr, "ERROR: Unable to write logs to provided file due to permissions error: %s\n %v\n", logFile, err)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "ERROR: Unable to write logs to provided file: %s\n %v\n", logFile, err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "WARN: Logging will be disabled\n Use `--log-file` to configure log file location\n")
|
||||||
|
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"NONE","stacktracelevel":"NONE","colorize":%t}`, colorize))
|
||||||
|
}()
|
||||||
|
|
||||||
|
if logFile == "-" {
|
||||||
|
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"trace","stacktracelevel":"NONE","colorize":%t}`, colorize))
|
||||||
|
} else {
|
||||||
|
log.NewLogger(1000, "doctor", "file", fmt.Sprintf(`{"filename":%q,"level":"trace","stacktracelevel":"NONE"}`, logFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,17 +171,22 @@ func runDoctor(ctx *cli.Context) error {
|
|||||||
stdCtx, cancel := installSignals()
|
stdCtx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
// Silence the default loggers
|
||||||
|
log.DelNamedLogger("console")
|
||||||
|
log.DelNamedLogger(log.DEFAULT)
|
||||||
|
|
||||||
|
// Now setup our own
|
||||||
|
setDoctorLogger(ctx)
|
||||||
|
|
||||||
colorize := log.CanColorStdout
|
colorize := log.CanColorStdout
|
||||||
if ctx.IsSet("color") {
|
if ctx.IsSet("color") {
|
||||||
colorize = ctx.Bool("color")
|
colorize = ctx.Bool("color")
|
||||||
}
|
}
|
||||||
|
|
||||||
setupDoctorDefaultLogger(ctx, colorize)
|
// Finally redirect the default golog to here
|
||||||
|
|
||||||
// Finally redirect the default golang's log to here
|
|
||||||
golog.SetFlags(0)
|
golog.SetFlags(0)
|
||||||
golog.SetPrefix("")
|
golog.SetPrefix("")
|
||||||
golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info))
|
golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
|
||||||
|
|
||||||
if ctx.IsSet("list") {
|
if ctx.IsSet("list") {
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
|
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
|
||||||
@@ -217,5 +234,17 @@ func runDoctor(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return doctor.RunChecks(stdCtx, colorize, ctx.Bool("fix"), checks)
|
// Now we can set up our own logger to return information about what the doctor is doing
|
||||||
|
if err := log.NewNamedLogger("doctorouter",
|
||||||
|
0,
|
||||||
|
"console",
|
||||||
|
"console",
|
||||||
|
fmt.Sprintf(`{"level":"INFO","stacktracelevel":"NONE","colorize":%t,"flags":-1}`, colorize)); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger := log.GetLogger("doctorouter")
|
||||||
|
defer logger.Close()
|
||||||
|
return doctor.RunChecks(stdCtx, logger, ctx.Bool("fix"), checks)
|
||||||
}
|
}
|
||||||
|
|||||||
42
cmd/dump.go
42
cmd/dump.go
@@ -112,10 +112,6 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
|||||||
Name: "verbose, V",
|
Name: "verbose, V",
|
||||||
Usage: "Show process details",
|
Usage: "Show process details",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "Only display warnings and errors",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "tempdir, t",
|
Name: "tempdir, t",
|
||||||
Value: os.TempDir(),
|
Value: os.TempDir(),
|
||||||
@@ -161,7 +157,7 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatal(format string, args ...any) {
|
func fatal(format string, args ...interface{}) {
|
||||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||||
log.Fatal(format, args...)
|
log.Fatal(format, args...)
|
||||||
}
|
}
|
||||||
@@ -172,7 +168,10 @@ func runDump(ctx *cli.Context) error {
|
|||||||
outType := ctx.String("type")
|
outType := ctx.String("type")
|
||||||
if fileName == "-" {
|
if fileName == "-" {
|
||||||
file = os.Stdout
|
file = os.Stdout
|
||||||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
err := log.DelLogger("console")
|
||||||
|
if err != nil {
|
||||||
|
fatal("Deleting default logger failed. Can not write to stdout: %v", err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, suffix := range outputTypeEnum.Enum {
|
for _, suffix := range outputTypeEnum.Enum {
|
||||||
if strings.HasSuffix(fileName, "."+suffix) {
|
if strings.HasSuffix(fileName, "."+suffix) {
|
||||||
@@ -182,7 +181,8 @@ func runDump(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
fileName += "." + outType
|
fileName += "." + outType
|
||||||
}
|
}
|
||||||
setting.MustInstalled()
|
setting.InitProviderFromExistingFile()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
|
|
||||||
// make sure we are logging to the console no matter what the configuration tells us do to
|
// make sure we are logging to the console no matter what the configuration tells us do to
|
||||||
// FIXME: don't use CfgProvider directly
|
// FIXME: don't use CfgProvider directly
|
||||||
@@ -192,25 +192,12 @@ func runDump(ctx *cli.Context) error {
|
|||||||
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
|
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
|
||||||
fatal("Setting console logger to stderr failed: %v", err)
|
fatal("Setting console logger to stderr failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set loglevel to Warn if quiet-mode is requested
|
|
||||||
if ctx.Bool("quiet") {
|
|
||||||
if _, err := setting.CfgProvider.Section("log.console").NewKey("LEVEL", "Warn"); err != nil {
|
|
||||||
fatal("Setting console log-level failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !setting.InstallLock {
|
if !setting.InstallLock {
|
||||||
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
||||||
return fmt.Errorf("gitea is not initialized")
|
return fmt.Errorf("gitea is not initialized")
|
||||||
}
|
}
|
||||||
setting.LoadSettings() // cannot access session settings otherwise
|
setting.LoadSettings() // cannot access session settings otherwise
|
||||||
|
|
||||||
verbose := ctx.Bool("verbose")
|
|
||||||
if verbose && ctx.Bool("quiet") {
|
|
||||||
return fmt.Errorf("--quiet and --verbose cannot both be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
stdCtx, cancel := installSignals()
|
stdCtx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -236,7 +223,8 @@ func runDump(ctx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var iface any
|
verbose := ctx.Bool("verbose")
|
||||||
|
var iface interface{}
|
||||||
if fileName == "-" {
|
if fileName == "-" {
|
||||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||||
} else {
|
} else {
|
||||||
@@ -264,7 +252,7 @@ func runDump(ctx *cli.Context) error {
|
|||||||
log.Info("Skip dumping LFS data")
|
log.Info("Skip dumping LFS data")
|
||||||
} else if !setting.LFS.StartServer {
|
} else if !setting.LFS.StartServer {
|
||||||
log.Info("LFS isn't enabled. Skip dumping LFS data")
|
log.Info("LFS isn't enabled. Skip dumping LFS data")
|
||||||
} else if err := storage.LFS.IterateObjects("", func(objPath string, object storage.Object) error {
|
} else if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error {
|
||||||
info, err := object.Stat()
|
info, err := object.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -353,9 +341,9 @@ func runDump(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
excludes = append(excludes, setting.RepoRootPath)
|
excludes = append(excludes, setting.RepoRootPath)
|
||||||
excludes = append(excludes, setting.LFS.Storage.Path)
|
excludes = append(excludes, setting.LFS.Path)
|
||||||
excludes = append(excludes, setting.Attachment.Storage.Path)
|
excludes = append(excludes, setting.Attachment.Path)
|
||||||
excludes = append(excludes, setting.Packages.Storage.Path)
|
excludes = append(excludes, setting.Packages.Path)
|
||||||
excludes = append(excludes, setting.Log.RootPath)
|
excludes = append(excludes, setting.Log.RootPath)
|
||||||
excludes = append(excludes, absFileName)
|
excludes = append(excludes, absFileName)
|
||||||
if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil {
|
if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil {
|
||||||
@@ -365,7 +353,7 @@ func runDump(ctx *cli.Context) error {
|
|||||||
|
|
||||||
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
|
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
|
||||||
log.Info("Skip dumping attachment data")
|
log.Info("Skip dumping attachment data")
|
||||||
} else if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error {
|
} else if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error {
|
||||||
info, err := object.Stat()
|
info, err := object.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -380,7 +368,7 @@ func runDump(ctx *cli.Context) error {
|
|||||||
log.Info("Skip dumping package data")
|
log.Info("Skip dumping package data")
|
||||||
} else if !setting.Packages.Enabled {
|
} else if !setting.Packages.Enabled {
|
||||||
log.Info("Packages isn't enabled. Skip dumping package data")
|
log.Info("Packages isn't enabled. Skip dumping package data")
|
||||||
} else if err := storage.Packages.IterateObjects("", func(objPath string, object storage.Object) error {
|
} else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error {
|
||||||
info, err := object.Stat()
|
info, err := object.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
116
cmd/embedded.go
116
cmd/embedded.go
@@ -1,6 +1,8 @@
|
|||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
//go:build bindata
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,9 +10,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/assetfs"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/options"
|
"code.gitea.io/gitea/modules/options"
|
||||||
"code.gitea.io/gitea/modules/public"
|
"code.gitea.io/gitea/modules/public"
|
||||||
@@ -22,9 +24,9 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdEmbedded represents the available extract sub-command.
|
// Cmdembedded represents the available extract sub-command.
|
||||||
var (
|
var (
|
||||||
CmdEmbedded = cli.Command{
|
Cmdembedded = cli.Command{
|
||||||
Name: "embedded",
|
Name: "embedded",
|
||||||
Usage: "Extract embedded resources",
|
Usage: "Extract embedded resources",
|
||||||
Description: "A command for extracting embedded resources, like templates and images",
|
Description: "A command for extracting embedded resources, like templates and images",
|
||||||
@@ -87,26 +89,50 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
matchedAssetFiles []assetFile
|
sections map[string]*section
|
||||||
|
assets []asset
|
||||||
)
|
)
|
||||||
|
|
||||||
type assetFile struct {
|
type section struct {
|
||||||
fs *assetfs.LayeredFS
|
Path string
|
||||||
name string
|
Names func() []string
|
||||||
path string
|
IsDir func(string) (bool, error)
|
||||||
|
Asset func(string) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type asset struct {
|
||||||
|
Section *section
|
||||||
|
Name string
|
||||||
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
func initEmbeddedExtractor(c *cli.Context) error {
|
func initEmbeddedExtractor(c *cli.Context) error {
|
||||||
setupConsoleLogger(log.ERROR, log.CanColorStderr, os.Stderr)
|
// Silence the console logger
|
||||||
|
log.DelNamedLogger("console")
|
||||||
|
log.DelNamedLogger(log.DEFAULT)
|
||||||
|
|
||||||
patterns, err := compileCollectPatterns(c.Args())
|
// Read configuration file
|
||||||
|
setting.InitProviderAllowEmpty()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
|
|
||||||
|
pats, err := getPatterns(c.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
sections := make(map[string]*section, 3)
|
||||||
|
|
||||||
collectAssetFilesByPattern(c, patterns, "options", options.BuiltinAssets())
|
sections["public"] = §ion{Path: "public", Names: public.AssetNames, IsDir: public.AssetIsDir, Asset: public.Asset}
|
||||||
collectAssetFilesByPattern(c, patterns, "public", public.BuiltinAssets())
|
sections["options"] = §ion{Path: "options", Names: options.AssetNames, IsDir: options.AssetIsDir, Asset: options.Asset}
|
||||||
collectAssetFilesByPattern(c, patterns, "templates", templates.BuiltinAssets())
|
sections["templates"] = §ion{Path: "templates", Names: templates.BuiltinAssetNames, IsDir: templates.BuiltinAssetIsDir, Asset: templates.BuiltinAsset}
|
||||||
|
|
||||||
|
for _, sec := range sections {
|
||||||
|
assets = append(assets, buildAssetList(sec, pats, c)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort assets
|
||||||
|
sort.SliceStable(assets, func(i, j int) bool {
|
||||||
|
return assets[i].Path < assets[j].Path
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -140,8 +166,8 @@ func runListDo(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range matchedAssetFiles {
|
for _, a := range assets {
|
||||||
fmt.Println(a.path)
|
fmt.Println(a.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -152,19 +178,19 @@ func runViewDo(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(matchedAssetFiles) == 0 {
|
if len(assets) == 0 {
|
||||||
return fmt.Errorf("no files matched the given pattern")
|
return fmt.Errorf("No files matched the given pattern")
|
||||||
} else if len(matchedAssetFiles) > 1 {
|
} else if len(assets) > 1 {
|
||||||
return fmt.Errorf("too many files matched the given pattern, try to be more specific")
|
return fmt.Errorf("Too many files matched the given pattern; try to be more specific")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := matchedAssetFiles[0].fs.ReadFile(matchedAssetFiles[0].name)
|
data, err := assets[0].Section.Asset(assets[0].Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %w", matchedAssetFiles[0].path, err)
|
return fmt.Errorf("%s: %w", assets[0].Path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = os.Stdout.Write(data); err != nil {
|
if _, err = os.Stdout.Write(data); err != nil {
|
||||||
return fmt.Errorf("%s: %w", matchedAssetFiles[0].path, err)
|
return fmt.Errorf("%s: %w", assets[0].Path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -176,7 +202,7 @@ func runExtractDo(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Args()) == 0 {
|
if len(c.Args()) == 0 {
|
||||||
return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
return fmt.Errorf("A list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||||
}
|
}
|
||||||
|
|
||||||
destdir := "."
|
destdir := "."
|
||||||
@@ -201,7 +227,7 @@ func runExtractDo(c *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %s", destdir, err)
|
return fmt.Errorf("%s: %s", destdir, err)
|
||||||
} else if !fi.IsDir() {
|
} else if !fi.IsDir() {
|
||||||
return fmt.Errorf("destination %q is not a directory", destdir)
|
return fmt.Errorf("%s is not a directory.", destdir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Extracting to %s:\n", destdir)
|
fmt.Printf("Extracting to %s:\n", destdir)
|
||||||
@@ -209,23 +235,23 @@ func runExtractDo(c *cli.Context) error {
|
|||||||
overwrite := c.Bool("overwrite")
|
overwrite := c.Bool("overwrite")
|
||||||
rename := c.Bool("rename")
|
rename := c.Bool("rename")
|
||||||
|
|
||||||
for _, a := range matchedAssetFiles {
|
for _, a := range assets {
|
||||||
if err := extractAsset(destdir, a, overwrite, rename); err != nil {
|
if err := extractAsset(destdir, a, overwrite, rename); err != nil {
|
||||||
// Non-fatal error
|
// Non-fatal error
|
||||||
fmt.Fprintf(os.Stderr, "%s: %v", a.path, err)
|
fmt.Fprintf(os.Stderr, "%s: %v", a.Path, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
func extractAsset(d string, a asset, overwrite, rename bool) error {
|
||||||
dest := filepath.Join(d, filepath.FromSlash(a.path))
|
dest := filepath.Join(d, filepath.FromSlash(a.Path))
|
||||||
dir := filepath.Dir(dest)
|
dir := filepath.Dir(dest)
|
||||||
|
|
||||||
data, err := a.fs.ReadFile(a.name)
|
data, err := a.Section.Asset(a.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %w", a.path, err)
|
return fmt.Errorf("%s: %w", a.Path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||||
@@ -246,7 +272,7 @@ func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
|||||||
return fmt.Errorf("%s already exists, but it's not a regular file", dest)
|
return fmt.Errorf("%s already exists, but it's not a regular file", dest)
|
||||||
} else if rename {
|
} else if rename {
|
||||||
if err := util.Rename(dest, dest+".bak"); err != nil {
|
if err := util.Rename(dest, dest+".bak"); err != nil {
|
||||||
return fmt.Errorf("error creating backup for %s: %w", dest, err)
|
return fmt.Errorf("Error creating backup for %s: %w", dest, err)
|
||||||
}
|
}
|
||||||
// Attempt to respect file permissions mask (even if user:group will be set anew)
|
// Attempt to respect file permissions mask (even if user:group will be set anew)
|
||||||
perms = fi.Mode()
|
perms = fi.Mode()
|
||||||
@@ -267,30 +293,32 @@ func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectAssetFilesByPattern(c *cli.Context, globs []glob.Glob, path string, layer *assetfs.Layer) {
|
func buildAssetList(sec *section, globs []glob.Glob, c *cli.Context) []asset {
|
||||||
fs := assetfs.Layered(layer)
|
results := make([]asset, 0, 64)
|
||||||
files, err := fs.ListAllFiles(".", true)
|
for _, name := range sec.Names() {
|
||||||
if err != nil {
|
if isdir, err := sec.IsDir(name); !isdir && err == nil {
|
||||||
log.Error("Error listing files in %q: %v", path, err)
|
if sec.Path == "public" &&
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, name := range files {
|
|
||||||
if path == "public" &&
|
|
||||||
strings.HasPrefix(name, "vendor/") &&
|
strings.HasPrefix(name, "vendor/") &&
|
||||||
!c.Bool("include-vendored") {
|
!c.Bool("include-vendored") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
matchName := path + "/" + name
|
matchName := sec.Path + "/" + name
|
||||||
for _, g := range globs {
|
for _, g := range globs {
|
||||||
if g.Match(matchName) {
|
if g.Match(matchName) {
|
||||||
matchedAssetFiles = append(matchedAssetFiles, assetFile{fs: fs, name: name, path: path + "/" + name})
|
results = append(results, asset{
|
||||||
|
Section: sec,
|
||||||
|
Name: name,
|
||||||
|
Path: sec.Path + "/" + name,
|
||||||
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
func compileCollectPatterns(args []string) ([]glob.Glob, error) {
|
func getPatterns(args []string) ([]glob.Glob, error) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
args = []string{"**"}
|
args = []string{"**"}
|
||||||
}
|
}
|
||||||
@@ -298,7 +326,7 @@ func compileCollectPatterns(args []string) ([]glob.Glob, error) {
|
|||||||
for i := range args {
|
for i := range args {
|
||||||
if g, err := glob.Compile(args[i], '/'); err != nil {
|
if g, err := glob.Compile(args[i], '/'); err != nil {
|
||||||
return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
|
return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
|
||||||
} else { //nolint:revive
|
} else {
|
||||||
pat[i] = g
|
pat[i] = g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
cmd/embedded_stub.go
Normal file
29
cmd/embedded_stub.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
//go:build !bindata
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cmdembedded represents the available extract sub-command.
|
||||||
|
var (
|
||||||
|
Cmdembedded = cli.Command{
|
||||||
|
Name: "embedded",
|
||||||
|
Usage: "Extract embedded resources",
|
||||||
|
Description: "A command for extracting embedded resources, like templates and images",
|
||||||
|
Action: extractorNotImplemented,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractorNotImplemented(c *cli.Context) error {
|
||||||
|
err := fmt.Errorf("Sorry: the 'embedded' subcommand is not available in builds without bindata")
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
163
cmd/hook.go
163
cmd/hook.go
@@ -6,19 +6,19 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@@ -33,7 +33,6 @@ var (
|
|||||||
Name: "hook",
|
Name: "hook",
|
||||||
Usage: "Delegate commands to corresponding Git hooks",
|
Usage: "Delegate commands to corresponding Git hooks",
|
||||||
Description: "This should only be called by Git",
|
Description: "This should only be called by Git",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
subcmdHookPreReceive,
|
subcmdHookPreReceive,
|
||||||
subcmdHookUpdate,
|
subcmdHookUpdate,
|
||||||
@@ -142,7 +141,7 @@ func (d *delayWriter) Close() error {
|
|||||||
if d == nil {
|
if d == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
stopped := d.timer.Stop()
|
stopped := util.StopTimer(d.timer)
|
||||||
if stopped || d.buf == nil {
|
if stopped || d.buf == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -168,11 +167,11 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("hooks/pre-receive.log", c.Bool("debug"))
|
||||||
|
|
||||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||||
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
return fail(`Rejecting changes as Gitea environment not set.
|
||||||
If you are pushing over SSH you must push with a key managed by
|
If you are pushing over SSH you must push with a key managed by
|
||||||
Gitea or set your environment appropriately.`, "")
|
Gitea or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
@@ -203,7 +202,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
oldCommitIDs := make([]string, hookBatchSize)
|
oldCommitIDs := make([]string, hookBatchSize)
|
||||||
newCommitIDs := make([]string, hookBatchSize)
|
newCommitIDs := make([]string, hookBatchSize)
|
||||||
refFullNames := make([]git.RefName, hookBatchSize)
|
refFullNames := make([]string, hookBatchSize)
|
||||||
count := 0
|
count := 0
|
||||||
total := 0
|
total := 0
|
||||||
lastline := 0
|
lastline := 0
|
||||||
@@ -238,14 +237,14 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
oldCommitID := string(fields[0])
|
oldCommitID := string(fields[0])
|
||||||
newCommitID := string(fields[1])
|
newCommitID := string(fields[1])
|
||||||
refFullName := git.RefName(fields[2])
|
refFullName := string(fields[2])
|
||||||
total++
|
total++
|
||||||
lastline++
|
lastline++
|
||||||
|
|
||||||
// If the ref is a branch or tag, check if it's protected
|
// If the ref is a branch or tag, check if it's protected
|
||||||
// if supportProcReceive all ref should be checked because
|
// if supportProcReceive all ref should be checked because
|
||||||
// permission check was delayed
|
// permission check was delayed
|
||||||
if supportProcReceive || refFullName.IsBranch() || refFullName.IsTag() {
|
if supportProcReceive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
|
||||||
oldCommitIDs[count] = oldCommitID
|
oldCommitIDs[count] = oldCommitID
|
||||||
newCommitIDs[count] = newCommitID
|
newCommitIDs[count] = newCommitID
|
||||||
refFullNames[count] = refFullName
|
refFullNames[count] = refFullName
|
||||||
@@ -258,9 +257,14 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
hookOptions.OldCommitIDs = oldCommitIDs
|
hookOptions.OldCommitIDs = oldCommitIDs
|
||||||
hookOptions.NewCommitIDs = newCommitIDs
|
hookOptions.NewCommitIDs = newCommitIDs
|
||||||
hookOptions.RefFullNames = refFullNames
|
hookOptions.RefFullNames = refFullNames
|
||||||
extra := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
statusCode, msg := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
||||||
if extra.HasError() {
|
switch statusCode {
|
||||||
return fail(ctx, extra.UserMsg, "HookPreReceive(batch) failed: %v", extra.Error)
|
case http.StatusOK:
|
||||||
|
// no-op
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("Internal Server Error", msg)
|
||||||
|
default:
|
||||||
|
return fail(msg, "")
|
||||||
}
|
}
|
||||||
count = 0
|
count = 0
|
||||||
lastline = 0
|
lastline = 0
|
||||||
@@ -281,9 +285,12 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
fmt.Fprintf(out, " Checking %d references\n", count)
|
fmt.Fprintf(out, " Checking %d references\n", count)
|
||||||
|
|
||||||
extra := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
statusCode, msg := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
||||||
if extra.HasError() {
|
switch statusCode {
|
||||||
return fail(ctx, extra.UserMsg, "HookPreReceive(last) failed: %v", extra.Error)
|
case http.StatusInternalServerError:
|
||||||
|
return fail("Internal Server Error", msg)
|
||||||
|
case http.StatusForbidden:
|
||||||
|
return fail(msg, "")
|
||||||
}
|
}
|
||||||
} else if lastline > 0 {
|
} else if lastline > 0 {
|
||||||
fmt.Fprintf(out, "\n")
|
fmt.Fprintf(out, "\n")
|
||||||
@@ -302,7 +309,7 @@ func runHookPostReceive(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("hooks/post-receive.log", c.Bool("debug"))
|
||||||
|
|
||||||
// First of all run update-server-info no matter what
|
// First of all run update-server-info no matter what
|
||||||
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
|
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
|
||||||
@@ -316,7 +323,7 @@ func runHookPostReceive(c *cli.Context) error {
|
|||||||
|
|
||||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||||
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
return fail(`Rejecting changes as Gitea environment not set.
|
||||||
If you are pushing over SSH you must push with a key managed by
|
If you are pushing over SSH you must push with a key managed by
|
||||||
Gitea or set your environment appropriately.`, "")
|
Gitea or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
@@ -353,7 +360,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
oldCommitIDs := make([]string, hookBatchSize)
|
oldCommitIDs := make([]string, hookBatchSize)
|
||||||
newCommitIDs := make([]string, hookBatchSize)
|
newCommitIDs := make([]string, hookBatchSize)
|
||||||
refFullNames := make([]git.RefName, hookBatchSize)
|
refFullNames := make([]string, hookBatchSize)
|
||||||
count := 0
|
count := 0
|
||||||
total := 0
|
total := 0
|
||||||
wasEmpty := false
|
wasEmpty := false
|
||||||
@@ -375,7 +382,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
fmt.Fprintf(out, ".")
|
fmt.Fprintf(out, ".")
|
||||||
oldCommitIDs[count] = string(fields[0])
|
oldCommitIDs[count] = string(fields[0])
|
||||||
newCommitIDs[count] = string(fields[1])
|
newCommitIDs[count] = string(fields[1])
|
||||||
refFullNames[count] = git.RefName(fields[2])
|
refFullNames[count] = string(fields[2])
|
||||||
if refFullNames[count] == git.BranchPrefix+"master" && newCommitIDs[count] != git.EmptySHA && count == total {
|
if refFullNames[count] == git.BranchPrefix+"master" && newCommitIDs[count] != git.EmptySHA && count == total {
|
||||||
masterPushed = true
|
masterPushed = true
|
||||||
}
|
}
|
||||||
@@ -387,11 +394,11 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
hookOptions.OldCommitIDs = oldCommitIDs
|
hookOptions.OldCommitIDs = oldCommitIDs
|
||||||
hookOptions.NewCommitIDs = newCommitIDs
|
hookOptions.NewCommitIDs = newCommitIDs
|
||||||
hookOptions.RefFullNames = refFullNames
|
hookOptions.RefFullNames = refFullNames
|
||||||
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
resp, err := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||||
if extra.HasError() {
|
if resp == nil {
|
||||||
_ = dWriter.Close()
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
return fail("Internal Server Error", err)
|
||||||
}
|
}
|
||||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||||
results = append(results, resp.Results...)
|
results = append(results, resp.Results...)
|
||||||
@@ -402,9 +409,9 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
if count == 0 {
|
if count == 0 {
|
||||||
if wasEmpty && masterPushed {
|
if wasEmpty && masterPushed {
|
||||||
// We need to tell the repo to reset the default branch to master
|
// We need to tell the repo to reset the default branch to master
|
||||||
extra := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
err := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
||||||
if extra.HasError() {
|
if err != nil {
|
||||||
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
|
return fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||||
@@ -420,11 +427,11 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
fmt.Fprintf(out, " Processing %d references\n", count)
|
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||||
|
|
||||||
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
resp, err := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
_ = dWriter.Close()
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
return fail("Internal Server Error", err)
|
||||||
}
|
}
|
||||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||||
results = append(results, resp.Results...)
|
results = append(results, resp.Results...)
|
||||||
@@ -433,9 +440,9 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
if wasEmpty && masterPushed {
|
if wasEmpty && masterPushed {
|
||||||
// We need to tell the repo to reset the default branch to master
|
// We need to tell the repo to reset the default branch to master
|
||||||
extra := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
err := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
||||||
if extra.HasError() {
|
if err != nil {
|
||||||
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
|
return fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = dWriter.Close()
|
_ = dWriter.Close()
|
||||||
@@ -478,22 +485,22 @@ func pushOptions() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runHookProcReceive(c *cli.Context) error {
|
func runHookProcReceive(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
setup("hooks/proc-receive.log", c.Bool("debug"))
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
|
||||||
|
|
||||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||||
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
return fail(`Rejecting changes as Gitea environment not set.
|
||||||
If you are pushing over SSH you must push with a key managed by
|
If you are pushing over SSH you must push with a key managed by
|
||||||
Gitea or set your environment appropriately.`, "")
|
Gitea or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx, cancel := installSignals()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
if git.CheckGitVersionAtLeast("2.29") != nil {
|
if git.CheckGitVersionAtLeast("2.29") != nil {
|
||||||
return fail(ctx, "No proc-receive support", "current git version doesn't support proc-receive.")
|
return fail("Internal Server Error", "git not support proc-receive.")
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
@@ -508,7 +515,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
// H: PKT-LINE(version=1\0push-options...)
|
// H: PKT-LINE(version=1\0push-options...)
|
||||||
// H: flush-pkt
|
// H: flush-pkt
|
||||||
|
|
||||||
rs, err := readPktLine(ctx, reader, pktLineTypeData)
|
rs, err := readPktLine(reader, pktLineTypeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -523,19 +530,19 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
index := bytes.IndexByte(rs.Data, byte(0))
|
index := bytes.IndexByte(rs.Data, byte(0))
|
||||||
if index >= len(rs.Data) {
|
if index >= len(rs.Data) {
|
||||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
return fail("Internal Server Error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
||||||
index = 9
|
index = 9
|
||||||
} else {
|
} else {
|
||||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
return fail("Internal Server Error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(rs.Data[0:index]) != VersionHead {
|
if string(rs.Data[0:index]) != VersionHead {
|
||||||
return fail(ctx, "Protocol: version error", "Received unsupported version: %s", string(rs.Data[0:index]))
|
return fail("Internal Server Error", "Received unsupported version: %s", string(rs.Data[0:index]))
|
||||||
}
|
}
|
||||||
requestOptions = strings.Split(string(rs.Data[index+1:]), " ")
|
requestOptions = strings.Split(string(rs.Data[index+1:]), " ")
|
||||||
|
|
||||||
@@ -548,17 +555,17 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
response = append(response, '\n')
|
response = append(response, '\n')
|
||||||
|
|
||||||
_, err = readPktLine(ctx, reader, pktLineTypeFlush)
|
_, err = readPktLine(reader, pktLineTypeFlush)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = writeDataPktLine(ctx, os.Stdout, response)
|
err = writeDataPktLine(os.Stdout, response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = writeFlushPktLine(ctx, os.Stdout)
|
err = writeFlushPktLine(os.Stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -577,11 +584,11 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
||||||
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
||||||
hookOptions.RefFullNames = make([]git.RefName, 0, hookBatchSize)
|
hookOptions.RefFullNames = make([]string, 0, hookBatchSize)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
|
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
rs, err = readPktLine(reader, pktLineTypeUnknow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -595,14 +602,14 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
hookOptions.OldCommitIDs = append(hookOptions.OldCommitIDs, t[0])
|
hookOptions.OldCommitIDs = append(hookOptions.OldCommitIDs, t[0])
|
||||||
hookOptions.NewCommitIDs = append(hookOptions.NewCommitIDs, t[1])
|
hookOptions.NewCommitIDs = append(hookOptions.NewCommitIDs, t[1])
|
||||||
hookOptions.RefFullNames = append(hookOptions.RefFullNames, git.RefName(t[2]))
|
hookOptions.RefFullNames = append(hookOptions.RefFullNames, t[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
hookOptions.GitPushOptions = make(map[string]string)
|
hookOptions.GitPushOptions = make(map[string]string)
|
||||||
|
|
||||||
if hasPushOptions {
|
if hasPushOptions {
|
||||||
for {
|
for {
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
rs, err = readPktLine(reader, pktLineTypeUnknow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -619,9 +626,9 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. run hook
|
// 3. run hook
|
||||||
resp, extra := private.HookProcReceive(ctx, repoUser, repoName, hookOptions)
|
resp, err := private.HookProcReceive(ctx, repoUser, repoName, hookOptions)
|
||||||
if extra.HasError() {
|
if err != nil {
|
||||||
return fail(ctx, extra.UserMsg, "HookProcReceive failed: %v", extra.Error)
|
return fail("Internal Server Error", "run proc-receive hook failed :%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. response result to service
|
// 4. response result to service
|
||||||
@@ -642,7 +649,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
for _, rs := range resp.Results {
|
for _, rs := range resp.Results {
|
||||||
if len(rs.Err) > 0 {
|
if len(rs.Err) > 0 {
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("ng "+rs.OriginalRef.String()+" "+rs.Err))
|
err = writeDataPktLine(os.Stdout, []byte("ng "+rs.OriginalRef+" "+rs.Err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -650,43 +657,43 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rs.IsNotMatched {
|
if rs.IsNotMatched {
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("ok "+rs.OriginalRef.String()))
|
err = writeDataPktLine(os.Stdout, []byte("ok "+rs.OriginalRef))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option fall-through"))
|
err = writeDataPktLine(os.Stdout, []byte("option fall-through"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("ok "+rs.OriginalRef))
|
err = writeDataPktLine(os.Stdout, []byte("ok "+rs.OriginalRef))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option refname "+rs.Ref))
|
err = writeDataPktLine(os.Stdout, []byte("option refname "+rs.Ref))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if rs.OldOID != git.EmptySHA {
|
if rs.OldOID != git.EmptySHA {
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
err = writeDataPktLine(os.Stdout, []byte("option old-oid "+rs.OldOID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option new-oid "+rs.NewOID))
|
err = writeDataPktLine(os.Stdout, []byte("option new-oid "+rs.NewOID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if rs.IsForcePush {
|
if rs.IsForcePush {
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option forced-update"))
|
err = writeDataPktLine(os.Stdout, []byte("option forced-update"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = writeFlushPktLine(ctx, os.Stdout)
|
err = writeFlushPktLine(os.Stdout)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -711,7 +718,7 @@ type gitPktLine struct {
|
|||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) {
|
func readPktLine(in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
r *gitPktLine
|
r *gitPktLine
|
||||||
@@ -722,33 +729,33 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
|||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
lengthBytes[i], err = in.ReadByte()
|
lengthBytes[i], err = in.ReadByte()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
return nil, fail("Internal Server Error", "Pkt-Line: read stdin failed : %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = new(gitPktLine)
|
r = new(gitPktLine)
|
||||||
r.Length, err = strconv.ParseUint(string(lengthBytes), 16, 32)
|
r.Length, err = strconv.ParseUint(string(lengthBytes), 16, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fail(ctx, "Protocol: format parse error", "Pkt-Line format is wrong :%v", err)
|
return nil, fail("Internal Server Error", "Pkt-Line format is wrong :%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Length == 0 {
|
if r.Length == 0 {
|
||||||
if requestType == pktLineTypeData {
|
if requestType == pktLineTypeData {
|
||||||
return nil, fail(ctx, "Protocol: format data error", "Pkt-Line format is wrong")
|
return nil, fail("Internal Server Error", "Pkt-Line format is wrong")
|
||||||
}
|
}
|
||||||
r.Type = pktLineTypeFlush
|
r.Type = pktLineTypeFlush
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Length <= 4 || r.Length > 65520 || requestType == pktLineTypeFlush {
|
if r.Length <= 4 || r.Length > 65520 || requestType == pktLineTypeFlush {
|
||||||
return nil, fail(ctx, "Protocol: format length error", "Pkt-Line format is wrong")
|
return nil, fail("Internal Server Error", "Pkt-Line format is wrong")
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Data = make([]byte, r.Length-4)
|
r.Data = make([]byte, r.Length-4)
|
||||||
for i := range r.Data {
|
for i := range r.Data {
|
||||||
r.Data[i], err = in.ReadByte()
|
r.Data[i], err = in.ReadByte()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fail(ctx, "Protocol: data error", "Pkt-Line: read stdin failed : %v", err)
|
return nil, fail("Internal Server Error", "Pkt-Line: read stdin failed : %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,15 +764,19 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlushPktLine(ctx context.Context, out io.Writer) error {
|
func writeFlushPktLine(out io.Writer) error {
|
||||||
l, err := out.Write([]byte("0000"))
|
l, err := out.Write([]byte("0000"))
|
||||||
if err != nil || l != 4 {
|
if err != nil {
|
||||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||||
}
|
}
|
||||||
|
if l != 4 {
|
||||||
|
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error {
|
func writeDataPktLine(out io.Writer, data []byte) error {
|
||||||
hexchar := []byte("0123456789abcdef")
|
hexchar := []byte("0123456789abcdef")
|
||||||
hex := func(n uint64) byte {
|
hex := func(n uint64) byte {
|
||||||
return hexchar[(n)&15]
|
return hexchar[(n)&15]
|
||||||
@@ -779,13 +790,19 @@ func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error {
|
|||||||
tmp[3] = hex(length)
|
tmp[3] = hex(length)
|
||||||
|
|
||||||
lr, err := out.Write(tmp)
|
lr, err := out.Write(tmp)
|
||||||
if err != nil || lr != 4 {
|
if err != nil {
|
||||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||||
|
}
|
||||||
|
if lr != 4 {
|
||||||
|
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lr, err = out.Write(data)
|
lr, err = out.Write(data)
|
||||||
if err != nil || int(length-4) != lr {
|
if err != nil {
|
||||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||||
|
}
|
||||||
|
if int(length-4) != lr {
|
||||||
|
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -15,28 +14,27 @@ import (
|
|||||||
|
|
||||||
func TestPktLine(t *testing.T) {
|
func TestPktLine(t *testing.T) {
|
||||||
// test read
|
// test read
|
||||||
ctx := context.Background()
|
|
||||||
s := strings.NewReader("0000")
|
s := strings.NewReader("0000")
|
||||||
r := bufio.NewReader(s)
|
r := bufio.NewReader(s)
|
||||||
result, err := readPktLine(ctx, r, pktLineTypeFlush)
|
result, err := readPktLine(r, pktLineTypeFlush)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, pktLineTypeFlush, result.Type)
|
assert.Equal(t, pktLineTypeFlush, result.Type)
|
||||||
|
|
||||||
s = strings.NewReader("0006a\n")
|
s = strings.NewReader("0006a\n")
|
||||||
r = bufio.NewReader(s)
|
r = bufio.NewReader(s)
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
result, err = readPktLine(r, pktLineTypeData)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, pktLineTypeData, result.Type)
|
assert.Equal(t, pktLineTypeData, result.Type)
|
||||||
assert.Equal(t, []byte("a\n"), result.Data)
|
assert.Equal(t, []byte("a\n"), result.Data)
|
||||||
|
|
||||||
// test write
|
// test write
|
||||||
w := bytes.NewBuffer([]byte{})
|
w := bytes.NewBuffer([]byte{})
|
||||||
err = writeFlushPktLine(ctx, w)
|
err = writeFlushPktLine(w)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []byte("0000"), w.Bytes())
|
assert.Equal(t, []byte("0000"), w.Bytes())
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
err = writeDataPktLine(ctx, w, []byte("a\nb"))
|
err = writeDataPktLine(w, []byte("a\nb"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
||||||
}
|
}
|
||||||
|
|||||||
11
cmd/keys.go
11
cmd/keys.go
@@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@@ -18,7 +17,6 @@ import (
|
|||||||
var CmdKeys = cli.Command{
|
var CmdKeys = cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
|
||||||
Action: runKeys,
|
Action: runKeys,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
@@ -66,12 +64,11 @@ func runKeys(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, false)
|
setup("keys.log", false)
|
||||||
|
|
||||||
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
authorizedString, err := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||||
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
if err != nil {
|
||||||
if extra.Error != nil {
|
return err
|
||||||
return extra.Error
|
|
||||||
}
|
}
|
||||||
fmt.Println(strings.TrimSpace(authorizedString))
|
fmt.Println(strings.TrimSpace(authorizedString))
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@@ -16,7 +17,8 @@ func runSendMail(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setting.MustInstalled()
|
setting.InitProviderFromExistingFile()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
|
|
||||||
if err := argsSet(c, "title"); err != nil {
|
if err := argsSet(c, "title"); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -41,10 +43,13 @@ func runSendMail(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
respText, extra := private.SendEmail(ctx, subject, body, nil)
|
status, message := private.SendEmail(ctx, subject, body, nil)
|
||||||
if extra.HasError() {
|
if status != http.StatusOK {
|
||||||
return handleCliResponseExtra(extra)
|
fmt.Printf("error: %s\n", message)
|
||||||
}
|
return nil
|
||||||
_, _ = fmt.Printf("Sent %s email(s) to all users\n", respText)
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Success: %s\n", message)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setting.SetCustomPathAndConf("", "", "")
|
||||||
|
setting.InitProviderAndLoadCommonSettingsForTest()
|
||||||
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
unittest.MainTest(m, &unittest.TestOptions{
|
unittest.MainTest(m, &unittest.TestOptions{
|
||||||
GiteaRootPath: "..",
|
GiteaRootPath: "..",
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -21,7 +23,6 @@ var (
|
|||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
subcmdShutdown,
|
subcmdShutdown,
|
||||||
subcmdRestart,
|
subcmdRestart,
|
||||||
subcmdReloadTemplates,
|
|
||||||
subcmdFlushQueues,
|
subcmdFlushQueues,
|
||||||
subcmdLogging,
|
subcmdLogging,
|
||||||
subCmdProcesses,
|
subCmdProcesses,
|
||||||
@@ -47,16 +48,6 @@ var (
|
|||||||
},
|
},
|
||||||
Action: runRestart,
|
Action: runRestart,
|
||||||
}
|
}
|
||||||
subcmdReloadTemplates = cli.Command{
|
|
||||||
Name: "reload-templates",
|
|
||||||
Usage: "Reload template files in the running process",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "debug",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: runReloadTemplates,
|
|
||||||
}
|
|
||||||
subcmdFlushQueues = cli.Command{
|
subcmdFlushQueues = cli.Command{
|
||||||
Name: "flush-queues",
|
Name: "flush-queues",
|
||||||
Usage: "Flush queues in the running process",
|
Usage: "Flush queues in the running process",
|
||||||
@@ -112,43 +103,57 @@ func runShutdown(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
extra := private.Shutdown(ctx)
|
statusCode, msg := private.Shutdown(ctx)
|
||||||
return handleCliResponseExtra(extra)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRestart(c *cli.Context) error {
|
func runRestart(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
extra := private.Restart(ctx)
|
statusCode, msg := private.Restart(ctx)
|
||||||
return handleCliResponseExtra(extra)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runReloadTemplates(c *cli.Context) error {
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
ctx, cancel := installSignals()
|
return nil
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
|
||||||
extra := private.ReloadTemplates(ctx)
|
|
||||||
return handleCliResponseExtra(extra)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runFlushQueues(c *cli.Context) error {
|
func runFlushQueues(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
extra := private.FlushQueues(ctx, c.Duration("timeout"), c.Bool("non-blocking"))
|
statusCode, msg := private.FlushQueues(ctx, c.Duration("timeout"), c.Bool("non-blocking"))
|
||||||
return handleCliResponseExtra(extra)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runProcesses(c *cli.Context) error {
|
func runProcesses(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
extra := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
|
statusCode, msg := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
|
||||||
return handleCliResponseExtra(extra)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
@@ -16,13 +17,13 @@ import (
|
|||||||
var (
|
var (
|
||||||
defaultLoggingFlags = []cli.Flag{
|
defaultLoggingFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "logger",
|
Name: "group, g",
|
||||||
Usage: `Logger name - will default to "default"`,
|
Usage: "Group to add logger to - will default to \"default\"",
|
||||||
}, cli.StringFlag{
|
}, cli.StringFlag{
|
||||||
Name: "writer",
|
Name: "name, n",
|
||||||
Usage: "Name of the log writer - will default to mode",
|
Usage: "Name of the new logger - will default to mode",
|
||||||
}, cli.StringFlag{
|
}, cli.StringFlag{
|
||||||
Name: "level",
|
Name: "level, l",
|
||||||
Usage: "Logging level for the new logger",
|
Usage: "Logging level for the new logger",
|
||||||
}, cli.StringFlag{
|
}, cli.StringFlag{
|
||||||
Name: "stacktrace-level, L",
|
Name: "stacktrace-level, L",
|
||||||
@@ -83,8 +84,8 @@ var (
|
|||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
}, cli.StringFlag{
|
}, cli.StringFlag{
|
||||||
Name: "logger",
|
Name: "group, g",
|
||||||
Usage: `Logger name - will default to "default"`,
|
Usage: "Group to add logger to - will default to \"default\"",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: runRemoveLogger,
|
Action: runRemoveLogger,
|
||||||
@@ -93,6 +94,15 @@ var (
|
|||||||
Usage: "Add a logger",
|
Usage: "Add a logger",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
{
|
{
|
||||||
|
Name: "console",
|
||||||
|
Usage: "Add a console logger",
|
||||||
|
Flags: append(defaultLoggingFlags,
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "stderr",
|
||||||
|
Usage: "Output console logs to stderr - only relevant for console",
|
||||||
|
}),
|
||||||
|
Action: runAddConsoleLogger,
|
||||||
|
}, {
|
||||||
Name: "file",
|
Name: "file",
|
||||||
Usage: "Add a file logger",
|
Usage: "Add a file logger",
|
||||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
Flags: append(defaultLoggingFlags, []cli.Flag{
|
||||||
@@ -139,6 +149,28 @@ var (
|
|||||||
},
|
},
|
||||||
}...),
|
}...),
|
||||||
Action: runAddConnLogger,
|
Action: runAddConnLogger,
|
||||||
|
}, {
|
||||||
|
Name: "smtp",
|
||||||
|
Usage: "Add an SMTP logger",
|
||||||
|
Flags: append(defaultLoggingFlags, []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "username, u",
|
||||||
|
Usage: "Mail server username",
|
||||||
|
}, cli.StringFlag{
|
||||||
|
Name: "password, P",
|
||||||
|
Usage: "Mail server password",
|
||||||
|
}, cli.StringFlag{
|
||||||
|
Name: "host, H",
|
||||||
|
Usage: "Mail server host (defaults to: 127.0.0.1:25)",
|
||||||
|
}, cli.StringSliceFlag{
|
||||||
|
Name: "send-to, s",
|
||||||
|
Usage: "Email address(es) to send to",
|
||||||
|
}, cli.StringFlag{
|
||||||
|
Name: "subject, S",
|
||||||
|
Usage: "Subject header of sent emails",
|
||||||
|
},
|
||||||
|
}...),
|
||||||
|
Action: runAddSMTPLogger,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@@ -159,26 +191,59 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func runRemoveLogger(c *cli.Context) error {
|
func runRemoveLogger(c *cli.Context) error {
|
||||||
|
setup("manager", c.Bool("debug"))
|
||||||
|
group := c.String("group")
|
||||||
|
if len(group) == 0 {
|
||||||
|
group = log.DEFAULT
|
||||||
|
}
|
||||||
|
name := c.Args().First()
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
statusCode, msg := private.RemoveLogger(ctx, group, name)
|
||||||
logger := c.String("logger")
|
switch statusCode {
|
||||||
if len(logger) == 0 {
|
case http.StatusInternalServerError:
|
||||||
logger = log.DEFAULT
|
return fail("InternalServerError", msg)
|
||||||
}
|
}
|
||||||
writer := c.Args().First()
|
|
||||||
|
|
||||||
extra := private.RemoveLogger(ctx, logger, writer)
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
return handleCliResponseExtra(extra)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runAddSMTPLogger(c *cli.Context) error {
|
||||||
|
setup("manager", c.Bool("debug"))
|
||||||
|
vals := map[string]interface{}{}
|
||||||
|
mode := "smtp"
|
||||||
|
if c.IsSet("host") {
|
||||||
|
vals["host"] = c.String("host")
|
||||||
|
} else {
|
||||||
|
vals["host"] = "127.0.0.1:25"
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.IsSet("username") {
|
||||||
|
vals["username"] = c.String("username")
|
||||||
|
}
|
||||||
|
if c.IsSet("password") {
|
||||||
|
vals["password"] = c.String("password")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.IsSet("send-to") {
|
||||||
|
return fmt.Errorf("Some recipients must be provided")
|
||||||
|
}
|
||||||
|
vals["sendTos"] = c.StringSlice("send-to")
|
||||||
|
|
||||||
|
if c.IsSet("subject") {
|
||||||
|
vals["subject"] = c.String("subject")
|
||||||
|
} else {
|
||||||
|
vals["subject"] = "Diagnostic message from Gitea"
|
||||||
|
}
|
||||||
|
|
||||||
|
return commonAddLogger(c, mode, vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAddConnLogger(c *cli.Context) error {
|
func runAddConnLogger(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
setup("manager", c.Bool("debug"))
|
||||||
defer cancel()
|
vals := map[string]interface{}{}
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
|
||||||
vals := map[string]any{}
|
|
||||||
mode := "conn"
|
mode := "conn"
|
||||||
vals["net"] = "tcp"
|
vals["net"] = "tcp"
|
||||||
if c.IsSet("protocol") {
|
if c.IsSet("protocol") {
|
||||||
@@ -204,11 +269,8 @@ func runAddConnLogger(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runAddFileLogger(c *cli.Context) error {
|
func runAddFileLogger(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
setup("manager", c.Bool("debug"))
|
||||||
defer cancel()
|
vals := map[string]interface{}{}
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
|
||||||
vals := map[string]any{}
|
|
||||||
mode := "file"
|
mode := "file"
|
||||||
if c.IsSet("filename") {
|
if c.IsSet("filename") {
|
||||||
vals["filename"] = c.String("filename")
|
vals["filename"] = c.String("filename")
|
||||||
@@ -236,12 +298,22 @@ func runAddFileLogger(c *cli.Context) error {
|
|||||||
return commonAddLogger(c, mode, vals)
|
return commonAddLogger(c, mode, vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
func runAddConsoleLogger(c *cli.Context) error {
|
||||||
|
setup("manager", c.Bool("debug"))
|
||||||
|
vals := map[string]interface{}{}
|
||||||
|
mode := "console"
|
||||||
|
if c.IsSet("stderr") && c.Bool("stderr") {
|
||||||
|
vals["stderr"] = c.Bool("stderr")
|
||||||
|
}
|
||||||
|
return commonAddLogger(c, mode, vals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
|
||||||
if len(c.String("level")) > 0 {
|
if len(c.String("level")) > 0 {
|
||||||
vals["level"] = log.LevelFromString(c.String("level")).String()
|
vals["level"] = log.FromString(c.String("level")).String()
|
||||||
}
|
}
|
||||||
if len(c.String("stacktrace-level")) > 0 {
|
if len(c.String("stacktrace-level")) > 0 {
|
||||||
vals["stacktraceLevel"] = log.LevelFromString(c.String("stacktrace-level")).String()
|
vals["stacktraceLevel"] = log.FromString(c.String("stacktrace-level")).String()
|
||||||
}
|
}
|
||||||
if len(c.String("expression")) > 0 {
|
if len(c.String("expression")) > 0 {
|
||||||
vals["expression"] = c.String("expression")
|
vals["expression"] = c.String("expression")
|
||||||
@@ -255,28 +327,39 @@ func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
|||||||
if c.IsSet("color") {
|
if c.IsSet("color") {
|
||||||
vals["colorize"] = c.Bool("color")
|
vals["colorize"] = c.Bool("color")
|
||||||
}
|
}
|
||||||
logger := log.DEFAULT
|
group := "default"
|
||||||
if c.IsSet("logger") {
|
if c.IsSet("group") {
|
||||||
logger = c.String("logger")
|
group = c.String("group")
|
||||||
}
|
}
|
||||||
writer := mode
|
name := mode
|
||||||
if c.IsSet("writer") {
|
if c.IsSet("name") {
|
||||||
writer = c.String("writer")
|
name = c.String("name")
|
||||||
}
|
}
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
extra := private.AddLogger(ctx, logger, writer, mode, vals)
|
statusCode, msg := private.AddLogger(ctx, group, name, mode, vals)
|
||||||
return handleCliResponseExtra(extra)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPauseLogging(c *cli.Context) error {
|
func runPauseLogging(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
userMsg := private.PauseLogging(ctx)
|
statusCode, msg := private.PauseLogging(ctx)
|
||||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,9 +367,14 @@ func runResumeLogging(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
userMsg := private.ResumeLogging(ctx)
|
statusCode, msg := private.ResumeLogging(ctx)
|
||||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,17 +382,28 @@ func runReleaseReopenLogging(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
userMsg := private.ReleaseReopenLogging(ctx)
|
statusCode, msg := private.ReleaseReopenLogging(ctx)
|
||||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSetLogSQL(c *cli.Context) error {
|
func runSetLogSQL(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("manager", c.Bool("debug"))
|
||||||
|
|
||||||
extra := private.SetLogSQL(ctx, !c.Bool("off"))
|
statusCode, msg := private.SetLogSQL(ctx, !c.Bool("off"))
|
||||||
return handleCliResponseExtra(extra)
|
switch statusCode {
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
return fail("InternalServerError", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, msg)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
"code.gitea.io/gitea/models/migrations"
|
"code.gitea.io/gitea/models/migrations"
|
||||||
@@ -33,7 +32,7 @@ var CmdMigrateStorage = cli.Command{
|
|||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "type, t",
|
Name: "type, t",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'",
|
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages'",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "storage, s",
|
Name: "storage, s",
|
||||||
@@ -135,22 +134,6 @@ func migratePackages(ctx context.Context, dstStorage storage.ObjectStorage) erro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateActionsLog(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
|
||||||
return db.Iterate(ctx, nil, func(ctx context.Context, task *actions_model.ActionTask) error {
|
|
||||||
if task.LogExpired {
|
|
||||||
// the log has been cleared
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if !task.LogInStorage {
|
|
||||||
// running tasks store logs in DBFS
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
p := task.LogFilename
|
|
||||||
_, err := storage.Copy(dstStorage, p, storage.Actions, p)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMigrateStorage(ctx *cli.Context) error {
|
func runMigrateStorage(ctx *cli.Context) error {
|
||||||
stdCtx, cancel := installSignals()
|
stdCtx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -179,7 +162,7 @@ func runMigrateStorage(ctx *cli.Context) error {
|
|||||||
switch strings.ToLower(ctx.String("storage")) {
|
switch strings.ToLower(ctx.String("storage")) {
|
||||||
case "":
|
case "":
|
||||||
fallthrough
|
fallthrough
|
||||||
case string(setting.LocalStorageType):
|
case string(storage.LocalStorageType):
|
||||||
p := ctx.String("path")
|
p := ctx.String("path")
|
||||||
if p == "" {
|
if p == "" {
|
||||||
log.Fatal("Path must be given when storage is loal")
|
log.Fatal("Path must be given when storage is loal")
|
||||||
@@ -187,14 +170,13 @@ func runMigrateStorage(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
dstStorage, err = storage.NewLocalStorage(
|
dstStorage, err = storage.NewLocalStorage(
|
||||||
stdCtx,
|
stdCtx,
|
||||||
&setting.Storage{
|
storage.LocalStorageConfig{
|
||||||
Path: p,
|
Path: p,
|
||||||
})
|
})
|
||||||
case string(setting.MinioStorageType):
|
case string(storage.MinioStorageType):
|
||||||
dstStorage, err = storage.NewMinioStorage(
|
dstStorage, err = storage.NewMinioStorage(
|
||||||
stdCtx,
|
stdCtx,
|
||||||
&setting.Storage{
|
storage.MinioStorageConfig{
|
||||||
MinioConfig: setting.MinioStorageConfig{
|
|
||||||
Endpoint: ctx.String("minio-endpoint"),
|
Endpoint: ctx.String("minio-endpoint"),
|
||||||
AccessKeyID: ctx.String("minio-access-key-id"),
|
AccessKeyID: ctx.String("minio-access-key-id"),
|
||||||
SecretAccessKey: ctx.String("minio-secret-access-key"),
|
SecretAccessKey: ctx.String("minio-secret-access-key"),
|
||||||
@@ -204,7 +186,6 @@ func runMigrateStorage(ctx *cli.Context) error {
|
|||||||
UseSSL: ctx.Bool("minio-use-ssl"),
|
UseSSL: ctx.Bool("minio-use-ssl"),
|
||||||
InsecureSkipVerify: ctx.Bool("minio-insecure-skip-verify"),
|
InsecureSkipVerify: ctx.Bool("minio-insecure-skip-verify"),
|
||||||
ChecksumAlgorithm: ctx.String("minio-checksum-algorithm"),
|
ChecksumAlgorithm: ctx.String("minio-checksum-algorithm"),
|
||||||
},
|
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported storage type: %s", ctx.String("storage"))
|
return fmt.Errorf("unsupported storage type: %s", ctx.String("storage"))
|
||||||
@@ -220,7 +201,6 @@ func runMigrateStorage(ctx *cli.Context) error {
|
|||||||
"repo-avatars": migrateRepoAvatars,
|
"repo-avatars": migrateRepoAvatars,
|
||||||
"repo-archivers": migrateRepoArchivers,
|
"repo-archivers": migrateRepoArchivers,
|
||||||
"packages": migratePackages,
|
"packages": migratePackages,
|
||||||
"actions-log": migrateActionsLog,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tp := strings.ToLower(ctx.String("type"))
|
tp := strings.ToLower(ctx.String("type"))
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
packages_module "code.gitea.io/gitea/modules/packages"
|
packages_module "code.gitea.io/gitea/modules/packages"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
packages_service "code.gitea.io/gitea/services/packages"
|
packages_service "code.gitea.io/gitea/services/packages"
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ func TestMigratePackages(t *testing.T) {
|
|||||||
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
||||||
buf, err := packages_module.CreateHashedBufferFromReaderWithSize(strings.NewReader(content), 1024)
|
buf, err := packages_module.CreateHashedBufferFromReader(strings.NewReader(content), 1024)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer buf.Close()
|
defer buf.Close()
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ func TestMigratePackages(t *testing.T) {
|
|||||||
|
|
||||||
dstStorage, err := storage.NewLocalStorage(
|
dstStorage, err := storage.NewLocalStorage(
|
||||||
ctx,
|
ctx,
|
||||||
&setting.Storage{
|
storage.LocalStorageConfig{
|
||||||
Path: p,
|
Path: p,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -68,7 +67,7 @@ func TestMigratePackages(t *testing.T) {
|
|||||||
|
|
||||||
entries, err := os.ReadDir(p)
|
entries, err := os.ReadDir(p)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, entries, 2)
|
assert.EqualValues(t, 2, len(entries))
|
||||||
assert.EqualValues(t, "01", entries[0].Name())
|
assert.EqualValues(t, "01", entries[0].Name())
|
||||||
assert.EqualValues(t, "tmp", entries[1].Name())
|
assert.EqualValues(t, "tmp", entries[1].Name())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
@@ -51,12 +54,13 @@ func runRestoreRepository(c *cli.Context) error {
|
|||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setting.MustInstalled()
|
setting.InitProviderFromExistingFile()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
var units []string
|
var units []string
|
||||||
if s := c.String("units"); s != "" {
|
if s := c.String("units"); s != "" {
|
||||||
units = strings.Split(s, ",")
|
units = strings.Split(s, ",")
|
||||||
}
|
}
|
||||||
extra := private.RestoreRepo(
|
statusCode, errStr := private.RestoreRepo(
|
||||||
ctx,
|
ctx,
|
||||||
c.String("repo_dir"),
|
c.String("repo_dir"),
|
||||||
c.String("owner_name"),
|
c.String("owner_name"),
|
||||||
@@ -64,5 +68,10 @@ func runRestoreRepository(c *cli.Context) error {
|
|||||||
units,
|
units,
|
||||||
c.Bool("validation"),
|
c.Bool("validation"),
|
||||||
)
|
)
|
||||||
return handleCliResponseExtra(extra)
|
if statusCode == http.StatusOK {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Fatal("Failed to restore repository: %v", errStr)
|
||||||
|
return errors.New(errStr)
|
||||||
}
|
}
|
||||||
|
|||||||
106
cmd/serv.go
106
cmd/serv.go
@@ -7,6 +7,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -15,7 +16,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
@@ -44,7 +44,6 @@ var CmdServ = cli.Command{
|
|||||||
Name: "serv",
|
Name: "serv",
|
||||||
Usage: "This command should only be called by SSH shell",
|
Usage: "This command should only be called by SSH shell",
|
||||||
Description: "Serv provides access auth for repositories",
|
Description: "Serv provides access auth for repositories",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
|
||||||
Action: runServ,
|
Action: runServ,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
@@ -56,13 +55,15 @@ var CmdServ = cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(ctx context.Context, debug bool) {
|
func setup(logPath string, debug bool) {
|
||||||
|
_ = log.DelLogger("console")
|
||||||
if debug {
|
if debug {
|
||||||
setupConsoleLogger(log.TRACE, false, os.Stderr)
|
_ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
|
||||||
} else {
|
} else {
|
||||||
setupConsoleLogger(log.FATAL, false, os.Stderr)
|
_ = log.NewLogger(1000, "console", "console", `{"level":"fatal","stacktracelevel":"NONE","stderr":true}`)
|
||||||
}
|
}
|
||||||
setting.MustInstalled()
|
setting.InitProviderFromExistingFile()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
if debug {
|
if debug {
|
||||||
setting.RunMode = "dev"
|
setting.RunMode = "dev"
|
||||||
}
|
}
|
||||||
@@ -71,15 +72,15 @@ func setup(ctx context.Context, debug bool) {
|
|||||||
// `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
|
// `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
|
||||||
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
_ = fail(ctx, "Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
|
_ = fail("Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
|
||||||
} else {
|
} else {
|
||||||
_ = fail(ctx, "Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
|
_ = fail("Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := git.InitSimple(context.Background()); err != nil {
|
if err := git.InitSimple(context.Background()); err != nil {
|
||||||
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
_ = fail("Failed to init git", "Failed to init git, err: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,54 +94,32 @@ var (
|
|||||||
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
|
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
|
func fail(userMessage, logMessage string, args ...interface{}) error {
|
||||||
// The output will be passed to git client and shown to user.
|
|
||||||
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error {
|
|
||||||
if userMessage == "" {
|
|
||||||
userMessage = "Internal Server Error (no specific error)"
|
|
||||||
}
|
|
||||||
|
|
||||||
// There appears to be a chance to cause a zombie process and failure to read the Exit status
|
// There appears to be a chance to cause a zombie process and failure to read the Exit status
|
||||||
// if nothing is outputted on stdout.
|
// if nothing is outputted on stdout.
|
||||||
_, _ = fmt.Fprintln(os.Stdout, "")
|
_, _ = fmt.Fprintln(os.Stdout, "")
|
||||||
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
|
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
|
||||||
|
|
||||||
if logMsgFmt != "" {
|
if len(logMessage) > 0 {
|
||||||
logMsg := fmt.Sprintf(logMsgFmt, args...)
|
|
||||||
if !setting.IsProd {
|
if !setting.IsProd {
|
||||||
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", logMsg)
|
_, _ = fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
|
||||||
}
|
|
||||||
if userMessage != "" {
|
|
||||||
if unicode.IsPunct(rune(userMessage[len(userMessage)-1])) {
|
|
||||||
logMsg = userMessage + " " + logMsg
|
|
||||||
} else {
|
|
||||||
logMsg = userMessage + ". " + logMsg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = private.SSHLog(ctx, true, logMsg)
|
ctx, cancel := installSignals()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if len(logMessage) > 0 {
|
||||||
|
_ = private.SSHLog(ctx, true, fmt.Sprintf(logMessage+": ", args...))
|
||||||
}
|
}
|
||||||
return cli.NewExitError("", 1)
|
return cli.NewExitError("", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleCliResponseExtra handles the extra response from the cli sub-commands
|
|
||||||
// If there is a user message it will be printed to stdout
|
|
||||||
// If the command failed it will return an error (the error will be printed by cli framework)
|
|
||||||
func handleCliResponseExtra(extra private.ResponseExtra) error {
|
|
||||||
if extra.UserMsg != "" {
|
|
||||||
_, _ = fmt.Fprintln(os.Stdout, extra.UserMsg)
|
|
||||||
}
|
|
||||||
if extra.HasError() {
|
|
||||||
return cli.NewExitError(extra.Error, 1)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func runServ(c *cli.Context) error {
|
func runServ(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// FIXME: This needs to internationalised
|
// FIXME: This needs to internationalised
|
||||||
setup(ctx, c.Bool("debug"))
|
setup("serv.log", c.Bool("debug"))
|
||||||
|
|
||||||
if setting.SSH.Disabled {
|
if setting.SSH.Disabled {
|
||||||
println("Gitea: SSH has been disabled")
|
println("Gitea: SSH has been disabled")
|
||||||
@@ -156,18 +135,18 @@ func runServ(c *cli.Context) error {
|
|||||||
|
|
||||||
keys := strings.Split(c.Args()[0], "-")
|
keys := strings.Split(c.Args()[0], "-")
|
||||||
if len(keys) != 2 || keys[0] != "key" {
|
if len(keys) != 2 || keys[0] != "key" {
|
||||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
return fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||||
}
|
}
|
||||||
keyID, err := strconv.ParseInt(keys[1], 10, 64)
|
keyID, err := strconv.ParseInt(keys[1], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Key ID parsing error", "Invalid key argument: %s", c.Args()[1])
|
return fail("Key ID format error", "Invalid key argument: %s", c.Args()[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||||
if len(cmd) == 0 {
|
if len(cmd) == 0 {
|
||||||
key, user, err := private.ServNoCommand(ctx, keyID)
|
key, user, err := private.ServNoCommand(ctx, keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Key check failed", "Failed to check provided key: %v", err)
|
return fail("Internal error", "Failed to check provided key: %v", err)
|
||||||
}
|
}
|
||||||
switch key.Type {
|
switch key.Type {
|
||||||
case asymkey_model.KeyTypeDeploy:
|
case asymkey_model.KeyTypeDeploy:
|
||||||
@@ -185,7 +164,7 @@ func runServ(c *cli.Context) error {
|
|||||||
|
|
||||||
words, err := shellquote.Split(cmd)
|
words, err := shellquote.Split(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Error parsing arguments", "Failed to parse arguments: %v", err)
|
return fail("Error parsing arguments", "Failed to parse arguments: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(words) < 2 {
|
if len(words) < 2 {
|
||||||
@@ -196,7 +175,7 @@ func runServ(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fail(ctx, "Too few arguments", "Too few arguments in cmd: %s", cmd)
|
return fail("Too few arguments", "Too few arguments in cmd: %s", cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
verb := words[0]
|
verb := words[0]
|
||||||
@@ -208,7 +187,7 @@ func runServ(c *cli.Context) error {
|
|||||||
var lfsVerb string
|
var lfsVerb string
|
||||||
if verb == lfsAuthenticateVerb {
|
if verb == lfsAuthenticateVerb {
|
||||||
if !setting.LFS.StartServer {
|
if !setting.LFS.StartServer {
|
||||||
return fail(ctx, "Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
|
return fail("Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(words) > 2 {
|
if len(words) > 2 {
|
||||||
@@ -221,37 +200,37 @@ func runServ(c *cli.Context) error {
|
|||||||
|
|
||||||
rr := strings.SplitN(repoPath, "/", 2)
|
rr := strings.SplitN(repoPath, "/", 2)
|
||||||
if len(rr) != 2 {
|
if len(rr) != 2 {
|
||||||
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
|
return fail("Invalid repository path", "Invalid repository path: %v", repoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
username := strings.ToLower(rr[0])
|
username := strings.ToLower(rr[0])
|
||||||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||||
|
|
||||||
if alphaDashDotPattern.MatchString(reponame) {
|
if alphaDashDotPattern.MatchString(reponame) {
|
||||||
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
|
return fail("Invalid repo name", "Invalid repo name: %s", reponame)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bool("enable-pprof") {
|
if c.Bool("enable-pprof") {
|
||||||
if err := os.MkdirAll(setting.PprofDataPath, os.ModePerm); err != nil {
|
if err := os.MkdirAll(setting.PprofDataPath, os.ModePerm); err != nil {
|
||||||
return fail(ctx, "Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err)
|
return 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)
|
stopCPUProfiler, err := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Unable to start CPU profiler", "Unable to start CPU profile: %v", err)
|
return fail("Internal Server Error", "Unable to start CPU profile: %v", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
stopCPUProfiler()
|
stopCPUProfiler()
|
||||||
err := pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
err := pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = fail(ctx, "Unable to dump Mem profile", "Unable to dump Mem Profile: %v", err)
|
_ = fail("Internal Server Error", "Unable to dump Mem Profile: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
requestedMode, has := allowedCommands[verb]
|
requestedMode, has := allowedCommands[verb]
|
||||||
if !has {
|
if !has {
|
||||||
return fail(ctx, "Unknown git command", "Unknown git command %s", verb)
|
return fail("Unknown git command", "Unknown git command %s", verb)
|
||||||
}
|
}
|
||||||
|
|
||||||
if verb == lfsAuthenticateVerb {
|
if verb == lfsAuthenticateVerb {
|
||||||
@@ -260,13 +239,20 @@ func runServ(c *cli.Context) error {
|
|||||||
} else if lfsVerb == "download" {
|
} else if lfsVerb == "download" {
|
||||||
requestedMode = perm.AccessModeRead
|
requestedMode = perm.AccessModeRead
|
||||||
} else {
|
} else {
|
||||||
return fail(ctx, "Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
|
return fail("Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results, extra := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
|
results, err := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
|
||||||
if extra.HasError() {
|
if err != nil {
|
||||||
return fail(ctx, extra.UserMsg, "ServCommand failed: %s", extra.Error)
|
if private.IsErrServCommand(err) {
|
||||||
|
errServCommand := err.(private.ErrServCommand)
|
||||||
|
if errServCommand.StatusCode != http.StatusInternalServerError {
|
||||||
|
return fail("Unauthorized", "%s", errServCommand.Error())
|
||||||
|
}
|
||||||
|
return fail("Internal Server Error", "%s", errServCommand.Error())
|
||||||
|
}
|
||||||
|
return fail("Internal Server Error", "%s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// LFS token authentication
|
// LFS token authentication
|
||||||
@@ -288,7 +274,7 @@ func runServ(c *cli.Context) error {
|
|||||||
// Sign and get the complete encoded token as a string using the secret
|
// Sign and get the complete encoded token as a string using the secret
|
||||||
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
|
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Failed to sign JWT Token", "Failed to sign JWT token: %v", err)
|
return fail("Internal error", "Failed to sign JWT token: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenAuthentication := &git_model.LFSTokenResponse{
|
tokenAuthentication := &git_model.LFSTokenResponse{
|
||||||
@@ -300,7 +286,7 @@ func runServ(c *cli.Context) error {
|
|||||||
enc := json.NewEncoder(os.Stdout)
|
enc := json.NewEncoder(os.Stdout)
|
||||||
err = enc.Encode(tokenAuthentication)
|
err = enc.Encode(tokenAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Failed to encode LFS json response", "Failed to encode LFS json response: %v", err)
|
return fail("Internal error", "Failed to encode LFS json response: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -346,13 +332,13 @@ func runServ(c *cli.Context) error {
|
|||||||
gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...)
|
gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...)
|
||||||
|
|
||||||
if err = gitcmd.Run(); err != nil {
|
if err = gitcmd.Run(); err != nil {
|
||||||
return fail(ctx, "Failed to execute git command", "Failed to execute git command: %v", err)
|
return fail("Internal error", "Failed to execute git command: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user key activity.
|
// Update user key activity.
|
||||||
if results.KeyID > 0 {
|
if results.KeyID > 0 {
|
||||||
if err = private.UpdatePublicKeyInRepo(ctx, results.KeyID, results.RepoID); err != nil {
|
if err = private.UpdatePublicKeyInRepo(ctx, results.KeyID, results.RepoID); err != nil {
|
||||||
return fail(ctx, "Failed to update public key", "UpdatePublicKeyInRepo: %v", err)
|
return fail("Internal error", "UpdatePublicKeyInRepo: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
219
cmd/web.go
219
cmd/web.go
@@ -9,8 +9,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
||||||
@@ -24,18 +22,15 @@ import (
|
|||||||
|
|
||||||
"github.com/felixge/fgprof"
|
"github.com/felixge/fgprof"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
ini "gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PIDFile could be set from build tag
|
|
||||||
var PIDFile = "/run/gitea.pid"
|
|
||||||
|
|
||||||
// CmdWeb represents the available web sub-command.
|
// CmdWeb represents the available web sub-command.
|
||||||
var CmdWeb = cli.Command{
|
var CmdWeb = cli.Command{
|
||||||
Name: "web",
|
Name: "web",
|
||||||
Usage: "Start Gitea web server",
|
Usage: "Start Gitea web server",
|
||||||
Description: `Gitea web server is the only thing you need to run,
|
Description: `Gitea web server is the only thing you need to run,
|
||||||
and it takes care of all the other things for you`,
|
and it takes care of all the other things for you`,
|
||||||
Before: PrepareConsoleLoggerLevel(log.INFO),
|
|
||||||
Action: runWeb,
|
Action: runWeb,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
@@ -50,7 +45,7 @@ and it takes care of all the other things for you`,
|
|||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "pid, P",
|
Name: "pid, P",
|
||||||
Value: PIDFile,
|
Value: setting.PIDFile,
|
||||||
Usage: "Custom pid file path",
|
Usage: "Custom pid file path",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
@@ -86,127 +81,14 @@ func runHTTPRedirector() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPIDFile(pidPath string) {
|
|
||||||
currentPid := os.Getpid()
|
|
||||||
if err := os.MkdirAll(filepath.Dir(pidPath), os.ModePerm); err != nil {
|
|
||||||
log.Fatal("Failed to create PID folder: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Create(pidPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to create PID file: %v", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
if _, err := file.WriteString(strconv.FormatInt(int64(currentPid), 10)); err != nil {
|
|
||||||
log.Fatal("Failed to write PID information: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveInstall(ctx *cli.Context) error {
|
|
||||||
log.Info("Gitea version: %s%s", setting.AppVer, setting.AppBuiltWith)
|
|
||||||
log.Info("App path: %s", setting.AppPath)
|
|
||||||
log.Info("Work path: %s", setting.AppWorkPath)
|
|
||||||
log.Info("Custom path: %s", setting.CustomPath)
|
|
||||||
log.Info("Config file: %s", setting.CustomConf)
|
|
||||||
log.Info("Prepare to run install page")
|
|
||||||
|
|
||||||
routers.InitWebInstallPage(graceful.GetManager().HammerContext())
|
|
||||||
|
|
||||||
// Flag for port number in case first time run conflict
|
|
||||||
if ctx.IsSet("port") {
|
|
||||||
if err := setPort(ctx.String("port")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ctx.IsSet("install-port") {
|
|
||||||
if err := setPort(ctx.String("install-port")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c := install.Routes()
|
|
||||||
err := listen(c, false)
|
|
||||||
if err != nil {
|
|
||||||
log.Critical("Unable to open listener for installer. Is Gitea already running?")
|
|
||||||
graceful.GetManager().DoGracefulShutdown()
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-graceful.GetManager().IsShutdown():
|
|
||||||
<-graceful.GetManager().Done()
|
|
||||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
|
||||||
log.GetManager().Close()
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveInstalled(ctx *cli.Context) error {
|
|
||||||
setting.InitCfgProvider(setting.CustomConf)
|
|
||||||
setting.LoadCommonSettings()
|
|
||||||
setting.MustInstalled()
|
|
||||||
|
|
||||||
log.Info("Gitea version: %s%s", setting.AppVer, setting.AppBuiltWith)
|
|
||||||
log.Info("App path: %s", setting.AppPath)
|
|
||||||
log.Info("Work path: %s", setting.AppWorkPath)
|
|
||||||
log.Info("Custom path: %s", setting.CustomPath)
|
|
||||||
log.Info("Config file: %s", setting.CustomConf)
|
|
||||||
log.Info("Run mode: %s", setting.RunMode)
|
|
||||||
log.Info("Prepare to run web server")
|
|
||||||
|
|
||||||
if setting.AppWorkPathMismatch {
|
|
||||||
log.Error("WORK_PATH from config %q doesn't match other paths from environment variables or command arguments. "+
|
|
||||||
"Only WORK_PATH in config should be set and used. Please remove the other outdated work paths from environment variables and command arguments", setting.CustomConf)
|
|
||||||
}
|
|
||||||
|
|
||||||
rootCfg := setting.CfgProvider
|
|
||||||
if rootCfg.Section("").Key("WORK_PATH").String() == "" {
|
|
||||||
saveCfg, err := rootCfg.PrepareSaving()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Unable to prepare saving WORK_PATH=%s to config %q: %v\nYou must set it manually, otherwise there might be bugs when accessing the git repositories.", setting.AppWorkPath, setting.CustomConf, err)
|
|
||||||
} else {
|
|
||||||
rootCfg.Section("").Key("WORK_PATH").SetValue(setting.AppWorkPath)
|
|
||||||
saveCfg.Section("").Key("WORK_PATH").SetValue(setting.AppWorkPath)
|
|
||||||
if err = saveCfg.Save(); err != nil {
|
|
||||||
log.Error("Unable to update WORK_PATH=%s to config %q: %v\nYou must set it manually, otherwise there might be bugs when accessing the git repositories.", setting.AppWorkPath, setting.CustomConf, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
routers.InitWebInstalled(graceful.GetManager().HammerContext())
|
|
||||||
|
|
||||||
// We check that AppDataPath exists here (it should have been created during installation)
|
|
||||||
// We can't check it in `InitWebInstalled`, because some integration tests
|
|
||||||
// use cmd -> InitWebInstalled, but the AppDataPath doesn't exist during those tests.
|
|
||||||
if _, err := os.Stat(setting.AppDataPath); err != nil {
|
|
||||||
log.Fatal("Can not find APP_DATA_PATH %q", setting.AppDataPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override the provided port number within the configuration
|
|
||||||
if ctx.IsSet("port") {
|
|
||||||
if err := setPort(ctx.String("port")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up Chi routes
|
|
||||||
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
|
|
||||||
err := listen(c, true)
|
|
||||||
<-graceful.GetManager().Done()
|
|
||||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
|
||||||
log.GetManager().Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func servePprof() {
|
|
||||||
http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
|
|
||||||
_, _, finished := process.GetManager().AddTypedContext(context.Background(), "Web: PProf Server", process.SystemProcessType, true)
|
|
||||||
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment it's not worth to introduce a configurable option for it.
|
|
||||||
log.Info("Starting pprof server on localhost:6060")
|
|
||||||
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil))
|
|
||||||
finished()
|
|
||||||
}
|
|
||||||
|
|
||||||
func runWeb(ctx *cli.Context) error {
|
func runWeb(ctx *cli.Context) error {
|
||||||
|
if ctx.Bool("verbose") {
|
||||||
|
_ = log.DelLogger("console")
|
||||||
|
log.NewLogger(0, "console", "console", fmt.Sprintf(`{"level": "trace", "colorize": %t, "stacktraceLevel": "none"}`, log.CanColorStdout))
|
||||||
|
} else if ctx.Bool("quiet") {
|
||||||
|
_ = log.DelLogger("console")
|
||||||
|
log.NewLogger(0, "console", "console", fmt.Sprintf(`{"level": "fatal", "colorize": %t, "stacktraceLevel": "none"}`, log.CanColorStdout))
|
||||||
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if panicked := recover(); panicked != nil {
|
if panicked := recover(); panicked != nil {
|
||||||
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
||||||
@@ -225,22 +107,82 @@ func runWeb(ctx *cli.Context) error {
|
|||||||
|
|
||||||
// Set pid file setting
|
// Set pid file setting
|
||||||
if ctx.IsSet("pid") {
|
if ctx.IsSet("pid") {
|
||||||
createPIDFile(ctx.String("pid"))
|
setting.PIDFile = ctx.String("pid")
|
||||||
|
setting.WritePIDFile = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !setting.InstallLock {
|
// Perform pre-initialization
|
||||||
if err := serveInstall(ctx); err != nil {
|
needsInstall := install.PreloadSettings(graceful.GetManager().HammerContext())
|
||||||
|
if needsInstall {
|
||||||
|
// Flag for port number in case first time run conflict
|
||||||
|
if ctx.IsSet("port") {
|
||||||
|
if err := setPort(ctx.String("port")); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ctx.IsSet("install-port") {
|
||||||
|
if err := setPort(ctx.String("install-port")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
installCtx, cancel := context.WithCancel(graceful.GetManager().HammerContext())
|
||||||
|
c := install.Routes(installCtx)
|
||||||
|
err := listen(c, false)
|
||||||
|
cancel()
|
||||||
|
if err != nil {
|
||||||
|
log.Critical("Unable to open listener for installer. Is Gitea already running?")
|
||||||
|
graceful.GetManager().DoGracefulShutdown()
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-graceful.GetManager().IsShutdown():
|
||||||
|
<-graceful.GetManager().Done()
|
||||||
|
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||||
|
log.Close()
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
NoInstallListener()
|
NoInstallListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.EnablePprof {
|
if setting.EnablePprof {
|
||||||
go servePprof()
|
go func() {
|
||||||
|
http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
|
||||||
|
_, _, finished := process.GetManager().AddTypedContext(context.Background(), "Web: PProf Server", process.SystemProcessType, true)
|
||||||
|
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment it's not worth to introduce a configurable option for it.
|
||||||
|
log.Info("Starting pprof server on localhost:6060")
|
||||||
|
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil))
|
||||||
|
finished()
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
return serveInstalled(ctx)
|
log.Info("Global init")
|
||||||
|
// Perform global initialization
|
||||||
|
setting.InitProviderFromExistingFile()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
|
routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
|
||||||
|
|
||||||
|
// We check that AppDataPath exists here (it should have been created during installation)
|
||||||
|
// We can't check it in `GlobalInitInstalled`, because some integration tests
|
||||||
|
// use cmd -> GlobalInitInstalled, but the AppDataPath doesn't exist during those tests.
|
||||||
|
if _, err := os.Stat(setting.AppDataPath); err != nil {
|
||||||
|
log.Fatal("Can not find APP_DATA_PATH '%s'", setting.AppDataPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the provided port number within the configuration
|
||||||
|
if ctx.IsSet("port") {
|
||||||
|
if err := setPort(ctx.String("port")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up Chi routes
|
||||||
|
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
|
||||||
|
err := listen(c, true)
|
||||||
|
<-graceful.GetManager().Done()
|
||||||
|
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||||
|
log.Close()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func setPort(port string) error {
|
func setPort(port string) error {
|
||||||
@@ -261,16 +203,9 @@ func setPort(port string) error {
|
|||||||
defaultLocalURL += ":" + setting.HTTPPort + "/"
|
defaultLocalURL += ":" + setting.HTTPPort + "/"
|
||||||
|
|
||||||
// Save LOCAL_ROOT_URL if port changed
|
// Save LOCAL_ROOT_URL if port changed
|
||||||
rootCfg := setting.CfgProvider
|
setting.CreateOrAppendToCustomConf("server.LOCAL_ROOT_URL", func(cfg *ini.File) {
|
||||||
saveCfg, err := rootCfg.PrepareSaving()
|
cfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||||
if err != nil {
|
})
|
||||||
return fmt.Errorf("failed to save config file: %v", err)
|
|
||||||
}
|
|
||||||
rootCfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
|
||||||
saveCfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
|
||||||
if err = saveCfg.Save(); err != nil {
|
|
||||||
return fmt.Errorf("failed to save config file: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
2
contrib/autoboot.sh
Executable file
2
contrib/autoboot.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
su git -c "/home/git/gogs/scripts/gogs_supervisord.sh restart"
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//nolint:forbidigo
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -17,7 +16,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/google/go-github/v52/github"
|
"github.com/google/go-github/v45/github"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,13 +5,21 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"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() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "environment-to-ini"
|
app.Name = "environment-to-ini"
|
||||||
@@ -24,10 +32,6 @@ func main() {
|
|||||||
will be mapped to the ini section "[section_name]" and the key
|
will be mapped to the ini section "[section_name]" and the key
|
||||||
"KEY_NAME" with the value as provided.
|
"KEY_NAME" with the value as provided.
|
||||||
|
|
||||||
Environment variables of the form "GITEA__SECTION_NAME__KEY_NAME__FILE"
|
|
||||||
will be mapped to the ini section "[section_name]" and the key
|
|
||||||
"KEY_NAME" with the value loaded from the specified file.
|
|
||||||
|
|
||||||
Environment variables are usually restricted to a reduced character
|
Environment variables are usually restricted to a reduced character
|
||||||
set "0-9A-Z_" - in order to allow the setting of sections with
|
set "0-9A-Z_" - in order to allow the setting of sections with
|
||||||
characters outside of that set, they should be escaped as following:
|
characters outside of that set, they should be escaped as following:
|
||||||
@@ -66,8 +70,19 @@ func main() {
|
|||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Destination file to write to",
|
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
|
app.Action = runEnvironmentToIni
|
||||||
|
setting.SetCustomPathAndConf("", "", "")
|
||||||
|
|
||||||
err := app.Run(os.Args)
|
err := app.Run(os.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
||||||
@@ -75,22 +90,66 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runEnvironmentToIni(c *cli.Context) error {
|
func runEnvironmentToIni(c *cli.Context) error {
|
||||||
// the config system may change the environment variables, so get a copy first, to be used later
|
providedCustom := c.String("custom-path")
|
||||||
env := append([]string{}, os.Environ()...)
|
providedConf := c.String("config")
|
||||||
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
providedWorkPath := c.String("work-path")
|
||||||
WorkPath: c.String("work-path"),
|
setting.SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath)
|
||||||
CustomPath: c.String("custom-path"),
|
|
||||||
CustomConf: c.String("config"),
|
|
||||||
})
|
|
||||||
|
|
||||||
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
cfg := ini.Empty()
|
||||||
|
isFile, err := util.IsFile(setting.CustomConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Unable to check if %s is a file. Error: %v", setting.CustomConf, err)
|
||||||
|
}
|
||||||
|
if isFile {
|
||||||
|
if err := cfg.Append(setting.CustomConf); err != nil {
|
||||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
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
|
||||||
|
|
||||||
changed := setting.EnvironmentToConfig(cfg, env)
|
changed := false
|
||||||
|
|
||||||
// try to save the config file
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldValue := key.Value()
|
||||||
|
if !changed && oldValue != value {
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
key.SetValue(value)
|
||||||
|
}
|
||||||
destination := c.String("out")
|
destination := c.String("out")
|
||||||
if len(destination) == 0 {
|
if len(destination) == 0 {
|
||||||
destination = setting.CustomConf
|
destination = setting.CustomConf
|
||||||
@@ -102,6 +161,76 @@ func runEnvironmentToIni(c *cli.Context) error {
|
|||||||
return err
|
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
|
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]
|
||||||
|
key += remaining[splitter+2:]
|
||||||
|
} else {
|
||||||
|
section += remaining
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
key += remaining
|
||||||
|
}
|
||||||
|
section = strings.ToLower(section)
|
||||||
|
return section, key
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//nolint:forbidigo
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
### BEGIN INIT INFO
|
|
||||||
# Provides: gitea
|
|
||||||
# Required-Start: $syslog $network
|
|
||||||
# Required-Stop: $syslog
|
|
||||||
# Default-Start: 2 3 4 5
|
|
||||||
# Default-Stop: 0 1 6
|
|
||||||
# Short-Description: A self-hosted Git service written in Go.
|
|
||||||
# Description: A self-hosted Git service written in Go.
|
|
||||||
### END INIT INFO
|
|
||||||
|
|
||||||
# Do NOT "set -e"
|
|
||||||
|
|
||||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
|
||||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
|
|
||||||
DESC="Gitea - Git with a cup of tea"
|
|
||||||
NAME=gitea
|
|
||||||
SERVICEVERBOSE=yes
|
|
||||||
PIDFILE=/run/$NAME.pid
|
|
||||||
SCRIPTNAME=/etc/init.d/$NAME
|
|
||||||
WORKINGDIR=/var/lib/$NAME
|
|
||||||
DAEMON=/usr/local/bin/$NAME
|
|
||||||
DAEMON_ARGS="web -c /etc/$NAME/app.ini"
|
|
||||||
USER=git
|
|
||||||
STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/1/KILL/5}"
|
|
||||||
|
|
||||||
# Read configuration variable file if it is present
|
|
||||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
|
||||||
|
|
||||||
# Exit if the package is not installed
|
|
||||||
[ -x "$DAEMON" ] || exit 0
|
|
||||||
|
|
||||||
do_start()
|
|
||||||
{
|
|
||||||
GITEA_ENVS="USER=$USER GITEA_WORK_DIR=$WORKINGDIR HOME=/home/$USER"
|
|
||||||
GITEA_EXEC="$DAEMON -- $DAEMON_ARGS"
|
|
||||||
sh -c "start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \\
|
|
||||||
--background --chdir $WORKINGDIR --chuid $USER \\
|
|
||||||
--exec /bin/bash -- -c '/usr/bin/env $GITEA_ENVS $GITEA_EXEC'"
|
|
||||||
}
|
|
||||||
|
|
||||||
do_stop()
|
|
||||||
{
|
|
||||||
start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PIDFILE --name $NAME --oknodo
|
|
||||||
rm -f $PIDFILE
|
|
||||||
}
|
|
||||||
|
|
||||||
do_status()
|
|
||||||
{
|
|
||||||
if [ -f $PIDFILE ]; then
|
|
||||||
if kill -0 $(cat "$PIDFILE"); then
|
|
||||||
echo "$NAME is running, PID is $(cat $PIDFILE)"
|
|
||||||
else
|
|
||||||
echo "$NAME process is dead, but pidfile exists"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "$NAME is not running"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
echo "Starting $DESC" "$NAME"
|
|
||||||
do_start
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
echo "Stopping $DESC" "$NAME"
|
|
||||||
do_stop
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
do_status
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
echo "Restarting $DESC" "$NAME"
|
|
||||||
do_stop
|
|
||||||
do_start
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
|
|
||||||
exit 2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
2
contrib/mysql.sql
Normal file
2
contrib/mysql.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
DROP DATABASE IF EXISTS gitea;
|
||||||
|
CREATE DATABASE IF NOT EXISTS gitea CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||||
267
contrib/pr/checkout.go
Normal file
267
contrib/pr/checkout.go
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checkout a PR and load the tests data into sqlite database
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
gitea_git "code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
|
"code.gitea.io/gitea/modules/markup"
|
||||||
|
"code.gitea.io/gitea/modules/markup/external"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
"code.gitea.io/gitea/routers"
|
||||||
|
markup_service "code.gitea.io/gitea/services/markup"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/go-git/go-git/v5/config"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"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.InitProviderAllowEmpty()
|
||||||
|
setting.LoadCommonSettings()
|
||||||
|
|
||||||
|
setting.RepoRootPath, err = os.MkdirTemp(os.TempDir(), "repos")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("TempDir: %v\n", err)
|
||||||
|
}
|
||||||
|
setting.AppDataPath, err = os.MkdirTemp(os.TempDir(), "appdata")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("TempDir: %v\n", err)
|
||||||
|
}
|
||||||
|
setting.AppWorkPath = curDir
|
||||||
|
setting.StaticRootPath = curDir
|
||||||
|
setting.GravatarSource = "https://secure.gravatar.com/avatar/"
|
||||||
|
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")
|
||||||
|
//models.LoadConfigs()
|
||||||
|
/*
|
||||||
|
setting.Database.Type = "sqlite3"
|
||||||
|
setting.Database.Path = ":memory:"
|
||||||
|
setting.Database.Timeout = 500
|
||||||
|
*/
|
||||||
|
dbCfg := setting.CfgProvider.Section("database")
|
||||||
|
dbCfg.NewKey("DB_TYPE", "sqlite3")
|
||||||
|
dbCfg.NewKey("PATH", ":memory:")
|
||||||
|
|
||||||
|
routers.InitGitServices()
|
||||||
|
setting.Database.LogSQL = true
|
||||||
|
// x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
||||||
|
|
||||||
|
db.InitEngineWithMigration(context.Background(), func(_ *xorm.Engine) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
db.HasEngine = true
|
||||||
|
// x.ShowSQL(true)
|
||||||
|
err = unittest.InitFixtures(
|
||||||
|
unittest.FixturesOptions{
|
||||||
|
Dir: path.Join(curDir, "models/fixtures/"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error initializing test database: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
unittest.LoadFixtures()
|
||||||
|
util.RemoveAll(setting.RepoRootPath)
|
||||||
|
util.RemoveAll(repo_module.LocalCopyPath())
|
||||||
|
unittest.CopyDir(path.Join(curDir, "tests/gitea-repositories-meta"), setting.RepoRootPath)
|
||||||
|
|
||||||
|
log.Printf("[PR] Setting up router\n")
|
||||||
|
// routers.GlobalInit()
|
||||||
|
external.RegisterRenderers()
|
||||||
|
markup.Init(markup_service.ProcessorHelper())
|
||||||
|
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
|
||||||
|
|
||||||
|
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", c)
|
||||||
|
|
||||||
|
log.Printf("[PR] Cleaning up ...\n")
|
||||||
|
/*
|
||||||
|
if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
||||||
|
fmt.Printf("util.RemoveAll: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = util.RemoveAll(setting.Indexer.RepoPath); err != nil {
|
||||||
|
fmt.Printf("Unable to remove repo indexer: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if err = util.RemoveAll(setting.RepoRootPath); err != nil {
|
||||||
|
log.Fatalf("util.RemoveAll: %v\n", err)
|
||||||
|
}
|
||||||
|
if err = util.RemoveAll(setting.AppDataPath); err != nil {
|
||||||
|
log.Fatalf("util.RemoveAll: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
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 := os.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.git" ||
|
||||||
|
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("%s%s/head:%s", gitea_git.PullPrefix, 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), 0o755)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
|
||||||
|
}
|
||||||
|
err = os.WriteFile(codeFilePath, dat, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Force build of js, css, bin, ...
|
||||||
|
runCmd("make", "build")
|
||||||
|
// Start with integration test
|
||||||
|
runCmd("go", "run", "-mod", "vendor", "-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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ After=network.target
|
|||||||
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
|
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
|
||||||
# LimitNOFILE=524288:524288
|
# LimitNOFILE=524288:524288
|
||||||
RestartSec=2s
|
RestartSec=2s
|
||||||
Type=notify
|
Type=simple
|
||||||
User=git
|
User=git
|
||||||
Group=git
|
Group=git
|
||||||
WorkingDirectory=/var/lib/gitea/
|
WorkingDirectory=/var/lib/gitea/
|
||||||
@@ -62,7 +62,6 @@ WorkingDirectory=/var/lib/gitea/
|
|||||||
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
|
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
|
||||||
Restart=always
|
Restart=always
|
||||||
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
|
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
|
||||||
WatchdogSec=30s
|
|
||||||
# If you install Git to directory prefix other than default PATH (which happens
|
# If you install Git to directory prefix other than default PATH (which happens
|
||||||
# for example if you install other versions of Git side-to-side with
|
# for example if you install other versions of Git side-to-side with
|
||||||
# distribution version), uncomment below line and add that prefix to PATH
|
# distribution version), uncomment below line and add that prefix to PATH
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# This is an update script for gitea installed via the binary distribution
|
# This is an update script for gitea installed via the binary distribution
|
||||||
# from dl.gitea.com on linux as systemd service. It performs a backup and updates
|
# from dl.gitea.io on linux as systemd service. It performs a backup and updates
|
||||||
# Gitea in place.
|
# Gitea in place.
|
||||||
# NOTE: This adds the GPG Signing Key of the Gitea maintainers to the keyring.
|
# NOTE: This adds the GPG Signing Key of the Gitea maintainers to the keyring.
|
||||||
# Depends on: bash, curl, xz, sha256sum. optionally jq, gpg
|
# Depends on: bash, curl, xz, sha256sum. optionally jq, gpg
|
||||||
@@ -10,15 +10,6 @@
|
|||||||
# upgrade.sh 1.15.10
|
# upgrade.sh 1.15.10
|
||||||
# giteahome=/opt/gitea giteaconf=$giteahome/app.ini upgrade.sh
|
# giteahome=/opt/gitea giteaconf=$giteahome/app.ini upgrade.sh
|
||||||
|
|
||||||
# Check if gitea service is running
|
|
||||||
if ! pidof gitea &> /dev/null; then
|
|
||||||
echo "Error: gitea is not running."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Continue with rest of the script if gitea is running
|
|
||||||
echo "Gitea is running. Continuing with rest of script..."
|
|
||||||
|
|
||||||
# apply variables from environment
|
# apply variables from environment
|
||||||
: "${giteabin:="/usr/local/bin/gitea"}"
|
: "${giteabin:="/usr/local/bin/gitea"}"
|
||||||
: "${giteahome:="/var/lib/gitea"}"
|
: "${giteahome:="/var/lib/gitea"}"
|
||||||
@@ -78,7 +69,7 @@ require curl xz sha256sum "$sudocmd"
|
|||||||
# select version to install
|
# select version to install
|
||||||
if [[ -z "${giteaversion:-}" ]]; then
|
if [[ -z "${giteaversion:-}" ]]; then
|
||||||
require jq
|
require jq
|
||||||
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.com/gitea/version.json | jq -r .latest.version)
|
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.io/gitea/version.json | jq -r .latest.version)
|
||||||
echo "Latest available version is $giteaversion"
|
echo "Latest available version is $giteaversion"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -100,7 +91,7 @@ cd "$giteahome" # needed for gitea dump later
|
|||||||
|
|
||||||
# download new binary
|
# download new binary
|
||||||
binname="gitea-${giteaversion}-${arch}"
|
binname="gitea-${giteaversion}-${arch}"
|
||||||
binurl="https://dl.gitea.com/gitea/${giteaversion}/${binname}.xz"
|
binurl="https://dl.gitea.io/gitea/${giteaversion}/${binname}.xz"
|
||||||
echo "Downloading $binurl..."
|
echo "Downloading $binurl..."
|
||||||
curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.sha256,.asc}"
|
curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.sha256,.asc}"
|
||||||
|
|
||||||
|
|||||||
@@ -16,23 +16,26 @@
|
|||||||
;;
|
;;
|
||||||
;; - _`AppPath`_: This is the absolute path of the running gitea binary.
|
;; - _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||||
;; - _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
;; - _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||||
;; - The "WORK_PATH" option in "app.ini" file
|
|
||||||
;; - The `--work-path` flag passed to the binary
|
;; - The `--work-path` flag passed to the binary
|
||||||
;; - The environment variable `$GITEA_WORK_DIR`
|
;; - The environment variable `$GITEA_WORK_DIR`
|
||||||
;; - A built-in value set at build time (see building from source)
|
;; - A built-in value set at build time (see building from source)
|
||||||
;; - Otherwise it defaults to the directory of the _`AppPath`_
|
;; - Otherwise it defaults to the directory of the _`AppPath`_
|
||||||
;; - If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_
|
;; - If any of the above are relative paths then they are made absolute against the
|
||||||
;; - _`CustomPath`_: This is the base directory for custom templates and other options. It is determined by using the first set thing in the following hierarchy:
|
;; the directory of the _`AppPath`_
|
||||||
|
;; - _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||||
|
;; It is determined by using the first set thing in the following hierarchy:
|
||||||
;; - The `--custom-path` flag passed to the binary
|
;; - The `--custom-path` flag passed to the binary
|
||||||
;; - The environment variable `$GITEA_CUSTOM`
|
;; - The environment variable `$GITEA_CUSTOM`
|
||||||
;; - A built-in value set at build time (see building from source)
|
;; - A built-in value set at build time (see building from source)
|
||||||
;; - Otherwise it defaults to _`AppWorkPath`_`/custom`
|
;; - Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||||
;; - If any of the above are relative paths then they are made absolute against the directory of the _`AppWorkPath`_
|
;; - If any of the above are relative paths then they are made absolute against the
|
||||||
|
;; the directory of the _`AppWorkPath`_
|
||||||
;; - _`CustomConf`_: This is the path to the `app.ini` file.
|
;; - _`CustomConf`_: This is the path to the `app.ini` file.
|
||||||
;; - The `--config` flag passed to the binary
|
;; - The `--config` flag passed to the binary
|
||||||
;; - A built-in value set at build time (see building from source)
|
;; - A built-in value set at build time (see building from source)
|
||||||
;; - Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
;; - Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||||
;; - If any of the above are relative paths then they are made absolute against the directory of the _`CustomPath`_
|
;; - If any of the above are relative paths then they are made absolute against the
|
||||||
|
;; the directory of the _`CustomPath`_
|
||||||
;;
|
;;
|
||||||
;; In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
;; In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||||
|
|
||||||
@@ -46,12 +49,8 @@ APP_NAME = ; Gitea: Git with a cup of tea
|
|||||||
;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally
|
;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally
|
||||||
RUN_USER = ; git
|
RUN_USER = ; git
|
||||||
;;
|
;;
|
||||||
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
|
;; Application run mode, affects performance and debugging. Either "dev", "prod" or "test", default is "prod"
|
||||||
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
|
RUN_MODE = ; prod
|
||||||
;RUN_MODE = prod
|
|
||||||
;;
|
|
||||||
;; The working directory, see the comment of AppWorkPath above
|
|
||||||
;WORK_PATH =
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -187,8 +186,8 @@ RUN_USER = ; git
|
|||||||
;; default is the system temporary directory.
|
;; default is the system temporary directory.
|
||||||
;SSH_KEY_TEST_PATH =
|
;SSH_KEY_TEST_PATH =
|
||||||
;;
|
;;
|
||||||
;; Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
|
;; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
|
||||||
;SSH_KEYGEN_PATH =
|
;SSH_KEYGEN_PATH = ssh-keygen
|
||||||
;;
|
;;
|
||||||
;; Enable SSH Authorized Key Backup when rewriting all keys, default is true
|
;; Enable SSH Authorized Key Backup when rewriting all keys, default is true
|
||||||
;SSH_AUTHORIZED_KEYS_BACKUP = true
|
;SSH_AUTHORIZED_KEYS_BACKUP = true
|
||||||
@@ -231,6 +230,7 @@ RUN_USER = ; git
|
|||||||
;;
|
;;
|
||||||
;; Disable CDN even in "prod" mode
|
;; Disable CDN even in "prod" mode
|
||||||
;OFFLINE_MODE = false
|
;OFFLINE_MODE = false
|
||||||
|
;DISABLE_ROUTER_LOG = false
|
||||||
;;
|
;;
|
||||||
;; TLS Settings: Either ACME or manual
|
;; TLS Settings: Either ACME or manual
|
||||||
;; (Other common TLS configuration are found before)
|
;; (Other common TLS configuration are found before)
|
||||||
@@ -303,7 +303,7 @@ RUN_USER = ; git
|
|||||||
LFS_JWT_SECRET =
|
LFS_JWT_SECRET =
|
||||||
;;
|
;;
|
||||||
;; LFS authentication validity period (in time.Duration), pushes taking longer than this may fail.
|
;; LFS authentication validity period (in time.Duration), pushes taking longer than this may fail.
|
||||||
;LFS_HTTP_AUTH_EXPIRY = 24h
|
;LFS_HTTP_AUTH_EXPIRY = 20m
|
||||||
;;
|
;;
|
||||||
;; Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
;; Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
||||||
;LFS_MAX_FILE_SIZE = 0
|
;LFS_MAX_FILE_SIZE = 0
|
||||||
@@ -387,7 +387,7 @@ USER = root
|
|||||||
;ITERATE_BUFFER_SIZE = 50
|
;ITERATE_BUFFER_SIZE = 50
|
||||||
;;
|
;;
|
||||||
;; Show the database generated SQL
|
;; Show the database generated SQL
|
||||||
;LOG_SQL = false
|
LOG_SQL = false ; if unset defaults to true
|
||||||
;;
|
;;
|
||||||
;; Maximum number of DB Connect retries
|
;; Maximum number of DB Connect retries
|
||||||
;DB_RETRIES = 10
|
;DB_RETRIES = 10
|
||||||
@@ -550,67 +550,78 @@ ENABLE = true
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Main Logger
|
;; Main Logger
|
||||||
;;
|
;;
|
||||||
;; Either "console", "file" or "conn", default is "console"
|
;; Either "console", "file", "conn", "smtp" or "database", default is "console"
|
||||||
;; Use comma to separate multiple modes, e.g. "console, file"
|
;; Use comma to separate multiple modes, e.g. "console, file"
|
||||||
MODE = console
|
MODE = console
|
||||||
;;
|
;;
|
||||||
;; Either "Trace", "Debug", "Info", "Warn", "Error" or "None", default is "Info"
|
;; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical" or "None", default is "Info"
|
||||||
LEVEL = Info
|
LEVEL = Info
|
||||||
;;
|
;;
|
||||||
;; Print Stacktrace with logs (rarely helpful, do not set) Either "Trace", "Debug", "Info", "Warn", "Error", default is "None"
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;STACKTRACE_LEVEL = None
|
;; Router Logger
|
||||||
;;
|
;;
|
||||||
;; Buffer length of the channel, keep it as it is if you don't know what it is.
|
;; Switch off the router log
|
||||||
;BUFFER_LEN = 10000
|
;DISABLE_ROUTER_LOG=false
|
||||||
;;
|
;;
|
||||||
;; Sub logger modes, a single comma means use default MODE above, empty means disable it
|
;; Set the log "modes" for the router log (if file is set the log file will default to router.log)
|
||||||
;logger.access.MODE=
|
ROUTER = console
|
||||||
;logger.router.MODE=,
|
|
||||||
;logger.xorm.MODE=,
|
|
||||||
;;
|
;;
|
||||||
;; Collect SSH logs (Creates log from ssh git request)
|
;; The router will log different things at different levels.
|
||||||
;;
|
;;
|
||||||
;ENABLE_SSH_LOG = false
|
;; * started messages will be logged at TRACE level
|
||||||
|
;; * polling/completed routers will be logged at INFO
|
||||||
|
;; * slow routers will be logged at WARN
|
||||||
|
;; * failed routers will be logged at WARN
|
||||||
;;
|
;;
|
||||||
|
;; The routing level will default to that of the system but individual router level can be set in
|
||||||
|
;; [log.<mode>.router] LEVEL
|
||||||
|
;;
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Access Logger (Creates log in NCSA common log format)
|
;; Access Logger (Creates log in NCSA common log format)
|
||||||
;;
|
;;
|
||||||
;; Print request id which parsed from request headers in access log, when access log is enabled.
|
;ENABLE_ACCESS_LOG = false
|
||||||
;; * E.g:
|
|
||||||
;; * In request Header: X-Request-ID: test-id-123
|
|
||||||
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
|
|
||||||
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "test-id-123"
|
|
||||||
;;
|
;;
|
||||||
;; If you configure more than one in the .ini file, it will match in the order of configuration,
|
;; Set the log "modes" for the access log (if file is set the log file will default to access.log)
|
||||||
;; and the first match will be finally printed in the log.
|
;ACCESS = file
|
||||||
;; * E.g:
|
|
||||||
;; * In request Header: X-Trace-ID: trace-id-1q2w3e4r
|
|
||||||
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID, X-Trace-ID, X-Req-ID
|
|
||||||
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "trace-id-1q2w3e4r"
|
|
||||||
;;
|
|
||||||
;REQUEST_ID_HEADERS =
|
|
||||||
;;
|
;;
|
||||||
;; Sets the template used to create the access log.
|
;; Sets the template used to create the access log.
|
||||||
;ACCESS_LOG_TEMPLATE = {{.Ctx.RemoteHost}} - {{.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}}"
|
;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}}"
|
||||||
|
;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Log modes (aka log writers)
|
;; SSH log (Creates log from ssh git request)
|
||||||
;;
|
;;
|
||||||
;[log.%(WriterMode)]
|
;ENABLE_SSH_LOG = false
|
||||||
;MODE=console/file/conn/...
|
;;
|
||||||
|
;; Other Settings
|
||||||
|
;;
|
||||||
|
;; Print Stacktraces with logs. (Rarely helpful.) Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "None"
|
||||||
|
;STACKTRACE_LEVEL = None
|
||||||
|
;;
|
||||||
|
;; Buffer length of the channel, keep it as it is if you don't know what it is.
|
||||||
|
;BUFFER_LEN = 10000
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Creating specific log configuration
|
||||||
|
;;
|
||||||
|
;; You can set specific configuration for individual modes and subloggers
|
||||||
|
;;
|
||||||
|
;; Configuration available to all log modes/subloggers
|
||||||
;LEVEL=
|
;LEVEL=
|
||||||
;FLAGS = stdflags
|
;FLAGS = stdflags
|
||||||
;EXPRESSION =
|
;EXPRESSION =
|
||||||
;PREFIX =
|
;PREFIX =
|
||||||
;COLORIZE = false
|
;COLORIZE = false
|
||||||
;;
|
;;
|
||||||
;[log.console]
|
;; For "console" mode only
|
||||||
;STDERR = false
|
;STDERR = false
|
||||||
;;
|
;;
|
||||||
;[log.file]
|
;; For "file" mode only
|
||||||
;; Set the file_name for the logger. If this is a relative path this will be relative to ROOT_PATH
|
;LEVEL =
|
||||||
|
;; Set the file_name for the logger. If this is a relative path this
|
||||||
|
;; will be relative to ROOT_PATH
|
||||||
;FILE_NAME =
|
;FILE_NAME =
|
||||||
;; This enables automated log rotate(switch of following options), default is true
|
;; This enables automated log rotate(switch of following options), default is true
|
||||||
;LOG_ROTATE = true
|
;LOG_ROTATE = true
|
||||||
@@ -624,8 +635,9 @@ LEVEL = Info
|
|||||||
;COMPRESS = true
|
;COMPRESS = true
|
||||||
;; compression level see godoc for compress/gzip
|
;; compression level see godoc for compress/gzip
|
||||||
;COMPRESSION_LEVEL = -1
|
;COMPRESSION_LEVEL = -1
|
||||||
;;
|
;
|
||||||
;[log.conn]
|
;; For "conn" mode only
|
||||||
|
;LEVEL =
|
||||||
;; Reconnect host for every single message, default is false
|
;; Reconnect host for every single message, default is false
|
||||||
;RECONNECT_ON_MSG = false
|
;RECONNECT_ON_MSG = false
|
||||||
;; Try to reconnect when connection is lost, default is false
|
;; Try to reconnect when connection is lost, default is false
|
||||||
@@ -634,6 +646,19 @@ LEVEL = Info
|
|||||||
;PROTOCOL = tcp
|
;PROTOCOL = tcp
|
||||||
;; Host address
|
;; Host address
|
||||||
;ADDR =
|
;ADDR =
|
||||||
|
;
|
||||||
|
;; For "smtp" mode only
|
||||||
|
;LEVEL =
|
||||||
|
;; Name displayed in mail title, default is "Diagnostic message from server"
|
||||||
|
;SUBJECT = Diagnostic message from server
|
||||||
|
;; Mail server
|
||||||
|
;HOST =
|
||||||
|
;; Mailer user name and password
|
||||||
|
;USER =
|
||||||
|
;; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||||
|
;PASSWD =
|
||||||
|
;; Receivers, can be one or more, e.g. 1@example.com,2@example.com
|
||||||
|
;RECEIVERS =
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -683,24 +708,6 @@ LEVEL = Info
|
|||||||
;; Disable the usage of using partial clones for git.
|
;; Disable the usage of using partial clones for git.
|
||||||
;DISABLE_PARTIAL_CLONE = false
|
;DISABLE_PARTIAL_CLONE = false
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Git Operation timeout in seconds
|
|
||||||
;[git.timeout]
|
|
||||||
;DEFAULT = 360
|
|
||||||
;MIGRATE = 600
|
|
||||||
;MIRROR = 300
|
|
||||||
;CLONE = 300
|
|
||||||
;PULL = 300
|
|
||||||
;GC = 60
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Git config options
|
|
||||||
;; This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
|
|
||||||
;[git.config]
|
|
||||||
;diff.algorithm = histogram
|
|
||||||
;core.logAllRefUpdates = true
|
|
||||||
;gc.reflogExpire = 90
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
[service]
|
[service]
|
||||||
@@ -719,11 +726,11 @@ LEVEL = Info
|
|||||||
;; Whether a new user needs to be confirmed manually after registration. (Requires `REGISTER_EMAIL_CONFIRM` to be disabled.)
|
;; Whether a new user needs to be confirmed manually after registration. (Requires `REGISTER_EMAIL_CONFIRM` to be disabled.)
|
||||||
;REGISTER_MANUAL_CONFIRM = false
|
;REGISTER_MANUAL_CONFIRM = false
|
||||||
;;
|
;;
|
||||||
;; List of domain names that are allowed to be used to register on a Gitea instance, wildcard is supported
|
;; List of domain names that are allowed to be used to register on a Gitea instance
|
||||||
;; eg: gitea.io,example.com,*.mydomain.com
|
;; gitea.io,example.com
|
||||||
;EMAIL_DOMAIN_ALLOWLIST =
|
;EMAIL_DOMAIN_WHITELIST =
|
||||||
;;
|
;;
|
||||||
;; Comma-separated list of domain names that are not allowed to be used to register on a Gitea instance, wildcard is supported
|
;; Comma-separated list of domain names that are not allowed to be used to register on a Gitea instance
|
||||||
;EMAIL_DOMAIN_BLOCKLIST =
|
;EMAIL_DOMAIN_BLOCKLIST =
|
||||||
;;
|
;;
|
||||||
;; Disallow registration, only allow admins to create accounts.
|
;; Disallow registration, only allow admins to create accounts.
|
||||||
@@ -903,6 +910,12 @@ LEVEL = Info
|
|||||||
;; Global limit of repositories per user, applied at creation time. -1 means no limit
|
;; Global limit of repositories per user, applied at creation time. -1 means no limit
|
||||||
;MAX_CREATION_LIMIT = -1
|
;MAX_CREATION_LIMIT = -1
|
||||||
;;
|
;;
|
||||||
|
;; Mirror sync queue length, increase if mirror syncing starts hanging (DEPRECATED: please use [queue.mirror] LENGTH instead)
|
||||||
|
;MIRROR_QUEUE_LENGTH = 1000
|
||||||
|
;;
|
||||||
|
;; Patch test queue length, increase if pull request patch testing starts hanging (DEPRECATED: please use [queue.pr_patch_checker] LENGTH instead)
|
||||||
|
;PULL_REQUEST_QUEUE_LENGTH = 1000
|
||||||
|
;;
|
||||||
;; Preferred Licenses to place at the top of the List
|
;; Preferred Licenses to place at the top of the List
|
||||||
;; The name here must match the filename in options/license or custom/options/license
|
;; The name here must match the filename in options/license or custom/options/license
|
||||||
;PREFERRED_LICENSES = Apache License 2.0,MIT License
|
;PREFERRED_LICENSES = Apache License 2.0,MIT License
|
||||||
@@ -917,9 +930,6 @@ LEVEL = Info
|
|||||||
;; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
;; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
||||||
;USE_COMPAT_SSH_URI = false
|
;USE_COMPAT_SSH_URI = false
|
||||||
;;
|
;;
|
||||||
;; Value for the "go get" request returns the repository url as https or ssh, default is https
|
|
||||||
;GO_GET_CLONE_URL_PROTOCOL = https
|
|
||||||
;;
|
|
||||||
;; Close issues as long as a commit on any branch marks it as fixed
|
;; Close issues as long as a commit on any branch marks it as fixed
|
||||||
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions.
|
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions.
|
||||||
;DISABLED_REPO_UNITS =
|
;DISABLED_REPO_UNITS =
|
||||||
@@ -966,7 +976,11 @@ LEVEL = Info
|
|||||||
;;
|
;;
|
||||||
;; List of file extensions for which lines should be wrapped in the Monaco editor
|
;; List of file extensions for which lines should be wrapped in the Monaco editor
|
||||||
;; Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
;; Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||||
;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,.livemd,
|
;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
|
||||||
|
;;
|
||||||
|
;; Valid file modes that have a preview API associated with them, such as api/v1/markdown
|
||||||
|
;; Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match
|
||||||
|
;PREVIEWABLE_FILE_MODES = markdown
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -1044,9 +1058,6 @@ LEVEL = Info
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; List of reasons why a Pull Request or Issue can be locked
|
;; List of reasons why a Pull Request or Issue can be locked
|
||||||
;LOCK_REASONS = Too heated,Off-topic,Resolved,Spam
|
;LOCK_REASONS = Too heated,Off-topic,Resolved,Spam
|
||||||
;; Maximum number of pinned Issues per repo
|
|
||||||
;; Set to 0 to disable pinning Issues
|
|
||||||
;MAX_PINNED = 3
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -1180,6 +1191,11 @@ LEVEL = Info
|
|||||||
;; Number of line of codes shown for a code comment
|
;; Number of line of codes shown for a code comment
|
||||||
;CODE_COMMENT_LINES = 4
|
;CODE_COMMENT_LINES = 4
|
||||||
;;
|
;;
|
||||||
|
;; Value of `theme-color` meta tag, used by Android >= 5.0
|
||||||
|
;; An invalid color like "none" or "disable" will have the default style
|
||||||
|
;; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||||
|
;THEME_COLOR_META_TAG = `#6cc644`
|
||||||
|
;;
|
||||||
;; Max size of files to be displayed (default is 8MiB)
|
;; Max size of files to be displayed (default is 8MiB)
|
||||||
;MAX_DISPLAY_FILE_SIZE = 8388608
|
;MAX_DISPLAY_FILE_SIZE = 8388608
|
||||||
;;
|
;;
|
||||||
@@ -1208,6 +1224,9 @@ LEVEL = Info
|
|||||||
;; Whether to search within description at repository search on explore page.
|
;; Whether to search within description at repository search on explore page.
|
||||||
;SEARCH_REPO_DESCRIPTION = true
|
;SEARCH_REPO_DESCRIPTION = true
|
||||||
;;
|
;;
|
||||||
|
;; Whether to enable a Service Worker to cache frontend assets
|
||||||
|
;USE_SERVICE_WORKER = false
|
||||||
|
;;
|
||||||
;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
||||||
;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
||||||
;ONLY_SHOW_RELEVANT_REPOS = false
|
;ONLY_SHOW_RELEVANT_REPOS = false
|
||||||
@@ -1300,12 +1319,11 @@ LEVEL = Info
|
|||||||
;; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
|
;; 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)
|
;; 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.
|
;; URLs starting with http and https are always displayed, whatever is put in this entry.
|
||||||
;; If this entry is empty, all URL schemes are allowed.
|
|
||||||
;CUSTOM_URL_SCHEMES =
|
;CUSTOM_URL_SCHEMES =
|
||||||
;;
|
;;
|
||||||
;; List of file extensions that should be rendered/edited as Markdown
|
;; 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
|
;; Separate the extensions with a comma. To render files without any extension as markdown, just put a comma
|
||||||
;FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd,.livemd
|
;FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||||
;;
|
;;
|
||||||
;; Enables math inline and block detection
|
;; Enables math inline and block detection
|
||||||
;ENABLE_MATH = true
|
;ENABLE_MATH = true
|
||||||
@@ -1331,13 +1349,13 @@ LEVEL = Info
|
|||||||
;; Issue Indexer settings
|
;; Issue Indexer settings
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Issue indexer type, currently support: bleve, db, elasticsearch or meilisearch default is bleve
|
;; Issue indexer type, currently support: bleve, db or elasticsearch, default is bleve
|
||||||
;ISSUE_INDEXER_TYPE = bleve
|
;ISSUE_INDEXER_TYPE = bleve
|
||||||
;;
|
;;
|
||||||
;; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
|
;; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
|
||||||
;ISSUE_INDEXER_PATH = indexers/issues.bleve ; Relative paths will be made absolute against _`AppWorkPath`_.
|
;ISSUE_INDEXER_PATH = indexers/issues.bleve ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
;;
|
;;
|
||||||
;; Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch or meilisearch
|
;; Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||||
;ISSUE_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
|
;ISSUE_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
|
||||||
;;
|
;;
|
||||||
;; Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
;; Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||||
@@ -1347,6 +1365,22 @@ LEVEL = Info
|
|||||||
;; Set to -1 to disable timeout.
|
;; Set to -1 to disable timeout.
|
||||||
;STARTUP_TIMEOUT = 30s
|
;STARTUP_TIMEOUT = 30s
|
||||||
;;
|
;;
|
||||||
|
;; Issue indexer queue, currently support: channel, levelqueue or redis, default is levelqueue (deprecated - use [queue.issue_indexer])
|
||||||
|
;ISSUE_INDEXER_QUEUE_TYPE = levelqueue; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
;;
|
||||||
|
;; When ISSUE_INDEXER_QUEUE_TYPE is levelqueue, this will be the path where the queue will be saved.
|
||||||
|
;; This can be overridden by `ISSUE_INDEXER_QUEUE_CONN_STR`.
|
||||||
|
;; default is queues/common
|
||||||
|
;ISSUE_INDEXER_QUEUE_DIR = queues/common; **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
|
;;
|
||||||
|
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
|
||||||
|
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of
|
||||||
|
;; the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`.
|
||||||
|
;ISSUE_INDEXER_QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
;;
|
||||||
|
;; Batch queue number, default is 20
|
||||||
|
;ISSUE_INDEXER_QUEUE_BATCH_NUMBER = 20; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Repository Indexer settings
|
;; Repository Indexer settings
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -1354,10 +1388,6 @@ LEVEL = Info
|
|||||||
;; repo indexer by default disabled, since it uses a lot of disk space
|
;; repo indexer by default disabled, since it uses a lot of disk space
|
||||||
;REPO_INDEXER_ENABLED = false
|
;REPO_INDEXER_ENABLED = false
|
||||||
;;
|
;;
|
||||||
;; repo indexer units, the items to index, could be `sources`, `forks`, `mirrors`, `templates` or any combination of them separated by a comma.
|
|
||||||
;; If empty then it defaults to `sources` only, as if you'd like to disable fully please see REPO_INDEXER_ENABLED.
|
|
||||||
;REPO_INDEXER_REPO_TYPES = sources,forks,mirrors,templates
|
|
||||||
;;
|
|
||||||
;; Code search engine type, could be `bleve` or `elasticsearch`.
|
;; Code search engine type, could be `bleve` or `elasticsearch`.
|
||||||
;REPO_INDEXER_TYPE = bleve
|
;REPO_INDEXER_TYPE = bleve
|
||||||
;;
|
;;
|
||||||
@@ -1377,6 +1407,8 @@ LEVEL = Info
|
|||||||
;; A comma separated list of glob patterns to exclude from the index; ; default is empty
|
;; A comma separated list of glob patterns to exclude from the index; ; default is empty
|
||||||
;REPO_INDEXER_EXCLUDE =
|
;REPO_INDEXER_EXCLUDE =
|
||||||
;;
|
;;
|
||||||
|
;;
|
||||||
|
;UPDATE_BUFFER_LEN = 20; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
;MAX_FILE_SIZE = 1048576
|
;MAX_FILE_SIZE = 1048576
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -1398,15 +1430,15 @@ LEVEL = Info
|
|||||||
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
;;
|
;;
|
||||||
;; Default queue length before a channel queue will block
|
;; Default queue length before a channel queue will block
|
||||||
;LENGTH = 100
|
;LENGTH = 20
|
||||||
;;
|
;;
|
||||||
;; Batch size to send for batched queues
|
;; Batch size to send for batched queues
|
||||||
;BATCH_LENGTH = 20
|
;BATCH_LENGTH = 20
|
||||||
;;
|
;;
|
||||||
;; Connection string for redis queues this will store the redis or redis-cluster connection string.
|
;; Connection string for redis queues this will store the redis connection string.
|
||||||
;; When `TYPE` is `persistable-channel`, this provides a directory for the underlying leveldb
|
;; When `TYPE` is `persistable-channel`, this provides a directory for the underlying leveldb
|
||||||
;; or additional options of the form `leveldb://path/to/db?option=value&....`, and will override `DATADIR`.
|
;; or additional options of the form `leveldb://path/to/db?option=value&....`, and will override `DATADIR`.
|
||||||
;CONN_STR = "redis://127.0.0.1:6379/0"
|
;CONN_STR = "addrs=127.0.0.1:6379 db=0"
|
||||||
;;
|
;;
|
||||||
;; Provides the suffix of the default redis/disk queue name - specific queues can be overridden within in their [queue.name] sections.
|
;; Provides the suffix of the default redis/disk queue name - specific queues can be overridden within in their [queue.name] sections.
|
||||||
;QUEUE_NAME = "_queue"
|
;QUEUE_NAME = "_queue"
|
||||||
@@ -1414,8 +1446,29 @@ LEVEL = Info
|
|||||||
;; Provides the suffix of the default redis/disk unique queue set name - specific queues can be overridden within in their [queue.name] sections.
|
;; Provides the suffix of the default redis/disk unique queue set name - specific queues can be overridden within in their [queue.name] sections.
|
||||||
;SET_NAME = "_unique"
|
;SET_NAME = "_unique"
|
||||||
;;
|
;;
|
||||||
|
;; 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 = 0
|
||||||
|
;;
|
||||||
;; Dynamically scale the worker pool to at this many workers
|
;; Dynamically scale the worker pool to at this many workers
|
||||||
;MAX_WORKERS = 10
|
;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 = 1
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -1675,9 +1728,8 @@ LEVEL = Info
|
|||||||
;; For "memory" only, GC interval in seconds, default is 60
|
;; For "memory" only, GC interval in seconds, default is 60
|
||||||
;INTERVAL = 60
|
;INTERVAL = 60
|
||||||
;;
|
;;
|
||||||
;; For "redis", "redis-cluster" and "memcache", connection host address
|
;; For "redis" and "memcache", connection host address
|
||||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||||
;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
|
||||||
;; memcache: `127.0.0.1:11211`
|
;; memcache: `127.0.0.1:11211`
|
||||||
;; twoqueue: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000`
|
;; twoqueue: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000`
|
||||||
;HOST =
|
;HOST =
|
||||||
@@ -1709,7 +1761,7 @@ LEVEL = Info
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Either "memory", "file", "redis", "redis-cluster", "db", "mysql", "couchbase", "memcache" or "postgres"
|
;; Either "memory", "file", "redis", "db", "mysql", "couchbase", "memcache" or "postgres"
|
||||||
;; Default is "memory". "db" will reuse the configuration in [database]
|
;; Default is "memory". "db" will reuse the configuration in [database]
|
||||||
;PROVIDER = memory
|
;PROVIDER = memory
|
||||||
;;
|
;;
|
||||||
@@ -1717,7 +1769,6 @@ LEVEL = Info
|
|||||||
;; memory: doesn't have any config yet
|
;; memory: doesn't have any config yet
|
||||||
;; file: session file path, e.g. `data/sessions`
|
;; file: session file path, e.g. `data/sessions`
|
||||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||||
;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
|
||||||
;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||||
;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_.
|
;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
;;
|
;;
|
||||||
@@ -1753,19 +1804,16 @@ LEVEL = Info
|
|||||||
;; Max Width and Height of uploaded avatars.
|
;; Max Width and Height of uploaded avatars.
|
||||||
;; This is to limit the amount of RAM used when resizing the image.
|
;; This is to limit the amount of RAM used when resizing the image.
|
||||||
;AVATAR_MAX_WIDTH = 4096
|
;AVATAR_MAX_WIDTH = 4096
|
||||||
;AVATAR_MAX_HEIGHT = 4096
|
;AVATAR_MAX_HEIGHT = 3072
|
||||||
;;
|
;;
|
||||||
;; The multiplication factor for rendered avatar images.
|
;; The multiplication factor for rendered avatar images.
|
||||||
;; Larger values result in finer rendering on HiDPI devices.
|
;; Larger values result in finer rendering on HiDPI devices.
|
||||||
;AVATAR_RENDERED_SIZE_FACTOR = 2
|
;AVATAR_RENDERED_SIZE_FACTOR = 3
|
||||||
;;
|
;;
|
||||||
;; Maximum allowed file size for uploaded avatars.
|
;; Maximum allowed file size for uploaded avatars.
|
||||||
;; This is to limit the amount of RAM used when resizing the image.
|
;; This is to limit the amount of RAM used when resizing the image.
|
||||||
;AVATAR_MAX_FILE_SIZE = 1048576
|
;AVATAR_MAX_FILE_SIZE = 1048576
|
||||||
;;
|
;;
|
||||||
;; If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
|
|
||||||
;AVATAR_MAX_ORIGIN_SIZE = 262144
|
|
||||||
;;
|
|
||||||
;; Chinese users can choose "duoshuo"
|
;; Chinese users can choose "duoshuo"
|
||||||
;; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
;; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||||
;GRAVATAR_SOURCE = gravatar
|
;GRAVATAR_SOURCE = gravatar
|
||||||
@@ -1840,6 +1888,11 @@ LEVEL = Info
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
|
;; Specifies the format for fully outputted dates. Defaults to RFC1123
|
||||||
|
;; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
|
||||||
|
;; For more information about the format see http://golang.org/pkg/time/#pkg-constants
|
||||||
|
;FORMAT =
|
||||||
|
;;
|
||||||
;; Location the UI time display i.e. Asia/Shanghai
|
;; Location the UI time display i.e. Asia/Shanghai
|
||||||
;; Empty means server's location setting
|
;; Empty means server's location setting
|
||||||
;DEFAULT_UI_LOCATION =
|
;DEFAULT_UI_LOCATION =
|
||||||
@@ -2159,7 +2212,7 @@ LEVEL = Info
|
|||||||
;RUN_AT_START = false
|
;RUN_AT_START = false
|
||||||
;ENABLE_SUCCESS_NOTICE = false
|
;ENABLE_SUCCESS_NOTICE = false
|
||||||
;SCHEDULE = @every 168h
|
;SCHEDULE = @every 168h
|
||||||
;HTTP_ENDPOINT = https://dl.gitea.com/gitea/version.json
|
;HTTP_ENDPOINT = https://dl.gitea.io/gitea/version.json
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -2195,6 +2248,32 @@ LEVEL = Info
|
|||||||
;Check at least this proportion of LFSMetaObjects per repo. (This may cause all stale LFSMetaObjects to be checked.)
|
;Check at least this proportion of LFSMetaObjects per repo. (This may cause all stale LFSMetaObjects to be checked.)
|
||||||
;PROPORTION_TO_CHECK_PER_REPO = 0.6
|
;PROPORTION_TO_CHECK_PER_REPO = 0.6
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Git Operation timeout in seconds
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;[git.timeout]
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;DEFAULT = 360
|
||||||
|
;MIGRATE = 600
|
||||||
|
;MIRROR = 300
|
||||||
|
;CLONE = 300
|
||||||
|
;PULL = 300
|
||||||
|
;GC = 60
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Git Reflog timeout in days
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;[git.reflog]
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;ENABLED = true
|
||||||
|
;EXPIRATION = 90
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;[mirror]
|
;[mirror]
|
||||||
@@ -2249,6 +2328,7 @@ LEVEL = Info
|
|||||||
;[other]
|
;[other]
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;SHOW_FOOTER_BRANDING = false
|
||||||
;; Show version information about Gitea and Go in the footer
|
;; Show version information about Gitea and Go in the footer
|
||||||
;SHOW_FOOTER_VERSION = true
|
;SHOW_FOOTER_VERSION = true
|
||||||
;; Show template execution time in the footer
|
;; Show template execution time in the footer
|
||||||
@@ -2325,7 +2405,7 @@ LEVEL = Info
|
|||||||
;QUEUE_LENGTH = 1000
|
;QUEUE_LENGTH = 1000
|
||||||
;;
|
;;
|
||||||
;; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
|
;; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
|
||||||
;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for `redis-clsuter`.
|
;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`.
|
||||||
;QUEUE_CONN_STR = "redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s"
|
;QUEUE_CONN_STR = "redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s"
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -2392,10 +2472,6 @@ LEVEL = Info
|
|||||||
;; Enable/Disable package registry capabilities
|
;; Enable/Disable package registry capabilities
|
||||||
;ENABLED = true
|
;ENABLED = true
|
||||||
;;
|
;;
|
||||||
;STORAGE_TYPE = local
|
|
||||||
;; override the minio base path if storage type is minio
|
|
||||||
;MINIO_BASE_PATH = packages/
|
|
||||||
;;
|
|
||||||
;; Path for chunked uploads. Defaults to APP_DATA_PATH + `tmp/package-upload`
|
;; Path for chunked uploads. Defaults to APP_DATA_PATH + `tmp/package-upload`
|
||||||
;CHUNKED_UPLOAD_PATH = tmp/package-upload
|
;CHUNKED_UPLOAD_PATH = tmp/package-upload
|
||||||
;;
|
;;
|
||||||
@@ -2403,8 +2479,6 @@ LEVEL = Info
|
|||||||
;LIMIT_TOTAL_OWNER_COUNT = -1
|
;LIMIT_TOTAL_OWNER_COUNT = -1
|
||||||
;; Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_TOTAL_OWNER_SIZE = -1
|
;LIMIT_TOTAL_OWNER_SIZE = -1
|
||||||
;; Maximum size of an Alpine upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
;LIMIT_SIZE_ALPINE = -1
|
|
||||||
;; Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_CARGO = -1
|
;LIMIT_SIZE_CARGO = -1
|
||||||
;; Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
@@ -2417,14 +2491,8 @@ LEVEL = Info
|
|||||||
;LIMIT_SIZE_CONDA = -1
|
;LIMIT_SIZE_CONDA = -1
|
||||||
;; Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_CONTAINER = -1
|
;LIMIT_SIZE_CONTAINER = -1
|
||||||
;; Maximum size of a CRAN upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
;LIMIT_SIZE_CRAN = -1
|
|
||||||
;; Maximum size of a Debian upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
;LIMIT_SIZE_DEBIAN = -1
|
|
||||||
;; Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_GENERIC = -1
|
;LIMIT_SIZE_GENERIC = -1
|
||||||
;; Maximum size of a Go upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
;LIMIT_SIZE_GO = -1
|
|
||||||
;; Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_HELM = -1
|
;LIMIT_SIZE_HELM = -1
|
||||||
;; Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
@@ -2437,12 +2505,8 @@ LEVEL = Info
|
|||||||
;LIMIT_SIZE_PUB = -1
|
;LIMIT_SIZE_PUB = -1
|
||||||
;; Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_PYPI = -1
|
;LIMIT_SIZE_PYPI = -1
|
||||||
;; Maximum size of a RPM upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
;LIMIT_SIZE_RPM = -1
|
|
||||||
;; Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_RUBYGEMS = -1
|
;LIMIT_SIZE_RUBYGEMS = -1
|
||||||
;; Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
;LIMIT_SIZE_SWIFT = -1
|
|
||||||
;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_VAGRANT = -1
|
;LIMIT_SIZE_VAGRANT = -1
|
||||||
|
|
||||||
@@ -2456,19 +2520,6 @@ LEVEL = Info
|
|||||||
;; storage type
|
;; storage type
|
||||||
;STORAGE_TYPE = local
|
;STORAGE_TYPE = local
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; repo-archive storage will override storage
|
|
||||||
;;
|
|
||||||
;[repo-archive]
|
|
||||||
;STORAGE_TYPE = local
|
|
||||||
;;
|
|
||||||
;; Where your lfs files reside, default is data/lfs.
|
|
||||||
;PATH = data/repo-archive
|
|
||||||
;;
|
|
||||||
;; override the minio base path if storage type is minio
|
|
||||||
;MINIO_BASE_PATH = repo-archive/
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; settings for repository archives, will override storage setting
|
;; settings for repository archives, will override storage setting
|
||||||
@@ -2488,9 +2539,6 @@ LEVEL = Info
|
|||||||
;;
|
;;
|
||||||
;; Where your lfs files reside, default is data/lfs.
|
;; Where your lfs files reside, default is data/lfs.
|
||||||
;PATH = data/lfs
|
;PATH = data/lfs
|
||||||
;;
|
|
||||||
;; override the minio base path if storage type is minio
|
|
||||||
;MINIO_BASE_PATH = lfs/
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -2540,9 +2588,8 @@ LEVEL = Info
|
|||||||
; [actions]
|
; [actions]
|
||||||
;; Enable/Disable actions capabilities
|
;; Enable/Disable actions capabilities
|
||||||
;ENABLED = false
|
;ENABLED = false
|
||||||
;;
|
;; Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
|
||||||
;; Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
;DEFAULT_ACTIONS_URL = https://gitea.com
|
||||||
;DEFAULT_ACTIONS_URL = github
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-rootless
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-rootless
|
||||||
{{#if build.tags}}
|
{{#if build.tags}}
|
||||||
{{#unless (contains "-rc" build.tag)}}
|
{{#unless (contains "-rc" build.tag)}}
|
||||||
tags:
|
tags:
|
||||||
@@ -10,12 +10,12 @@ tags:
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
manifests:
|
manifests:
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-amd64-rootless
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64-rootless
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-arm64-rootless
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64-rootless
|
||||||
platform:
|
platform:
|
||||||
architecture: arm64
|
architecture: arm64
|
||||||
os: linux
|
os: linux
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}
|
||||||
{{#if build.tags}}
|
{{#if build.tags}}
|
||||||
{{#unless (contains "-rc" build.tag)}}
|
{{#unless (contains "-rc" build.tag)}}
|
||||||
tags:
|
tags:
|
||||||
@@ -10,12 +10,12 @@ tags:
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
manifests:
|
manifests:
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-amd64
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-arm64
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64
|
||||||
platform:
|
platform:
|
||||||
architecture: arm64
|
architecture: arm64
|
||||||
os: linux
|
os: linux
|
||||||
|
|||||||
@@ -2,15 +2,7 @@
|
|||||||
|
|
||||||
if [ ! -d /data/git/.ssh ]; then
|
if [ ! -d /data/git/.ssh ]; then
|
||||||
mkdir -p /data/git/.ssh
|
mkdir -p /data/git/.ssh
|
||||||
fi
|
|
||||||
|
|
||||||
# Set the correct permissions on the .ssh directory and authorized_keys file,
|
|
||||||
# or sshd will refuse to use them and lead to clone/push/pull failures.
|
|
||||||
# It could happen when users have copied their data to a new volume and changed the file permission by accident,
|
|
||||||
# and it would be very hard to troubleshoot unless users know how to check the logs of sshd which is started by s6.
|
|
||||||
chmod 700 /data/git/.ssh
|
chmod 700 /data/git/.ssh
|
||||||
if [ -f /data/git/.ssh/authorized_keys ]; then
|
|
||||||
chmod 600 /data/git/.ssh/authorized_keys
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f /data/git/.ssh/environment ]; then
|
if [ ! -f /data/git/.ssh/environment ]; then
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#
|
#
|
||||||
# And place the original in /usr/lib/gitea with working files in /data/gitea
|
# And place the original in /usr/lib/gitea with working files in /data/gitea
|
||||||
GITEA="/app/gitea/gitea"
|
GITEA="/app/gitea/gitea"
|
||||||
WORK_DIR="/data/gitea"
|
WORK_DIR="/app/gitea"
|
||||||
CUSTOM_PATH="/data/gitea"
|
CUSTOM_PATH="/data/gitea"
|
||||||
|
|
||||||
# Provide docker defaults
|
# Provide docker defaults
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ function doSearch() {
|
|||||||
} else {
|
} else {
|
||||||
const para = document.createElement('P');
|
const para = document.createElement('P');
|
||||||
para.textContent = 'Please enter a word or phrase above';
|
para.textContent = 'Please enter a word or phrase above';
|
||||||
document.getElementById('search-results').append(para);
|
document.getElementById('search-results').appendChild(para);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ function executeSearch(searchQuery) {
|
|||||||
} else {
|
} else {
|
||||||
const para = document.createElement('P');
|
const para = document.createElement('P');
|
||||||
para.textContent = 'No matches found';
|
para.textContent = 'No matches found';
|
||||||
document.getElementById('search-results').append(para);
|
document.getElementById('search-results').appendChild(para);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ function populateResults(result) {
|
|||||||
categories: value.item.categories,
|
categories: value.item.categories,
|
||||||
snippet
|
snippet
|
||||||
});
|
});
|
||||||
document.getElementById('search-results').append(htmlToElement(output));
|
document.getElementById('search-results').appendChild(htmlToElement(output));
|
||||||
|
|
||||||
for (const snipvalue of snippetHighlights) {
|
for (const snipvalue of snippetHighlights) {
|
||||||
new Mark(document.getElementById(`summary-${key}`)).mark(snipvalue);
|
new Mark(document.getElementById(`summary-${key}`)).mark(snipvalue);
|
||||||
@@ -138,8 +138,8 @@ function populateResults(result) {
|
|||||||
|
|
||||||
function render(templateString, data) {
|
function render(templateString, data) {
|
||||||
let conditionalMatches, copy;
|
let conditionalMatches, copy;
|
||||||
const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*\}/g;
|
const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g;
|
||||||
// since loop below depends on re.lastIndex, we use a copy to capture any manipulations whilst inside the loop
|
// since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop
|
||||||
copy = templateString;
|
copy = templateString;
|
||||||
while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) {
|
while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) {
|
||||||
if (data[conditionalMatches[1]]) {
|
if (data[conditionalMatches[1]]) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ enableEmoji: true
|
|||||||
|
|
||||||
permalinks:
|
permalinks:
|
||||||
post: /:year/:month/:title/
|
post: /:year/:month/:title/
|
||||||
doc: /:sections[1:]/:slug/
|
doc: /:slug/
|
||||||
page: /:slug/
|
page: /:slug/
|
||||||
default: /:slug/
|
default: /:slug/
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@ params:
|
|||||||
description: Git with a cup of tea
|
description: Git with a cup of tea
|
||||||
author: The Gitea Authors
|
author: The Gitea Authors
|
||||||
website: https://docs.gitea.io
|
website: https://docs.gitea.io
|
||||||
version: 1.19.0 # FIXME: this version was used as "latest stable release", but it always gets outdated and doesn't make sense
|
version: 1.18.5
|
||||||
minGoVersion: 1.20
|
minGoVersion: 1.19
|
||||||
goVersion: 1.20
|
goVersion: 1.20
|
||||||
minNodeVersion: 16
|
minNodeVersion: 16
|
||||||
search: nav
|
search: nav
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
date: "2023-04-27T14:00:00+08:00"
|
|
||||||
title: "Actions"
|
|
||||||
slug: "actions"
|
|
||||||
weight: 36
|
|
||||||
toc: false
|
|
||||||
draft: false
|
|
||||||
menu:
|
|
||||||
sidebar:
|
|
||||||
name: "Usage - Actions"
|
|
||||||
weight: 31
|
|
||||||
identifier: "actions"
|
|
||||||
---
|
|
||||||
@@ -5,8 +5,6 @@ slug: adding-legal-pages
|
|||||||
weight: 110
|
weight: 110
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/adding-legal-pages
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
---
|
|
||||||
date: "2023-05-23T09:00:00+08:00"
|
|
||||||
title: "添加法律页面"
|
|
||||||
slug: adding-legal-pages
|
|
||||||
weight: 110
|
|
||||||
toc: false
|
|
||||||
draft: false
|
|
||||||
aliases:
|
|
||||||
- /zh-cn/adding-legal-pages
|
|
||||||
menu:
|
|
||||||
sidebar:
|
|
||||||
parent: "administration"
|
|
||||||
name: "添加法律页面"
|
|
||||||
identifier: "adding-legal-pages"
|
|
||||||
weight: 110
|
|
||||||
---
|
|
||||||
|
|
||||||
一些法域(例如欧盟)要求在网站上添加特定的法律页面(例如隐私政策)。按照以下步骤将它们添加到你的 Gitea 实例中。
|
|
||||||
|
|
||||||
## 获取页面
|
|
||||||
|
|
||||||
Gitea 源代码附带了示例页面,位于 `contrib/legal` 目录中。将它们复制到 `custom/public/` 目录下。例如,如果要添加隐私政策:
|
|
||||||
|
|
||||||
```
|
|
||||||
wget -O /path/to/custom/public/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
|
|
||||||
```
|
|
||||||
|
|
||||||
现在,你需要编辑该页面以满足你的需求。特别是,你必须更改电子邮件地址、网址以及与 "Your Gitea Instance" 相关的引用,以匹配你的情况。
|
|
||||||
|
|
||||||
请务必不要放置会暗示 Gitea 项目对你的服务器负责的一般服务条款或隐私声明。
|
|
||||||
|
|
||||||
## 使其可见
|
|
||||||
|
|
||||||
创建或追加到 `/path/to/custom/templates/custom/extra_links_footer.tmpl` 文件中:
|
|
||||||
|
|
||||||
```go
|
|
||||||
<a class="item" href="{{AppSubUrl}}/assets/privacy.html">隐私政策</a>
|
|
||||||
```
|
|
||||||
|
|
||||||
重启 Gitea 以查看更改。
|
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
---
|
---
|
||||||
date: "2017-01-01T16:00:00+02:00"
|
date: "2017-01-01T16:00:00+02:00"
|
||||||
title: "Backup and Restore"
|
title: "Usage: Backup and Restore"
|
||||||
slug: "backup-and-restore"
|
slug: "backup-and-restore"
|
||||||
weight: 11
|
weight: 11
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/backup-and-restore
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -46,9 +44,9 @@ directory. There should be some output similar to the following:
|
|||||||
|
|
||||||
Inside the `gitea-dump-1482906742.zip` file, will be the following:
|
Inside the `gitea-dump-1482906742.zip` file, will be the following:
|
||||||
|
|
||||||
- `app.ini` - Optional copy of configuration file if originally stored outside the default `custom/` directory
|
- `app.ini` - Optional copy of configuration file if originally stored outside of the default `custom/` directory
|
||||||
- `custom` - All config or customization files in `custom/`.
|
- `custom` - All config or customization files in `custom/`.
|
||||||
- `data` - Data directory (APP_DATA_PATH), except sessions if you are using file session. This directory includes `attachments`, `avatars`, `lfs`, `indexers`, SQLite file if you are using SQLite.
|
- `data` - Data directory in <GITEA_WORK_DIR>, except sessions if you are using file session. This directory includes `attachments`, `avatars`, `lfs`, `indexers`, SQLite file if you are using SQLite.
|
||||||
- `gitea-db.sql` - SQL dump of database
|
- `gitea-db.sql` - SQL dump of database
|
||||||
- `gitea-repo.zip` - Complete copy of the repository directory.
|
- `gitea-repo.zip` - Complete copy of the repository directory.
|
||||||
- `log/` - Various logs. They are not needed for a recovery or migration.
|
- `log/` - Various logs. They are not needed for a recovery or migration.
|
||||||
@@ -139,6 +137,16 @@ chown -R git:git /data
|
|||||||
|
|
||||||
The default user in the gitea container is `git` (1000:1000). Please replace `2a83b293548e` with your gitea container id or name.
|
The default user in the gitea container is `git` (1000:1000). Please replace `2a83b293548e` with your gitea container id or name.
|
||||||
|
|
||||||
|
These are the default paths used in the container:
|
||||||
|
|
||||||
|
```text
|
||||||
|
DEFAULT CONFIGURATION:
|
||||||
|
CustomPath: /data/gitea (GITEA_CUSTOM)
|
||||||
|
CustomConf: /data/gitea/conf/app.ini
|
||||||
|
AppPath: /usr/local/bin/gitea
|
||||||
|
AppWorkPath: /usr/local/bin
|
||||||
|
```
|
||||||
|
|
||||||
### Using Docker-rootless (`restore`)
|
### Using Docker-rootless (`restore`)
|
||||||
|
|
||||||
The restore workflow in Docker-rootless containers differs only in the directories to be used:
|
The restore workflow in Docker-rootless containers differs only in the directories to be used:
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
---
|
---
|
||||||
date: "2018-06-06T09:33:00+08:00"
|
date: "2018-06-06T09:33:00+08:00"
|
||||||
title: "备份与恢复"
|
title: "使用:备份与恢复"
|
||||||
slug: "backup-and-restore"
|
slug: "backup-and-restore"
|
||||||
weight: 11
|
weight: 11
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /zh-cn/backup-and-restore
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "backup-and-restore"
|
|||||||
weight: 11
|
weight: 11
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /zh-tw/backup-and-restore
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "cmd-embedded"
|
|||||||
weight: 20
|
weight: 20
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/cmd-embedded
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -40,7 +38,7 @@ gitea embedded list [--include-vendored] [patterns...]
|
|||||||
|
|
||||||
The `--include-vendored` flag makes the command include vendored files, which are
|
The `--include-vendored` flag makes the command include vendored files, which are
|
||||||
normally excluded; that is, files from external libraries that are required for Gitea
|
normally excluded; that is, files from external libraries that are required for Gitea
|
||||||
(e.g. [octicons](https://octicons.github.com/), etc).
|
(e.g. [font-awesome](https://fontawesome.com/), [octicons](https://octicons.github.com/), etc).
|
||||||
|
|
||||||
A list of file search patterns can be provided. Gitea uses [gobwas/glob](https://github.com/gobwas/glob)
|
A list of file search patterns can be provided. Gitea uses [gobwas/glob](https://github.com/gobwas/glob)
|
||||||
for its glob syntax. Here are some examples:
|
for its glob syntax. Here are some examples:
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
---
|
|
||||||
date: "2023-05-23T09:00:00+08:00"
|
|
||||||
title: "嵌入资源提取工具"
|
|
||||||
slug: "cmd-embedded"
|
|
||||||
weight: 20
|
|
||||||
toc: false
|
|
||||||
draft: false
|
|
||||||
aliases:
|
|
||||||
- /zh-cn/cmd-embedded
|
|
||||||
menu:
|
|
||||||
sidebar:
|
|
||||||
parent: "administration"
|
|
||||||
name: "嵌入资源提取工具"
|
|
||||||
weight: 20
|
|
||||||
identifier: "cmd-embedded"
|
|
||||||
---
|
|
||||||
|
|
||||||
# 嵌入资源提取工具
|
|
||||||
|
|
||||||
**目录**
|
|
||||||
|
|
||||||
{{< toc >}}
|
|
||||||
|
|
||||||
Gitea 的可执行文件包含了运行所需的所有资源:模板、图片、样式表和翻译文件。你可以通过在 `custom` 目录下的相应路径中放置替换文件来覆盖其中的任何资源(详见 [自定义 Gitea 配置]({{< relref "doc/administration/customizing-gitea.zh-cn.md" >}}))。
|
|
||||||
|
|
||||||
要获取嵌入资源的副本以进行编辑,可以使用 CLI 中的 `embedded` 命令,通过操作系统的 shell 执行。
|
|
||||||
|
|
||||||
**注意:** 嵌入资源提取工具包含在 Gitea 1.12 及以上版本中。
|
|
||||||
|
|
||||||
## 资源列表
|
|
||||||
|
|
||||||
要列出嵌入在 Gitea 可执行文件中的资源,请使用以下语法:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
gitea embedded list [--include-vendored] [patterns...]
|
|
||||||
```
|
|
||||||
|
|
||||||
`--include-vendored` 标志使命令包括被供应的文件,这些文件通常被排除在外;即来自外部库的文件,这些文件是 Gitea 所需的(例如 [octicons](https://octicons.github.com/) 等)。
|
|
||||||
|
|
||||||
可以提供一系列文件搜索模式。Gitea 使用 [gobwas/glob](https://github.com/gobwas/glob) 作为其 glob 语法。以下是一些示例:
|
|
||||||
|
|
||||||
- 列出所有模板文件,无论在哪个虚拟目录下:`**.tmpl`
|
|
||||||
- 列出所有邮件模板文件:`templates/mail/**.tmpl`
|
|
||||||
- 列出 `public/img` 目录下的所有文件:`public/img/**`
|
|
||||||
|
|
||||||
不要忘记为模式使用引号,因为空格、`*` 和其他字符可能对命令行解释器有特殊含义。
|
|
||||||
|
|
||||||
如果未提供模式,则列出所有文件。
|
|
||||||
|
|
||||||
### 示例
|
|
||||||
|
|
||||||
列出所有路径中包含 `openid` 的嵌入文件:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ gitea embedded list '**openid**'
|
|
||||||
public/img/auth/openid_connect.svg
|
|
||||||
public/img/openid-16x16.png
|
|
||||||
templates/user/auth/finalize_openid.tmpl
|
|
||||||
templates/user/auth/signin_openid.tmpl
|
|
||||||
templates/user/auth/signup_openid_connect.tmpl
|
|
||||||
templates/user/auth/signup_openid_navbar.tmpl
|
|
||||||
templates/user/auth/signup_openid_register.tmpl
|
|
||||||
templates/user/settings/security_openid.tmpl
|
|
||||||
```
|
|
||||||
|
|
||||||
## 提取资源
|
|
||||||
|
|
||||||
要提取嵌入在 Gitea 可执行文件中的资源,请使用以下语法:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
gitea [--config {file}] embedded extract [--destination {dir}|--custom] [--overwrite|--rename] [--include-vendored] {patterns...}
|
|
||||||
```
|
|
||||||
|
|
||||||
`--config` 选项用于告知 Gitea `app.ini` 配置文件的位置(如果不在默认位置)。此选项仅在使用 `--custom` 标志时使用。
|
|
||||||
|
|
||||||
`--destination` 选项用于指定提取文件的目标目录。默认为当前目录。
|
|
||||||
|
|
||||||
`--custom` 标志告知 Gitea 直接将文件提取到 `custom` 目录中。为使其正常工作,该命令需要知道 `app.ini` 配置文件的位置(通过 `--config` 指定),并且根据配置的不同,需要从 Gitea 通常启动的目录运行。有关详细信息,请参阅 [自定义 Gitea 配置]({{< relref "doc/administration/customizing-gitea.zh-cn.md" >}})。
|
|
||||||
|
|
||||||
`--overwrite` 标志允许覆盖目标目录中的任何现有文件。
|
|
||||||
|
|
||||||
`--rename` 标志告知 Gitea 将目标目录中的任何现有文件重命名为 `filename.bak`。之前的 `.bak` 文件将被覆盖。
|
|
||||||
|
|
||||||
至少需要提供一个文件搜索模式;有关模式的语法和示例,请参阅上述 `list` 子命令。
|
|
||||||
|
|
||||||
### 重要提示
|
|
||||||
|
|
||||||
请确保**只提取需要自定义的文件**。位于 `custom` 目录中的文件不会受到 Gitea 的升级过程的影响。当 Gitea 升级到新版本(通过替换可执行文件)时,许多嵌入文件将发生变化。Gitea 将尊重并使用在 `custom` 目录中找到的任何文件,即使这些文件是旧的和不兼容的。
|
|
||||||
|
|
||||||
### 示例
|
|
||||||
|
|
||||||
将邮件模板提取到临时目录:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ mkdir tempdir
|
|
||||||
$ gitea embedded extract --destination tempdir 'templates/mail/**.tmpl'
|
|
||||||
Extracting to tempdir:
|
|
||||||
tempdir/templates/mail/auth/activate.tmpl
|
|
||||||
tempdir/templates/mail/auth/activate_email.tmpl
|
|
||||||
tempdir/templates/mail/auth/register_notify.tmpl
|
|
||||||
tempdir/templates/mail/auth/reset_passwd.tmpl
|
|
||||||
tempdir/templates/mail/issue/assigned.tmpl
|
|
||||||
tempdir/templates/mail/issue/default.tmpl
|
|
||||||
tempdir/templates/mail/notify/collaborator.tmpl
|
|
||||||
```
|
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
---
|
---
|
||||||
date: "2017-01-01T16:00:00+02:00"
|
date: "2017-01-01T16:00:00+02:00"
|
||||||
title: "Gitea Command Line"
|
title: "Usage: Command Line"
|
||||||
slug: "command-line"
|
slug: "command-line"
|
||||||
weight: 1
|
weight: 1
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/command-line
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -31,9 +29,9 @@ All global options can be placed at the command level.
|
|||||||
|
|
||||||
- `--help`, `-h`: Show help text and exit. Optional.
|
- `--help`, `-h`: Show help text and exit. Optional.
|
||||||
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
||||||
- `--work-path path`, `-w path`: Gitea's work path. Optional. (default: the binary's path or `$GITEA_WORK_DIR`)
|
- `--custom-path path`, `-C path`: Location of the Gitea custom folder. Optional. (default: `AppWorkPath`/custom or `$GITEA_CUSTOM`).
|
||||||
- `--custom-path path`, `-C path`: Gitea's custom folder path. Optional. (default: `WorkPath`/custom or `$GITEA_CUSTOM`).
|
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `custom`/conf/app.ini).
|
||||||
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `CustomPath`/conf/app.ini).
|
- `--work-path path`, `-w path`: Gitea `AppWorkPath`. Optional. (default: LOCATION_OF_GITEA_BINARY or `$GITEA_WORK_DIR`)
|
||||||
|
|
||||||
NB: The defaults custom-path, config and work-path can also be
|
NB: The defaults custom-path, config and work-path can also be
|
||||||
changed at build time (if preferred).
|
changed at build time (if preferred).
|
||||||
@@ -108,14 +106,6 @@ Admin operations:
|
|||||||
- `--all`, `-A`: Force a password change for all users
|
- `--all`, `-A`: Force a password change for all users
|
||||||
- `--exclude username`, `-e username`: Exclude the given user. Can be set multiple times.
|
- `--exclude username`, `-e username`: Exclude the given user. Can be set multiple times.
|
||||||
- `--unset`: Revoke forced password change for the given users
|
- `--unset`: Revoke forced password change for the given users
|
||||||
- `generate-access-token`:
|
|
||||||
- Options:
|
|
||||||
- `--username value`, `-u value`: Username. Required.
|
|
||||||
- `--token-name value`, `-t value`: Token name. Required.
|
|
||||||
- `--scopes value`: Comma-separated list of scopes. Scopes follow the format `[read|write]:<block>` or `all` where `<block>` is one of the available visual groups you can see when opening the API page showing the available routes (for example `repo`).
|
|
||||||
- Examples:
|
|
||||||
- `gitea admin user generate-access-token --username myname --token-name mytoken`
|
|
||||||
- `gitea admin user generate-access-token --help`
|
|
||||||
- `regenerate`
|
- `regenerate`
|
||||||
- Options:
|
- Options:
|
||||||
- `hooks`: Regenerate Git Hooks for all repositories
|
- `hooks`: Regenerate Git Hooks for all repositories
|
||||||
@@ -233,7 +223,7 @@ Admin operations:
|
|||||||
- `--synchronize-users`: Enable user synchronization.
|
- `--synchronize-users`: Enable user synchronization.
|
||||||
- `--page-size value`: Search page size.
|
- `--page-size value`: Search page size.
|
||||||
- Examples:
|
- Examples:
|
||||||
- `gitea admin auth add-ldap --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-search-base "ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))" --email-attribute mail`
|
- `gitea admin auth add-ldap --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-search-base "ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(uid=%s))" --email-attribute mail`
|
||||||
- `update-ldap`: Update existing LDAP (via Bind DN) authentication source
|
- `update-ldap`: Update existing LDAP (via Bind DN) authentication source
|
||||||
- Options:
|
- Options:
|
||||||
- `--id value`: ID of authentication source. Required.
|
- `--id value`: ID of authentication source. Required.
|
||||||
@@ -561,28 +551,3 @@ Restore-repo restore repository data from disk dir:
|
|||||||
- `--owner_name lunny`: Restore destination owner name
|
- `--owner_name lunny`: Restore destination owner name
|
||||||
- `--repo_name tango`: Restore destination repository name
|
- `--repo_name tango`: Restore destination repository name
|
||||||
- `--units <units>`: Which items will be restored, one or more units should be separated as comma. wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.
|
- `--units <units>`: Which items will be restored, one or more units should be separated as comma. wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.
|
||||||
|
|
||||||
### actions generate-runner-token
|
|
||||||
|
|
||||||
Generate a new token for a runner to use to register with the server
|
|
||||||
|
|
||||||
- Options:
|
|
||||||
- `--scope {owner}[/{repo}]`, `-s {owner}[/{repo}]`: To limit the scope of the runner, no scope means the runner can be used for all repos, but you can also limit it to a specific repo or owner
|
|
||||||
|
|
||||||
To register a global runner:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea actions generate-runner-token
|
|
||||||
```
|
|
||||||
|
|
||||||
To register a runner for a specific organization, in this case `org`:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea actions generate-runner-token -s org
|
|
||||||
```
|
|
||||||
|
|
||||||
To register a runner for a specific repo, in this case `username/test-repo`:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea actions generate-runner-token -s username/test-repo
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,556 +0,0 @@
|
|||||||
---
|
|
||||||
date: "2023-05-23T09:00:00+08:00"
|
|
||||||
title: "Gitea 命令行"
|
|
||||||
slug: "command-line"
|
|
||||||
weight: 1
|
|
||||||
toc: false
|
|
||||||
draft: false
|
|
||||||
aliases:
|
|
||||||
- /zh-cn/command-line
|
|
||||||
menu:
|
|
||||||
sidebar:
|
|
||||||
parent: "administration"
|
|
||||||
name: "Gitea 命令行"
|
|
||||||
weight: 1
|
|
||||||
identifier: "command-line"
|
|
||||||
---
|
|
||||||
|
|
||||||
# 命令行
|
|
||||||
|
|
||||||
**目录**
|
|
||||||
|
|
||||||
{{< toc >}}
|
|
||||||
|
|
||||||
## 用法
|
|
||||||
|
|
||||||
`gitea [全局选项] 命令 [命令或全局选项] [参数...]`
|
|
||||||
|
|
||||||
## 全局选项
|
|
||||||
|
|
||||||
所有全局选项均可被放置在命令级别。
|
|
||||||
|
|
||||||
- `--help`,`-h`:显示帮助文本并退出。可选。
|
|
||||||
- `--version`,`-v`:显示版本信息并退出。可选。 (示例:`Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`)。
|
|
||||||
- `--custom-path path`,`-C path`:Gitea 自定义文件夹的路径。可选。 (默认值:`AppWorkPath`/custom 或 `$GITEA_CUSTOM`)。
|
|
||||||
- `--config path`,`-c path`:Gitea 配置文件的路径。可选。 (默认值:`custom`/conf/app.ini)。
|
|
||||||
- `--work-path path`,`-w path`:Gitea 的 `AppWorkPath`。可选。 (默认值:LOCATION_OF_GITEA_BINARY 或 `$GITEA_WORK_DIR`)
|
|
||||||
|
|
||||||
注意:默认的 custom-path、config 和 work-path 也可以在构建时更改(如果需要)。
|
|
||||||
|
|
||||||
## 命令
|
|
||||||
|
|
||||||
### web
|
|
||||||
|
|
||||||
启动服务器:
|
|
||||||
|
|
||||||
- 选项:
|
|
||||||
- `--port number`,`-p number`:端口号。可选。 (默认值:3000)。覆盖配置文件中的设置。
|
|
||||||
- `--install-port number`:运行安装页面的端口号。可选。 (默认值:3000)。覆盖配置文件中的设置。
|
|
||||||
- `--pid path`,`-P path`:Pid 文件的路径。可选。
|
|
||||||
- `--quiet`,`-q`:只在控制台上输出 Fatal 日志,用于在设置日志之前发出的日志。
|
|
||||||
- `--verbose`:在控制台上输出跟踪日志,用于在设置日志之前发出的日志。
|
|
||||||
- 示例:
|
|
||||||
- `gitea web`
|
|
||||||
- `gitea web --port 80`
|
|
||||||
- `gitea web --config /etc/gitea.ini --pid /some/custom/gitea.pid`
|
|
||||||
- 注意:
|
|
||||||
- Gitea 不应以 root 用户身份运行。要绑定到低于 1024 的端口,您可以在 Linux 上使用 setcap 命令:`sudo setcap 'cap_net_bind_service=+ep' /path/to/gitea`。每次更新 Gitea 都需要重新执行此操作。
|
|
||||||
|
|
||||||
### admin
|
|
||||||
|
|
||||||
管理员操作:
|
|
||||||
|
|
||||||
- 命令:
|
|
||||||
- `user`:
|
|
||||||
- `list`:
|
|
||||||
- 选项:
|
|
||||||
- `--admin`:仅列出管理员用户。可选。
|
|
||||||
- 描述:列出所有现有用户。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin user list`
|
|
||||||
- `delete`:
|
|
||||||
- 选项:
|
|
||||||
- `--email`:要删除的用户的电子邮件。
|
|
||||||
- `--username`:要删除的用户的用户名。
|
|
||||||
- `--id`:要删除的用户的ID。
|
|
||||||
- 必须提供 `--id`、`--username` 或 `--email` 中的一个。如果提供多个,则所有条件必须匹配。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin user delete --id 1`
|
|
||||||
- `create`:
|
|
||||||
- 选项:
|
|
||||||
- `--name value`:用户名。必填。自 Gitea 1.9.0 版本起,请改用 `--username` 标志。
|
|
||||||
- `--username value`:用户名。必填。Gitea 1.9.0 新增。
|
|
||||||
- `--password value`:密码。必填。
|
|
||||||
- `--email value`:邮箱。必填。
|
|
||||||
- `--admin`:如果提供此选项,将创建一个管理员用户。可选。
|
|
||||||
- `--access-token`:如果提供,将为用户创建访问令牌。可选。(默认值:false)。
|
|
||||||
- `--must-change-password`:如果提供,创建的用户将在初始登录后需要选择一个新密码。可选。(默认值:true)。
|
|
||||||
- `--random-password`:如果提供,将使用随机生成的密码作为创建用户的密码。`--password` 的值将被忽略。可选。
|
|
||||||
- `--random-password-length`:如果提供,将用于配置随机生成密码的长度。可选。(默认值:12)
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin user create --username myname --password asecurepassword --email me@example.com`
|
|
||||||
- `change-password`:
|
|
||||||
- 选项:
|
|
||||||
- `--username value`,`-u value`:用户名。必填。
|
|
||||||
- `--password value`,`-p value`:新密码。必填。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin user change-password --username myname --password asecurepassword`
|
|
||||||
- `must-change-password`:
|
|
||||||
- 参数:
|
|
||||||
- `[username...]`:需要更改密码的用户
|
|
||||||
- 选项:
|
|
||||||
- `--all`,`-A`:强制所有用户更改密码
|
|
||||||
- `--exclude username`,`-e username`:排除给定的用户。可以多次设置。
|
|
||||||
- `--unset`:撤销对给定用户的强制密码更改
|
|
||||||
- `regenerate`:
|
|
||||||
- 选项:
|
|
||||||
- `hooks`:重新生成所有仓库的 Git Hooks。
|
|
||||||
- `keys`:重新生成 authorized_keys 文件。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin regenerate hooks`
|
|
||||||
- `gitea admin regenerate keys`
|
|
||||||
- `auth`:
|
|
||||||
- `list`:
|
|
||||||
- 描述:列出所有存在的外部认证源。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth list`
|
|
||||||
- `delete`:
|
|
||||||
- 选项:
|
|
||||||
- `--id`:要删除的源的 ID。必填。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth delete --id 1`
|
|
||||||
- `add-oauth`:
|
|
||||||
- 选项:
|
|
||||||
- `--name`:应用程序名称。
|
|
||||||
- `--provider`:OAuth2 提供者。
|
|
||||||
- `--key`:客户端 ID(Key)。
|
|
||||||
- `--secret`:客户端密钥。
|
|
||||||
- `--auto-discover-url`:OpenID Connect 自动发现 URL(仅在使用 OpenID Connect 作为提供程序时需要)。
|
|
||||||
- `--use-custom-urls`:在 GitLab/GitHub OAuth 端点上使用自定义 URL。
|
|
||||||
- `--custom-tenant-id`:在 OAuth 端点上使用自定义租户 ID。
|
|
||||||
- `--custom-auth-url`:使用自定义授权 URL(GitLab/GitHub 的选项)。
|
|
||||||
- `--custom-token-url`:使用自定义令牌 URL(GitLab/GitHub 的选项)。
|
|
||||||
- `--custom-profile-url`:使用自定义配置文件 URL(GitLab/GitHub 的选项)。
|
|
||||||
- `--custom-email-url`:使用自定义电子邮件 URL(GitHub 的选项)。
|
|
||||||
- `--icon-url`:OAuth2 登录源的自定义图标 URL。
|
|
||||||
- `--skip-local-2fa`:允许源覆盖本地 2FA。(可选)
|
|
||||||
- `--scopes`:请求此 OAuth2 源的附加范围。(可选)
|
|
||||||
- `--required-claim-name`:必须设置的声明名称,以允许用户使用此源登录。(可选)
|
|
||||||
- `--required-claim-value`:必须设置的声明值,以允许用户使用此源登录。(可选)
|
|
||||||
- `--group-claim-name`:提供此源的组名的声明名称。(可选)
|
|
||||||
- `--admin-group`:管理员用户的组声明值。(可选)
|
|
||||||
- `--restricted-group`:受限用户的组声明值。(可选)
|
|
||||||
- `--group-team-map`:组与组织团队之间的 JSON 映射。(可选)
|
|
||||||
- `--group-team-map-removal`:根据组自动激活团队成员资格的删除。(可选)
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth add-oauth --name external-github --provider github --key OBTAIN_FROM_SOURCE --secret OBTAIN_FROM_SOURCE`
|
|
||||||
- `update-oauth`:
|
|
||||||
- 选项:
|
|
||||||
- `--id`:要更新的源的 ID。必填。
|
|
||||||
- `--name`:应用程序名称。
|
|
||||||
- `--provider`:OAuth2 提供者。
|
|
||||||
- `--key`:客户端 ID(Key)。
|
|
||||||
- `--secret`:客户端密钥。
|
|
||||||
- `--auto-discover-url`:OpenID Connect 自动发现 URL(仅在使用 OpenID Connect 作为提供程序时需要)。
|
|
||||||
- `--use-custom-urls`:在 GitLab/GitHub OAuth 端点上使用自定义 URL。
|
|
||||||
- `--custom-tenant-id`:在 OAuth 端点上使用自定义租户 ID。
|
|
||||||
- `--custom-auth-url`:使用自定义授权 URL(GitLab/GitHub 的选项)。
|
|
||||||
- `--custom-token-url`:使用自定义令牌 URL(GitLab/GitHub 的选项)。
|
|
||||||
- `--custom-profile-url`:使用自定义配置文件 URL(GitLab/GitHub 的选项)。
|
|
||||||
- `--custom-email-url`:使用自定义电子邮件 URL(GitHub 的选项)。
|
|
||||||
- `--icon-url`:OAuth2 登录源的自定义图标 URL。
|
|
||||||
- `--skip-local-2fa`:允许源覆盖本地 2FA。(可选)
|
|
||||||
- `--scopes`:请求此 OAuth2 源的附加范围。
|
|
||||||
- `--required-claim-name`:必须设置的声明名称,以允许用户使用此源登录。(可选)
|
|
||||||
- `--required-claim-value`:必须设置的声明值,以允许用户使用此源登录。(可选)
|
|
||||||
- `--group-claim-name`:提供此源的组名的声明名称。(可选)
|
|
||||||
- `--admin-group`:管理员用户的组声明值。(可选)
|
|
||||||
- `--restricted-group`:受限用户的组声明值。(可选)
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth update-oauth --id 1 --name external-github-updated`
|
|
||||||
- `add-smtp`:
|
|
||||||
- 选项:
|
|
||||||
- `--name`:应用程序名称。必填。
|
|
||||||
- `--auth-type`:SMTP 认证类型(PLAIN/LOGIN/CRAM-MD5)。默认为 PLAIN。
|
|
||||||
- `--host`:SMTP 主机。必填。
|
|
||||||
- `--port`:SMTP 端口。必填。
|
|
||||||
- `--force-smtps`:SMTPS 始终在端口 465 上使用。设置此选项以强制在其他端口上使用 SMTPS。
|
|
||||||
- `--skip-verify`:跳过 TLS 验证。
|
|
||||||
- `--helo-hostname`:发送 HELO 时使用的主机名。留空以发送当前主机名。
|
|
||||||
- `--disable-helo`:禁用 SMTP helo。
|
|
||||||
- `--allowed-domains`:留空以允许所有域。使用逗号(',')分隔多个域。
|
|
||||||
- `--skip-local-2fa`:跳过 2FA 登录。
|
|
||||||
- `--active`:启用此认证源。
|
|
||||||
备注:
|
|
||||||
`--force-smtps`、`--skip-verify`、`--disable-helo`、`--skip-local-2fs` 和 `--active` 选项可以采用以下形式使用:
|
|
||||||
- `--option`、`--option=true` 以启用选项
|
|
||||||
- `--option=false` 以禁用选项
|
|
||||||
如果未指定这些选项,则在 `update-smtp` 中不会更改值,或者在 `add-smtp` 中将使用默认的 `false` 值。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth add-smtp --name ldap --host smtp.mydomain.org --port 587 --skip-verify --active`
|
|
||||||
- `update-smtp`:
|
|
||||||
- 选项:
|
|
||||||
- `--id`:要更新的源的 ID。必填。
|
|
||||||
- 其他选项与 `add-smtp` 共享
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth update-smtp --id 1 --host smtp.mydomain.org --port 587 --skip-verify=false`
|
|
||||||
- `gitea admin auth update-smtp --id 1 --active=false`
|
|
||||||
- `add-ldap`:添加新的 LDAP(通过 Bind DN)认证源
|
|
||||||
- 选项:
|
|
||||||
- `--name value`:认证名称。必填。
|
|
||||||
- `--not-active`:停用认证源。
|
|
||||||
- `--security-protocol value`:安全协议名称。必填。
|
|
||||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
|
||||||
- `--host value`:LDAP 服务器的地址。必填。
|
|
||||||
- `--port value`:连接到 LDAP 服务器时使用的端口。必填。
|
|
||||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。必填。
|
|
||||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。必填。
|
|
||||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
|
||||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
|
||||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
|
||||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
|
||||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
|
||||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。必填。
|
|
||||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
|
||||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
|
||||||
- `--bind-dn value`:在搜索用户时绑定到 LDAP 服务器的 DN。
|
|
||||||
- `--bind-password value`:绑定 DN 的密码(如果有)。
|
|
||||||
- `--attributes-in-bind`:在绑定 DN 上下文中获取属性。
|
|
||||||
- `--synchronize-users`:启用用户同步。
|
|
||||||
- `--page-size value`:搜索页面大小。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth add-ldap --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-search-base "ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))" --email-attribute mail`
|
|
||||||
- `update-ldap`:更新现有的 LDAP(通过 Bind DN)认证源
|
|
||||||
- 选项:
|
|
||||||
- `--id value`:认证源的 ID。必填。
|
|
||||||
- `--name value`:认证名称。
|
|
||||||
- `--not-active`:停用认证源。
|
|
||||||
- `--security-protocol value`:安全协议名称。
|
|
||||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
|
||||||
- `--host value`:LDAP 服务器的地址。
|
|
||||||
- `--port value`:连接到 LDAP 服务器时使用的端口。
|
|
||||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。
|
|
||||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。
|
|
||||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
|
||||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
|
||||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
|
||||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
|
||||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
|
||||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。
|
|
||||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
|
||||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
|
||||||
- `--bind-dn value`:在搜索用户时绑定到 LDAP 服务器的 DN。
|
|
||||||
- `--bind-password value`:绑定 DN 的密码(如果有)。
|
|
||||||
- `--attributes-in-bind`:在绑定 DN 上下文中获取属性。
|
|
||||||
- `--synchronize-users`:启用用户同步。
|
|
||||||
- `--page-size value`:搜索页面大小。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth update-ldap --id 1 --name "my ldap auth source"`
|
|
||||||
- `gitea admin auth update-ldap --id 1 --username-attribute uid --firstname-attribute givenName --surname-attribute sn`
|
|
||||||
- `add-ldap-simple`:添加新的 LDAP(简单身份验证)认证源
|
|
||||||
- 选项:
|
|
||||||
- `--name value`:认证名称。必填。
|
|
||||||
- `--not-active`:停用认证源。
|
|
||||||
- `--security-protocol value`:安全协议名称。必填。
|
|
||||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
|
||||||
- `--host value`:LDAP 服务器的地址。必填。
|
|
||||||
- `--port value`:连接到 LDAP 服务器时使用的端口。必填。
|
|
||||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。
|
|
||||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。必填。
|
|
||||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
|
||||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
|
||||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
|
||||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
|
||||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
|
||||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。必填。
|
|
||||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
|
||||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
|
||||||
- `--user-dn value`:用户的 DN。必填。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth add-ldap-simple --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-dn "cn=%s,ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(cn=%s))" --email-attribute mail`
|
|
||||||
- `update-ldap-simple`:更新现有的 LDAP(简单身份验证)认证源
|
|
||||||
- 选项:
|
|
||||||
- `--id value`:认证源的 ID。必填。
|
|
||||||
- `--name value`:认证名称。
|
|
||||||
- `--not-active`:停用认证源。
|
|
||||||
- `--security-protocol value`:安全协议名称。
|
|
||||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
|
||||||
- `--host value`:LDAP 服务器的地址。
|
|
||||||
- `--port value`:连接到 LDAP 服务器时使用的端口。
|
|
||||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。
|
|
||||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。
|
|
||||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
|
||||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
|
||||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
|
||||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
|
||||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
|
||||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。
|
|
||||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
|
||||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
|
||||||
- `--user-dn value`:用户的 DN。
|
|
||||||
- 示例:
|
|
||||||
- `gitea admin auth update-ldap-simple --id 1 --name "my ldap auth source"`
|
|
||||||
- `gitea admin auth update-ldap-simple --id 1 --username-attribute uid --firstname-attribute givenName --surname-attribute sn`
|
|
||||||
|
|
||||||
### cert
|
|
||||||
|
|
||||||
生成自签名的SSL证书。将输出到当前目录下的`cert.pem`和`key.pem`文件中,并且会覆盖任何现有文件。
|
|
||||||
|
|
||||||
- 选项:
|
|
||||||
- `--host value`:逗号分隔的主机名和IP地址列表,此证书适用于这些主机。支持使用通配符。必填。
|
|
||||||
- `--ecdsa-curve value`:用于生成密钥的ECDSA曲线。可选。有效选项为P224、P256、P384、P521。
|
|
||||||
- `--rsa-bits value`:要生成的RSA密钥的大小。可选。如果设置了--ecdsa-curve,则忽略此选项。(默认值:2048)。
|
|
||||||
- `--start-date value`:证书的创建日期。可选。(格式:`Jan 1 15:04:05 2011`)。
|
|
||||||
- `--duration value`:证书有效期。可选。(默认值:8760h0m0s)
|
|
||||||
- `--ca`:如果提供此选项,则证书将生成自己的证书颁发机构。可选。
|
|
||||||
- 示例:
|
|
||||||
- `gitea cert --host git.example.com,example.com,www.example.com --ca`
|
|
||||||
|
|
||||||
### dump
|
|
||||||
|
|
||||||
将所有文件和数据库导出到一个zip文件中。输出文件将保存在当前目录下,类似于`gitea-dump-1482906742.zip`。
|
|
||||||
|
|
||||||
- 选项:
|
|
||||||
- `--file name`,`-f name`:指定要创建的导出文件的名称。可选。(默认值:gitea-dump-[timestamp].zip)。
|
|
||||||
- `--tempdir path`,`-t path`:指定临时目录的路径。可选。(默认值:/tmp)。
|
|
||||||
- `--skip-repository`,`-R`:跳过仓库的导出。可选。
|
|
||||||
- `--skip-custom-dir`:跳过自定义目录的导出。可选。
|
|
||||||
- `--skip-lfs-data`:跳过LFS数据的导出。可选。
|
|
||||||
- `--skip-attachment-data`:跳过附件数据的导出。可选。
|
|
||||||
- `--skip-package-data`:跳过包数据的导出。可选。
|
|
||||||
- `--skip-log`:跳过日志数据的导出。可选。
|
|
||||||
- `--database`,`-d`:指定数据库的SQL语法。可选。
|
|
||||||
- `--verbose`,`-V`:如果提供此选项,显示附加详细信息。可选。
|
|
||||||
- `--type`:设置导出的格式。可选。(默认值:zip)
|
|
||||||
- 示例:
|
|
||||||
- `gitea dump`
|
|
||||||
- `gitea dump --verbose`
|
|
||||||
|
|
||||||
### generate
|
|
||||||
|
|
||||||
用于在配置文件中生成随机值和令牌。对于自动部署时生成值非常有用。
|
|
||||||
|
|
||||||
- 命令:
|
|
||||||
- `secret`:
|
|
||||||
- 选项:
|
|
||||||
- `INTERNAL_TOKEN`: 用于内部 API 调用身份验证的令牌。
|
|
||||||
- `JWT_SECRET`: 用于 LFS 和 OAUTH2 JWT 身份验证的密钥(LFS_JWT_SECRET 是此选项的别名,用于向后兼容)。
|
|
||||||
- `SECRET_KEY`: 全局密钥。
|
|
||||||
- 示例:
|
|
||||||
- `gitea generate secret INTERNAL_TOKEN`
|
|
||||||
- `gitea generate secret JWT_SECRET`
|
|
||||||
- `gitea generate secret SECRET_KEY`
|
|
||||||
|
|
||||||
### keys
|
|
||||||
|
|
||||||
提供一个 SSHD AuthorizedKeysCommand。需要在 sshd 配置文件中进行配置:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
...
|
|
||||||
# -e 的值和 AuthorizedKeysCommandUser 应与运行 Gitea 的用户名匹配
|
|
||||||
AuthorizedKeysCommandUser git
|
|
||||||
AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k
|
|
||||||
```
|
|
||||||
|
|
||||||
该命令将返回适用于提供的密钥的合适 authorized_keys 行。您还应在 `app.ini` 的 `[server]` 部分设置值 `SSH_CREATE_AUTHORIZED_KEYS_FILE=false`。
|
|
||||||
|
|
||||||
注意: opensshd 要求 Gitea 程序由 root 拥有,并且不可由组或其他人写入。程序必须使用绝对路径指定。
|
|
||||||
注意: Gitea 必须在运行此命令时处于运行状态才能成功。
|
|
||||||
|
|
||||||
### migrate
|
|
||||||
|
|
||||||
迁移数据库。该命令可用于在首次启动服务器之前运行其他命令。此命令是幂等的。
|
|
||||||
|
|
||||||
### convert
|
|
||||||
|
|
||||||
将现有的 MySQL 数据库从 utf8 转换为 utf8mb4。
|
|
||||||
|
|
||||||
### doctor
|
|
||||||
|
|
||||||
根据给定的配置诊断当前 Gitea 实例的问题。目前有以下检查清单:
|
|
||||||
|
|
||||||
- 检查 OpenSSH 的 authorized_keys 文件是否正确
|
|
||||||
当您的 Gitea 实例支持 OpenSSH 时,当您的 Gitea 实例添加或更改任何公钥时,Gitea 实例的二进制路径将被写入 `authorized_keys` 文件。
|
|
||||||
有时,如果您在升级时移动或重命名了 Gitea 二进制文件,并且您没有在管理面板上运行“使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件”操作。那么通过 SSH 的所有拉取/推送操作将无法正常工作。
|
|
||||||
此检查将帮助您检查它是否正常工作。
|
|
||||||
|
|
||||||
对于贡献者,如果您想添加更多的检查项,您可以编写一个新的函数,如 `func(ctx *cli.Context) ([]string, error)`,并将其追加到 `doctor.go` 文件中。
|
|
||||||
|
|
||||||
```go
|
|
||||||
var checklist = []check{
|
|
||||||
{
|
|
||||||
title: "Check if OpenSSH authorized_keys file id correct",
|
|
||||||
f: runDoctorLocationMoved,
|
|
||||||
},
|
|
||||||
// more checks please append here
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
此函数将接收一个命令行上下文,并返回有关问题或错误的详细信息列表。
|
|
||||||
|
|
||||||
#### doctor recreate-table
|
|
||||||
|
|
||||||
有时,在迁移时,旧的列和默认值可能会在数据库模式中保持不变。这可能会导致警告,如下所示:
|
|
||||||
|
|
||||||
```
|
|
||||||
2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync2() [W] Table user Column keep_activity_private db default is , struct default is 0
|
|
||||||
```
|
|
||||||
|
|
||||||
您可以通过以下方式让 Gitea 重新创建这些表,并将旧数据复制到新表中,并适当设置默认值:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea doctor recreate-table user
|
|
||||||
```
|
|
||||||
|
|
||||||
您可以使用以下方式让 Gitea 重新创建多个表:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea doctor recreate-table table1 table2 ...
|
|
||||||
```
|
|
||||||
|
|
||||||
如果您希望 Gitea 重新创建所有表,请直接调用:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea doctor recreate-table
|
|
||||||
```
|
|
||||||
|
|
||||||
强烈建议在运行这些命令之前备份您的数据库。
|
|
||||||
|
|
||||||
### manager
|
|
||||||
|
|
||||||
管理运行中的服务器操作:
|
|
||||||
|
|
||||||
- 命令:
|
|
||||||
- `shutdown`: 优雅地关闭运行中的进程
|
|
||||||
- `restart`: 优雅地重新启动运行中的进程(对于Windows服务器尚未实现)
|
|
||||||
- `flush-queues`: 刷新运行中的进程中的队列
|
|
||||||
- 选项:
|
|
||||||
- `--timeout value`: 刷新过程的超时时间(默认值: 1m0s)
|
|
||||||
- `--non-blocking`: 设置为true,以在返回之前不等待刷新完成
|
|
||||||
- `logging`: 调整日志命令
|
|
||||||
- 命令:
|
|
||||||
- `pause`: 暂停日志记录
|
|
||||||
- 注意:
|
|
||||||
- 如果日志级别低于此级别,日志级别将被临时提升为INFO。
|
|
||||||
- Gitea将在一定程度上缓冲日志,并在超过该点后丢弃日志。
|
|
||||||
- `resume`: 恢复日志记录
|
|
||||||
- `release-and-reopen`: 使Gitea释放和重新打开用于日志记录的文件和连接(相当于向Gitea发送SIGUSR1信号)。
|
|
||||||
- `remove name`: 删除指定的日志记录器
|
|
||||||
- 选项:
|
|
||||||
- `--group group`, `-g group`: 从中删除子记录器的组(默认为`default`)
|
|
||||||
- `add`: 添加日志记录器
|
|
||||||
- 命令:
|
|
||||||
- `console`: 添加控制台日志记录器
|
|
||||||
- 选项:
|
|
||||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
|
||||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
|
||||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
|
||||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
|
||||||
- `--flags value`, `-F value`: 日志记录器的标志
|
|
||||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
|
||||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
|
||||||
- `--color`: 在日志中使用颜色
|
|
||||||
- `--stderr`: 将控制台日志输出到stderr - 仅适用于控制台
|
|
||||||
- `file`: 添加文件日志记录器
|
|
||||||
- 选项:
|
|
||||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
|
||||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
|
||||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
|
||||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
|
||||||
- `--flags value`, `-F value`: 日志记录器的标志
|
|
||||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
|
||||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
|
||||||
- `--color`: 在日志中使用颜色
|
|
||||||
- `--filename value`, `-f value`: 日志记录器的文件名
|
|
||||||
- `--rotate`, `-r`: 轮转日志
|
|
||||||
- `--max-size value`, `-s value`: 在轮转之前的最大大小(以字节为单位)
|
|
||||||
- `--daily`, `-d`: 每天轮转日志
|
|
||||||
- `--max-days value`, `-D value`: 保留的每日日志的最大数量
|
|
||||||
- `--compress`, `-z`: 压缩轮转的日志
|
|
||||||
- `--compression-level value`, `-Z value`: 使用的压缩级别
|
|
||||||
- `conn`: 添加网络连接日志记录器
|
|
||||||
- 选项:
|
|
||||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
|
||||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
|
||||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
|
||||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
|
||||||
- `--flags value`, `-F value`: 日志记录器的标志
|
|
||||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
|
||||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
|
||||||
- `--color`: 在日志中使用颜色
|
|
||||||
- `--reconnect-on-message`, `-R`: 对于每个消息重新连接主机
|
|
||||||
- `--reconnect`, `-r`: 连接中断时重新连接主机
|
|
||||||
- `--protocol value`, `-P value`: 设置要使用的协议:tcp、unix或udp(默认为tcp)
|
|
||||||
- `--address value`, `-a value`: 要连接到的主机地址和端口(默认为:7020)
|
|
||||||
- `smtp`: 添加SMTP日志记录器
|
|
||||||
- 选项:
|
|
||||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
|
||||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
|
||||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
|
||||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
|
||||||
- `--flags value`, `-F value`: 日志记录器的标志
|
|
||||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
|
||||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
|
||||||
- `--color`: 在日志中使用颜色
|
|
||||||
- `--username value`, `-u value`: 邮件服务器用户名
|
|
||||||
- `--password value`, `-P value`: 邮件服务器密码
|
|
||||||
- `--host value`, `-H value`: 邮件服务器主机(默认为: 127.0.0.1:25)
|
|
||||||
- `--send-to value`, `-s value`: 要发送到的电子邮件地址
|
|
||||||
- `--subject value`, `-S value`: 发送电子邮件的主题标题
|
|
||||||
- `processes`: 显示 Gitea 进程和 Goroutine 信息
|
|
||||||
- 选项:
|
|
||||||
- `--flat`: 以平面表格形式显示进程,而不是树形结构
|
|
||||||
- `--no-system`: 不显示系统进程
|
|
||||||
- `--stacktraces`: 显示与进程关联的 Goroutine 的堆栈跟踪
|
|
||||||
- `--json`: 输出为 JSON 格式
|
|
||||||
- `--cancel PID`: 向具有 PID 的进程发送取消命令(仅适用于非系统进程)
|
|
||||||
|
|
||||||
### dump-repo
|
|
||||||
|
|
||||||
`dump-repo` 从 Git/GitHub/Gitea/GitLab 中转储存储库数据:
|
|
||||||
|
|
||||||
- 选项:
|
|
||||||
- `--git_service service`:Git 服务,可以是 `git`、`github`、`gitea`、`gitlab`。如果 `clone_addr` 可以被识别,则可以忽略此选项。
|
|
||||||
- `--repo_dir dir`,`-r dir`:存储数据的存储库目录路径。
|
|
||||||
- `--clone_addr addr`:将被克隆的 URL,目前可以是 git/github/gitea/gitlab 的 http/https URL。例如:https://github.com/lunny/tango.git
|
|
||||||
- `--auth_username lunny`:访问 `clone_addr` 的用户名。
|
|
||||||
- `--auth_password <password>`:访问 `clone_addr` 的密码。
|
|
||||||
- `--auth_token <token>`:访问 `clone_addr` 的个人令牌。
|
|
||||||
- `--owner_name lunny`:如果非空,数据将存储在具有所有者名称的目录中。
|
|
||||||
- `--repo_name tango`:如果非空,数据将存储在具有存储库名称的目录中。
|
|
||||||
- `--units <units>`:要迁移的项目,一个或多个项目应以逗号分隔。允许的项目有 wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments。如果为空,则表示所有项目。
|
|
||||||
|
|
||||||
### restore-repo
|
|
||||||
|
|
||||||
`restore-repo` 从磁盘目录中还原存储库数据:
|
|
||||||
|
|
||||||
- 选项:
|
|
||||||
- `--repo_dir dir`,`-r dir`:还原数据的存储库目录路径。
|
|
||||||
- `--owner_name lunny`:还原目标所有者名称。
|
|
||||||
- `--repo_name tango`:还原目标存储库名称。
|
|
||||||
- `--units <units>`:要还原的项目,一个或多个项目应以逗号分隔。允许的项目有 wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments。如果为空,则表示所有项目。
|
|
||||||
|
|
||||||
### actions generate-runner-token
|
|
||||||
|
|
||||||
生成一个供 Runner 使用的新令牌,用于向服务器注册。
|
|
||||||
|
|
||||||
- 选项:
|
|
||||||
- `--scope {owner}[/{repo}]`,`-s {owner}[/{repo}]`:限制 Runner 的范围,没有范围表示该 Runner 可用于所有仓库,但你也可以将其限制为特定的仓库或所有者。
|
|
||||||
|
|
||||||
要注册全局 Runner:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea actions generate-runner-token
|
|
||||||
```
|
|
||||||
|
|
||||||
要注册特定组织的 Runner,例如 `org`:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea actions generate-runner-token -s org
|
|
||||||
```
|
|
||||||
|
|
||||||
要注册特定仓库的 Runner,例如 `username/test-repo`:
|
|
||||||
|
|
||||||
```
|
|
||||||
gitea actions generate-runner-token -s username/test-repo
|
|
||||||
```
|
|
||||||
@@ -5,8 +5,6 @@ slug: "config-cheat-sheet"
|
|||||||
weight: 30
|
weight: 30
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/config-cheat-sheet
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -44,27 +42,28 @@ reported as part of the default configuration when running `gitea --help` or on
|
|||||||
|
|
||||||
- _`AppPath`_: This is the absolute path of the running gitea binary.
|
- _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||||
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||||
- The `WORK_PATH` option in `app.ini`
|
|
||||||
- The `--work-path` flag passed to the binary
|
- The `--work-path` flag passed to the binary
|
||||||
- The environment variable `$GITEA_WORK_DIR`
|
- The environment variable `$GITEA_WORK_DIR`
|
||||||
- A built-in value set at build time (see building from source)
|
- A built-in value set at build time (see building from source)
|
||||||
- Otherwise, it defaults to the directory of the _`AppPath`_
|
- Otherwise it defaults to the directory of the _`AppPath`_
|
||||||
- If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
|
the directory of the _`AppPath`_
|
||||||
- _`CustomPath`_: This is the base directory for custom templates and other options.
|
- _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||||
It is determined by using the first set thing in the following hierarchy:
|
It is determined by using the first set thing in the following hierarchy:
|
||||||
- The `--custom-path` flag passed to the binary
|
- The `--custom-path` flag passed to the binary
|
||||||
- The environment variable `$GITEA_CUSTOM`
|
- The environment variable `$GITEA_CUSTOM`
|
||||||
- A built-in value set at build time (see building from source)
|
- A built-in value set at build time (see building from source)
|
||||||
- Otherwise, it defaults to _`AppWorkPath`_`/custom`
|
- Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||||
- If any of the above are relative paths then they are made absolute against the
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
the directory of the _`AppWorkPath`_
|
the directory of the _`AppWorkPath`_
|
||||||
- _`CustomConf`_: This is the path to the `app.ini` file.
|
- _`CustomConf`_: This is the path to the `app.ini` file.
|
||||||
- The `--config` flag passed to the binary
|
- The `--config` flag passed to the binary
|
||||||
- A built-in value set at build time (see building from source)
|
- A built-in value set at build time (see building from source)
|
||||||
- Otherwise, it defaults to _`CustomPath`_`/conf/app.ini`
|
- Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||||
- If any of the above are relative paths then they are made absolute against the directory of the _`CustomPath`_
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
|
the directory of the _`CustomPath`_
|
||||||
|
|
||||||
In addition, there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||||
|
|
||||||
## Overall (`DEFAULT`)
|
## Overall (`DEFAULT`)
|
||||||
|
|
||||||
@@ -72,8 +71,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
|||||||
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as.
|
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as.
|
||||||
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
|
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
|
||||||
to not start.
|
to not start.
|
||||||
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging: `dev` or `prod`, default is `prod`. Mode `dev` makes Gitea easier to develop and debug, values other than `dev` are treated as `prod` which is for production use.
|
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
|
||||||
- `WORK_PATH`: **_the-work-path_**: The working directory, see the comment of AppWorkPath above.
|
|
||||||
|
|
||||||
## Repository (`repository`)
|
## Repository (`repository`)
|
||||||
|
|
||||||
@@ -89,14 +87,16 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
|||||||
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: Default private when creating a new repository with push-to-create.
|
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: Default private when creating a new repository with push-to-create.
|
||||||
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
|
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
|
||||||
`-1` means no limit.
|
`-1` means no limit.
|
||||||
|
- `PULL_REQUEST_QUEUE_LENGTH`: **1000**: Length of pull request patch test queue, make it. **DEPRECATED** use `LENGTH` in `[queue.pr_patch_checker]`.
|
||||||
|
as large as possible. Use caution when editing this value.
|
||||||
|
- `MIRROR_QUEUE_LENGTH`: **1000**: Patch test queue length, increase if pull request patch
|
||||||
|
testing starts hanging. **DEPRECATED** use `LENGTH` in `[queue.mirror]`.
|
||||||
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at
|
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at
|
||||||
the top of the list. Name must match file name in options/license or custom/options/license.
|
the top of the list. Name must match file name in options/license or custom/options/license.
|
||||||
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the
|
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the
|
||||||
HTTP protocol.
|
HTTP protocol.
|
||||||
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when
|
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when
|
||||||
default SSH port is used.
|
default SSH port is used.
|
||||||
- `GO_GET_CLONE_URL_PROTOCOL`: **https**: Value for the "go get" request returns the repository url as https or ssh
|
|
||||||
default is https.
|
|
||||||
- `ACCESS_CONTROL_ALLOW_ORIGIN`: **\<empty\>**: Value for Access-Control-Allow-Origin header,
|
- `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
|
default is not to present. **WARNING**: This maybe harmful to you website if you do not
|
||||||
give it a right value.
|
give it a right value.
|
||||||
@@ -117,7 +117,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
|||||||
|
|
||||||
### Repository - Editor (`repository.editor`)
|
### Repository - Editor (`repository.editor`)
|
||||||
|
|
||||||
- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,.livemd,**: List of file extensions for which lines should be wrapped in the Monaco editor. Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,**: List of file extensions for which lines should be wrapped in the Monaco editor. Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||||
- `PREVIEWABLE_FILE_MODES`: **markdown**: Valid file modes that have a preview API associated with them, such as `api/v1/markdown`. Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match.
|
- `PREVIEWABLE_FILE_MODES`: **markdown**: Valid file modes that have a preview API associated with them, such as `api/v1/markdown`. Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match.
|
||||||
|
|
||||||
### Repository - Pull Request (`repository.pull-request`)
|
### Repository - Pull Request (`repository.pull-request`)
|
||||||
@@ -141,7 +141,6 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
|||||||
### Repository - Issue (`repository.issue`)
|
### 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
|
- `LOCK_REASONS`: **Too heated,Off-topic,Resolved,Spam**: A list of reasons why a Pull Request or Issue can be locked
|
||||||
- `MAX_PINNED`: **3**: Maximum number of pinned Issues per Repo. Set to 0 to disable pinning Issues.
|
|
||||||
|
|
||||||
### Repository - Upload (`repository.upload`)
|
### Repository - Upload (`repository.upload`)
|
||||||
|
|
||||||
@@ -221,6 +220,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
|
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
|
||||||
- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes.
|
- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes.
|
||||||
regardless of the value of `DEFAULT_THEME`.
|
regardless of the value of `DEFAULT_THEME`.
|
||||||
|
- `THEME_COLOR_META_TAG`: **#6cc644**: Value of `theme-color` meta tag, used by Android >= 5.0. An invalid color like "none" or "disable" will have the default style. More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||||
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
||||||
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
||||||
Values can be emoji alias (:smile:) or a unicode emoji.
|
Values can be emoji alias (:smile:) or a unicode emoji.
|
||||||
@@ -230,6 +230,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
add it to this config.
|
add it to this config.
|
||||||
- `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.
|
- `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.
|
- `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page.
|
||||||
|
- `USE_SERVICE_WORKER`: **false**: Whether to enable a Service Worker to cache frontend assets.
|
||||||
- `ONLY_SHOW_RELEVANT_REPOS`: **false** Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
- `ONLY_SHOW_RELEVANT_REPOS`: **false** Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
||||||
A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
||||||
|
|
||||||
@@ -275,8 +276,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
trailing whitespace to paragraphs is not necessary to force a line break.
|
trailing whitespace to paragraphs is not necessary to force a line break.
|
||||||
- `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional
|
- `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
|
URL hyperlinks to be rendered in Markdown. URLs beginning in http and https are
|
||||||
always displayed. If this entry is empty, all URL schemes are allowed
|
always displayed
|
||||||
- `FILE_EXTENSIONS`: **.md,.markdown,.mdown,.mkd,.livemd**: 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.
|
|
||||||
- `ENABLE_MATH`: **true**: Enables detection of `\(...\)`, `\[...\]`, `$...$` and `$$...$$` blocks as math blocks.
|
- `ENABLE_MATH`: **true**: Enables detection of `\(...\)`, `\[...\]`, `$...$` and `$$...$$` blocks as math blocks.
|
||||||
|
|
||||||
## Server (`server`)
|
## Server (`server`)
|
||||||
@@ -345,7 +345,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `SSH_SERVER_MACS`: **hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect
|
- `SSH_SERVER_MACS`: **hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect
|
||||||
- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If no key exists a 4096 bit RSA key will be created for you.
|
- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If no key exists a 4096 bit RSA key will be created for you.
|
||||||
- `SSH_KEY_TEST_PATH`: **/tmp**: Directory to create temporary files in when testing public keys using ssh-keygen, default is the system temporary directory.
|
- `SSH_KEY_TEST_PATH`: **/tmp**: Directory to create temporary files in when testing public keys using ssh-keygen, default is the system temporary directory.
|
||||||
- `SSH_KEYGEN_PATH`: **\<empty\>**: Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
|
- `SSH_KEYGEN_PATH`: **ssh-keygen**: Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
|
||||||
- `SSH_EXPOSE_ANONYMOUS`: **false**: Enable exposure of SSH clone URL to anonymous visitors, default is false.
|
- `SSH_EXPOSE_ANONYMOUS`: **false**: Enable exposure of SSH clone URL to anonymous visitors, default is false.
|
||||||
- `SSH_PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the SSH connections. (Set to
|
- `SSH_PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the SSH connections. (Set to
|
||||||
-1 to disable all timeouts.)
|
-1 to disable all timeouts.)
|
||||||
@@ -365,7 +365,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `LFS_START_SERVER`: **false**: Enables Git LFS support.
|
- `LFS_START_SERVER`: **false**: Enables Git LFS support.
|
||||||
- `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)s/lfs**: Default LFS content path. (if it is on local storage.) **DEPRECATED** use settings in `[lfs]`.
|
- `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)s/lfs**: Default LFS content path. (if it is on local storage.) **DEPRECATED** use settings in `[lfs]`.
|
||||||
- `LFS_JWT_SECRET`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
- `LFS_JWT_SECRET`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
||||||
- `LFS_HTTP_AUTH_EXPIRY`: **24h**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
- `LFS_HTTP_AUTH_EXPIRY`: **20m**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
||||||
- `LFS_MAX_FILE_SIZE`: **0**: Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
- `LFS_MAX_FILE_SIZE`: **0**: Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
||||||
- `LFS_LOCKS_PAGING_NUM`: **50**: Maximum number of LFS Locks returned per page.
|
- `LFS_LOCKS_PAGING_NUM`: **50**: Maximum number of LFS Locks returned per page.
|
||||||
|
|
||||||
@@ -458,13 +458,17 @@ relation to port exhaustion.
|
|||||||
|
|
||||||
## Indexer (`indexer`)
|
## Indexer (`indexer`)
|
||||||
|
|
||||||
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db`, `elasticsearch` or `meilisearch`.
|
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db` or `elasticsearch`.
|
||||||
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch, or meilisearch. i.e. http://elastic:changeme@localhost:9200
|
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
||||||
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch. Relative paths will be made absolute against _`AppWorkPath`_.
|
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
|
- 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`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
- `ISSUE_INDEXER_QUEUE_DIR`: **queues/common**: When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this will be the path where the queue will be saved. **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
|
- `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. When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: Batch queue number. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
|
||||||
- `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, about 6 times more than the repository size).
|
||||||
- `REPO_INDEXER_REPO_TYPES`: **sources,forks,mirrors,templates**: Repo indexer units. The items to index could be `sources`, `forks`, `mirrors`, `templates` or any combination of them separated by a comma. If empty then it defaults to `sources` only, as if you'd like to disable fully please see `REPO_INDEXER_ENABLED`.
|
|
||||||
- `REPO_INDEXER_TYPE`: **bleve**: Code search engine type, could be `bleve` or `elasticsearch`.
|
- `REPO_INDEXER_TYPE`: **bleve**: Code search engine type, could be `bleve` or `elasticsearch`.
|
||||||
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: Index file used for code search.
|
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: Index file used for code search.
|
||||||
- `REPO_INDEXER_CONN_STR`: ****: Code indexer connection string, available when `REPO_INDEXER_TYPE` is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
- `REPO_INDEXER_CONN_STR`: ****: Code indexer connection string, available when `REPO_INDEXER_TYPE` is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
||||||
@@ -473,6 +477,7 @@ relation to port exhaustion.
|
|||||||
- `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_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`.
|
- `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`.
|
||||||
- `REPO_INDEXER_EXCLUDE_VENDORED`: **true**: Exclude vendored files from index.
|
- `REPO_INDEXER_EXCLUDE_VENDORED`: **true**: Exclude vendored files from index.
|
||||||
|
- `UPDATE_BUFFER_LEN`: **20**: Buffer length of index request. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
- `MAX_FILE_SIZE`: **1048576**: Maximum size in bytes of files to be indexed.
|
- `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 -1 to never timeout.
|
- `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 -1 to never timeout.
|
||||||
|
|
||||||
@@ -480,14 +485,23 @@ relation to port exhaustion.
|
|||||||
|
|
||||||
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
|
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
|
||||||
|
|
||||||
- `TYPE`: **level**: General queue type, currently support: `level` (uses a LevelDB internally), `channel`, `redis`, `dummy`. Invalid types are treated as `level`.
|
- `TYPE`: **persistable-channel**: General queue type, currently support: `persistable-channel` (uses a LevelDB internally), `channel`, `level`, `redis`, `dummy`
|
||||||
- `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
- `DATADIR`: **queues/**: Base DataDir for storing persistent and level queues. `DATADIR` for individual queues can be set in `queue.name` sections but will default to `DATADIR/`**`common`**. (Previously each queue would default to `DATADIR/`**`name`**.) Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
- `LENGTH`: **100**: Maximal queue size before channel queues block
|
- `LENGTH`: **20**: Maximal queue size before channel queues block
|
||||||
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
||||||
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. For `redis-cluster` use `redis+cluster://127.0.0.1:6379/0`. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Options can be set using query params. Similarly LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
||||||
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
|
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
|
||||||
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to **`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
|
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to
|
||||||
|
**`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden 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`: **0**: Number of initial workers for the queue.
|
||||||
- `MAX_WORKERS`: **10**: Maximum number of worker go-routines 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`: **1**: This many workers will be added to the worker pool if there is a boost.
|
||||||
|
|
||||||
Gitea creates the following non-unique queues:
|
Gitea creates the following non-unique queues:
|
||||||
|
|
||||||
@@ -505,6 +519,21 @@ And the following unique queues:
|
|||||||
- `mirror`
|
- `mirror`
|
||||||
- `pr_patch_checker`
|
- `pr_patch_checker`
|
||||||
|
|
||||||
|
Certain queues have defaults that override the defaults set in `[queue]` (this occurs mostly to support older configuration):
|
||||||
|
|
||||||
|
- `[queue.issue_indexer]`
|
||||||
|
- `TYPE` this will default to `[queue]` `TYPE` if it is set but if not it will appropriately convert `[indexer]` `ISSUE_INDEXER_QUEUE_TYPE` if that is set.
|
||||||
|
- `LENGTH` will default to `[indexer]` `UPDATE_BUFFER_LEN` if that is set.
|
||||||
|
- `BATCH_LENGTH` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_BATCH_NUMBER` if that is set.
|
||||||
|
- `DATADIR` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_DIR` if that is set.
|
||||||
|
- `CONN_STR` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_CONN_STR` if that is set.
|
||||||
|
- `[queue.mailer]`
|
||||||
|
- `LENGTH` will default to **100** or whatever `[mailer]` `SEND_BUFFER_LEN` is.
|
||||||
|
- `[queue.pr_patch_checker]`
|
||||||
|
- `LENGTH` will default to **1000** or whatever `[repository]` `PULL_REQUEST_QUEUE_LENGTH` is.
|
||||||
|
- `[queue.mirror]`
|
||||||
|
- `LENGTH` will default to **1000** or whatever `[repository]` `MIRROR_QUEUE_LENGTH` is.
|
||||||
|
|
||||||
## Admin (`admin`)
|
## Admin (`admin`)
|
||||||
|
|
||||||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
||||||
@@ -514,7 +543,7 @@ And the following unique queues:
|
|||||||
|
|
||||||
- `INSTALL_LOCK`: **false**: Controls access to the installation page. When set to "true", the installation page is not accessible.
|
- `INSTALL_LOCK`: **false**: Controls access to the installation page. When set to "true", the installation page is not accessible.
|
||||||
- `SECRET_KEY`: **\<random at every install\>**: Global secret key. This key is VERY IMPORTANT, if you lost it, the data encrypted by it (like 2FA secret) can't be decrypted anymore.
|
- `SECRET_KEY`: **\<random at every install\>**: Global secret key. This key is VERY IMPORTANT, if you lost it, the data encrypted by it (like 2FA secret) can't be decrypted anymore.
|
||||||
- `SECRET_KEY_URI`: **\<empty\>**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY.
|
- `SECRET_KEY_URI`: **<empty>**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY.
|
||||||
- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days.
|
- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days.
|
||||||
- `COOKIE_USERNAME`: **gitea\_awesome**: Name of the cookie used to store the current username.
|
- `COOKIE_USERNAME`: **gitea\_awesome**: Name of the cookie used to store the current username.
|
||||||
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication
|
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication
|
||||||
@@ -540,7 +569,7 @@ And the following unique queues:
|
|||||||
- `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.
|
- `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.
|
- `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`: **\<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`)
|
- `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 \[argon2, pbkdf2, pbkdf2_v1, pbkdf2_hi, scrypt, bcrypt\], argon2 and scrypt will spend significant amounts of memory.
|
- `PASSWORD_HASH_ALGO`: **pbkdf2**: The hash algorithm to use \[argon2, pbkdf2, pbkdf2_v1, pbkdf2_hi, scrypt, bcrypt\], argon2 and scrypt will spend significant amounts of memory.
|
||||||
- Note: The default parameters for `pbkdf2` hashing have changed - the previous settings are available as `pbkdf2_v1` but are not recommended.
|
- Note: The default parameters for `pbkdf2` hashing have changed - the previous settings are available as `pbkdf2_v1` but are not recommended.
|
||||||
- The hash functions may be tuned by using `$` after the algorithm:
|
- The hash functions may be tuned by using `$` after the algorithm:
|
||||||
@@ -571,8 +600,8 @@ And the following unique queues:
|
|||||||
## Camo (`camo`)
|
## Camo (`camo`)
|
||||||
|
|
||||||
- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
|
- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
|
||||||
- `SERVER_URL`: **\<empty\>**: URL of camo server, it **is required** if camo is enabled.
|
- `SERVER_URL`: **<empty>**: URL of camo server, it **is required** if camo is enabled.
|
||||||
- `HMAC_KEY`: **\<empty\>**: Provide the HMAC key for encoding URLs, it **is required** if camo is enabled.
|
- `HMAC_KEY`: **<empty>**: Provide the HMAC key for encoding URLs, it **is required** if camo is enabled.
|
||||||
- `ALLWAYS`: **false**: Set to true to use camo for both HTTP and HTTPS content, otherwise only non-HTTPS URLs are proxied
|
- `ALLWAYS`: **false**: Set to true to use camo for both HTTP and HTTPS content, otherwise only non-HTTPS URLs are proxied
|
||||||
|
|
||||||
## OpenID (`openid`)
|
## OpenID (`openid`)
|
||||||
@@ -651,8 +680,9 @@ And the following unique queues:
|
|||||||
- `ENABLE_TIMETRACKING`: **true**: Enable Timetracking feature.
|
- `ENABLE_TIMETRACKING`: **true**: Enable Timetracking feature.
|
||||||
- `DEFAULT_ENABLE_TIMETRACKING`: **true**: Allow repositories to use timetracking by default.
|
- `DEFAULT_ENABLE_TIMETRACKING`: **true**: Allow repositories to use timetracking by default.
|
||||||
- `DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME`: **true**: Only allow users with write permissions to track time.
|
- `DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME`: **true**: Only allow users with write permissions to track time.
|
||||||
- `EMAIL_DOMAIN_ALLOWLIST`: **\<empty\>**: If non-empty, comma separated list of domain names that can only be used to register on this instance, wildcard is supported.
|
- `EMAIL_DOMAIN_WHITELIST`: **\<empty\>**: If non-empty, list of domain names that can only be used to register
|
||||||
- `EMAIL_DOMAIN_BLOCKLIST`: **\<empty\>**: If non-empty, comma separated list of domain names that cannot be used to register on this instance, wildcard is supported.
|
on this instance.
|
||||||
|
- `EMAIL_DOMAIN_BLOCKLIST`: **\<empty\>**: If non-empty, list of domain names that cannot be used to register on this instance
|
||||||
- `SHOW_REGISTRATION_BUTTON`: **! DISABLE\_REGISTRATION**: Show Registration Button
|
- `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
|
- `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_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
|
||||||
@@ -755,11 +785,10 @@ and
|
|||||||
## Cache (`cache`)
|
## Cache (`cache`)
|
||||||
|
|
||||||
- `ENABLED`: **true**: Enable the cache.
|
- `ENABLED`: **true**: Enable the cache.
|
||||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `redis-cluster`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
||||||
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
|
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
|
||||||
- `HOST`: **\<empty\>**: Connection string for `redis`, `redis-cluster` and `memcache`. For `twoqueue` sets configuration for the queue.
|
- `HOST`: **\<empty\>**: Connection string for `redis` and `memcache`. For `twoqueue` sets configuration for the queue.
|
||||||
- Redis: `redis://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
- Redis: `redis://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||||
- Redis-cluster `redis+cluster://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
|
||||||
- Memcache: `127.0.0.1:9090;127.0.0.1:9091`
|
- Memcache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||||
- TwoQueue LRU cache: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000` representing the maximum number of objects stored in the cache.
|
- TwoQueue LRU cache: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000` representing the maximum number of objects stored in the cache.
|
||||||
- `ITEM_TTL`: **16h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
|
- `ITEM_TTL`: **16h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
|
||||||
@@ -772,7 +801,7 @@ and
|
|||||||
|
|
||||||
## Session (`session`)
|
## Session (`session`)
|
||||||
|
|
||||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, redis-cluster, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
||||||
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
|
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
|
- `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.
|
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
|
||||||
@@ -792,10 +821,9 @@ and
|
|||||||
- `AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
|
- `AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
|
||||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store user avatar image files.
|
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store user avatar image files.
|
||||||
- `AVATAR_MAX_WIDTH`: **4096**: Maximum avatar image width in pixels.
|
- `AVATAR_MAX_WIDTH`: **4096**: Maximum avatar image width in pixels.
|
||||||
- `AVATAR_MAX_HEIGHT`: **4096**: Maximum avatar image height in pixels.
|
- `AVATAR_MAX_HEIGHT`: **3072**: Maximum avatar image height in pixels.
|
||||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1MiB): Maximum avatar image file size in bytes.
|
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1Mb): Maximum avatar image file size in bytes.
|
||||||
- `AVATAR_MAX_ORIGIN_SIZE`: **262144** (256KiB): If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
|
- `AVATAR_RENDERED_SIZE_FACTOR`: **3**: The multiplication factor for rendered avatar images. Larger values result in finer rendering on HiDPI devices.
|
||||||
- `AVATAR_RENDERED_SIZE_FACTOR`: **2**: The multiplication factor for rendered avatar images. Larger values result in finer rendering on HiDPI devices.
|
|
||||||
|
|
||||||
- `REPOSITORY_AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
|
- `REPOSITORY_AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
|
||||||
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: Path to store repository avatar image files.
|
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: Path to store repository avatar image files.
|
||||||
@@ -834,48 +862,48 @@ Default templates for project boards:
|
|||||||
## Log (`log`)
|
## Log (`log`)
|
||||||
|
|
||||||
- `ROOT_PATH`: **\<empty\>**: Root path for log files.
|
- `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.writer-mode-name\]`.
|
- `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\]
|
- `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 (rarely useful, do not set it). \[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\]
|
||||||
- `ENABLE_SSH_LOG`: **false**: save ssh log to log file
|
- `ENABLE_SSH_LOG`: **false**: save ssh log to log file
|
||||||
- `logger.access.MODE`: **\<empty\>**: The "access" logger
|
- `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.
|
||||||
- `logger.router.MODE`: **,**: The "router" logger, a single comma means it will use the default MODE above
|
|
||||||
- `logger.xorm.MODE`: **,**: The "xorm" logger
|
### Router Log (`log`)
|
||||||
|
|
||||||
|
- `DISABLE_ROUTER_LOG`: **false**: Mute printing of the router log.
|
||||||
|
- `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 have `DISABLE_ROUTER_LOG` set to `false` for this option to take effect. Configure each mode in per mode log subsections `\[log.modename.router\]`.
|
||||||
|
|
||||||
### Access Log (`log`)
|
### Access Log (`log`)
|
||||||
|
|
||||||
- `ACCESS_LOG_TEMPLATE`: **`{{.Ctx.RemoteHost}} - {{.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.
|
- `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:
|
- The following variables are available:
|
||||||
- `Ctx`: the `context.Context` of the request.
|
- `Ctx`: the `context.Context` of the request.
|
||||||
- `Identity`: the SignedUserName or `"-"` if not logged in.
|
- `Identity`: the SignedUserName or `"-"` if not logged in.
|
||||||
- `Start`: the start time of the request.
|
- `Start`: the start time of the request.
|
||||||
- `ResponseWriter`: the responseWriter from the request.
|
- `ResponseWriter`: the responseWriter from the request.
|
||||||
- `RequestID`: the value matching REQUEST_ID_HEADERS(default: `-`, if not matched).
|
- 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.
|
||||||
- You must be very careful to ensure that this template does not throw errors or panics as this template runs outside the panic/recovery script.
|
|
||||||
- `REQUEST_ID_HEADERS`: **\<empty\>**: You can configure multiple values that are splited by comma here. It will match in the order of configuration, and the first match will be finally printed in the access log.
|
|
||||||
- e.g.
|
|
||||||
- In the Request Header: X-Request-ID: **test-id-123**
|
|
||||||
- Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
|
|
||||||
- Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
|
|
||||||
|
|
||||||
### Log subsections (`log.<writer-mode-name>`)
|
### Log subsections (`log.name`, `log.name.*`)
|
||||||
|
|
||||||
- `MODE`: **name**: Sets the mode of this log writer - Defaults to the provided subsection name. This allows you to have two different file loggers at different levels.
|
- `LEVEL`: **log.LEVEL**: Sets the log-level of this sublogger. Defaults to the `LEVEL` set in the global `[log]` section.
|
||||||
- `LEVEL`: **log.LEVEL**: Sets the log-level of this writer. 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.
|
- `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.
|
- `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/flags.go` for more information.
|
- `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/flags.go` for more information.
|
||||||
- `PREFIX`: **""**: An additional prefix for every log line in this logger. Defaults to empty.
|
- `PREFIX`: **""**: An additional prefix for every log line in this logger. Defaults to empty.
|
||||||
- `COLORIZE`: **false**: Whether to colorize the log lines
|
- `COLORIZE`: **false**: Whether to colorize the log lines
|
||||||
|
|
||||||
### Console log mode (`log.console`, or `MODE=console`)
|
### 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.
|
- 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.
|
- `STDERR`: **false**: Use Stderr instead of Stdout.
|
||||||
|
|
||||||
### File log mode (`log.file`, or `MODE=file`)
|
### File log mode (`log.file`, `log.file.*` or `MODE=file`)
|
||||||
|
|
||||||
- `FILE_NAME`: Set the file name for this logger. Defaults to `gitea.log` (exception: access log defaults to `access.log`). If relative will be relative to the `ROOT_PATH`
|
- `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.
|
- `LOG_ROTATE`: **true**: Rotate the log files.
|
||||||
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb.
|
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb.
|
||||||
- `DAILY_ROTATE`: **true**: Rotate logs daily.
|
- `DAILY_ROTATE`: **true**: Rotate logs daily.
|
||||||
@@ -883,13 +911,21 @@ Default templates for project boards:
|
|||||||
- `COMPRESS`: **true**: Compress old log files by default with gzip
|
- `COMPRESS`: **true**: Compress old log files by default with gzip
|
||||||
- `COMPRESSION_LEVEL`: **-1**: Compression level
|
- `COMPRESSION_LEVEL`: **-1**: Compression level
|
||||||
|
|
||||||
### Conn log mode (`log.conn`, or `MODE=conn`)
|
### Conn log mode (`log.conn`, `log.conn.*` or `MODE=conn`)
|
||||||
|
|
||||||
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
||||||
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
||||||
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
||||||
- `ADDR`: **:7020**: Sets the address to connect to.
|
- `ADDR`: **:7020**: Sets the address to connect to.
|
||||||
|
|
||||||
|
### SMTP log mode (`log.smtp`, `log.smtp.*` or `MODE=smtp`)
|
||||||
|
|
||||||
|
- `USER`: User email address to send from.
|
||||||
|
- `PASSWD`: Password for the smtp server.
|
||||||
|
- `HOST`: **127.0.0.1:25**: The SMTP host to connect to.
|
||||||
|
- `RECEIVERS`: Email addresses to send to.
|
||||||
|
- `SUBJECT`: **Diagnostic message from Gitea**
|
||||||
|
|
||||||
## Cron (`cron`)
|
## Cron (`cron`)
|
||||||
|
|
||||||
- `ENABLED`: **false**: Enable to run all cron tasks periodically with default settings.
|
- `ENABLED`: **false**: Enable to run all cron tasks periodically with default settings.
|
||||||
@@ -1005,7 +1041,7 @@ Default templates for project boards:
|
|||||||
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||||
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
|
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
|
||||||
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
||||||
- `OLDER_THAN`: **8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
|
- `OLDER_THAN`: **@every 8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
|
||||||
|
|
||||||
#### Cron - Check for new Gitea versions (`cron.update_checker`)
|
#### Cron - Check for new Gitea versions (`cron.update_checker`)
|
||||||
|
|
||||||
@@ -1013,7 +1049,7 @@ Default templates for project boards:
|
|||||||
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||||
- `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices.
|
- `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices.
|
||||||
- `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`.
|
- `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`.
|
||||||
- `HTTP_ENDPOINT`: **https://dl.gitea.com/gitea/version.json**: the endpoint that Gitea will check for newer versions
|
- `HTTP_ENDPOINT`: **https://dl.gitea.io/gitea/version.json**: the endpoint that Gitea will check for newer versions
|
||||||
|
|
||||||
#### Cron - Delete all old system notices from database (`cron.delete_old_system_notices`)
|
#### Cron - Delete all old system notices from database (`cron.delete_old_system_notices`)
|
||||||
|
|
||||||
@@ -1021,7 +1057,7 @@ Default templates for project boards:
|
|||||||
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||||
- `NO_SUCCESS_NOTICE`: **false**: Set to true to switch off success notices.
|
- `NO_SUCCESS_NOTICE`: **false**: Set to true to switch off success notices.
|
||||||
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
||||||
- `OLDER_THAN`: **8760h**: any system notice older than this expression will be deleted from database.
|
- `OLDER_THAN`: **@every 8760h**: any system notice older than this expression will be deleted from database.
|
||||||
|
|
||||||
#### Cron - Garbage collect LFS pointers in repositories (`cron.gc_lfs`)
|
#### Cron - Garbage collect LFS pointers in repositories (`cron.gc_lfs`)
|
||||||
|
|
||||||
@@ -1054,7 +1090,12 @@ Default templates for project boards:
|
|||||||
- `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false.
|
- `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false.
|
||||||
- `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git.
|
- `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git.
|
||||||
|
|
||||||
### Git - Timeout settings (`git.timeout`)
|
## Git - Reflog settings (`git.reflog`)
|
||||||
|
|
||||||
|
- `ENABLED`: **true** Set to true to enable Git to write changes to reflogs in each repo.
|
||||||
|
- `EXPIRATION`: **90** Reflog entry lifetime, in days. Entries are removed opportunistically by Git.
|
||||||
|
|
||||||
|
## Git - Timeout settings (`git.timeout`)
|
||||||
|
|
||||||
- `DEFAULT`: **360**: Git operations default timeout seconds.
|
- `DEFAULT`: **360**: Git operations default timeout seconds.
|
||||||
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
|
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
|
||||||
@@ -1063,15 +1104,6 @@ Default templates for project boards:
|
|||||||
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
|
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
|
||||||
- `GC`: **60**: Git repository GC timeout seconds.
|
- `GC`: **60**: Git repository GC timeout seconds.
|
||||||
|
|
||||||
### Git - Config options (`git.config`)
|
|
||||||
|
|
||||||
The key/value pairs in this section will be used as git config.
|
|
||||||
This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
|
|
||||||
|
|
||||||
- `diff.algorithm`: **histogram**
|
|
||||||
- `core.logAllRefUpdates`: **true**
|
|
||||||
- `gc.reflogExpire`: **90**
|
|
||||||
|
|
||||||
## Metrics (`metrics`)
|
## Metrics (`metrics`)
|
||||||
|
|
||||||
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
|
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
|
||||||
@@ -1115,7 +1147,7 @@ Gitea can support Markup using external tools. The example below will add a mark
|
|||||||
ENABLED = true
|
ENABLED = true
|
||||||
NEED_POSTPROCESS = true
|
NEED_POSTPROCESS = true
|
||||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||||
RENDER_COMMAND = "asciidoctor --embedded --safe-mode=secure --out-file=- -"
|
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||||
IS_INPUT_FILE = false
|
IS_INPUT_FILE = false
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1166,6 +1198,7 @@ in this mapping or the filetype using heuristics.
|
|||||||
|
|
||||||
## Time (`time`)
|
## Time (`time`)
|
||||||
|
|
||||||
|
- `FORMAT`: Time format to display 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. Asia/Shanghai
|
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
|
||||||
|
|
||||||
## Task (`task`)
|
## Task (`task`)
|
||||||
@@ -1174,7 +1207,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
|
|||||||
|
|
||||||
- `QUEUE_TYPE`: **channel**: Task queue type, could be `channel` or `redis`.
|
- `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_LENGTH`: **1000**: Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||||
- `QUEUE_CONN_STR`: **redis://127.0.0.1:6379/0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If redis needs a password, use `redis://123@127.0.0.1:6379/0` or `redis+cluster://123@127.0.0.1:6379/0`.
|
- `QUEUE_CONN_STR`: **redis://127.0.0.1:6379/0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If redis needs a password, use `redis://123@127.0.0.1:6379/0`.
|
||||||
|
|
||||||
## Migrations (`migrations`)
|
## Migrations (`migrations`)
|
||||||
|
|
||||||
@@ -1204,26 +1237,20 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
|
|||||||
- `CHUNKED_UPLOAD_PATH`: **tmp/package-upload**: Path for chunked uploads. Defaults to `APP_DATA_PATH` + `tmp/package-upload`
|
- `CHUNKED_UPLOAD_PATH`: **tmp/package-upload**: Path for chunked uploads. Defaults to `APP_DATA_PATH` + `tmp/package-upload`
|
||||||
- `LIMIT_TOTAL_OWNER_COUNT`: **-1**: Maximum count of package versions a single owner can have (`-1` means no limits)
|
- `LIMIT_TOTAL_OWNER_COUNT`: **-1**: Maximum count of package versions a single owner can have (`-1` means no limits)
|
||||||
- `LIMIT_TOTAL_OWNER_SIZE`: **-1**: Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_TOTAL_OWNER_SIZE`: **-1**: Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_ALPINE`: **-1**: Maximum size of an Alpine upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
- `LIMIT_SIZE_CARGO`: **-1**: Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_CARGO`: **-1**: Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_CHEF`: **-1**: Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_CHEF`: **-1**: Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_COMPOSER`: **-1**: Maximum size of a Composer upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_COMPOSER`: **-1**: Maximum size of a Composer upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_CONAN`: **-1**: Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_CONAN`: **-1**: Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_CONDA`: **-1**: Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_CONDA`: **-1**: Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_CRAN`: **-1**: Maximum size of a CRAN upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
- `LIMIT_SIZE_DEBIAN`: **-1**: Maximum size of a Debian upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
- `LIMIT_SIZE_GENERIC`: **-1**: Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_GENERIC`: **-1**: Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_GO`: **-1**: Maximum size of a Go upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
- `LIMIT_SIZE_HELM`: **-1**: Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_HELM`: **-1**: Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_MAVEN`: **-1**: Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_MAVEN`: **-1**: Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_NPM`: **-1**: Maximum size of a npm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_NPM`: **-1**: Maximum size of a npm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_NUGET`: **-1**: Maximum size of a NuGet upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_NUGET`: **-1**: Maximum size of a NuGet upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_RPM`: **-1**: Maximum size of a RPM upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
- `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
- `LIMIT_SIZE_SWIFT`: **-1**: Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
|
||||||
- `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
- `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
|
|
||||||
## Mirror (`mirror`)
|
## Mirror (`mirror`)
|
||||||
@@ -1254,9 +1281,8 @@ is `data/lfs` and the default of `MINIO_BASE_PATH` is `lfs/`.
|
|||||||
|
|
||||||
## Storage (`storage`)
|
## Storage (`storage`)
|
||||||
|
|
||||||
Default storage configuration for attachments, lfs, avatars, repo-avatars, repo-archive, packages, actions_log, actions_artifact.
|
Default storage configuration for attachments, lfs, avatars and etc.
|
||||||
|
|
||||||
- `STORAGE_TYPE`: **local**: Storage type, `local` for local disk or `minio` for s3 compatible object storage service.
|
|
||||||
- `SERVE_DIRECT`: **false**: Allows the storage driver to redirect to authenticated URLs to serve files directly. Currently, only Minio/S3 is supported via signed URLs, local does nothing.
|
- `SERVE_DIRECT`: **false**: Allows the storage driver to redirect to authenticated URLs to serve files directly. Currently, only Minio/S3 is supported via signed URLs, local does nothing.
|
||||||
- `MINIO_ENDPOINT`: **localhost:9000**: Minio endpoint to connect only available when `STORAGE_TYPE` is `minio`
|
- `MINIO_ENDPOINT`: **localhost:9000**: Minio endpoint to connect only available when `STORAGE_TYPE` is `minio`
|
||||||
- `MINIO_ACCESS_KEY_ID`: Minio accessKeyID to connect only available when `STORAGE_TYPE` is `minio`
|
- `MINIO_ACCESS_KEY_ID`: Minio accessKeyID to connect only available when `STORAGE_TYPE` is `minio`
|
||||||
@@ -1266,56 +1292,9 @@ Default storage configuration for attachments, lfs, avatars, repo-avatars, repo-
|
|||||||
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
|
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
|
||||||
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||||
|
|
||||||
The recommanded storage configuration for minio like below:
|
And you can also define a customize storage like below:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[storage]
|
|
||||||
STORAGE_TYPE = minio
|
|
||||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_ENDPOINT = localhost:9000
|
|
||||||
; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_ACCESS_KEY_ID =
|
|
||||||
; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_SECRET_ACCESS_KEY =
|
|
||||||
; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_BUCKET = gitea
|
|
||||||
; Minio location to create bucket only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_LOCATION = us-east-1
|
|
||||||
; Minio enabled ssl only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_USE_SSL = false
|
|
||||||
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_INSECURE_SKIP_VERIFY = false
|
|
||||||
SERVE_DIRECT = true
|
|
||||||
```
|
|
||||||
|
|
||||||
Defaultly every storage has their default base path like below
|
|
||||||
|
|
||||||
| storage | default base path |
|
|
||||||
| ----------------- | ------------------ |
|
|
||||||
| attachments | attachments/ |
|
|
||||||
| lfs | lfs/ |
|
|
||||||
| avatars | avatars/ |
|
|
||||||
| repo-avatars | repo-avatars/ |
|
|
||||||
| repo-archive | repo-archive/ |
|
|
||||||
| packages | packages/ |
|
|
||||||
| actions_log | actions_log/ |
|
|
||||||
| actions_artifacts | actions_artifacts/ |
|
|
||||||
|
|
||||||
And bucket, basepath or `SERVE_DIRECT` could be special or overrided, if you want to use a different you can:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[storage.actions_log]
|
|
||||||
MINIO_BUCKET = gitea_actions_log
|
|
||||||
SERVE_DIRECT = true
|
|
||||||
MINIO_BASE_PATH = my_actions_log/ ; default is actions_log/ if blank
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to customerize a different storage for `lfs` if above default storage defined
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[lfs]
|
|
||||||
STORAGE_TYPE = my_minio
|
|
||||||
|
|
||||||
[storage.my_minio]
|
[storage.my_minio]
|
||||||
STORAGE_TYPE = minio
|
STORAGE_TYPE = minio
|
||||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
||||||
@@ -1334,6 +1313,8 @@ MINIO_USE_SSL = false
|
|||||||
MINIO_INSECURE_SKIP_VERIFY = false
|
MINIO_INSECURE_SKIP_VERIFY = false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
And used by `[attachment]`, `[lfs]` and etc. as `STORAGE_TYPE`.
|
||||||
|
|
||||||
## Repository Archive Storage (`storage.repo-archive`)
|
## Repository Archive Storage (`storage.repo-archive`)
|
||||||
|
|
||||||
Configuration for repository archive storage. It will inherit from default `[storage]` or
|
Configuration for repository archive storage. It will inherit from default `[storage]` or
|
||||||
@@ -1352,11 +1333,6 @@ is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
|
|||||||
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
|
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
|
||||||
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||||
|
|
||||||
## Repository Archives (`repo-archive`)
|
|
||||||
|
|
||||||
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
|
||||||
- `MINIO_BASE_PATH`: **repo-archive/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
|
||||||
|
|
||||||
## Proxy (`proxy`)
|
## Proxy (`proxy`)
|
||||||
|
|
||||||
- `PROXY_ENABLED`: **false**: Enable the proxy if true, all requests to external via HTTP will be affected, if false, no proxy will be used even environment http_proxy/https_proxy
|
- `PROXY_ENABLED`: **false**: Enable the proxy if true, all requests to external via HTTP will be affected, if false, no proxy will be used even environment http_proxy/https_proxy
|
||||||
@@ -1374,25 +1350,41 @@ PROXY_HOSTS = *.github.com
|
|||||||
## Actions (`actions`)
|
## Actions (`actions`)
|
||||||
|
|
||||||
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
||||||
- `DEFAULT_ACTIONS_URL`: **github**: Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
- `DEFAULT_ACTIONS_URL`: **https://gitea.com**: Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
|
||||||
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
|
||||||
- `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
|
||||||
|
|
||||||
`DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path.
|
`DEFAULT_ACTIONS_URL` indicates where should we find the relative path action plugin. i.e. when use an action in a workflow file like
|
||||||
For example, `uses: actions/checkout@v3` means `https://github.com/actions/checkout@v3` since the value of `DEFAULT_ACTIONS_URL` is `github`.
|
|
||||||
And it can be changed to `self` to make it `root_url_of_your_gitea/actions/checkout@v3`.
|
|
||||||
|
|
||||||
Please note that using `self` is not recommended for most cases, as it could make names globally ambiguous.
|
```yaml
|
||||||
Additionally, it requires you to mirror all the actions you need to your Gitea instance, which may not be worth it.
|
name: versions
|
||||||
Therefore, please use `self` only if you understand what you are doing.
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- releases/*
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
```
|
||||||
|
|
||||||
In earlier versions (<= 1.19), `DEFAULT_ACTIONS_URL` cound be set to any custom URLs like `https://gitea.com` or `http://your-git-server,https://gitea.com`, and the default value was `https://gitea.com`.
|
Now we need to know how to get actions/checkout, this configuration is the default git server to get it. That means we will get the repository via git clone ${DEFAULT_ACTIONS_URL}/actions/checkout and fetch tag v3.
|
||||||
However, later updates removed those options, and now the only options are `github` and `self`, with the default value being `github`.
|
|
||||||
However, if you want to use actions from other git server, you can use a complete URL in `uses` field, it's supported by Gitea (but not GitHub).
|
To help people who don't want to mirror these actions in their git instances, the default value is https://gitea.com
|
||||||
Like `uses: https://gitea.com/actions/checkout@v3` or `uses: http://your-git-server/actions/checkout@v3`.
|
To help people run actions totally in their network, they can change the value and copy all necessary action repositories into their git server.
|
||||||
|
|
||||||
|
Of course we should support the form in future PRs like
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: gitea.com/actions/checkout@v3
|
||||||
|
```
|
||||||
|
|
||||||
|
although Github don't support this form.
|
||||||
|
|
||||||
## Other (`other`)
|
## Other (`other`)
|
||||||
|
|
||||||
|
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
|
||||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
|
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
|
||||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
||||||
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
|
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "config-cheat-sheet"
|
|||||||
weight: 30
|
weight: 30
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /zh-cn/config-cheat-sheet
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -18,7 +16,7 @@ menu:
|
|||||||
# 配置说明
|
# 配置说明
|
||||||
|
|
||||||
这是针对Gitea配置文件的说明,你可以了解Gitea的强大配置。需要说明的是,你的所有改变请修改 `custom/conf/app.ini` 文件而不是源文件。
|
这是针对Gitea配置文件的说明,你可以了解Gitea的强大配置。需要说明的是,你的所有改变请修改 `custom/conf/app.ini` 文件而不是源文件。
|
||||||
所有默认值可以通过 [app.example.ini](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini) 查看到。
|
所有默认值可以通过 [app.example.ini](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.example.ini) 查看到。
|
||||||
如果你发现 `%(X)s` 这样的内容,请查看 [ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。
|
如果你发现 `%(X)s` 这样的内容,请查看 [ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。
|
||||||
标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。
|
标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。
|
||||||
|
|
||||||
@@ -43,6 +41,7 @@ menu:
|
|||||||
- `DEFAULT_PRIVATE`: 默认创建的git工程为私有。 可以是`last`, `private` 或 `public`。默认值是 `last`表示用户最后创建的Repo的选择。
|
- `DEFAULT_PRIVATE`: 默认创建的git工程为私有。 可以是`last`, `private` 或 `public`。默认值是 `last`表示用户最后创建的Repo的选择。
|
||||||
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 通过 ``push-to-create`` 方式创建的仓库是否默认为私有仓库.
|
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 通过 ``push-to-create`` 方式创建的仓库是否默认为私有仓库.
|
||||||
- `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。
|
- `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。
|
||||||
|
- `PULL_REQUEST_QUEUE_LENGTH`: 小心:合并请求测试队列的长度,尽量放大。
|
||||||
|
|
||||||
### Repository - Release (`repository.release`)
|
### Repository - Release (`repository.release`)
|
||||||
|
|
||||||
@@ -110,6 +109,10 @@ menu:
|
|||||||
- `ISSUE_INDEXER_CONN_STR`: ****: 工单索引连接字符串,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
|
- `ISSUE_INDEXER_CONN_STR`: ****: 工单索引连接字符串,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
|
||||||
- `ISSUE_INDEXER_NAME`: **gitea_issues**: 工单索引名称,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。
|
- `ISSUE_INDEXER_NAME`: **gitea_issues**: 工单索引名称,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。
|
||||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: 工单索引文件存放路径,当索引类型为 `bleve` 时有效。
|
- `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**: 是否启用代码搜索(启用后会占用比较大的磁盘空间,如果是bleve可能需要占用约6倍存储空间)。
|
- `REPO_INDEXER_ENABLED`: **false**: 是否启用代码搜索(启用后会占用比较大的磁盘空间,如果是bleve可能需要占用约6倍存储空间)。
|
||||||
- `REPO_INDEXER_TYPE`: **bleve**: 代码搜索引擎类型,可以为 `bleve` 或者 `elasticsearch`。
|
- `REPO_INDEXER_TYPE`: **bleve**: 代码搜索引擎类型,可以为 `bleve` 或者 `elasticsearch`。
|
||||||
@@ -117,6 +120,7 @@ menu:
|
|||||||
- `REPO_INDEXER_CONN_STR`: ****: 代码搜索引擎连接字符串,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
|
- `REPO_INDEXER_CONN_STR`: ****: 代码搜索引擎连接字符串,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
|
||||||
- `REPO_INDEXER_NAME`: **gitea_codes**: 代码搜索引擎的名字,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。
|
- `REPO_INDEXER_NAME`: **gitea_codes**: 代码搜索引擎的名字,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。
|
||||||
|
|
||||||
|
- `UPDATE_BUFFER_LEN`: **20**: 代码索引请求的缓冲区长度。
|
||||||
- `MAX_FILE_SIZE`: **1048576**: 进行解析的源代码文件的最大长度,小于该值时才会索引。
|
- `MAX_FILE_SIZE`: **1048576**: 进行解析的源代码文件的最大长度,小于该值时才会索引。
|
||||||
|
|
||||||
## Security (`security`)
|
## Security (`security`)
|
||||||
@@ -214,8 +218,8 @@ menu:
|
|||||||
- `AVATAR_STORAGE_TYPE`: **local**: 头像存储类型,可以为 `local` 或 `minio`,分别支持本地文件系统和 minio 兼容的API。
|
- `AVATAR_STORAGE_TYPE`: **local**: 头像存储类型,可以为 `local` 或 `minio`,分别支持本地文件系统和 minio 兼容的API。
|
||||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: 存储头像的文件系统路径。
|
- `AVATAR_UPLOAD_PATH`: **data/avatars**: 存储头像的文件系统路径。
|
||||||
- `AVATAR_MAX_WIDTH`: **4096**: 头像最大宽度,单位像素。
|
- `AVATAR_MAX_WIDTH`: **4096**: 头像最大宽度,单位像素。
|
||||||
- `AVATAR_MAX_HEIGHT`: **4096**: 头像最大高度,单位像素。
|
- `AVATAR_MAX_HEIGHT`: **3072**: 头像最大高度,单位像素。
|
||||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1MiB): 头像最大大小。
|
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1Mb): 头像最大大小。
|
||||||
|
|
||||||
- `REPOSITORY_AVATAR_STORAGE_TYPE`: **local**: 仓库头像存储类型,可以为 `local` 或 `minio`,分别支持本地文件系统和 minio 兼容的API。
|
- `REPOSITORY_AVATAR_STORAGE_TYPE`: **local**: 仓库头像存储类型,可以为 `local` 或 `minio`,分别支持本地文件系统和 minio 兼容的API。
|
||||||
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: 存储仓库头像的路径。
|
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: 存储仓库头像的路径。
|
||||||
@@ -259,21 +263,6 @@ test01.xls: application/vnd.ms-excel; charset=binary
|
|||||||
- `ROOT_PATH`: 日志文件根目录。
|
- `ROOT_PATH`: 日志文件根目录。
|
||||||
- `MODE`: 日志记录模式,默认是为 `console`。如果要写到多个通道,用逗号分隔
|
- `MODE`: 日志记录模式,默认是为 `console`。如果要写到多个通道,用逗号分隔
|
||||||
- `LEVEL`: 日志级别,默认为`Trace`。
|
- `LEVEL`: 日志级别,默认为`Trace`。
|
||||||
- `DISABLE_ROUTER_LOG`: 关闭日志中的路由日志。
|
|
||||||
- `ENABLE_ACCESS_LOG`: 是否开启 Access Log, 默认为 false。
|
|
||||||
- `ACCESS_LOG_TEMPLATE`: `access.log` 输出内容的模板,默认模板:**`{{.Ctx.RemoteHost}} - {{.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}}"`**
|
|
||||||
模板支持以下参数:
|
|
||||||
- `Ctx`: 请求上下文。
|
|
||||||
- `Identity`: 登录用户名,默认: “`-`”。
|
|
||||||
- `Start`: 请求开始时间。
|
|
||||||
- `ResponseWriter`:
|
|
||||||
- `RequestID`: 从请求头中解析得到的与 `REQUEST_ID_HEADERS` 匹配的值,默认: “`-`”。
|
|
||||||
- 一定要谨慎配置该模板,否则可能会引起panic.
|
|
||||||
- `REQUEST_ID_HEADERS`: 从 Request Header 中匹配指定 Key,并将匹配到的值输出到 `access.log` 中(需要在 `ACCESS_LOG_TEMPLATE` 中指定输出位置)。如果在该参数中配置多个 Key, 请用逗号分割,程序将按照配置的顺序进行匹配。
|
|
||||||
- 示例:
|
|
||||||
- 请求头: X-Request-ID: **test-id-123**
|
|
||||||
- 配置文件: REQUEST_ID_HEADERS = X-Request-ID
|
|
||||||
- 日志输出: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
|
|
||||||
|
|
||||||
## Cron (`cron`)
|
## Cron (`cron`)
|
||||||
|
|
||||||
@@ -337,7 +326,7 @@ test01.xls: application/vnd.ms-excel; charset=binary
|
|||||||
ENABLED = false
|
ENABLED = false
|
||||||
NEED_POSTPROCESS = true
|
NEED_POSTPROCESS = true
|
||||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||||
RENDER_COMMAND = "asciidoctor --embedded --safe-mode=secure --out-file=- -"
|
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||||
IS_INPUT_FILE = false
|
IS_INPUT_FILE = false
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -414,7 +403,7 @@ LFS 的存储配置。 如果 `STORAGE_TYPE` 为空,则此配置将从 `[stora
|
|||||||
|
|
||||||
## Storage (`storage`)
|
## Storage (`storage`)
|
||||||
|
|
||||||
Attachments, lfs, avatars, repo-avatars, repo-archive, packages, actions_log, actions_artifact 的默认存储配置。
|
Attachments, lfs, avatars and etc 的默认存储配置。
|
||||||
|
|
||||||
- `STORAGE_TYPE`: **local**: 附件存储类型,`local` 将存储到本地文件夹, `minio` 将存储到 s3 兼容的对象存储服务中。
|
- `STORAGE_TYPE`: **local**: 附件存储类型,`local` 将存储到本地文件夹, `minio` 将存储到 s3 兼容的对象存储服务中。
|
||||||
- `SERVE_DIRECT`: **false**: 允许直接重定向到存储系统。当前,仅 Minio/S3 是支持的。
|
- `SERVE_DIRECT`: **false**: 允许直接重定向到存储系统。当前,仅 Minio/S3 是支持的。
|
||||||
@@ -425,59 +414,9 @@ Attachments, lfs, avatars, repo-avatars, repo-archive, packages, actions_log, ac
|
|||||||
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket,仅当 `STORAGE_TYPE` 是 `minio` 时有效。
|
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket,仅当 `STORAGE_TYPE` 是 `minio` 时有效。
|
||||||
- `MINIO_USE_SSL`: **false**: Minio enabled ssl,仅当 `STORAGE_TYPE` 是 `minio` 时有效。
|
- `MINIO_USE_SSL`: **false**: Minio enabled ssl,仅当 `STORAGE_TYPE` 是 `minio` 时有效。
|
||||||
|
|
||||||
以下为推荐的 recommanded storage configuration for minio like below:
|
你也可以自定义一个存储的名字如下:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[storage]
|
|
||||||
STORAGE_TYPE = minio
|
|
||||||
; uncomment when STORAGE_TYPE = local
|
|
||||||
; PATH = storage root path
|
|
||||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_ENDPOINT = localhost:9000
|
|
||||||
; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_ACCESS_KEY_ID =
|
|
||||||
; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_SECRET_ACCESS_KEY =
|
|
||||||
; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_BUCKET = gitea
|
|
||||||
; Minio location to create bucket only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_LOCATION = us-east-1
|
|
||||||
; Minio enabled ssl only available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_USE_SSL = false
|
|
||||||
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
|
||||||
MINIO_INSECURE_SKIP_VERIFY = false
|
|
||||||
SERVE_DIRECT = true
|
|
||||||
```
|
|
||||||
|
|
||||||
默认的,每一个存储都会有各自默认的 BasePath 在同一个minio中,默认值如下:
|
|
||||||
|
|
||||||
| storage | default base path |
|
|
||||||
| ----------------- | ------------------ |
|
|
||||||
| attachments | attachments/ |
|
|
||||||
| lfs | lfs/ |
|
|
||||||
| avatars | avatars/ |
|
|
||||||
| repo-avatars | repo-avatars/ |
|
|
||||||
| repo-archive | repo-archive/ |
|
|
||||||
| packages | packages/ |
|
|
||||||
| actions_log | actions_log/ |
|
|
||||||
| actions_artifacts | actions_artifacts/ |
|
|
||||||
|
|
||||||
同时 bucket, basepath or `SERVE_DIRECT` 是可以被覆写的,像如下所示:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[storage.actions_log]
|
|
||||||
MINIO_BUCKET = gitea_actions_log
|
|
||||||
SERVE_DIRECT = true
|
|
||||||
MINIO_BASE_PATH = my_actions_log/ ; default is actions_log/ if blank
|
|
||||||
```
|
|
||||||
|
|
||||||
当然你也可以完全自定义,像如下
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[lfs]
|
|
||||||
STORAGE_TYPE = my_minio
|
|
||||||
MINIO_BASE_PATH = my_lfs_basepath
|
|
||||||
|
|
||||||
[storage.my_minio]
|
[storage.my_minio]
|
||||||
STORAGE_TYPE = minio
|
STORAGE_TYPE = minio
|
||||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
||||||
@@ -494,9 +433,10 @@ MINIO_LOCATION = us-east-1
|
|||||||
MINIO_USE_SSL = false
|
MINIO_USE_SSL = false
|
||||||
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||||
MINIO_INSECURE_SKIP_VERIFY = false
|
MINIO_INSECURE_SKIP_VERIFY = false
|
||||||
SERVE_DIRECT = true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
然后你在 `[attachment]`, `[lfs]` 等中可以把这个名字用作 `STORAGE_TYPE` 的值。
|
||||||
|
|
||||||
## Repository Archive Storage (`storage.repo-archive`)
|
## Repository Archive Storage (`storage.repo-archive`)
|
||||||
|
|
||||||
Repository archive 的存储配置。 如果 `STORAGE_TYPE` 为空,则此配置将从 `[storage]` 继承。如果不为 `local` 或者 `minio` 而为 `xxx`, 则从 `[storage.xxx]` 继承。当继承时, `PATH` 默认为 `data/repo-archive`,`MINIO_BASE_PATH` 默认为 `repo-archive/`。
|
Repository archive 的存储配置。 如果 `STORAGE_TYPE` 为空,则此配置将从 `[storage]` 继承。如果不为 `local` 或者 `minio` 而为 `xxx`, 则从 `[storage.xxx]` 继承。当继承时, `PATH` 默认为 `data/repo-archive`,`MINIO_BASE_PATH` 默认为 `repo-archive/`。
|
||||||
@@ -528,4 +468,5 @@ PROXY_HOSTS = *.github.com
|
|||||||
|
|
||||||
## Other (`other`)
|
## Other (`other`)
|
||||||
|
|
||||||
|
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。
|
||||||
- `SHOW_FOOTER_VERSION`: 为真则在页面底部显示Gitea的版本。
|
- `SHOW_FOOTER_VERSION`: 为真则在页面底部显示Gitea的版本。
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "customizing-gitea"
|
|||||||
weight: 100
|
weight: 100
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/customizing-gitea
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -18,7 +16,7 @@ menu:
|
|||||||
# Customizing Gitea
|
# Customizing Gitea
|
||||||
|
|
||||||
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
||||||
the `custom` folder from the working directory (WorkPath), but may be different if your build has
|
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,
|
set this differently. This is the central place to override configuration settings,
|
||||||
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
|
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
|
||||||
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
|
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
|
||||||
@@ -282,22 +280,6 @@ Place custom files in corresponding sub-folder under `custom/options`.
|
|||||||
|
|
||||||
To add custom .gitignore, add a file with existing [.gitignore rules](https://git-scm.com/docs/gitignore) in it to `$GITEA_CUSTOM/options/gitignore`
|
To add custom .gitignore, add a file with existing [.gitignore rules](https://git-scm.com/docs/gitignore) in it to `$GITEA_CUSTOM/options/gitignore`
|
||||||
|
|
||||||
## Customizing the git configuration
|
|
||||||
|
|
||||||
Starting with Gitea 1.20, you can customize the git configuration via the `git.config` section.
|
|
||||||
|
|
||||||
### Enabling signed git pushes
|
|
||||||
|
|
||||||
To enable signed git pushes, set these two options:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[git.config]
|
|
||||||
receive.advertisePushOptions = true
|
|
||||||
receive.certNonceSeed = <randomstring>
|
|
||||||
```
|
|
||||||
|
|
||||||
`certNonceSeed` should be set to a random string and be kept secret.
|
|
||||||
|
|
||||||
### Labels
|
### Labels
|
||||||
|
|
||||||
Starting with Gitea 1.19, you can add a file that follows the [YAML label format](https://github.com/go-gitea/gitea/blob/main/options/label/Advanced.yaml) to `$GITEA_CUSTOM/options/label`:
|
Starting with Gitea 1.19, you can add a file that follows the [YAML label format](https://github.com/go-gitea/gitea/blob/main/options/label/Advanced.yaml) to `$GITEA_CUSTOM/options/label`:
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "customizing-gitea"
|
|||||||
weight: 100
|
weight: 100
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /zh-cn/customizing-gitea
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -24,7 +22,7 @@ Gitea 引用 `custom` 目录中的自定义配置文件来覆盖配置、模板
|
|||||||
`custom/conf/app.ini` 当中。在发行版中可能会以 `/etc/gitea/` 的形式为 `custom` 设置一个符号链接,查看配置详情请移步:
|
`custom/conf/app.ini` 当中。在发行版中可能会以 `/etc/gitea/` 的形式为 `custom` 设置一个符号链接,查看配置详情请移步:
|
||||||
|
|
||||||
- [快速备忘单](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
- [快速备忘单](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
||||||
- [完整配置清单](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
|
- [完整配置清单](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.example.ini)
|
||||||
|
|
||||||
如果您在 binary 同目录下无法找到 `custom` 文件夹,请检查您的 `GITEA_CUSTOM`
|
如果您在 binary 同目录下无法找到 `custom` 文件夹,请检查您的 `GITEA_CUSTOM`
|
||||||
环境变量配置, 因为它可能被配置到了其他地方(可能被一些启动脚本设置指定了目录)。
|
环境变量配置, 因为它可能被配置到了其他地方(可能被一些启动脚本设置指定了目录)。
|
||||||
@@ -67,7 +65,7 @@ Gitea 引用 `custom` 目录中的自定义配置文件来覆盖配置、模板
|
|||||||
|
|
||||||
同理,您可以将页签添加到 `extra_tabs.tmpl` 中,使用同样的方式来添加页签。它的具体样式需要与
|
同理,您可以将页签添加到 `extra_tabs.tmpl` 中,使用同样的方式来添加页签。它的具体样式需要与
|
||||||
`templates/repo/header.tmpl` 中已有的其他选项卡的样式匹配
|
`templates/repo/header.tmpl` 中已有的其他选项卡的样式匹配
|
||||||
([source in GitHub](https://github.com/go-gitea/gitea/blob/main/templates/repo/header.tmpl))
|
([source in GitHub](https://github.com/go-gitea/gitea/blob/master/templates/repo/header.tmpl))
|
||||||
|
|
||||||
### 页面的其他新增内容
|
### 页面的其他新增内容
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
---
|
---
|
||||||
date: "2019-10-15T10:10:00+05:00"
|
date: "2019-10-15T10:10:00+05:00"
|
||||||
title: "Email setup"
|
title: "Usage: Email setup"
|
||||||
slug: "email-setup"
|
slug: "email-setup"
|
||||||
weight: 12
|
weight: 12
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/email-setup
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
---
|
|
||||||
date: "2023-05-23T09:00:00+08:00"
|
|
||||||
title: "Email 设置"
|
|
||||||
slug: "email-setup"
|
|
||||||
weight: 12
|
|
||||||
toc: false
|
|
||||||
draft: false
|
|
||||||
aliases:
|
|
||||||
- /zh-cn/email-setup
|
|
||||||
menu:
|
|
||||||
sidebar:
|
|
||||||
parent: "administration"
|
|
||||||
name: "Email 设置"
|
|
||||||
weight: 12
|
|
||||||
identifier: "email-setup"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Email 设置
|
|
||||||
|
|
||||||
**目录**
|
|
||||||
|
|
||||||
{{< toc >}}
|
|
||||||
|
|
||||||
Gitea 具有邮件功能,用于发送事务性邮件(例如注册确认邮件)。它可以配置为使用 Sendmail(或兼容的 MTA,例如 Postfix 和 msmtp)或直接使用 SMTP 服务器。
|
|
||||||
|
|
||||||
## 使用 Sendmail
|
|
||||||
|
|
||||||
使用 `sendmail` 命令作为邮件传输代理(mailer)。
|
|
||||||
|
|
||||||
注意:对于在官方Gitea Docker镜像中使用,请使用SMTP版本进行配置(请参考下一节)。
|
|
||||||
|
|
||||||
注意:对于面向互联网的网站,请查阅您的 MTA 文档以了解通过TLS发送邮件的说明。同时设置 SPF、DMARC 和 DKIM DNS 记录,以使发送的邮件被各个电子邮件提供商接受为合法邮件。
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[mailer]
|
|
||||||
ENABLED = true
|
|
||||||
FROM = gitea@mydomain.com
|
|
||||||
MAILER_TYPE = sendmail
|
|
||||||
SENDMAIL_PATH = /usr/sbin/sendmail
|
|
||||||
SENDMAIL_ARGS = "--" ; 大多数 "sendmail" 程序都接受选项,使用 "--" 将防止电子邮件地址被解释为选项。
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用 SMTP
|
|
||||||
|
|
||||||
直接使用 SMTP 服务器作为中继。如果您不想在实例上设置 MTA,但在电子邮件提供商那里有一个帐户,这个选项非常有用。
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[mailer]
|
|
||||||
ENABLED = true
|
|
||||||
FROM = gitea@mydomain.com
|
|
||||||
MAILER_TYPE = smtp
|
|
||||||
SMTP_ADDR = mail.mydomain.com
|
|
||||||
SMTP_PORT = 587
|
|
||||||
IS_TLS_ENABLED = true
|
|
||||||
USER = gitea@mydomain.com
|
|
||||||
PASSWD = `password`
|
|
||||||
```
|
|
||||||
|
|
||||||
重启 Gitea 以使配置更改生效。
|
|
||||||
|
|
||||||
要发送测试邮件以验证设置,请转到 Gitea > 站点管理 > 配置 > SMTP 邮件配置。
|
|
||||||
|
|
||||||
有关所有选项的完整列表,请查看[配置速查表](doc/administration/config-cheat-sheet.zh-cn.md)。
|
|
||||||
|
|
||||||
请注意:只有在使用 TLS 或 `HOST=localhost` 加密 SMTP 服务器通信时才支持身份验证。TLS 加密可以通过以下方式进行:
|
|
||||||
|
|
||||||
- 通过端口 587 的 STARTTLS(也称为 Opportunistic TLS)。初始连接是明文的,但如果服务器支持,则可以升级为 TLS。
|
|
||||||
- 通过默认端口 465 的 SMTPS 连接。连接到服务器从一开始就使用 TLS。
|
|
||||||
- 使用 `IS_TLS_ENABLED=true` 进行强制的 SMTPS 连接。(这两种方式都被称为 Implicit TLS)
|
|
||||||
这是由于 Go 内部库对 STRIPTLS 攻击的保护机制。
|
|
||||||
|
|
||||||
请注意,自2018年起,[RFC8314](https://tools.ietf.org/html/rfc8314#section-3) 推荐使用 Implicit TLS。
|
|
||||||
|
|
||||||
### Gmail
|
|
||||||
|
|
||||||
以下配置应该适用于 Gmail 的 SMTP 服务器:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[mailer]
|
|
||||||
ENABLED = true
|
|
||||||
HOST = smtp.gmail.com:465 ; 对于 Gitea >= 1.18.0,删除此行
|
|
||||||
SMTP_ADDR = smtp.gmail.com
|
|
||||||
SMTP_PORT = 465
|
|
||||||
FROM = example.user@gmail.com
|
|
||||||
USER = example.user
|
|
||||||
PASSWD = `***`
|
|
||||||
MAILER_TYPE = smtp
|
|
||||||
IS_TLS_ENABLED = true
|
|
||||||
```
|
|
||||||
|
|
||||||
请注意,您需要创建并使用一个 [应用密码](https://support.google.com/accounts/answer/185833?hl=en) 并在您的 Google 帐户上启用 2FA。您将无法直接使用您的 Google 帐户密码。
|
|
||||||
@@ -5,8 +5,6 @@ slug: "environment-variables"
|
|||||||
weight: 10
|
weight: 10
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/environment-variables
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
@@ -43,7 +41,10 @@ For documentation about each of the variables available, refer to the
|
|||||||
## Gitea files
|
## Gitea files
|
||||||
|
|
||||||
- `GITEA_WORK_DIR`: Absolute path of working directory.
|
- `GITEA_WORK_DIR`: Absolute path of working directory.
|
||||||
- `GITEA_CUSTOM`: Gitea uses `WorkPath`/custom folder by default. Use this variable to change _custom_ directory.
|
- `GITEA_CUSTOM`: Gitea uses `GITEA_WORK_DIR`/custom folder by default. Use this variable
|
||||||
|
to change _custom_ directory.
|
||||||
|
- `GOGS_WORK_DIR`: Deprecated, use `GITEA_WORK_DIR`
|
||||||
|
- `GOGS_CUSTOM`: Deprecated, use `GITEA_CUSTOM`
|
||||||
|
|
||||||
## Operating system specifics
|
## Operating system specifics
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "environment-variables"
|
|||||||
weight: 10
|
weight: 10
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /zh-cn/environment-variables
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ slug: "external-renderers"
|
|||||||
weight: 60
|
weight: 60
|
||||||
toc: false
|
toc: false
|
||||||
draft: false
|
draft: false
|
||||||
aliases:
|
|
||||||
- /en-us/external-renderers
|
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
parent: "administration"
|
parent: "administration"
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
---
|
|
||||||
date: "2023-05-23T09:00:00+08:00"
|
|
||||||
title: "外部渲染器"
|
|
||||||
slug: "external-renderers"
|
|
||||||
weight: 60
|
|
||||||
toc: false
|
|
||||||
draft: false
|
|
||||||
aliases:
|
|
||||||
- /zh-cn/external-renderers
|
|
||||||
menu:
|
|
||||||
sidebar:
|
|
||||||
parent: "administration"
|
|
||||||
name: "外部渲染器"
|
|
||||||
weight: 60
|
|
||||||
identifier: "external-renderers"
|
|
||||||
---
|
|
||||||
|
|
||||||
# 自定义文件渲染配置
|
|
||||||
|
|
||||||
**目录**
|
|
||||||
|
|
||||||
{{< toc >}}
|
|
||||||
|
|
||||||
Gitea 通过外部二进制文件支持自定义文件渲染(例如 Jupyter notebooks、asciidoc 等),只需要进行以下步骤:
|
|
||||||
|
|
||||||
- 安装外部二进制文件
|
|
||||||
- 在您的 `app.ini` 文件中添加一些配置
|
|
||||||
- 重新启动 Gitea 实例
|
|
||||||
|
|
||||||
此功能支持整个文件的渲染。如果您想要在 Markdown 中渲染代码块,您需要使用 JavaScript 进行一些操作。请参阅 [自定义 Gitea 配置]({{< relref "doc/administration/customizing-gitea.zh-cn.md" >}}) 页面上的一些示例。
|
|
||||||
|
|
||||||
## 安装外部二进制文件
|
|
||||||
|
|
||||||
为了通过外部二进制文件进行文件渲染,必须安装它们的关联软件包。
|
|
||||||
如果您正在使用 Docker 镜像,则您的 `Dockerfile` 应该包含以下内容:
|
|
||||||
|
|
||||||
```docker
|
|
||||||
FROM gitea/gitea:{{< version >}}
|
|
||||||
[...]
|
|
||||||
|
|
||||||
COPY custom/app.ini /data/gitea/conf/app.ini
|
|
||||||
[...]
|
|
||||||
|
|
||||||
RUN apk --no-cache add asciidoctor freetype freetype-dev gcc g++ libpng libffi-dev py-pip python3-dev py3-pip py3-pyzmq
|
|
||||||
# 安装其他您需要的外部渲染器的软件包
|
|
||||||
|
|
||||||
RUN pip3 install --upgrade pip
|
|
||||||
RUN pip3 install -U setuptools
|
|
||||||
RUN pip3 install jupyter docutils
|
|
||||||
# 在上面添加您需要安装的任何其他 Python 软件包
|
|
||||||
```
|
|
||||||
|
|
||||||
## `app.ini` 文件配置
|
|
||||||
|
|
||||||
在您的自定义 `app.ini` 文件中为每个外部渲染器添加一个 `[markup.XXXXX]` 部分:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[markup.asciidoc]
|
|
||||||
ENABLED = true
|
|
||||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
|
||||||
RENDER_COMMAND = "asciidoctor -s -a showtitle --out-file=- -"
|
|
||||||
; 输入不是标准输入而是文件
|
|
||||||
IS_INPUT_FILE = false
|
|
||||||
|
|
||||||
[markup.jupyter]
|
|
||||||
ENABLED = true
|
|
||||||
FILE_EXTENSIONS = .ipynb
|
|
||||||
RENDER_COMMAND = "jupyter nbconvert --stdin --stdout --to html --template basic"
|
|
||||||
IS_INPUT_FILE = false
|
|
||||||
|
|
||||||
[markup.restructuredtext]
|
|
||||||
ENABLED = true
|
|
||||||
FILE_EXTENSIONS = .rst
|
|
||||||
RENDER_COMMAND = "timeout 30s pandoc +RTS -M512M -RTS -f rst"
|
|
||||||
IS_INPUT_FILE = false
|
|
||||||
```
|
|
||||||
|
|
||||||
如果您的外部标记语言依赖于在生成的 HTML 元素上的额外类和属性,您可能需要启用自定义的清理策略。Gitea 使用 [`bluemonday`](https://godoc.org/github.com/microcosm-cc/bluemonday) 包作为我们的 HTML 清理器。下面的示例可以用于支持从 [`pandoc`](https://pandoc.org/) 输出的服务器端 [KaTeX](https://katex.org/) 渲染结果。
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[markup.sanitizer.TeX]
|
|
||||||
; Pandoc 渲染 TeX 段落为带有 "math" 类的 <span> 元素,根据上下文可能还带有 "inline" 或 "display" 类。
|
|
||||||
; - 请注意,这与我们的 Markdown 解析器中内置的数学支持不同,后者使用 <code> 元素。
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
您必须在每个部分中定义 `ELEMENT` 和 `ALLOW_ATTR`。
|
|
||||||
|
|
||||||
要定义多个条目,请添加唯一的字母数字后缀(例如,`[markup.sanitizer.1]` 和 `[markup.sanitizer.something]`)。
|
|
||||||
|
|
||||||
要仅为特定的外部渲染器应用清理规则,它们必须使用渲染器名称,例如 `[markup.sanitizer.asciidoc.rule-1]`、`[markup.sanitizer.<renderer>.rule-1]`。
|
|
||||||
|
|
||||||
**注意**:如果规则在渲染器 ini 部分之前定义,或者名称与渲染器不匹配,它将应用于所有渲染器。
|
|
||||||
|
|
||||||
完成配置更改后,请重新启动 Gitea 以使更改生效。
|
|
||||||
|
|
||||||
**注意**:在 Gitea 1.12 之前,存在一个名为 `markup.sanitiser` 的单个部分,其中的键被重新定义为多个规则,但是,这种配置方法存在重大问题,需要通过多个部分进行配置。
|
|
||||||
|
|
||||||
### 示例:HTML
|
|
||||||
|
|
||||||
直接渲染 HTML 文件:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[markup.html]
|
|
||||||
ENABLED = true
|
|
||||||
FILE_EXTENSIONS = .html,.htm
|
|
||||||
RENDER_COMMAND = cat
|
|
||||||
; 输入不是标准输入,而是文件
|
|
||||||
IS_INPUT_FILE = true
|
|
||||||
|
|
||||||
[markup.sanitizer.html.1]
|
|
||||||
ELEMENT = div
|
|
||||||
ALLOW_ATTR = class
|
|
||||||
|
|
||||||
[markup.sanitizer.html.2]
|
|
||||||
ELEMENT = a
|
|
||||||
ALLOW_ATTR = class
|
|
||||||
```
|
|
||||||
|
|
||||||
请注意:此示例中的配置将允许渲染 HTML 文件,并使用 `cat` 命令将文件内容输出为 HTML。此外,配置中的两个清理规则将允许 `<div>` 和 `<a>` 元素使用 `class` 属性。
|
|
||||||
|
|
||||||
在进行配置更改后,请重新启动 Gitea 以使更改生效。
|
|
||||||
|
|
||||||
### 示例:Office DOCX
|
|
||||||
|
|
||||||
使用 [`pandoc`](https://pandoc.org/) 显示 Office DOCX 文件:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[markup.docx]
|
|
||||||
ENABLED = true
|
|
||||||
FILE_EXTENSIONS = .docx
|
|
||||||
RENDER_COMMAND = "pandoc --from docx --to html --self-contained --template /path/to/basic.html"
|
|
||||||
|
|
||||||
[markup.sanitizer.docx.img]
|
|
||||||
ALLOW_DATA_URI_IMAGES = true
|
|
||||||
```
|
|
||||||
|
|
||||||
在此示例中,配置将允许显示 Office DOCX 文件,并使用 `pandoc` 命令将文件转换为 HTML 格式。同时,清理规则中的 `ALLOW_DATA_URI_IMAGES` 设置为 `true`,允许使用 Data URI 格式的图片。
|
|
||||||
|
|
||||||
模板文件的内容如下:
|
|
||||||
|
|
||||||
```
|
|
||||||
$body$
|
|
||||||
```
|
|
||||||
|
|
||||||
### 示例:Jupyter Notebook
|
|
||||||
|
|
||||||
使用 [`nbconvert`](https://github.com/jupyter/nbconvert) 显示 Jupyter Notebook 文件:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[markup.jupyter]
|
|
||||||
ENABLED = true
|
|
||||||
FILE_EXTENSIONS = .ipynb
|
|
||||||
RENDER_COMMAND = "jupyter-nbconvert --stdin --stdout --to html --template basic"
|
|
||||||
|
|
||||||
[markup.sanitizer.jupyter.img]
|
|
||||||
ALLOW_DATA_URI_IMAGES = true
|
|
||||||
```
|
|
||||||
|
|
||||||
在此示例中,配置将允许显示 Jupyter Notebook 文件,并使用 `nbconvert` 命令将文件转换为 HTML 格式。同样,清理规则中的 `ALLOW_DATA_URI_IMAGES` 设置为 `true`,允许使用 Data URI 格式的图片。
|
|
||||||
|
|
||||||
在进行配置更改后,请重新启动 Gitea 以使更改生效。
|
|
||||||
|
|
||||||
## 自定义 CSS
|
|
||||||
|
|
||||||
在 `.ini` 文件中,可以使用 `[markup.XXXXX]` 的格式指定外部渲染器,并且由外部渲染器生成的 HTML 将被包装在一个带有 `markup` 和 `XXXXX` 类的 `<div>` 中。`markup` 类提供了预定义的样式(如果 `XXXXX` 是 `markdown`,则使用 `markdown` 类)。否则,您可以使用这些类来针对渲染的 HTML 内容进行定制样式。
|
|
||||||
|
|
||||||
因此,您可以编写一些 CSS 样式:
|
|
||||||
|
|
||||||
```css
|
|
||||||
.markup.XXXXX html {
|
|
||||||
font-size: 100%;
|
|
||||||
overflow-y: scroll;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
-ms-text-size-adjust: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markup.XXXXX body {
|
|
||||||
color: #444;
|
|
||||||
font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.7;
|
|
||||||
padding: 1em;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 42em;
|
|
||||||
background: #fefefe;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markup.XXXXX p {
|
|
||||||
color: orangered;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
将您的样式表添加到自定义目录中,例如 `custom/public/css/my-style-XXXXX.css`,并使用自定义的头文件 `custom/templates/custom/header.tmpl` 进行导入:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<link rel="stylesheet" href="{{AppSubUrl}}/assets/css/my-style-XXXXX.css" />
|
|
||||||
```
|
|
||||||
|
|
||||||
通过以上步骤,您可以将自定义的 CSS 样式应用到特定的外部渲染器,使其具有所需的样式效果。
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user