mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-21 17:41:16 +02:00
Compare commits
536 Commits
v1.5.0-dev
...
v1.7.3
Author | SHA1 | Date | |
---|---|---|---|
|
8ab107c2dd | ||
|
cbfc7f52b9 | ||
|
d602ba564f | ||
|
55063f2524 | ||
|
585dd13cce | ||
|
12d883412f | ||
|
597a30b727 | ||
|
b5ae8945e5 | ||
|
5cca840bb8 | ||
|
f4c7e87fc9 | ||
|
fe99c9901d | ||
|
2e1540e827 | ||
|
3b612ce42e | ||
|
1d8e56e6bb | ||
|
57ab65d922 | ||
|
3ac4a7fab8 | ||
|
253efbcb51 | ||
|
c8f061e15b | ||
|
7f7c451de4 | ||
|
b0b574f805 | ||
|
d269179523 | ||
|
6416f06508 | ||
|
1a8ab63dda | ||
|
477b4de0d1 | ||
|
849c85a2ec | ||
|
731275247d | ||
|
022634aa75 | ||
|
dfad569e40 | ||
|
c3b67ff2f6 | ||
|
5c30817b5f | ||
|
438848a2ca | ||
|
9d4aa78113 | ||
|
e5af93af20 | ||
|
3f802a2846 | ||
|
0190d3c243 | ||
|
4fe1a3050e | ||
|
29799537a7 | ||
|
d3a334d99a | ||
|
28d9305ea3 | ||
|
8a9f5b3b50 | ||
|
f28e17473c | ||
|
2c26521579 | ||
|
f635041c98 | ||
|
3fa49f3780 | ||
|
4577cddd28 | ||
|
8da5237107 | ||
|
8006b1bc7a | ||
|
8d400320c6 | ||
|
e9c4609410 | ||
|
176a6048b4 | ||
|
483aa06b07 | ||
|
551dc58a4d | ||
|
41a2bfe3ae | ||
|
652e09fc3e | ||
|
c9b57a5135 | ||
|
2904d8d6aa | ||
|
109fc7975b | ||
|
3ee3a4b595 | ||
|
14e218cbd1 | ||
|
b5f4911afa | ||
|
9863591dca | ||
|
121da08730 | ||
|
76060613ef | ||
|
74b9a13f84 | ||
|
7c3722b366 | ||
|
f5be13efb6 | ||
|
8764f1512d | ||
|
4c52858c39 | ||
|
63bd1b9203 | ||
|
b46c279587 | ||
|
64995bae0f | ||
|
2c7661a524 | ||
|
945804f800 | ||
|
8bb0a6f425 | ||
|
2058c362a8 | ||
|
6e20b504b1 | ||
|
21357a4ae0 | ||
|
a82ba73346 | ||
|
4a685f8b87 | ||
|
58bdff53cd | ||
|
b0b35493ec | ||
|
ba2c02b75d | ||
|
4586ae390f | ||
|
f0db86b663 | ||
|
9f544e9356 | ||
|
a06ae0bdc7 | ||
|
b77c3eb5bd | ||
|
9a33798b30 | ||
|
330bf8d3b3 | ||
|
4a02a783c4 | ||
|
7cb1d8296d | ||
|
8dc09edb04 | ||
|
9d0dee88d2 | ||
|
b65e37ed72 | ||
|
c64963553a | ||
|
7fd34c0517 | ||
|
2a660a1de1 | ||
|
fe55ab2a68 | ||
|
e726e4b828 | ||
|
8730ee0e45 | ||
|
94c3963da0 | ||
|
b3b7598ec6 | ||
|
49ea6e0deb | ||
|
ebef3eff23 | ||
|
0bd802e3e1 | ||
|
f0374ad1ad | ||
|
af6bce3ad5 | ||
|
6db7dbd333 | ||
|
b1f3685015 | ||
|
58c4559d3b | ||
|
ba75319157 | ||
|
ccea91652f | ||
|
6e114f6791 | ||
|
15d6cf179d | ||
|
9681c83734 | ||
|
64680b72bd | ||
|
205a533645 | ||
|
284b0e12cb | ||
|
8a64e67456 | ||
|
1b3404eaca | ||
|
928417ae39 | ||
|
7e5abe2dc4 | ||
|
7c0c965532 | ||
|
da5a0b8382 | ||
|
4b4453cb92 | ||
|
8b864a328e | ||
|
fdec258c8d | ||
|
a0ecc5f24e | ||
|
20c54f88b2 | ||
|
2d707fe5e6 | ||
|
ce4885f761 | ||
|
9441bfaccc | ||
|
bc42b3ab6c | ||
|
552014a068 | ||
|
06ef5b68d4 | ||
|
c761625c69 | ||
|
f80b4f46ae | ||
|
c8a9384a70 | ||
|
0787056e07 | ||
|
a7ee4a6e95 | ||
|
fdb417643d | ||
|
5c13ba8d2e | ||
|
2dc805c0c6 | ||
|
d5d847e5c4 | ||
|
f17524bd0c | ||
|
eabbddcd98 | ||
|
0222623be9 | ||
|
08bf443016 | ||
|
294904321c | ||
|
e09fe48773 | ||
|
c03a9b3e42 | ||
|
3a1ed82529 | ||
|
ce9a5173fe | ||
|
5e022a98e6 | ||
|
d9b0b7f56e | ||
|
499d132124 | ||
|
7e587e097c | ||
|
fd37fb01fd | ||
|
3379141d81 | ||
|
49d9900b1f | ||
|
6467934d29 | ||
|
5af7f8bd72 | ||
|
0dcf31ae49 | ||
|
cef0f12c51 | ||
|
8ef177f8c5 | ||
|
499bff43d9 | ||
|
3a95e2d0ea | ||
|
e08c7e521b | ||
|
4651ba06c1 | ||
|
d9b51a781c | ||
|
241ee793b7 | ||
|
e033d217e9 | ||
|
89eea64e10 | ||
|
7278372388 | ||
|
e110943562 | ||
|
b97af15de6 | ||
|
4c1f1f9646 | ||
|
b3000ae623 | ||
|
d487a76ee2 | ||
|
7dd31eb8fb | ||
|
2852c3576a | ||
|
c5d098c32e | ||
|
599adde1bc | ||
|
de8f98192b | ||
|
c2f72b1346 | ||
|
e8b197d6f6 | ||
|
8f8ff5a295 | ||
|
078c404c3b | ||
|
92fb89f6e1 | ||
|
0fd56a71e4 | ||
|
18391c1410 | ||
|
7096085f2b | ||
|
57a8440db3 | ||
|
54259e2f88 | ||
|
225c48982b | ||
|
fa165621ed | ||
|
4b84928874 | ||
|
7d9a191a3c | ||
|
00533d3870 | ||
|
584844eada | ||
|
6c90dd1f4a | ||
|
c8b4c7af65 | ||
|
794049e824 | ||
|
7edb930240 | ||
|
6eff62ae09 | ||
|
22ad514297 | ||
|
b686bd0c94 | ||
|
10370651fc | ||
|
e5daa2698f | ||
|
d0f614a25b | ||
|
98ea1a5143 | ||
|
a3e084716e | ||
|
220ee6ae42 | ||
|
e61c6cd3db | ||
|
0ba57949e4 | ||
|
5fc0a12627 | ||
|
617a2433a3 | ||
|
aefeb8c465 | ||
|
db30d6d791 | ||
|
735b12eaf0 | ||
|
1ceae07560 | ||
|
d4e6278764 | ||
|
70a80e31cf | ||
|
7694c99ab3 | ||
|
abf6e0d90b | ||
|
8b4c4bd08f | ||
|
b8451190d8 | ||
|
a2ee2a3c67 | ||
|
fb14458010 | ||
|
48badd59e9 | ||
|
8a9e44d181 | ||
|
2b7c366f64 | ||
|
99c09dfbfa | ||
|
2af57c7820 | ||
|
f887085ee0 | ||
|
e500b82c2c | ||
|
e7822473e9 | ||
|
aeb5655c25 | ||
|
5f938c0c78 | ||
|
554581f848 | ||
|
890a0c3cee | ||
|
c258ae8ada | ||
|
ffd5fb8139 | ||
|
7e5eec430d | ||
|
70ad46133f | ||
|
317ddb7283 | ||
|
efa4e6bc6f | ||
|
159c2ffb0e | ||
|
25c49cf930 | ||
|
2ce72d4e00 | ||
|
6759237eda | ||
|
f38fce916e | ||
|
9458880c06 | ||
|
43f9233914 | ||
|
9b2fcadeef | ||
|
c2748ea7fe | ||
|
5a4648cdd6 | ||
|
583b1b8429 | ||
|
2313121354 | ||
|
22274464f4 | ||
|
dea3d849e1 | ||
|
cabdf84f1f | ||
|
971dccda16 | ||
|
a908b29a74 | ||
|
616b8f42f9 | ||
|
47e4efe0c5 | ||
|
fef0410b92 | ||
|
8db3bdc683 | ||
|
ea619b39b2 | ||
|
dd62ca7ba9 | ||
|
7bb4d610e5 | ||
|
eb0c848f5b | ||
|
637c5fe1eb | ||
|
1e34413238 | ||
|
e4b8103ac7 | ||
|
97da83d008 | ||
|
486e989a39 | ||
|
e79e9248fd | ||
|
c37d1a9e99 | ||
|
384ef124e7 | ||
|
35ae14050e | ||
|
1972383216 | ||
|
25def0a808 | ||
|
cc63985876 | ||
|
8683c72483 | ||
|
4cdab02273 | ||
|
34695f460a | ||
|
4090204944 | ||
|
970c690681 | ||
|
0cd8cecdf8 | ||
|
c42b366f0e | ||
|
c0b2c8a5d6 | ||
|
1ecf92ade2 | ||
|
f44d066876 | ||
|
fb3954f9a5 | ||
|
6df46c50b1 | ||
|
378af8ea88 | ||
|
c6daee6da6 | ||
|
94cd7bb25b | ||
|
d7ca839c67 | ||
|
513db27377 | ||
|
2b8dc17db7 | ||
|
2e2eacf62a | ||
|
dba955be7c | ||
|
b8d048fa0d | ||
|
ab5b245182 | ||
|
fc0001caa1 | ||
|
81702e6ec9 | ||
|
6780661192 | ||
|
e6d54d511d | ||
|
31d5488059 | ||
|
39735723f5 | ||
|
b3393b5ca7 | ||
|
79b4d4729c | ||
|
4092b32bad | ||
|
36e7cb9755 | ||
|
dab02b80fd | ||
|
07af31d004 | ||
|
364c029246 | ||
|
043ab2cd59 | ||
|
8b113cd8b6 | ||
|
91b164c778 | ||
|
552d8d3a4e | ||
|
d6b97c8557 | ||
|
4befec242a | ||
|
756eafaaf6 | ||
|
acb6f8a518 | ||
|
f6eb669b51 | ||
|
3e76e7826e | ||
|
661fd901bd | ||
|
2a6d3ba058 | ||
|
f98040ad50 | ||
|
126ba796dc | ||
|
10a2a904d7 | ||
|
ea20adaa84 | ||
|
7dd93b2441 | ||
|
e91a2cf2ea | ||
|
8e3e59fdb8 | ||
|
b5b39a56ad | ||
|
08ed515b62 | ||
|
c64c595acc | ||
|
f1ad4bb3d5 | ||
|
8ee9922fe6 | ||
|
e47df0b301 | ||
|
387a4b09c1 | ||
|
15ebe4b853 | ||
|
be48397945 | ||
|
6e03390aa8 | ||
|
eea76a5241 | ||
|
e9dbfc70b7 | ||
|
1dee960b45 | ||
|
c43399cad8 | ||
|
d293a2b9d6 | ||
|
e6a03813d4 | ||
|
fab7937c62 | ||
|
fa4663e61e | ||
|
bf55276189 | ||
|
13e8a0fe56 | ||
|
303d7f7e9c | ||
|
3c6cc56143 | ||
|
bd1bf2a072 | ||
|
a5cc3a9baf | ||
|
061b1aa2d4 | ||
|
668a477c69 | ||
|
e48df3ee47 | ||
|
a4ee5627ed | ||
|
01fd05a5cb | ||
|
83d1173634 | ||
|
aad5cccec8 | ||
|
9500d394ec | ||
|
b9ae16d15e | ||
|
fcea86877f | ||
|
a938ddf704 | ||
|
080428b2bf | ||
|
179123de35 | ||
|
74d65b5b5b | ||
|
34831afaa7 | ||
|
51c3b4b4bf | ||
|
56d931aeac | ||
|
4ae5a54c1f | ||
|
b63e2e0ded | ||
|
0a24f5cac8 | ||
|
194a11eb11 | ||
|
912953e82a | ||
|
127f477056 | ||
|
0dac1ff677 | ||
|
f766e9713b | ||
|
3c39b6351c | ||
|
33bc2ebdfa | ||
|
6ca8fbd2f9 | ||
|
05dcfcfc33 | ||
|
b82c14b3d2 | ||
|
6c1a31ffaa | ||
|
fa93857117 | ||
|
a6cdda115d | ||
|
b1ad5734c6 | ||
|
1b2aff02a2 | ||
|
50ce19eff7 | ||
|
8273479b41 | ||
|
b30f6b4099 | ||
|
f24ba27d79 | ||
|
8f86c43b90 | ||
|
bc06ab4a31 | ||
|
92466129ec | ||
|
0449330dbc | ||
|
ca112f0a04 | ||
|
03e558c29b | ||
|
e6777f7b9d | ||
|
df0eb7372c | ||
|
7781e8cef2 | ||
|
52c2cb15db | ||
|
a4fa6bbc89 | ||
|
6e68b61479 | ||
|
ce7c64c7e1 | ||
|
3422077a89 | ||
|
7fbdd4f2ac | ||
|
3ad5399a31 | ||
|
69a855f3d4 | ||
|
4a7de87071 | ||
|
5dfe8b4340 | ||
|
8da45ae2b3 | ||
|
0e04a2091a | ||
|
578cf52ce5 | ||
|
0e464995ce | ||
|
152c6af97e | ||
|
00bd6277a8 | ||
|
3b51c4f3fb | ||
|
32145b6de8 | ||
|
67a8688538 | ||
|
b1bc08e268 | ||
|
ed3589f429 | ||
|
5ae8408725 | ||
|
a42900c17f | ||
|
0df7cab4fb | ||
|
59b10e66f7 | ||
|
c7a6ee5c0b | ||
|
7cb1c1cf20 | ||
|
9c0a374f3f | ||
|
9ea327f1f7 | ||
|
6e64f9db8e | ||
|
9c354a539a | ||
|
c40f5d2d4c | ||
|
819f50ccd5 | ||
|
ced08d18a4 | ||
|
d57233680b | ||
|
b11ddd8d4c | ||
|
e277b3e0e4 | ||
|
895e538836 | ||
|
a74426d631 | ||
|
412583a3f2 | ||
|
c1224124ea | ||
|
5927599e43 | ||
|
adf3f004b6 | ||
|
ac968c3c6f | ||
|
be4ec0cbba | ||
|
a847d16f5b | ||
|
8d1ad55598 | ||
|
f847884d16 | ||
|
1b9b894731 | ||
|
7a30208e05 | ||
|
630f234223 | ||
|
32f25598b3 | ||
|
4bf0cae1f5 | ||
|
d0fef4395f | ||
|
344dc07239 | ||
|
ba358ecbf5 | ||
|
ae9dd239fb | ||
|
ec43e5619b | ||
|
bed623600d | ||
|
5fa403c874 | ||
|
0bb1c84208 | ||
|
b174817b6a | ||
|
cc9fa062e6 | ||
|
0c59edaafa | ||
|
1e2da5d396 | ||
|
492ec97a46 | ||
|
d1337299e2 | ||
|
9ca8aaecb4 | ||
|
91373901f6 | ||
|
fe78154895 | ||
|
1bff02de55 | ||
|
7be5935c55 | ||
|
ef6813abc9 | ||
|
55d9ddf24a | ||
|
ca474af3c6 | ||
|
8e103d3e76 | ||
|
a7c5e58635 | ||
|
ca8c7bb2b5 | ||
|
aa27cbf229 | ||
|
6813640d2f | ||
|
e95417ea2c | ||
|
659bc727bd | ||
|
e6b51200ab | ||
|
a7f90905df | ||
|
8afd500c48 | ||
|
8b21cdba78 | ||
|
3e950ef112 | ||
|
c55caeaf0c | ||
|
d84490a0df | ||
|
c2ec38f9b7 | ||
|
61f4ad2fc5 | ||
|
c9687c036d | ||
|
3e445cce06 | ||
|
80169460ec | ||
|
efd202f40f | ||
|
ab55ca7ebd | ||
|
1675fc4301 | ||
|
61b40520ba | ||
|
f1d6a1fffc | ||
|
28c1c90230 | ||
|
2a60e72fcd | ||
|
cfb76cd99e | ||
|
7c943b1cad | ||
|
5bc8782d33 | ||
|
e07d3ad0fc | ||
|
f035dcd4f2 | ||
|
54fedd4070 | ||
|
07063e3e11 | ||
|
69e2ab1611 | ||
|
4eae810d63 | ||
|
4a8ee0b5cc | ||
|
b46066f17c | ||
|
95f0f62ea4 | ||
|
74f9f98f78 | ||
|
2e3475f02c | ||
|
df77ad31d5 | ||
|
c3bbf43970 | ||
|
fc53f95f23 | ||
|
823318bfbe | ||
|
5676f60cba | ||
|
3fed13b0ee | ||
|
51ba3df5ff | ||
|
4b654ad17f | ||
|
5d1a6382b6 | ||
|
c71ee33057 | ||
|
9d4c1ddfa1 |
108
.drone.yml
108
.drone.yml
@@ -22,7 +22,7 @@ pipeline:
|
||||
branch: [ master ]
|
||||
|
||||
update-translations:
|
||||
image: alpine:3.6
|
||||
image: alpine:3.7
|
||||
commands:
|
||||
- mv ./options/locale/locale_en-US.ini ./options/
|
||||
- sed -i -e 's/="/=/g' -e 's/"$$//g' ./options/locale/*.ini
|
||||
@@ -56,7 +56,7 @@ pipeline:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
build-without-gcc:
|
||||
image: golang:1.8
|
||||
image: golang:1.9
|
||||
pull: true
|
||||
commands:
|
||||
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||
@@ -64,10 +64,10 @@ pipeline:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
build:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
commands:
|
||||
- make clean
|
||||
- make generate
|
||||
@@ -83,11 +83,11 @@ pipeline:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
test:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
commands:
|
||||
- make unit-test-coverage
|
||||
when:
|
||||
@@ -95,11 +95,11 @@ pipeline:
|
||||
branch: [ master ]
|
||||
|
||||
test:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
commands:
|
||||
- make test
|
||||
when:
|
||||
@@ -107,7 +107,7 @@ pipeline:
|
||||
branch: [ release/* ]
|
||||
|
||||
test:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
@@ -117,20 +117,22 @@ pipeline:
|
||||
when:
|
||||
event: [ tag ]
|
||||
|
||||
# Commented until db locking have been resolved!
|
||||
# test-sqlite:
|
||||
# image: golang:1.10
|
||||
# pull: true
|
||||
# group: test
|
||||
# environment:
|
||||
# TAGS: bindata
|
||||
# commands:
|
||||
# - make test-sqlite
|
||||
# when:
|
||||
# event: [ push, tag, pull_request ]
|
||||
test-sqlite:
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- (sleep 1200 && (echo 'kill -ABRT $(pidof gitea) $(pidof integrations.sqlite.test)' | sh)) &
|
||||
- make test-sqlite
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
test-mysql:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
@@ -145,7 +147,7 @@ pipeline:
|
||||
branch: [ master ]
|
||||
|
||||
test-mysql:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
@@ -154,12 +156,13 @@ pipeline:
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- (sleep 1200 && (echo 'kill -ABRT $(pidof gitea) $(pidof integrations.test)' | sh)) &
|
||||
- make test-mysql
|
||||
when:
|
||||
event: [ tag ]
|
||||
|
||||
test-pgsql:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
@@ -168,12 +171,27 @@ pipeline:
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- (sleep 1200 && (echo 'kill -ABRT $(pidof gitea) $(pidof integrations.test)' | sh)) &
|
||||
- make test-pgsql
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
test-mssql:
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata
|
||||
TEST_LDAP: "1"
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- make test-mssql
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
generate-coverage:
|
||||
image: golang:1.10
|
||||
image: golang:1.11
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata
|
||||
@@ -193,17 +211,17 @@ pipeline:
|
||||
branch: [ master ]
|
||||
|
||||
static:
|
||||
image: karalabe/xgo-latest:latest
|
||||
image: techknowlogick/xgo:latest
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
commands:
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make release
|
||||
when:
|
||||
event: [ push, tag ]
|
||||
|
||||
build_docs:
|
||||
build-docs:
|
||||
image: webhippie/hugo:latest
|
||||
pull: true
|
||||
commands:
|
||||
@@ -212,26 +230,12 @@ pipeline:
|
||||
- make clean
|
||||
- make build
|
||||
|
||||
docker_docs:
|
||||
image: plugins/docker:17.05
|
||||
publish-docs:
|
||||
image: lucap/drone-netlify:latest
|
||||
pull: true
|
||||
secrets: [ docker_username, docker_password ]
|
||||
repo: gitea/docs
|
||||
context: docs
|
||||
dockerfile: docs/Dockerfile
|
||||
tags: [ '${DRONE_BRANCH##release/v}' ]
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ release/* ]
|
||||
|
||||
docker_docs:
|
||||
image: plugins/docker:17.05
|
||||
pull: true
|
||||
secrets: [ docker_username, docker_password ]
|
||||
repo: gitea/docs
|
||||
context: docs
|
||||
dockerfile: docs/Dockerfile
|
||||
tags: [ 'latest' ]
|
||||
secrets: [ netlify_token ]
|
||||
site_id: d2260bae-7861-4c02-8646-8f6440b12672
|
||||
path: docs/public/
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
@@ -272,6 +276,7 @@ pipeline:
|
||||
pull: true
|
||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||
bucket: releases
|
||||
acl: public-read
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
@@ -285,6 +290,7 @@ pipeline:
|
||||
pull: true
|
||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||
bucket: releases
|
||||
acl: public-read
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
@@ -299,6 +305,7 @@ pipeline:
|
||||
pull: true
|
||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||
bucket: releases
|
||||
acl: public-read
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
@@ -354,6 +361,15 @@ services:
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
mssql:
|
||||
image: microsoft/mssql-server-linux:latest
|
||||
environment:
|
||||
- ACCEPT_EULA=Y
|
||||
- SA_PASSWORD=MwantsaSecurePassword1
|
||||
- MSSQL_PID=Standard
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
ldap:
|
||||
image: gitea/test-openldap:latest
|
||||
when:
|
||||
|
52
.github/stale.yml
vendored
Normal file
52
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 14
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- status/blocked
|
||||
- kind/security
|
||||
- lgtm/done
|
||||
- reviewed/confirmed
|
||||
- priority/critical
|
||||
- kind/proposal
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs during the next 2 weeks. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
This issue has been automatically closed because of inactivity.
|
||||
You can re-open it if needed.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 1
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
pulls:
|
||||
daysUntilStale: 60
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs during the next 2 months. Thank you
|
||||
for your contributions.
|
||||
closeComment: >
|
||||
This pull request has been automatically closed because of inactivity.
|
||||
You can re-open it if needed.
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -53,11 +53,14 @@ coverage.all
|
||||
/integrations/gitea-integration-mysql
|
||||
/integrations/gitea-integration-pgsql
|
||||
/integrations/gitea-integration-sqlite
|
||||
/integrations/gitea-integration-mssql
|
||||
/integrations/indexers-mysql
|
||||
/integrations/indexers-pgsql
|
||||
/integrations/indexers-sqlite
|
||||
/integrations/indexers-mssql
|
||||
/integrations/mysql.ini
|
||||
/integrations/pgsql.ini
|
||||
/integrations/mssql.ini
|
||||
/node_modules
|
||||
|
||||
|
||||
|
25
.revive.toml
Normal file
25
.revive.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
ignoreGeneratedHeader = false
|
||||
severity = "warning"
|
||||
confidence = 0.8
|
||||
errorCode = 1
|
||||
warningCode = 1
|
||||
|
||||
[rule.blank-imports]
|
||||
[rule.context-as-argument]
|
||||
[rule.context-keys-type]
|
||||
[rule.dot-imports]
|
||||
[rule.error-return]
|
||||
[rule.error-strings]
|
||||
[rule.error-naming]
|
||||
[rule.exported]
|
||||
[rule.if-return]
|
||||
[rule.increment-decrement]
|
||||
[rule.var-naming]
|
||||
[rule.var-declaration]
|
||||
[rule.package-comments]
|
||||
[rule.range]
|
||||
[rule.receiver-naming]
|
||||
[rule.time-naming]
|
||||
[rule.unexported-return]
|
||||
[rule.indent-error-flow]
|
||||
[rule.errorf]
|
51
BSDmakefile
Normal file
51
BSDmakefile
Normal file
@@ -0,0 +1,51 @@
|
||||
# GNU makefile proxy script for BSD make
|
||||
# Written and maintained by Mahmoud Al-Qudsi <mqudsi@neosmart.net>
|
||||
# Copyright NeoSmart Technologies <https://neosmart.net/> 2014-2018
|
||||
# Obtain updates from <https://github.com/neosmart/gmake-proxy>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
JARG =
|
||||
GMAKE = "gmake"
|
||||
#When gmake is called from another make instance, -w is automatically added
|
||||
#which causes extraneous messages about directory changes to be emitted.
|
||||
#--no-print-directory silences these messages.
|
||||
GARGS = "--no-print-directory"
|
||||
|
||||
.if "$(.MAKE.JOBS)" != ""
|
||||
JARG = -j$(.MAKE.JOBS)
|
||||
.endif
|
||||
|
||||
#by default bmake will cd into ./obj first
|
||||
.OBJDIR: ./
|
||||
|
||||
.PHONY: FRC
|
||||
$(.TARGETS): FRC
|
||||
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
|
||||
.DONE .DEFAULT: .SILENT
|
||||
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
|
||||
.ERROR: .SILENT
|
||||
if ! which $(GMAKE) > /dev/null; then \
|
||||
echo "GNU Make is required!"; \
|
||||
fi
|
447
CHANGELOG.md
447
CHANGELOG.md
@@ -4,10 +4,455 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.5.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.5.0-rc1) - 2018-07-04
|
||||
## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
|
||||
* BUGFIXES
|
||||
* Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)
|
||||
* Load Issue attributes for API /repos/{owner}/{repo}/issues/{index} (#6122) (#6185)
|
||||
* Fix bug whereby user could change private repository to public when force private enabled. (#6156) (#6165)
|
||||
* Fix bug when update owner team then visit team's repo return 404 (#6119) (#6166)
|
||||
* Fix heatmap and repository menu display in Internet Explorer 9+ (#6117) (#6137)
|
||||
* Fix prohibit login check on authorization (#6106) (#6115)
|
||||
* Fix LDAP protocol error regression by moving to ldap.v3 (#6105) (#6107)
|
||||
* Fix deadlock in webhook PullRequest (#6102) (#6104)
|
||||
* Fix redirect loop when password change is required and Gitea is installed as a suburl (#5965) (#6101)
|
||||
* Fix compare button regression (#5929) (#6098)
|
||||
* Recover panic in orgmode.Render if bad orgfile (#4982) (#5903) (#6097)
|
||||
|
||||
## [1.7.2](https://github.com/go-gitea/gitea/releases/tag/v1.7.2) - 2019-02-14
|
||||
* BUGFIXES
|
||||
* Remove all CommitStatus when a repo is deleted (#5940) (#5941)
|
||||
* Fix notifications on pushing with deploy keys by setting hook environment variables (#5935) (#5944)
|
||||
* Silence console logger in gitea serv (#5887) (#5943)
|
||||
* Handle milestone webhook events for issues and PR (#5947) (#5955)
|
||||
* Show user who created the repository instead of the organization in action feed (#5948) (#5956)
|
||||
* Fix ssh deploy and user key constraints (#1357) (#5939) (#5966)
|
||||
* Fix bug when deleting a linked account will removed all (#5989) (#5990)
|
||||
* Fix empty ssh key importing in ldap (#5984) (#6009)
|
||||
* Fix metrics auth token detection (#6006) (#6017)
|
||||
* Create repository on organisation by default on its dashboard (#6026) (#6048)
|
||||
* Make sure labels are actually returned in API (#6053) (#6059)
|
||||
* Switch to more recent build of xgo (#6070) (#6072)
|
||||
* In basic auth check for tokens before call UserSignIn (#5725) (#6083)
|
||||
|
||||
## [1.7.1](https://github.com/go-gitea/gitea/releases/tag/v1.7.1) - 2019-01-31
|
||||
* SECURITY
|
||||
* Disable redirect for i18n (#5910) (#5916)
|
||||
* Only allow local login if password is non-empty (#5906) (#5908)
|
||||
* Fix go-get URL generation (#5905) (#5907)
|
||||
* BUGFIXES
|
||||
* Fix TLS errors when using acme/autocert for local connections (#5820) (#5826)
|
||||
* Request for public keys only if LDAP attribute is set (#5816) (#5819)
|
||||
* Fix delete correct temp directory (#5840) (#5839)
|
||||
* Fix an error while adding a dependency via UI (#5862) (#5876)
|
||||
* Fix null pointer in attempt to Sudo if not logged in (#5872) (#5884)
|
||||
* When creating new repository fsck option should be enabled (#5817) (#5885)
|
||||
* Prevent nil dereference in mailIssueCommentToParticipants (#5891) (#5895) (#5894)
|
||||
* Fix bug when read public repo lfs file (#5913) (#5912)
|
||||
* Respect value of REQUIRE_SIGNIN_VIEW (#5901) (#5915)
|
||||
* Fix compare button on upstream repo leading to 404 (#5877) (#5914)
|
||||
* DOCS
|
||||
* Added docs for the tree api (#5835)
|
||||
* MISC
|
||||
* Include Go toolchain to --version (#5832) (#5830)
|
||||
|
||||
## [1.7.0](https://github.com/go-gitea/gitea/releases/tag/v1.7.0) - 2019-01-22
|
||||
* SECURITY
|
||||
* Do not display the raw OpenID error in the UI (#5705) (#5712)
|
||||
* When redirecting clean the path to avoid redirecting to external site (#5669) (#5679)
|
||||
* Prevent DeleteFilePost doing arbitrary deletion (#5631)
|
||||
* BREAKING
|
||||
* Restrict permission check on repositories and fix some problems (#5314)
|
||||
* Show only opened milestones on issues page milestone filter (#5051)
|
||||
* FEATURE
|
||||
* Implement git refs API for listing references (branches, tags and other) (#5354)
|
||||
* Approvals at Branch Protection (#5350)
|
||||
* Add raw blob endpoint to get objects by SHA ID (#5334)
|
||||
* Add api for user to create org (#5268)
|
||||
* Create AuthorizedKeysCommand (#5236)
|
||||
* User action heatmap (#5131)
|
||||
* Refactor heatmap to vue component (#5401)
|
||||
* Webhook for Pull Request approval/rejection (#5027)
|
||||
* Add command for migrating database (#4954)
|
||||
* Search keyword by splitting provided values by , (#4939)
|
||||
* Create Progressive Web App (#4730)
|
||||
* Give user a link to create PR after push (#4716)
|
||||
* Add rebase with merge commit merge style (#3844) (#4052)
|
||||
* BUGFIXES
|
||||
* Disallow empty titles (#5785) (#5794)
|
||||
* Fix sqlite deadlock when assigning to a PR (#5640) (#5642)
|
||||
* Don't close issues via commits on non-default branch. (#5622) (#5643)
|
||||
* Fix commit page showing status for current default branch (#5650) (#5653)
|
||||
* Only count users own actions for heatmap contributions (#5647) (#5655)
|
||||
* Update xorm to fix issue postgresql dumping issues (#5680) (#5692)
|
||||
* Use correct value for "MSpan Structures Obtained" (#5706) (#5716)
|
||||
* Fix bug on modifying sshd username (#5624)
|
||||
* Delete tags in mirror which are removed for original repo. (#5609)
|
||||
* Fix wrong text getting saved on editing second comment on an issue. (#5608)
|
||||
* Fix nil pointer when adding a due date (#5587)
|
||||
* Fix type mismatch of format string (#5574)
|
||||
* Fix bug on upload file name (#5571)
|
||||
* Issue is not overdue when it is on the same date #5566 (#5568)
|
||||
* Fix indexer reindex bug when gitea restart (#5563)
|
||||
* Fix table name typo on SQL (#5562)
|
||||
* Synchronize SSH keys on login with LDAP + Fix SQLite deadlock on ldap ssh key deletion (#5557)
|
||||
* Fix makefile generate buildstep (#5556)
|
||||
* Fix nil pointer base branch bug (#5555)
|
||||
* Fix permission check on api create org (#5523)
|
||||
* Fix detect force push failure on deletion of protected branches (#5522)
|
||||
* Fix approvals limitation (#5521)
|
||||
* Fix bug when a read perm user to edit his issue (#5516)
|
||||
* Fix adding reaction fail for read permission user (#5515)
|
||||
* Fixing MSSQL timestamp type (#5511)
|
||||
* Fix forgot deletion of notification when delete repository (#5506)
|
||||
* Fix empty wiki (#5504)
|
||||
* Fix clone wiki failed via ssh (#5503)
|
||||
* Fix code review on mssql (#5502)
|
||||
* Fix lfs version check warning log when using ssh protocol (#5501)
|
||||
* Fix topic name length on database (#5493)
|
||||
* Ensure that the `closed_at` is set for closed issues (#5449)
|
||||
* Admin should be able to delete repos via the API even if he is not a member of the organization (#5443)
|
||||
* Word-Break the WebHook url to prevent a ui-break (#5432)
|
||||
* Fix forgot removed records when deleting user (#5429)
|
||||
* Fix repository deletion when there is large number of issues in it (#5426)
|
||||
* Fix heatmap colors for Chrome/Safari (#5421)
|
||||
* Fix password variable shadowing (#5405)
|
||||
* Fix dependent issue searching when gitea is run in subpath (#5392)
|
||||
* Don't force a password change for the admin user when creating an account via cli (#5391)
|
||||
* API: '/orgs/:org/repos': return private repos with read access (#5383)
|
||||
* Don't send assign webhooks when creating issue (#5365)
|
||||
* Removing Labels via EditPullRequest API (#5348)
|
||||
* Migration fixes for gogs (0.11.66) to gitea (1.6.0) #5318 (#5341)
|
||||
* Fix bug when users have serval teams with different units on different repositories (#5307)
|
||||
* Fix U2F if gitea is configured in subpath (#5302)
|
||||
* Fix file edit change preview functionality (#5300)
|
||||
* Update gitignore list (#5258)
|
||||
* Fixed heatmap not working in mssql (#5248)
|
||||
* Fixed wrong api request url for instances running in subfolders (#5247)
|
||||
* Fix compatibility heatmap with mysql 8 (#5232)
|
||||
* Fix data race on migrate repository (#5224)
|
||||
* Fix sqlite and mssql lock (#5214)
|
||||
* Fix sqlite lock (#5210)
|
||||
* Fix: Accept web-command cli flags if web-command is commited (#5200)
|
||||
* Fix: Add secret to all webhook's payload where it has been missing (#5199)
|
||||
* Fix race on updatesize (#5190)
|
||||
* Fix create team, update team missing units (#5188)
|
||||
* Fix sqlite lock (#5184 & #5176)
|
||||
* Fix showing pull request link when delete a branch (#5166)
|
||||
* Fix JSON result of empty array in heatmap data array (#5154)
|
||||
* Update build tags for sqlite_unlock notify (#5144)
|
||||
* This commit will reduce join star, repo_topic, topic tables on repo search, so that fix extra columns problem on mssql (#5136)
|
||||
* Fix deadlock when sqlite (#5118)
|
||||
* Add comment replies (#5104)
|
||||
* Fix home page template regression (#5102)
|
||||
* Fix regex to support optional end line of old section in diff hunk (#5096)
|
||||
* LDAP via simple auth separate bind user and search base (#5055)
|
||||
* Fix markdown image with link (#4675)
|
||||
* Fix to 3819 - Filtering issues by tags on main screen issues (#3824)
|
||||
* ENHANCEMENT
|
||||
* Delete organization endpoint added (#5601)
|
||||
* Update Licenses (#5558)
|
||||
* Support reverse proxy providing email (#5554)
|
||||
* Add git protocol v2 support via SSH on Docker image (#5520)
|
||||
* Add tests for api user orgs (#5494)
|
||||
* Allow link verification for services like Mastodon (#5481)
|
||||
* Improve team members and repositories settings UI (#5457)
|
||||
* Remove the required class from optional ssh port in installation page (#5428)
|
||||
* Explicitly disable Git credential helper (#5367)
|
||||
* Setting Labels via EditPullRequest API (#5347)
|
||||
* Implement pasting image from clipboard for browsers that supports that (#5317)
|
||||
* Milestone issues and pull requests (#5293)
|
||||
* Support envs on external render commands (#5278)
|
||||
* Add option to disable automatic mirror syncing. (#5242)
|
||||
* Remove unused db init on commands serv, update, hooks (#5225)
|
||||
* Serve audio files using HTML5 audio tag (#5221)
|
||||
* Pass link prefixes to external markup parsers (#5201)
|
||||
* Add AutoHead functionality. (#5186)
|
||||
* Fix emojis not showing in commit messages (#5168)
|
||||
* Block registration based on email domain (#5157)
|
||||
* Update vendor/go-sqlite3 (#5133 & #5162)
|
||||
* Update x/net lib (#5169)
|
||||
* Show review summary in pull requests (#5132)
|
||||
* Use type switch (#5122)
|
||||
* Remove duplicated if bodies (#5121)
|
||||
* Remove check for negative length (#5120)
|
||||
* Make switch more clear (#5119)
|
||||
* Use named const instead of a raw string (#5115)
|
||||
* Fix issue where ecdsa and other key types are not synced from LDAP (#5092) (#5094)
|
||||
* Refactor: err != nil check, just return error instead (#5093)
|
||||
* Add notification interface and refactor UI notifications (#5085)
|
||||
* Use APP_NAME on home page (#5048)
|
||||
* Explicitly decide whether to use TLS in mailer's configuration (#5024)
|
||||
* Generate random password (#5023)
|
||||
* UX of link account (Step 1) (#5006)
|
||||
* Make sure argsSet verifies string isn't empty too (#4980)
|
||||
* Improve performance of dashboard (#4977)
|
||||
* Keys API changes (#4960)
|
||||
* Add must-change-password flag to cli for creating a user (#4955)
|
||||
* Use native go method to get current user rather than environment variable (#4930)
|
||||
* Make gitea serv use api/internal (#4886)
|
||||
* Add support for search by uid (#4876)
|
||||
* Allow to add organization members as collaborators on organization owned repositories (#4748)
|
||||
* TESTING
|
||||
* Kill testing processes if the test takes too long (#5174)
|
||||
* Update outdated Go toolchain version for .drone.yml (#5146)
|
||||
* Increase the retry limit to 20 times and the interval to 200ms (#5134)
|
||||
* Retry test-fixtures loading in case of transaction rollback (#5125)
|
||||
* Added test environment for mssql (#4282)
|
||||
* BUILD
|
||||
* Replace lint to revive (#5422)
|
||||
* Update golang version in Dockerfile (#5246)
|
||||
* DOCS
|
||||
* Typo in routers/api/v1/org/org.go fixed. (#5598)
|
||||
* Update the docs for sqlite_unlock_notify (#5145)
|
||||
* CN translation of docs part (#5049)
|
||||
* Kubernetes deployment file (#5046)
|
||||
* MISC
|
||||
* Upgrade alpine to 3.8 (#5423)
|
||||
* Git-Trees API (#5403)
|
||||
* Only chown directories during docker setup if necessary. Fix #4425 (#5064)
|
||||
|
||||
## [1.6.4](https://github.com/go-gitea/gitea/releases/tag/v1.6.4) - 2019-01-15
|
||||
* BUGFIX
|
||||
* Fix SSH key now can be reused as public key after deleting as deploy key (#5671) (#5685)
|
||||
* When redirecting clean the path to avoid redirecting to external site (#5669) (#5703)
|
||||
* Fix to use correct value for "MSpan Structures Obtained" (#5706) (#5715)
|
||||
|
||||
## [1.6.3](https://github.com/go-gitea/gitea/releases/tag/v1.6.3) - 2019-01-04
|
||||
* SECURITY
|
||||
* Prevent DeleteFilePost doing arbitrary deletion (#5631)
|
||||
* BUGFIX
|
||||
* Fix wrong text getting saved on editing second comment on an issue (#5608)
|
||||
|
||||
## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
|
||||
* SECURITY
|
||||
* Sanitize uploaded file names (#5571) (#5573)
|
||||
* HTMLEncode user added text (#5570) (#5575)
|
||||
* BUGFIXES
|
||||
* Fix indexer reindex bug when gitea restart (#5563) (#5564)
|
||||
* Remove a double slash in the HTTPS redirect with Let's Encrypt (#5537) (#5539)
|
||||
* Fix bug when a read perm user to edit his issue (#5516) (#5534)
|
||||
* Detect force push failure on deletion of protected branches (#5522) (#5531)
|
||||
* Let's Encrypt handler listens on correct port for certificate validation (#5525) (#5527)
|
||||
* Fix forgot deletion of notification when delete repository (#5506) (#5514)
|
||||
* Fix undeleted content when deleting user (#5429) (#5509)
|
||||
* Fix empty wiki (#5504) (#5508)
|
||||
|
||||
## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
|
||||
* BUGFIXES
|
||||
* Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
|
||||
* API: '/orgs/:org/repos': return private repos with read access (#5393)
|
||||
* Fix repository deletion when there is large number of issues in it (#5426) (#5434)
|
||||
* Word-break the WebHook url to prevent a ui-break (#5445)
|
||||
* Admin should be able to delete repos via the API even if they are not a member of the organization (#5443) (#5447)
|
||||
* Ensure that the `closed_at` is set for closed (#5450)
|
||||
* Fix topic name length on database (#5493) (#5495)
|
||||
|
||||
## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
|
||||
* BREAKING
|
||||
* Respect email privacy option in user search via API (#4512)
|
||||
* Simply remove tidb and deps (#3993)
|
||||
* Swagger.v1.json template (#3572)
|
||||
* SECURITY
|
||||
* Add CSRF checking to reqToken and add reqToken to admin API routes (#5272) (#5250)
|
||||
* Improve URL validation for external wiki and external issues (#4710)
|
||||
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
|
||||
* Don't disclose emails of all users when sending out emails (#4664)
|
||||
* Check that repositories can only be migrated to own user or organizations (#4366)
|
||||
* FEATURE
|
||||
* Add comment replies (#5147) (#5104)
|
||||
* Pull request review/approval and comment on code (#3748)
|
||||
* Added dependencies for issues (#2196) (#2531)
|
||||
* Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198)
|
||||
* Add sudo functionality to the API (#4809)
|
||||
* Add oauth providers via cli (#4591)
|
||||
* Disable merging a WIP Pull request (#4529)
|
||||
* Force user to change password (#4489)
|
||||
* Add letsencrypt to Gitea (#4189)
|
||||
* Add push webhook support for mirrored repositories (#4127)
|
||||
* Add csv file render support defaultly (#4105)
|
||||
* Add Recaptcha functionality to Gitea (#4044)
|
||||
* ENHANCEMENT
|
||||
* Fix milestones sorted wrongly (#4987)
|
||||
* Allow api to create tags for releases if they don't exist (#4890)
|
||||
* Fix #4877 to follow the OpenID Connect Audiences spec (#4878)
|
||||
* Enforce token on api routes [fixed critical security issue #4357] (#4840)
|
||||
* Update legacy branch and tag URLs in dashboard to new format (#4812)
|
||||
* Slack webhook channel name cannot be empty or just contain an hashtag (#4786)
|
||||
* Add whitespace handling to PR-comparsion (#4683)
|
||||
* Make reverse proxy auth optional (#4643)
|
||||
* MySQL TLS (#4642)
|
||||
* Make sure to set PR split view when creating/previewing a pull request (#4617)
|
||||
* Log user in after a successful sign up (#4615)
|
||||
* Fix typo IsPullReuqestBroken -> IsPullRequestBroken (#4578)
|
||||
* Allow admin toggle forcing a password change for newly created users (#4563)
|
||||
* Update jQuery to v1.12.4 (#4551)
|
||||
* Env var GITEA_PUSHER_EMAIL (#4516)
|
||||
* Feat(repo): support search repository by topic name (#4505)
|
||||
* Small improvements to dependency UI (#4503)
|
||||
* Make max commits in graph configurable (#4498)
|
||||
* Add valid for lfs oid (#4461)
|
||||
* Add shortcut to save wiki page (#4452)
|
||||
* Allow administrator to create repository for any organization (#4368)
|
||||
* Fix repository last updated time update when delete a user who watched the repo (#4363)
|
||||
* Switch plaintext scratch tokens to use hash instead (#4331)
|
||||
* Increase default TOTP secret size to 320 bits (#4287)
|
||||
* Keep preseeded database password (#4284)
|
||||
* Implemented hover text showing user FullName (#4261)
|
||||
* Add ability to delete a token (#4235)
|
||||
* Fix typos in i18n variable names. (#4080)
|
||||
* Api: repos/search: add parameters to control the sort order (#3964)
|
||||
* Add missing path in the Docker app.ini template (#2181)
|
||||
* Add file name and branch to page title (#4902)
|
||||
* Offline use of google fonts (#4872)
|
||||
* Add missing History link to directory listings v2 (#4829)
|
||||
* Locale for Edit and Remove due date issue (#4802)
|
||||
* Disable 'May Import Local Repository' when is disabled by setting (Is… (#4780)
|
||||
* API /admin/users/{username} missing parameter (#4775)
|
||||
* Display error when adding a user to a team twice (#4746)
|
||||
* Remove UsePrivilegeSeparation from the Docker sshd_config, see #2876 (#4722)
|
||||
* Focus title input when clicking helper link (#4696)
|
||||
* Add vendor to user reserved words and format words list according alphabet (#4685)
|
||||
* Add gitea/issues link to 500 page (#4654)
|
||||
* Hide home button when landing page is not set to home (#4651)
|
||||
* Remove link to GitHub issues in 404 template (#4639)
|
||||
* Cmd/serve: pprof cpu and memory profile dumps to disk (#4560)
|
||||
* Add flash message after an account has been successfully activated (#4510)
|
||||
* Prevent html entity escaping on delete branch (#4471)
|
||||
* Locale for button Edit on protected branch (#4442)
|
||||
* Update notification icon (#4343)
|
||||
* Added front-end topics validation (#4316)
|
||||
* Don't display buttons if there are no system notifications (#4280)
|
||||
* Issue due date api (#3890)
|
||||
* BUGFIXES
|
||||
* dont' send assign webhooks when creating issue (#5365)
|
||||
* Fix create team, update team missing units (#5188)
|
||||
* Fix file edit change preview functionality (#5300)
|
||||
* *ix bug when users have serval teams with different units on different repositories (#5307)
|
||||
* Fix U2F if gitea is configured in subpath (#5302)
|
||||
* Fix markdown image with link (#4675)
|
||||
* Remove maxlines option for file logger (#5282)
|
||||
* Fix wrong api request url for instances running in subfolders (#5261) (#5247)
|
||||
* Accept web-command cli flags if web-command is commited (#5245) (#5200)
|
||||
* Reduce join star, repo_topic, topic tables on repo search, to resolve extra columns problem on MSSQL (#5136) (#5229)
|
||||
* Fix data race on migrate repository (#5224) (#5230)
|
||||
* Add secret to all webhook's payload where it has been missing (#5208) (#5199)
|
||||
* Fix sqlite and MSSQL lock (#5210) (#5223) (#5214) (#5218) (#5176) (#5179)
|
||||
* Fix race on updatesize (#5190) (#5215)
|
||||
* Fix filtering issues by tags on main screen issues (#5219) (#3824)
|
||||
* Fix SQL quoting (#5137) (#5117)
|
||||
* Fix regex to support optional end line of old section in diff hunk (#5097) (#5096)
|
||||
* Fix release creation via API (#5076)
|
||||
* Remove links from topics in edit mode (#5026)
|
||||
* Fix missing AppSubUrl in few more templates (fixup) (#5021)
|
||||
* Fix missing AppSubUrl in some templates (#5020)
|
||||
* Hide outdated comments in file view (#5017)
|
||||
* Upgrade gopkg.in/testfixtures.v2 (#4999)
|
||||
* Disable debug routes unless PPROF is enabled in configuration (#4995)
|
||||
* Fix user menu item styling (#4985)
|
||||
* Fix layout of the topics editing form (#4971)
|
||||
* Fix null pointer dereference in ParseCommitWithSignature (#4962)
|
||||
* Fix url in discord webhook (#4953)
|
||||
* Detect charset and convert non UTF-8 files for display (#4950)
|
||||
* Make sure to catch the right error so it is displayed on the UI (#4945)
|
||||
* Fix(topics): don't redirect to explore page. (#4938)
|
||||
* Fix bug forget to remove Stopwatch when remove repository (#4928)
|
||||
* Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
|
||||
* Fix: Crippled diff (#4726) (#4900)
|
||||
* Fix trimming of markup section names (#4863)
|
||||
* Issues api allow pulls and fix #4832 (#4852)
|
||||
* Do not autocreate directory for new users/orgs (#4828) (#4849)
|
||||
* Fix redirect with non-ascii branch names (#4764) (#4810)
|
||||
* Fix missing release title in webhook (#4783) (#4796)
|
||||
* User shouldn't be able to approve or reject his/her own PR (#4729)
|
||||
* Make sure to reset commit count in the cache on mirror syncing (#4720)
|
||||
* Fixed bug where team with admin privelege type doesn't get any unit (#4719)
|
||||
* Fix incorrect caption of webhook setting (#4701) (#4717)
|
||||
* Allow WIP marker to contains < or > (#4709)
|
||||
* Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
|
||||
* Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
|
||||
* Fix custom templates being ignored (#4638)
|
||||
* Fix starring icon after semantic ui update (#4628)
|
||||
* Fix Split-View line adjustment (#4622)
|
||||
* Fix integer constant overflows in tests (#4616)
|
||||
* Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
|
||||
* Fix bugs when too many IN variables (#4594)
|
||||
* Fix failure on creating pull request with assignees (#4419) (#4583)
|
||||
* Fix panic issue on update avatar email (#4580) (#4581)
|
||||
* Fix status code label for a successful webhook (#4540)
|
||||
* An inactive user shouldn't be able to be added as a collaborator (#4535)
|
||||
* Don't fail silently if trying to add a collaborator twice (#4533)
|
||||
* Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
|
||||
* Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
|
||||
* Fix migration from older releases (#4495)
|
||||
* Accept 'Data:' in commit graph (#4487)
|
||||
* Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
|
||||
* Relative URLs for LibreJS page (#4460)
|
||||
* Redirect to correct page after using scratch token (#4458)
|
||||
* Fix column droping for MSSQL that need new transaction for that (#4440)
|
||||
* Replace src with raw to fix image paths (#4377)
|
||||
* Add default merge options when creating new repository (#4369)
|
||||
* Fix docker build (#4358)
|
||||
* Fixes repo membership check in API (#4341)
|
||||
* Dep upgrade mysql lib (#4161)
|
||||
* Fix some issues with special chars in branch names (#3767)
|
||||
* Responsive design fixes (#4508)
|
||||
* TRANSLATION
|
||||
* Fix punctuation in English translation (#4958)
|
||||
* Fix translation (#4355)
|
||||
|
||||
## [1.5.3](https://github.com/go-gitea/gitea/releases/tag/v1.5.3) - 2018-10-31
|
||||
* SECURITY
|
||||
* Fix remote command execution vulnerability in upstream library (#5177) (#5196)
|
||||
|
||||
## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
|
||||
* SECURITY
|
||||
* Enforce token on api routes (#4840) (#4905)
|
||||
* BUGFIXES
|
||||
* Remove links from topics in edit mode (#5030)
|
||||
* Detect charset and convert non UTF-8 files for display (#4950) (#4994)
|
||||
* Fix layout of the topics editing form (#4971) (#4993)
|
||||
* Fix null pointer dereference in ParseCommitWithSignature (#4964)
|
||||
* Fix url in discord webhook (#4951)
|
||||
* Fix font-cropping UI bug in diff (#4726) (#4929)
|
||||
* Fix bug forget to remove Stopwatch when remove repository (#4933)
|
||||
* Fix bug when repo remained bare if multiple branches pushed (#4927)
|
||||
* Fix redirect with non-ascii branch names (#4764) (#4887)
|
||||
* Fix issues api allow pulls (#4852) (#4862)
|
||||
* Fix trimming of markup section names (#4864)
|
||||
|
||||
## [1.5.1](https://github.com/go-gitea/gitea/releases/tag/v1.5.1) - 2018-09-03
|
||||
* SECURITY
|
||||
* Don't disclose emails of all users when sending out emails (#4784)
|
||||
* Improve URL validation for external wiki and external issues (#4710) (#4740)
|
||||
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706) (#4707)
|
||||
* BUGFIXES
|
||||
* Fix missing release title in webhook (#4783) (#4800)
|
||||
* Make sure to reset commit count in the cache on mirror syncing (#4770)
|
||||
* Fixed bug where team with admin privelege type doesn't get any unit (#4759)
|
||||
* Fix failure on creating pull request with assignees (#4583) (#4727)
|
||||
* Hide org/create menu item in Dashboard if user has no rights (#4678) (#4686)
|
||||
* TRANSLATION
|
||||
* Fix incorrect caption of webhook setting (#4701) (#4718)
|
||||
|
||||
## [1.5.0](https://github.com/go-gitea/gitea/releases/tag/v1.5.0) - 2018-08-10
|
||||
* SECURITY
|
||||
* Check that repositories can only be migrated to own user or organizations (#4366) (#4370)
|
||||
* Limit uploaded avatar image-size to 4096px x 3072px by default (#4353)
|
||||
* Do not allow to reuse TOTP passcode (#3878)
|
||||
* BUGFIXES
|
||||
* Fix column droping for MSSQL that need new transaction for that (#4440) (#4484)
|
||||
* Redirect to correct page after using scratch token (#4458) (#4472)
|
||||
* Replace src with raw to fix image paths (#4377) (#4386)
|
||||
* Fixes repo membership check in API (#4341) (#4379)
|
||||
* Add default merge options when adding new repository (#4369) (#4373)
|
||||
* Fix repository last updated time update when delete a user who watched the repo (#4363) (#4371)
|
||||
* Fix html entity escaping in branch deletion message (#4471) (#4485)
|
||||
* Fix out-of-transaction query in removeOrgUser (#4521) (#4524)
|
||||
* Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519)
|
||||
* Fix panic issue on update avatar email (#4580) (#4590)
|
||||
* Fix bugs when too many IN variables (#4594) (#4597)
|
||||
* Push whitelist now doesn't apply to branch deletion (#4601) (#4640)
|
||||
* Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645) (#4650)
|
||||
* FEATURE
|
||||
* Add cli commands to regen hooks & keys (#3979)
|
||||
* Add support for FIDO U2F (#3971)
|
||||
|
@@ -16,6 +16,7 @@
|
||||
- [Maintainers](#maintainers)
|
||||
- [Owners](#owners)
|
||||
- [Versions](#versions)
|
||||
- [Releasing Gitea](#releasing-gitea)
|
||||
- [Copyright](#copyright)
|
||||
|
||||
## Introduction
|
||||
@@ -68,7 +69,7 @@ whole tree to make sure the changes don't break other usage
|
||||
and keep the compatibility on upgrade. To make sure you are
|
||||
running the test suite exactly like we do, you should install
|
||||
the CLI for [Drone CI](https://github.com/drone/drone), as
|
||||
we are using the server for continous testing, following [these
|
||||
we are using the server for continuous testing, following [these
|
||||
instructions](http://docs.drone.io/cli-installation/). After that,
|
||||
you can simply call `drone exec --local --build-event "pull_request"` within
|
||||
your working directory and it will try to run the test suite locally.
|
||||
@@ -92,7 +93,7 @@ You can find more information on how to get started with it on the [dep project
|
||||
We do all translation work inside [Crowdin](https://crowdin.com/project/gitea).
|
||||
The only translation that is maintained in this git repository is
|
||||
[`en_US.ini`](https://github.com/go-gitea/gitea/blob/master/options/locale/locale_en-US.ini)
|
||||
and is synced regularily to Crowdin. Once a translation has reached
|
||||
and is synced regularly to Crowdin. Once a translation has reached
|
||||
A SATISFACTORY PERCENTAGE it will be synced back into this repo and
|
||||
included in the next released version.
|
||||
|
||||
@@ -243,6 +244,11 @@ they served:
|
||||
* [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||
* [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||
|
||||
* 2019-01-01 ~ 2019-12-31
|
||||
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
* [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||
* [Matti Ranta](https://github.com/techknowlogick) <matti@mdranta.net>
|
||||
|
||||
## Versions
|
||||
|
||||
Gitea has the `master` branch as a tip branch and has version branches
|
||||
@@ -256,12 +262,25 @@ in production, please download the latest release tag version. All the
|
||||
branches will be protected via GitHub, all the PRs to every branch must
|
||||
be reviewed by two maintainers and must pass the automatic tests.
|
||||
|
||||
## Releasing Gitea
|
||||
|
||||
* Let $vmaj, $vmin and $vpat be Major, Minor and Patch version numbers, $vpat should be rc1, rc2, 0, 1, ...... $vmaj.$vmin will be kept the same as milestones on github or gitea in future.
|
||||
* Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody against in about serval hours.
|
||||
* If this is a big version first you have to create PR for changelog on branch `master` with PRs with label `changelog` and after it has been merged do following steps:
|
||||
* Create `-dev` tag as `git tag -s -F release.notes v$vmaj.$vmin.0-dev` and push the tag as `git push origin v$vmaj.$vmin.0-dev`.
|
||||
* When CI has finished building tag then you have to create a new branch named `release/v$vmaj.$vmin`
|
||||
* If it is bugfix version create PR for changelog on branch `release/v$vmaj.$vmin` and wait till it is reviewed and merged.
|
||||
* Add a tag as `git tag -s -F release.notes v$vmaj.$vmin.$`, release.notes file could be a temporary file to only include the changelog this version which you added to `CHANGELOG.md`.
|
||||
* And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically created a release and upload all the compiled binary. (But currently it didn't add the release notes automatically. Maybe we should fix that.)
|
||||
* If needed send PR for changelog on branch `master`.
|
||||
* Send PR to [blog repository](https://github.com/go-gitea/blog) announcing the release.
|
||||
|
||||
## Copyright
|
||||
|
||||
Code that you contribute should use the standard copyright header:
|
||||
|
||||
```
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
```
|
||||
|
@@ -1,10 +1,10 @@
|
||||
|
||||
###################################
|
||||
#Build stage
|
||||
FROM golang:1.10-alpine3.7 AS build-env
|
||||
FROM golang:1.11-alpine3.8 AS build-env
|
||||
|
||||
ARG GITEA_VERSION
|
||||
ARG TAGS="sqlite"
|
||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||
ENV TAGS "bindata $TAGS"
|
||||
|
||||
#Build deps
|
||||
@@ -18,7 +18,7 @@ WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
&& make clean generate build
|
||||
|
||||
FROM alpine:3.7
|
||||
FROM alpine:3.8
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 22 3000
|
||||
@@ -58,3 +58,4 @@ CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY docker /
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
RUN ln -s /app/gitea/gitea /usr/local/bin/gitea
|
||||
|
766
Gopkg.lock
generated
766
Gopkg.lock
generated
File diff suppressed because it is too large
Load Diff
44
Gopkg.toml
44
Gopkg.toml
@@ -15,11 +15,17 @@ ignored = ["google.golang.org/appengine*"]
|
||||
name = "code.gitea.io/sdk"
|
||||
|
||||
[[constraint]]
|
||||
revision = "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94"
|
||||
# branch = "master"
|
||||
revision = "c74e08f039e56cef576e4336382b2a2d12d9e026"
|
||||
name = "github.com/blevesearch/bleve"
|
||||
#Not targetting v0.7.0 since standard where use only just after this tag
|
||||
|
||||
[[constraint]]
|
||||
revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[[constraint]]
|
||||
revision = "a646d33e2ee3172a661fc09bca23bb4889a41bc8"
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
|
||||
[[constraint]]
|
||||
@@ -27,18 +33,24 @@ ignored = ["google.golang.org/appengine*"]
|
||||
name = "golang.org/x/text"
|
||||
|
||||
[[constraint]]
|
||||
revision = "f2499483f923065a842d38eb4c7f1927e6fc6e6d"
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
#version = "v1.0.0"
|
||||
revision = "33197485abe227dcb254644cf5081c9a3c281669"
|
||||
name = "github.com/pingcap/tidb"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
#version = "0.6.5"
|
||||
revision = "d4149d1eee0c2c488a74a5863fd9caf13d60fd03"
|
||||
revision = "1cd2662be938bfee0e34af92fe448513e0560fb1"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-xorm/builder"
|
||||
version = "0.3.3"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/mattn/go-sqlite3"
|
||||
revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/gorilla/mux"
|
||||
@@ -58,7 +70,7 @@ ignored = ["google.golang.org/appengine*"]
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/markbates/goth"
|
||||
version = "1.45.5"
|
||||
version = "1.47.2"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
@@ -85,8 +97,8 @@ ignored = ["google.golang.org/appengine*"]
|
||||
version = "1.31.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/ldap.v2"
|
||||
version = "2.4.1"
|
||||
name = "gopkg.in/ldap.v3"
|
||||
version = "3.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/macaron.v1"
|
||||
@@ -102,5 +114,9 @@ ignored = ["google.golang.org/appengine*"]
|
||||
source = "github.com/go-gitea/bolt"
|
||||
|
||||
[[override]]
|
||||
revision = "c10ba270aa0bf8b8c1c986e103859c67a9103061"
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
version = "0.9.0"
|
||||
|
@@ -20,7 +20,9 @@ Jonas Östanbäck <jonas.ostanback@gmail.com> (@cez81)
|
||||
David Schneiderbauer <dschneiderbauer@gmail.com> (@daviian)
|
||||
Peter Žeby <morlinest@gmail.com> (@morlinest)
|
||||
Matti Ranta <matti@mdranta.net> (@techknowlogick)
|
||||
Michael Lustfield <mtecknology@debian.org> (@MTecknology)
|
||||
Jonas Franz <info@jonasfranz.software> (@JonasFranzDEV)
|
||||
Flynn Lufmons <fluf@warpmail.net> (@flufmonster)
|
||||
Jonas Franz <info@jonasfranz.software> (@jonasfranz)
|
||||
Alexey Terentyev <axifnx@gmail.com> (@axifive)
|
||||
Lanre Adelowo <yo@lanre.wtf> (@adelowo)
|
||||
Konrad Langenberg <k@knt.li> (@kolaente)
|
||||
He-Long Zhang <outman99@hotmail.com> (@BetaCat0)
|
||||
Andrew Thornton <art27@cantab.net> (@zeripath)
|
||||
|
76
Makefile
76
Makefile
@@ -21,7 +21,19 @@ GOFMT ?= gofmt -s
|
||||
GOFLAGS := -i -v
|
||||
EXTRA_GOFLAGS ?=
|
||||
|
||||
LDFLAGS := -X "main.Version=$(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')" -X "main.Tags=$(TAGS)"
|
||||
ifneq ($(DRONE_TAG),)
|
||||
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||
GITEA_VERSION := $(VERSION)
|
||||
else
|
||||
ifneq ($(DRONE_BRANCH),)
|
||||
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||
else
|
||||
VERSION ?= master
|
||||
endif
|
||||
GITEA_VERSION := $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||
endif
|
||||
|
||||
LDFLAGS := -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||
|
||||
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||
@@ -30,6 +42,10 @@ TAGS ?=
|
||||
|
||||
TMPDIR := $(shell mktemp -d 2>/dev/null || mktemp -d -t 'gitea-temp')
|
||||
|
||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||
SWAGGER_SPEC_S_TMPL := s|"basePath":\s*"/api/v1"|"basePath": "{{AppSubUrl}}/api/v1"|g
|
||||
SWAGGER_SPEC_S_JSON := s|"basePath":\s*"{{AppSubUrl}}/api/v1"|"basePath": "/api/v1"|g
|
||||
|
||||
TEST_MYSQL_HOST ?= mysql:3306
|
||||
TEST_MYSQL_DBNAME ?= testgitea
|
||||
TEST_MYSQL_USERNAME ?= root
|
||||
@@ -38,6 +54,10 @@ TEST_PGSQL_HOST ?= pgsql:5432
|
||||
TEST_PGSQL_DBNAME ?= testgitea
|
||||
TEST_PGSQL_USERNAME ?= postgres
|
||||
TEST_PGSQL_PASSWORD ?= postgres
|
||||
TEST_MSSQL_HOST ?= mssql:1433
|
||||
TEST_MSSQL_DBNAME ?= gitea
|
||||
TEST_MSSQL_USERNAME ?= sa
|
||||
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
EXECUTABLE := gitea.exe
|
||||
@@ -45,15 +65,8 @@ else
|
||||
EXECUTABLE := gitea
|
||||
endif
|
||||
|
||||
ifneq ($(DRONE_TAG),)
|
||||
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||
else
|
||||
ifneq ($(DRONE_BRANCH),)
|
||||
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||
else
|
||||
VERSION ?= master
|
||||
endif
|
||||
endif
|
||||
# $(call strip-suffix,filename)
|
||||
strip-suffix = $(firstword $(subst ., ,$(1)))
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
@@ -65,9 +78,9 @@ clean:
|
||||
$(GO) clean -i ./...
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) \
|
||||
integrations*.test \
|
||||
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ \
|
||||
integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite \
|
||||
integrations/mysql.ini integrations/pgsql.ini
|
||||
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ integrations/gitea-integration-mssql/ \
|
||||
integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite integrations/indexers-mssql \
|
||||
integrations/mysql.ini integrations/pgsql.ini integrations/mssql.ini
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
@@ -80,7 +93,7 @@ vet:
|
||||
.PHONY: generate
|
||||
generate:
|
||||
@hash go-bindata > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/jteeuwen/go-bindata/...; \
|
||||
$(GO) get -u github.com/jteeuwen/go-bindata/go-bindata; \
|
||||
fi
|
||||
$(GO) generate $(PACKAGES)
|
||||
|
||||
@@ -89,11 +102,12 @@ generate-swagger:
|
||||
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger; \
|
||||
fi
|
||||
swagger generate spec -o ./public/swagger.v1.json
|
||||
swagger generate spec -o './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||
|
||||
.PHONY: swagger-check
|
||||
swagger-check: generate-swagger
|
||||
@diff=$$(git diff public/swagger.v1.json); \
|
||||
@diff=$$(git diff '$(SWAGGER_SPEC)'); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make generate-swagger' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
@@ -105,7 +119,9 @@ swagger-validate:
|
||||
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger; \
|
||||
fi
|
||||
swagger validate ./public/swagger.v1.json
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
|
||||
swagger validate './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||
|
||||
.PHONY: errcheck
|
||||
errcheck:
|
||||
@@ -116,10 +132,10 @@ errcheck:
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
@hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/golang/lint/golint; \
|
||||
@hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/mgechev/revive; \
|
||||
fi
|
||||
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;
|
||||
revive -config .revive.toml -exclude=./vendor/... ./... || exit 1
|
||||
|
||||
.PHONY: misspell-check
|
||||
misspell-check:
|
||||
@@ -147,7 +163,7 @@ fmt-check:
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) test -tags=sqlite $(PACKAGES)
|
||||
$(GO) test -tags='sqlite sqlite_unlock_notify' $(PACKAGES)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
@@ -158,7 +174,7 @@ coverage:
|
||||
|
||||
.PHONY: unit-test-coverage
|
||||
unit-test-coverage:
|
||||
for PKG in $(PACKAGES); do $(GO) test -tags=sqlite -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
for PKG in $(PACKAGES); do $(GO) test -tags='sqlite sqlite_unlock_notify' -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
|
||||
.PHONY: vendor
|
||||
vendor:
|
||||
@@ -192,6 +208,11 @@ generate-ini:
|
||||
-e 's|{{TEST_PGSQL_USERNAME}}|${TEST_PGSQL_USERNAME}|g' \
|
||||
-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
|
||||
integrations/pgsql.ini.tmpl > integrations/pgsql.ini
|
||||
sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \
|
||||
-e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \
|
||||
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
|
||||
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
|
||||
integrations/mssql.ini.tmpl > integrations/mssql.ini
|
||||
|
||||
.PHONY: test-mysql
|
||||
test-mysql: integrations.test generate-ini
|
||||
@@ -201,6 +222,10 @@ test-mysql: integrations.test generate-ini
|
||||
test-pgsql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test
|
||||
|
||||
.PHONY: test-mssql
|
||||
test-mssql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.test
|
||||
|
||||
.PHONY: bench-sqlite
|
||||
bench-sqlite: integrations.sqlite.test
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||
@@ -222,7 +247,7 @@ integrations.test: $(SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -o integrations.test
|
||||
|
||||
integrations.sqlite.test: $(SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite'
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite sqlite_unlock_notify'
|
||||
|
||||
integrations.cover.test: $(SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
||||
@@ -301,7 +326,7 @@ public/js/index.js: $(JAVASCRIPTS)
|
||||
|
||||
.PHONY: stylesheets-check
|
||||
stylesheets-check: generate-stylesheets
|
||||
@diff=$$(git diff public/css/index.css); \
|
||||
@diff=$$(git diff public/css/*); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make generate-stylesheets' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
@@ -311,6 +336,7 @@ stylesheets-check: generate-stylesheets
|
||||
.PHONY: generate-stylesheets
|
||||
generate-stylesheets:
|
||||
node_modules/.bin/lessc --clean-css public/less/index.less public/css/index.css
|
||||
$(foreach file, $(filter-out public/less/themes/_base.less, $(wildcard public/less/themes/*)),node_modules/.bin/lessc --clean-css public/less/themes/$(notdir $(file)) > public/css/theme-$(notdir $(call strip-suffix,$(file))).css;)
|
||||
|
||||
.PHONY: swagger-ui
|
||||
swagger-ui:
|
||||
@@ -334,6 +360,8 @@ update-translations:
|
||||
generate-images:
|
||||
mkdir -p $(TMPDIR)/images
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 880 -h 880 -e $(PWD)/public/img/gitea-lg.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 512 -h 512 -e $(PWD)/public/img/gitea-512.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 192 -h 192 -e $(PWD)/public/img/gitea-192.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer1 -e $(TMPDIR)/images/sm-1.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer2 -e $(TMPDIR)/images/sm-2.png
|
||||
composite -compose atop $(TMPDIR)/images/sm-2.png $(TMPDIR)/images/sm-1.png $(PWD)/public/img/gitea-sm.png
|
||||
|
@@ -29,7 +29,7 @@ This project has been
|
||||
|
||||
From the root of the source tree, run:
|
||||
|
||||
make generate all
|
||||
TAGS="bindata" make generate all
|
||||
|
||||
More info: https://docs.gitea.io/en-us/install-from-source/
|
||||
|
||||
@@ -38,7 +38,7 @@ More info: https://docs.gitea.io/en-us/install-from-source/
|
||||
./gitea web
|
||||
|
||||
NOTE: If you're interested in using our APIs, we have experimental
|
||||
support with [documentation](https://godoc.org/code.gitea.io/sdk/gitea).
|
||||
support with [documentation](https://try.gitea.io/api/swagger).
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -90,6 +90,10 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
|
||||
|
||||
Gitea is pronounced [/ɡɪ’ti:/](https://youtu.be/EM71-2uDAoY) as in "gi-tea" with a hard g.
|
||||
|
||||
**Why is this not hosted on a Gitea instance?**
|
||||
|
||||
We're [working on it](https://github.com/go-gitea/gitea/issues/1029).
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
|
18
README_ZH.md
18
README_ZH.md
@@ -11,16 +11,9 @@
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://opencollective.com/gitea)
|
||||
|
||||
| | | |
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
||||
## 目标
|
||||
|
||||
Gitea的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用Go作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了x86,amd64,还包括 ARM 和 PowerPC。
|
||||
Gitea 的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用 Go 作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了 x86,amd64,还包括 ARM 和 PowerPC。
|
||||
|
||||
如果您想试用一下,请访问 [在线Demo](https://try.gitea.io/)!
|
||||
|
||||
@@ -47,3 +40,12 @@ Fork -> Patch -> Push -> Pull Request
|
||||
## 授权许可
|
||||
|
||||
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/go-gitea/gitea/blob/master/LICENSE) 文件中。
|
||||
|
||||
## 截图
|
||||
|
||||
| | | |
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
336
cmd/admin.go
336
cmd/admin.go
@@ -6,10 +6,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth/oauth2"
|
||||
"code.gitea.io/gitea/modules/generate"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
@@ -26,6 +31,7 @@ var (
|
||||
subcmdChangePassword,
|
||||
subcmdRepoSyncReleases,
|
||||
subcmdRegenerate,
|
||||
subcmdAuth,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -55,6 +61,19 @@ var (
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "random-password",
|
||||
Usage: "Generate a random password for the user",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "Force the user to change his/her password after initial login",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "random-password-length",
|
||||
Usage: "Length of the random password to be generated",
|
||||
Value: 12,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -121,6 +140,121 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
subcmdAuth = cli.Command{
|
||||
Name: "auth",
|
||||
Usage: "Modify external auth providers",
|
||||
Subcommands: []cli.Command{
|
||||
microcmdAuthAddOauth,
|
||||
microcmdAuthUpdateOauth,
|
||||
microcmdAuthList,
|
||||
microcmdAuthDelete,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthList = cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
idFlag = cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of OAuth authentication source",
|
||||
}
|
||||
|
||||
microcmdAuthDelete = cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Action: runDeleteAuth,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
idFlag,
|
||||
},
|
||||
}
|
||||
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "provider",
|
||||
Value: "",
|
||||
Usage: "OAuth2 Provider",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "Client ID (Key)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "secret",
|
||||
Value: "",
|
||||
Usage: "Client Secret",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "auto-discover-url",
|
||||
Value: "",
|
||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "use-custom-urls",
|
||||
Value: "false",
|
||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-auth-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-token-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-profile-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-email-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Email URL (option for GitHub)",
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
}
|
||||
)
|
||||
|
||||
func runChangePassword(c *cli.Context) error {
|
||||
@@ -154,10 +288,30 @@ func runChangePassword(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runCreateUser(c *cli.Context) error {
|
||||
if err := argsSet(c, "name", "password", "email"); err != nil {
|
||||
if err := argsSet(c, "name", "email"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsSet("password") && c.IsSet("random-password") {
|
||||
return errors.New("cannot set both -random-password and -password flags")
|
||||
}
|
||||
|
||||
var password string
|
||||
|
||||
if c.IsSet("password") {
|
||||
password = c.String("password")
|
||||
} else if c.IsSet("random-password") {
|
||||
var err error
|
||||
password, err = generate.GetRandomString(c.Int("random-password-length"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("generated random password is '%s'\n", password)
|
||||
} else {
|
||||
return errors.New("must set either password or random-password flag")
|
||||
}
|
||||
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
@@ -166,12 +320,26 @@ func runCreateUser(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// always default to true
|
||||
var changePassword = true
|
||||
|
||||
// If this is the first user being created.
|
||||
// Take it as the admin and don't force a password update.
|
||||
if n := models.CountUsers(); n == 0 {
|
||||
changePassword = false
|
||||
}
|
||||
|
||||
if c.IsSet("must-change-password") {
|
||||
changePassword = c.Bool("must-change-password")
|
||||
}
|
||||
|
||||
if err := models.CreateUser(&models.User{
|
||||
Name: c.String("name"),
|
||||
Email: c.String("email"),
|
||||
Passwd: c.String("password"),
|
||||
IsActive: true,
|
||||
IsAdmin: c.Bool("admin"),
|
||||
Name: c.String("name"),
|
||||
Email: c.String("email"),
|
||||
Passwd: password,
|
||||
IsActive: true,
|
||||
IsAdmin: c.Bool("admin"),
|
||||
MustChangePassword: changePassword,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("CreateUser: %v", err)
|
||||
}
|
||||
@@ -262,3 +430,159 @@ func runRegenerateKeys(c *cli.Context) error {
|
||||
}
|
||||
return models.RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *models.OAuth2Config {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
TokenURL: c.String("custom-token-url"),
|
||||
AuthURL: c.String("custom-auth-url"),
|
||||
ProfileURL: c.String("custom-profile-url"),
|
||||
EmailURL: c.String("custom-email-url"),
|
||||
}
|
||||
} else {
|
||||
customURLMapping = nil
|
||||
}
|
||||
return &models.OAuth2Config{
|
||||
Provider: c.String("provider"),
|
||||
ClientID: c.String("key"),
|
||||
ClientSecret: c.String("secret"),
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return models.CreateLoginSource(&models.LoginSource{
|
||||
Type: models.LoginOAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActived: true,
|
||||
Cfg: parseOAuth2Config(c),
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := models.GetLoginSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oAuth2Config := source.OAuth2()
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("provider") {
|
||||
oAuth2Config.Provider = c.String("provider")
|
||||
}
|
||||
|
||||
if c.IsSet("key") {
|
||||
oAuth2Config.ClientID = c.String("key")
|
||||
}
|
||||
|
||||
if c.IsSet("secret") {
|
||||
oAuth2Config.ClientSecret = c.String("secret")
|
||||
}
|
||||
|
||||
if c.IsSet("auto-discover-url") {
|
||||
oAuth2Config.OpenIDConnectAutoDiscoveryURL = c.String("auto-discover-url")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
|
||||
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
|
||||
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
|
||||
}
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
|
||||
customURLMapping.TokenURL = c.String("custom-token-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-auth-url") {
|
||||
customURLMapping.AuthURL = c.String("custom-auth-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-profile-url") {
|
||||
customURLMapping.ProfileURL = c.String("custom-profile-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-email-url") {
|
||||
customURLMapping.EmailURL = c.String("custom-email-url")
|
||||
}
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return models.UpdateSource(source)
|
||||
}
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginSources, err := models.LoginSources()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled")
|
||||
for _, source := range loginSources {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t", source.ID, source.Name, models.LoginNames[source.Type], source.IsActived)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := models.GetLoginSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return models.DeleteSource(source)
|
||||
}
|
||||
|
12
cmd/cmd.go
12
cmd/cmd.go
@@ -12,6 +12,8 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@@ -22,15 +24,23 @@ func argsSet(c *cli.Context, args ...string) error {
|
||||
if !c.IsSet(a) {
|
||||
return errors.New(a + " is not set")
|
||||
}
|
||||
|
||||
if util.IsEmptyString(a) {
|
||||
return errors.New(a + " is required")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initDB() error {
|
||||
return initDBDisableConsole(false)
|
||||
}
|
||||
|
||||
func initDBDisableConsole(disableConsole bool) error {
|
||||
setting.NewContext()
|
||||
models.LoadConfigs()
|
||||
|
||||
setting.NewXORMLogService(false)
|
||||
setting.NewXORMLogService(disableConsole)
|
||||
if err := models.SetEngine(); err != nil {
|
||||
return fmt.Errorf("models.SetEngine: %v", err)
|
||||
}
|
||||
|
80
cmd/hook.go
80
cmd/hook.go
@@ -8,8 +8,8 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -62,12 +62,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func hookSetup(logPath string) {
|
||||
setting.NewContext()
|
||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||
models.LoadConfigs()
|
||||
}
|
||||
|
||||
func runHookPreReceive(c *cli.Context) error {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
@@ -79,7 +73,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
hookSetup("hooks/pre-receive.log")
|
||||
setup("hooks/pre-receive.log")
|
||||
|
||||
// the environment setted on serv command
|
||||
repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
|
||||
@@ -112,10 +106,15 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
|
||||
if err != nil {
|
||||
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
||||
fail("Internal error", fmt.Sprintf("retrieve protected branches information failed: %v", err))
|
||||
}
|
||||
|
||||
if protectBranch != nil && protectBranch.IsProtected() {
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
}
|
||||
|
||||
// detect force push
|
||||
if git.EmptySHA != oldCommitID {
|
||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
||||
@@ -126,17 +125,12 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
} else {
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +149,7 @@ func runHookUpdate(c *cli.Context) error {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
hookSetup("hooks/update.log")
|
||||
setup("hooks/update.log")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -171,9 +165,10 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
hookSetup("hooks/post-receive.log")
|
||||
setup("hooks/post-receive.log")
|
||||
|
||||
// the environment setted on serv command
|
||||
repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
|
||||
repoUser := os.Getenv(models.EnvRepoUsername)
|
||||
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
||||
repoName := os.Getenv(models.EnvRepoName)
|
||||
@@ -211,6 +206,47 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
}); err != nil {
|
||||
log.GitLogger.Error(2, "Update: %v", err)
|
||||
}
|
||||
|
||||
if newCommitID != git.EmptySHA && strings.HasPrefix(refFullName, git.BranchPrefix) {
|
||||
branch := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
repo, pullRequestAllowed, err := private.GetRepository(repoID)
|
||||
if err != nil {
|
||||
log.GitLogger.Error(2, "get repo: %v", err)
|
||||
break
|
||||
}
|
||||
if !pullRequestAllowed {
|
||||
break
|
||||
}
|
||||
|
||||
baseRepo := repo
|
||||
if repo.IsFork {
|
||||
baseRepo = repo.BaseRepo
|
||||
}
|
||||
|
||||
if !repo.IsFork && branch == baseRepo.DefaultBranch {
|
||||
break
|
||||
}
|
||||
|
||||
pr, err := private.ActivePullRequest(baseRepo.ID, repo.ID, baseRepo.DefaultBranch, branch)
|
||||
if err != nil {
|
||||
log.GitLogger.Error(2, "get active pr: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if pr == nil {
|
||||
if repo.IsFork {
|
||||
branch = fmt.Sprintf("%s:%s", repo.OwnerName, branch)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
|
||||
fmt.Fprintf(os.Stderr, " %s/compare/%s...%s\n", baseRepo.HTMLURL(), url.QueryEscape(baseRepo.DefaultBranch), url.QueryEscape(branch))
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s/pulls/%d\n", baseRepo.HTMLURL(), pr.Index)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
85
cmd/keys.go
Normal file
85
cmd/keys.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdKeys represents the available keys sub-command
|
||||
var CmdKeys = cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||
Action: runKeys,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "expected, e",
|
||||
Value: "git",
|
||||
Usage: "Expected user for whom provide key commands",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username, u",
|
||||
Value: "",
|
||||
Usage: "Username trying to log in by SSH",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "type, t",
|
||||
Value: "",
|
||||
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "content, k",
|
||||
Value: "",
|
||||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runKeys(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if !c.IsSet("username") {
|
||||
return errors.New("No username provided")
|
||||
}
|
||||
// Check username matches the expected username
|
||||
if strings.TrimSpace(c.String("username")) != strings.TrimSpace(c.String("expected")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
content := ""
|
||||
|
||||
if c.IsSet("type") && c.IsSet("content") {
|
||||
content = fmt.Sprintf("%s %s", strings.TrimSpace(c.String("type")), strings.TrimSpace(c.String("content")))
|
||||
}
|
||||
|
||||
if content == "" {
|
||||
return errors.New("No key type and content provided")
|
||||
}
|
||||
|
||||
if err := initDBDisableConsole(true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
publicKey, err := models.SearchPublicKeyByContent(content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(publicKey.AuthorizedString())
|
||||
return nil
|
||||
}
|
52
cmd/migrate.go
Normal file
52
cmd/migrate.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdMigrate represents the available migrate sub-command.
|
||||
var CmdMigrate = cli.Command{
|
||||
Name: "migrate",
|
||||
Usage: "Migrate the database",
|
||||
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
||||
Action: runMigrate,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runMigrate(ctx *cli.Context) error {
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("AppPath: %s", setting.AppPath)
|
||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||
log.Trace("Custom path: %s", setting.CustomPath)
|
||||
log.Trace("Log path: %s", setting.LogRootPath)
|
||||
models.LoadConfigs()
|
||||
|
||||
if err := models.NewEngine(migrations.Migrate); err != nil {
|
||||
log.Fatal(4, "Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
115
cmd/serv.go
115
cmd/serv.go
@@ -14,14 +14,16 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/pprof"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
version "github.com/mcuadros/go-version"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@@ -42,23 +44,36 @@ var CmdServ = cli.Command{
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "enable-pprof",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func setup(logPath string) error {
|
||||
setting.NewContext()
|
||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||
models.LoadConfigs()
|
||||
func checkLFSVersion() {
|
||||
if setting.LFS.StartServer {
|
||||
//Disable LFS client hooks if installed for the current OS user
|
||||
//Needs at least git v2.1.2
|
||||
binVersion, err := git.BinVersion()
|
||||
if err != nil {
|
||||
fail(fmt.Sprintf("Error retrieving git version: %v", err), fmt.Sprintf("Error retrieving git version: %v", err))
|
||||
}
|
||||
|
||||
if setting.UseSQLite3 || setting.UseTiDB {
|
||||
workPath := setting.AppWorkPath
|
||||
if err := os.Chdir(workPath); err != nil {
|
||||
log.GitLogger.Fatal(4, "Failed to change directory %s: %v", workPath, err)
|
||||
if !version.Compare(binVersion, "2.1.2", ">=") {
|
||||
setting.LFS.StartServer = false
|
||||
println("LFS server support needs at least Git v2.1.2, disabled")
|
||||
} else {
|
||||
git.GlobalCommandArgs = append(git.GlobalCommandArgs, "-c", "filter.lfs.required=",
|
||||
"-c", "filter.lfs.smudge=", "-c", "filter.lfs.clean=")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setting.NewXORMLogService(true)
|
||||
return models.SetEngine()
|
||||
func setup(logPath string) {
|
||||
log.DelLogger("console")
|
||||
setting.NewContext()
|
||||
checkLFSVersion()
|
||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||
}
|
||||
|
||||
func parseCmd(cmd string) (string, string) {
|
||||
@@ -97,10 +112,7 @@ func runServ(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := setup("serv.log"); err != nil {
|
||||
fail("System init failed", fmt.Sprintf("setup: %v", err))
|
||||
}
|
||||
setup("serv.log")
|
||||
|
||||
if setting.SSH.Disabled {
|
||||
println("Gitea: SSH has been disabled")
|
||||
@@ -143,11 +155,27 @@ func runServ(c *cli.Context) error {
|
||||
username := strings.ToLower(rr[0])
|
||||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||
|
||||
isWiki := false
|
||||
unitType := models.UnitTypeCode
|
||||
if setting.EnablePprof || c.Bool("enable-pprof") {
|
||||
if err := os.MkdirAll(setting.PprofDataPath, os.ModePerm); err != nil {
|
||||
fail("Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err)
|
||||
}
|
||||
|
||||
stopCPUProfiler := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username)
|
||||
defer func() {
|
||||
stopCPUProfiler()
|
||||
pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
||||
}()
|
||||
}
|
||||
|
||||
var (
|
||||
isWiki bool
|
||||
unitType = models.UnitTypeCode
|
||||
unitName = "code"
|
||||
)
|
||||
if strings.HasSuffix(reponame, ".wiki") {
|
||||
isWiki = true
|
||||
unitType = models.UnitTypeWiki
|
||||
unitName = "wiki"
|
||||
reponame = reponame[:len(reponame)-5]
|
||||
}
|
||||
|
||||
@@ -159,9 +187,9 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
os.Setenv(models.EnvRepoName, reponame)
|
||||
|
||||
repo, err := models.GetRepositoryByOwnerAndName(username, reponame)
|
||||
repo, err := private.GetRepositoryByOwnerAndName(username, reponame)
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
if strings.Contains(err.Error(), "Failed to get repository: repository does not exist") {
|
||||
fail(accessDenied, "Repository does not exist: %s/%s", username, reponame)
|
||||
}
|
||||
fail("Internal error", "Failed to get repository: %v", err)
|
||||
@@ -192,13 +220,13 @@ func runServ(c *cli.Context) error {
|
||||
keyID int64
|
||||
user *models.User
|
||||
)
|
||||
if requestedMode == models.AccessModeWrite || repo.IsPrivate {
|
||||
if requestedMode == models.AccessModeWrite || repo.IsPrivate || setting.Service.RequireSignInView {
|
||||
keys := strings.Split(c.Args()[0], "-")
|
||||
if len(keys) != 2 {
|
||||
fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||
}
|
||||
|
||||
key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
|
||||
key, err := private.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
|
||||
if err != nil {
|
||||
fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
|
||||
}
|
||||
@@ -206,26 +234,32 @@ func runServ(c *cli.Context) error {
|
||||
|
||||
// Check deploy key or user key.
|
||||
if key.Type == models.KeyTypeDeploy {
|
||||
if key.Mode < requestedMode {
|
||||
fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
|
||||
// Now we have to get the deploy key for this repo
|
||||
deployKey, err := private.GetDeployKey(key.ID, repo.ID)
|
||||
if err != nil {
|
||||
fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
||||
}
|
||||
// Check if this deploy key belongs to current repository.
|
||||
if !models.HasDeployKey(key.ID, repo.ID) {
|
||||
|
||||
if deployKey == nil {
|
||||
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
||||
}
|
||||
|
||||
// Update deploy key activity.
|
||||
deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
|
||||
if err != nil {
|
||||
fail("Internal error", "GetDeployKey: %v", err)
|
||||
if deployKey.Mode < requestedMode {
|
||||
fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID)
|
||||
}
|
||||
|
||||
deployKey.UpdatedUnix = util.TimeStampNow()
|
||||
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
|
||||
// Update deploy key activity.
|
||||
if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil {
|
||||
fail("Internal error", "UpdateDeployKey: %v", err)
|
||||
}
|
||||
|
||||
// FIXME: Deploy keys aren't really the owner of the repo pushing changes
|
||||
// however we don't have good way of representing deploy keys in hook.go
|
||||
// so for now use the owner
|
||||
os.Setenv(models.EnvPusherName, username)
|
||||
os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID))
|
||||
} else {
|
||||
user, err = models.GetUserByKeyID(key.ID)
|
||||
user, err = private.GetUserByKeyID(key.ID)
|
||||
if err != nil {
|
||||
fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
|
||||
}
|
||||
@@ -236,25 +270,19 @@ func runServ(c *cli.Context) error {
|
||||
user.Name, repoPath)
|
||||
}
|
||||
|
||||
mode, err := models.AccessLevel(user.ID, repo)
|
||||
mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType)
|
||||
if err != nil {
|
||||
fail("Internal error", "Failed to check access: %v", err)
|
||||
} else if mode < requestedMode {
|
||||
} else if *mode < requestedMode {
|
||||
clientMessage := accessDenied
|
||||
if mode >= models.AccessModeRead {
|
||||
if *mode >= models.AccessModeRead {
|
||||
clientMessage = "You do not have sufficient authorization for this action"
|
||||
}
|
||||
fail(clientMessage,
|
||||
"User %s does not have level %v access to repository %s",
|
||||
"User %s does not have level %v access to repository %s's "+unitName,
|
||||
user.Name, requestedMode, repoPath)
|
||||
}
|
||||
|
||||
if !repo.CheckUnitUser(user.ID, user.IsAdmin, unitType) {
|
||||
fail("You do not have allowed for this action",
|
||||
"User %s does not have allowed access to repository %s 's code",
|
||||
user.Name, repoPath)
|
||||
}
|
||||
|
||||
os.Setenv(models.EnvPusherName, user.Name)
|
||||
os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID))
|
||||
}
|
||||
@@ -309,9 +337,8 @@ func runServ(c *cli.Context) error {
|
||||
} else {
|
||||
gitcmd = exec.Command(verb, repoPath)
|
||||
}
|
||||
|
||||
if isWiki {
|
||||
if err = repo.InitWiki(); err != nil {
|
||||
if err = private.InitWiki(repo.ID); err != nil {
|
||||
fail("Internal error", "Failed to init wiki repo: %v", err)
|
||||
}
|
||||
}
|
||||
|
42
cmd/web.go
42
cmd/web.go
@@ -5,6 +5,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
"github.com/Unknwon/com"
|
||||
context2 "github.com/gorilla/context"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
@@ -71,6 +73,42 @@ func runHTTPRedirector() {
|
||||
}
|
||||
}
|
||||
|
||||
func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler) error {
|
||||
certManager := autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
HostPolicy: autocert.HostWhitelist(domain),
|
||||
Cache: autocert.DirCache(directory),
|
||||
Email: email,
|
||||
}
|
||||
go func() {
|
||||
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||
var err = http.ListenAndServe(setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||
}
|
||||
}()
|
||||
server := &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: m,
|
||||
TLSConfig: &tls.Config{
|
||||
GetCertificate: certManager.GetCertificate,
|
||||
},
|
||||
}
|
||||
return server.ListenAndServeTLS("", "")
|
||||
}
|
||||
|
||||
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" && r.Method != "HEAD" {
|
||||
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// Remove the trailing slash at the end of setting.AppURL, the request
|
||||
// URI always contains a leading slash, which would result in a double
|
||||
// slash
|
||||
target := strings.TrimRight(setting.AppURL, "/") + r.URL.RequestURI()
|
||||
http.Redirect(w, r, target, http.StatusFound)
|
||||
}
|
||||
|
||||
func runWeb(ctx *cli.Context) error {
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
@@ -143,6 +181,10 @@ func runWeb(ctx *cli.Context) error {
|
||||
case setting.HTTP:
|
||||
err = runHTTP(listenAddr, context2.ClearHandler(m))
|
||||
case setting.HTTPS:
|
||||
if setting.EnableLetsEncrypt {
|
||||
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, context2.ClearHandler(m))
|
||||
break
|
||||
}
|
||||
if setting.RedirectOtherPort {
|
||||
go runHTTPRedirector()
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"buildFlags": "-tags=\"sqlite\"",
|
||||
"buildFlags": "-tags=\"sqlite sqlite_unlock_notify\"",
|
||||
"port": 2345,
|
||||
"host": "127.0.0.1",
|
||||
"program": "${workspaceRoot}/main.go",
|
||||
|
@@ -35,7 +35,7 @@
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"args": ["build", "-tags=\"sqlite\""],
|
||||
"args": ["build", "-tags=\"sqlite sqlite_unlock_notify\""],
|
||||
"linux": {
|
||||
"args": ["-o", "gitea", "${workspaceRoot}/main.go"]
|
||||
},
|
||||
|
107
contrib/k8s/gitea.yml
Normal file
107
contrib/k8s/gitea.yml
Normal file
@@ -0,0 +1,107 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: gitea
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
labels:
|
||||
app: gitea
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
name: gitea
|
||||
labels:
|
||||
app: gitea
|
||||
spec:
|
||||
containers:
|
||||
- name: gitea
|
||||
image: gitea/gitea:latest
|
||||
imagePullPolicy: Always
|
||||
volumeMounts:
|
||||
- mountPath: "/var/lib/gitea"
|
||||
name: "root"
|
||||
- mountPath: "/data"
|
||||
name: "data"
|
||||
ports:
|
||||
- containerPort: 22
|
||||
name: ssh
|
||||
protocol: TCP
|
||||
- containerPort: 3000
|
||||
name: http
|
||||
protocol: TCP
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
# Set up a data directory for gitea
|
||||
# For production usage, you should consider using PV/PVC instead(or simply using storage like NAS)
|
||||
# For more details, please see https://kubernetes.io/docs/concepts/storage/volumes/
|
||||
- name: "root"
|
||||
hostPath:
|
||||
# directory location on host
|
||||
path: "/var/lib/gitea"
|
||||
# this field is optional
|
||||
type: Directory
|
||||
- name: "data"
|
||||
hostPath:
|
||||
path: "/data/gitea"
|
||||
type: Directory
|
||||
selector:
|
||||
matchLabels:
|
||||
app: gitea
|
||||
---
|
||||
# Using cluster mode
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-web
|
||||
namespace: gitea
|
||||
labels:
|
||||
app: gitea-web
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
name: http
|
||||
selector:
|
||||
app: gitea
|
||||
---
|
||||
# Using node-port mode
|
||||
# This mainly open a specific TCP port for SSH usage on each host,
|
||||
# so you can use a proxy layer to handle it(e.g. slb, nginx)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-ssh
|
||||
namespace: gitea
|
||||
labels:
|
||||
app: gitea-ssh
|
||||
spec:
|
||||
ports:
|
||||
- port: 22
|
||||
targetPort: 22
|
||||
nodePort: 30022
|
||||
name: ssh
|
||||
selector:
|
||||
app: gitea
|
||||
type: NodePort
|
||||
---
|
||||
# Ingress is always suitable for HTTP usage,
|
||||
# we suggest using an proxy layer such as slb to send traffic to different ports.
|
||||
# Usually 80/443 for web and 22 directly for SSH.
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
spec:
|
||||
rules:
|
||||
- host: your-gitea-host.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: gitea-web
|
||||
servicePort: 80
|
@@ -60,6 +60,10 @@ FILE_MAX_SIZE = 3
|
||||
; Max number of files per upload. Defaults to 5
|
||||
MAX_FILES = 5
|
||||
|
||||
[repository.pull-request]
|
||||
; List of prefixes used in Pull Request title to mark them as Work In Progress
|
||||
WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP]
|
||||
|
||||
[ui]
|
||||
; Number of repositories that are displayed on one explore page
|
||||
EXPLORE_PAGING_NUM = 20
|
||||
@@ -67,6 +71,10 @@ EXPLORE_PAGING_NUM = 20
|
||||
ISSUE_PAGING_NUM = 10
|
||||
; Number of maximum commits displayed in one activity feed
|
||||
FEED_MAX_COMMIT_NUM = 5
|
||||
; Number of maximum commits displayed in commit graph.
|
||||
GRAPH_MAX_COMMIT_NUM = 100
|
||||
; Number of line of codes shown for a code comment
|
||||
CODE_COMMENT_LINES = 4
|
||||
; Value of `theme-color` meta tag, used by Android >= 5.0
|
||||
; An invalid color like "none" or "disable" will have the default style
|
||||
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||
@@ -75,13 +83,15 @@ THEME_COLOR_META_TAG = `#6cc644`
|
||||
MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
; Whether the email of the user should be shown in the Explore Users page
|
||||
SHOW_USER_EMAIL = true
|
||||
; Set the default theme for the Gitea install
|
||||
DEFAULT_THEME = gitea
|
||||
|
||||
[ui.admin]
|
||||
; Number of users that are displayed on one page
|
||||
USER_PAGING_NUM = 50
|
||||
; Number of repos that are displayed on one page
|
||||
REPO_PAGING_NUM = 50
|
||||
; Number of notices that are displayed on in one page
|
||||
; Number of notices that are displayed on one page
|
||||
NOTICE_PAGING_NUM = 25
|
||||
; Number of organizations that are displayed on one page
|
||||
ORG_PAGING_NUM = 50
|
||||
@@ -134,7 +144,7 @@ START_SSH_SERVER = false
|
||||
BUILTIN_SSH_SERVER_USER =
|
||||
; Domain name to be exposed in clone URL
|
||||
SSH_DOMAIN = %(DOMAIN)s
|
||||
; THe network interface the builtin SSH server should listen on
|
||||
; The network interface the builtin SSH server should listen on
|
||||
SSH_LISTEN_HOST =
|
||||
; Port number to be exposed in clone URL
|
||||
SSH_PORT = 22
|
||||
@@ -142,6 +152,9 @@ SSH_PORT = 22
|
||||
SSH_LISTEN_PORT = %(SSH_PORT)s
|
||||
; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
|
||||
SSH_ROOT_PATH =
|
||||
; Gitea will create a authorized_keys file by default when it is not using the internal ssh server
|
||||
; If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
|
||||
SSH_CREATE_AUTHORIZED_KEYS_FILE = true
|
||||
; For the built-in SSH server, choose the ciphers to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_CIPHERS = aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128
|
||||
@@ -181,6 +194,12 @@ STATIC_ROOT_PATH =
|
||||
APP_DATA_PATH = data
|
||||
; Application level GZIP support
|
||||
ENABLE_GZIP = false
|
||||
; Application profiling (memory and cpu)
|
||||
; For "web" command it listens on localhost:6060
|
||||
; For "serve" command it dumps to disk at PPROF_DATA_PATH as (cpuprofile|memprofile)_<username>_<temporary id>
|
||||
ENABLE_PPROF = false
|
||||
; PPROF_DATA_PATH, use an absolute path when you start gitea as service
|
||||
PPROF_DATA_PATH = data/tmp/pprof
|
||||
; Landing page, can be "home", "explore", or "organizations"
|
||||
LANDING_PAGE = home
|
||||
; Enables git-lfs support. true or false, default is false.
|
||||
@@ -207,9 +226,10 @@ NAME = gitea
|
||||
USER = root
|
||||
; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
PASSWD =
|
||||
; For "postgres" only, either "disable", "require" or "verify-full"
|
||||
; For Postgres, either "disable" (default), "require", or "verify-full"
|
||||
; For MySQL, either "false" (default), "true", or "skip-verify"
|
||||
SSL_MODE = disable
|
||||
; For "sqlite3" and "tidb", use absolute path when you start gitea as service
|
||||
; For "sqlite3" and "tidb", use an absolute path when you start gitea as service
|
||||
PATH = data/gitea.db
|
||||
; For "sqlite3" only. Query timeout
|
||||
SQLITE_TIMEOUT = 500
|
||||
@@ -241,11 +261,12 @@ COOKIE_USERNAME = gitea_awesome
|
||||
COOKIE_REMEMBER_NAME = gitea_incredible
|
||||
; Reverse proxy authentication header name of user name
|
||||
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
|
||||
REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
|
||||
; The minimum password length for new Users
|
||||
MIN_PASSWORD_LENGTH = 6
|
||||
; True when users are allowed to import local server paths
|
||||
; Set to true to allow users to import local server paths
|
||||
IMPORT_LOCAL_PATHS = false
|
||||
; Prevent all users (including admin) from creating custom git hooks
|
||||
; Set to true to prevent all users (including admin) from creating custom git hooks
|
||||
DISABLE_GIT_HOOKS = false
|
||||
|
||||
[openid]
|
||||
@@ -289,9 +310,12 @@ ACTIVE_CODE_LIVE_MINUTES = 180
|
||||
RESET_PASSWD_CODE_LIVE_MINUTES = 180
|
||||
; Whether a new user needs to confirm their email when registering.
|
||||
REGISTER_EMAIL_CONFIRM = false
|
||||
; List of domain names that are allowed to be used to register on a Gitea instance
|
||||
; gitea.io,example.com
|
||||
EMAIL_DOMAIN_WHITELIST=
|
||||
; Disallow registration, only allow admins to create accounts.
|
||||
DISABLE_REGISTRATION = false
|
||||
; Allow registration only using third part services, it works only when DISABLE_REGISTRATION is false
|
||||
; Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
|
||||
; User must sign in to view anything.
|
||||
REQUIRE_SIGNIN_VIEW = false
|
||||
@@ -300,14 +324,26 @@ ENABLE_NOTIFY_MAIL = false
|
||||
; More detail: https://github.com/gogits/gogs/issues/165
|
||||
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
|
||||
ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
|
||||
ENABLE_REVERSE_PROXY_EMAIL = false
|
||||
; Enable captcha validation for registration
|
||||
ENABLE_CAPTCHA = true
|
||||
ENABLE_CAPTCHA = false
|
||||
; Type of captcha you want to use. Options: image, recaptcha
|
||||
CAPTCHA_TYPE = image
|
||||
; Enable recaptcha to use Google's recaptcha service
|
||||
; Go to https://www.google.com/recaptcha/admin to sign up for a key
|
||||
RECAPTCHA_SECRET =
|
||||
RECAPTCHA_SITEKEY =
|
||||
; Default value for KeepEmailPrivate
|
||||
; Each new user will get the value of this setting copied into their profile
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = false
|
||||
; Default value for AllowCreateOrganization
|
||||
; Every new user will have rights set to create organizations depending on this setting
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
; Default value for EnableDependencies
|
||||
; Repositories will use dependencies by default depending on this setting
|
||||
DEFAULT_ENABLE_DEPENDENCIES = true
|
||||
; Enable heatmap on users profiles.
|
||||
ENABLE_USER_HEATMAP = true
|
||||
; Enable Timetracking
|
||||
ENABLE_TIMETRACKING = true
|
||||
; Default value for EnableTimetracking
|
||||
@@ -352,6 +388,8 @@ SKIP_VERIFY =
|
||||
USE_CERTIFICATE = false
|
||||
CERT_FILE = custom/mailer/cert.pem
|
||||
KEY_FILE = custom/mailer/key.pem
|
||||
; Should SMTP connection use TLS
|
||||
IS_TLS_ENABLED = false
|
||||
; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format
|
||||
FROM =
|
||||
; Mailer user name and password
|
||||
@@ -511,7 +549,7 @@ SCHEDULE = @every 10m
|
||||
SCHEDULE = @every 24h
|
||||
TIMEOUT = 60s
|
||||
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
|
||||
; see more on http://git-scm.com/docs/git-fsck/1.7.5
|
||||
; see more on http://git-scm.com/docs/git-fsck
|
||||
ARGS =
|
||||
|
||||
; Check repository statistics
|
||||
@@ -550,7 +588,7 @@ MAX_GIT_DIFF_LINE_CHARACTERS = 5000
|
||||
; Max number of files shown in diff view
|
||||
MAX_GIT_DIFF_FILES = 100
|
||||
; Arguments for command 'git gc', e.g. "--aggressive --auto"
|
||||
; see more on http://git-scm.com/docs/git-gc/1.7.5
|
||||
; see more on http://git-scm.com/docs/git-gc/
|
||||
GC_ARGS =
|
||||
|
||||
; Operation timeout in seconds
|
||||
@@ -568,8 +606,8 @@ DEFAULT_INTERVAL = 8h
|
||||
MIN_INTERVAL = 10m
|
||||
|
||||
[api]
|
||||
; Enables /api/swagger, /api/v1/swagger etc. endpoints. True or false; default is true.
|
||||
ENABLE_SWAGGER_ENDPOINT = true
|
||||
; Enables Swagger. True or false; default is true.
|
||||
ENABLE_SWAGGER = true
|
||||
; Max number of items in a page
|
||||
MAX_RESPONSE_ITEMS = 50
|
||||
|
||||
@@ -628,3 +666,9 @@ FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
; Don't pass the file on STDIN, pass the filename as argument instead.
|
||||
IS_INPUT_FILE = false
|
||||
|
||||
[metrics]
|
||||
; Enables metrics endpoint. True or false; default is false.
|
||||
ENABLED = false
|
||||
; If you want to add authorization, specify a token here
|
||||
TOKEN =
|
||||
|
2
docker/Makefile
vendored
2
docker/Makefile
vendored
@@ -8,7 +8,7 @@ DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||
.PHONY: docker
|
||||
docker:
|
||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite" .
|
||||
# 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:
|
||||
|
@@ -39,5 +39,8 @@ if [ ! -f /data/gitea/conf/app.ini ]; then
|
||||
envsubst < /etc/templates/app.ini > /data/gitea/conf/app.ini
|
||||
fi
|
||||
|
||||
chown -R ${USER}:git /data/gitea /app/gitea /data/git
|
||||
# only chown if current owner is not already the gitea ${USER}. No recursive check to save time
|
||||
if ! [[ $(ls -ld /data/gitea | awk '{print $3}') = ${USER} ]]; then chown -R ${USER}:git /data/gitea; fi
|
||||
if ! [[ $(ls -ld /app/gitea | awk '{print $3}') = ${USER} ]]; then chown -R ${USER}:git /app/gitea; fi
|
||||
if ! [[ $(ls -ld /data/git | awk '{print $3}') = ${USER} ]]; then chown -R ${USER}:git /data/git; fi
|
||||
chmod 0755 /data/gitea /app/gitea /data/git
|
||||
|
@@ -29,4 +29,5 @@ AllowUsers git
|
||||
|
||||
Banner none
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
||||
UsePrivilegeSeparation no
|
||||
|
||||
AcceptEnv GIT_PROTOCOL
|
@@ -4,6 +4,9 @@ RUN_MODE = $RUN_MODE
|
||||
[repository]
|
||||
ROOT = /data/git/repositories
|
||||
|
||||
[repository.local]
|
||||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
||||
|
||||
[repository.upload]
|
||||
TEMP_PATH = /data/gitea/uploads
|
||||
|
||||
@@ -14,6 +17,7 @@ HTTP_PORT = $HTTP_PORT
|
||||
ROOT_URL = $ROOT_URL
|
||||
DISABLE_SSH = $DISABLE_SSH
|
||||
SSH_PORT = $SSH_PORT
|
||||
LFS_CONTENT_PATH = /data/git/lfs
|
||||
|
||||
[database]
|
||||
PATH = /data/gitea/gitea.db
|
||||
@@ -23,6 +27,9 @@ NAME = $DB_NAME
|
||||
USER = $DB_USER
|
||||
PASSWD = $DB_PASSWD
|
||||
|
||||
[indexer]
|
||||
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
|
||||
|
||||
[session]
|
||||
PROVIDER_CONFIG = /data/gitea/sessions
|
||||
|
||||
|
@@ -4,7 +4,7 @@ if [ "${USER}" != "git" ]; then
|
||||
# rename user
|
||||
sed -i -e "s/^git\:/${USER}\:/g" /etc/passwd
|
||||
# switch sshd config to different user
|
||||
sed -i -e "s/AllowUsers git/AllowUsers ${USER}/g" /etc/ssh/sshd_config
|
||||
sed -i -e "s/AllowUsers git$/AllowUsers ${USER}/g" /etc/ssh/sshd_config
|
||||
fi
|
||||
|
||||
## Change GID for USER?
|
||||
|
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
public/
|
||||
templates/swagger/v1_json.tmpl
|
||||
themes/
|
||||
|
@@ -1,22 +0,0 @@
|
||||
# build stage
|
||||
FROM golang:alpine AS build-env
|
||||
|
||||
RUN apk add --no-cache git
|
||||
RUN go get -d -v github.com/mholt/caddy/caddy github.com/pedronasser/caddy-search github.com/simia-tech/caddy-locale
|
||||
WORKDIR /go/src/github.com/mholt/caddy/caddy
|
||||
|
||||
RUN sed -i '/This is where other plugins get plugged in (imported)/a _ "github.com/pedronasser/caddy-search"' caddymain/run.go \
|
||||
&& sed -i '/This is where other plugins get plugged in (imported)/a _ "github.com/simia-tech/caddy-locale"' caddymain/run.go \
|
||||
&& go install -v . \
|
||||
&& /go/bin/caddy -version
|
||||
|
||||
FROM alpine:edge
|
||||
EXPOSE 80
|
||||
|
||||
RUN apk add --no-cache wget mailcap ca-certificates
|
||||
COPY --from=build-env /go/bin/caddy /usr/sbin/caddy
|
||||
|
||||
COPY docker/caddy.conf /etc/caddy.conf
|
||||
COPY public /srv/www
|
||||
|
||||
CMD ["/usr/sbin/caddy", "-conf", "/etc/caddy.conf"]
|
42
docs/README_ZH.md
Normal file
42
docs/README_ZH.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Gitea: 文档
|
||||
|
||||
[](http://drone.gitea.io/go-gitea/docs)
|
||||
[](https://discord.gg/NsatcWJ)
|
||||
[](http://microbadger.com/images/gitea/docs "Get your own image badge on microbadger.com")
|
||||
|
||||
## 关于托管方式
|
||||
|
||||
本页面托管在我们 Docker 容器内的基础设施上, 它会在每次推送到 `master` 分支的时候自动更新,如果你想自己管理这个页面,你可以从我们的 Docker 镜像 [gitea/docs](https://hub.docker.com/r/gitea/docs/) 中获取它。
|
||||
|
||||
## 安装 Hugo
|
||||
|
||||
本页面使用了 [Hugo](https://github.com/spf13/hugo) 静态页面生成工具,如果您有维护它的意愿,则需要在本地计算机上下载并安装 Hugo。Hugo 的安装教程不在本文档的讲述范围之内,详情请参见 [官方文档](https://gohugo.io/overview/installing/)。
|
||||
|
||||
## 如何部署
|
||||
|
||||
在 [localhost:1313](http://localhost:1313) 处构建和运行网站的命令如下,如果需要停止可以使用组合键 `Ctrl+C`:
|
||||
|
||||
```
|
||||
make server
|
||||
```
|
||||
|
||||
完成更改后,只需创建一个 Pull Request (PR),该 PR 一经合并网站将自动更新。
|
||||
|
||||
## 如何贡献您的代码
|
||||
|
||||
Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## 关于我们
|
||||
|
||||
* [维护者信息](https://github.com/orgs/go-gitea/people)
|
||||
* [代码贡献者信息](https://github.com/go-gitea/docs/graphs/contributors)
|
||||
|
||||
## 许可证
|
||||
|
||||
此项目采用 Apache-2.0 许可协议,请参见 [协议文件](LICENSE) 获取更多信息。
|
||||
|
||||
## 版权声明
|
||||
|
||||
```
|
||||
Copyright (c) 2016 The Gitea Authors <https://gitea.io>
|
||||
```
|
@@ -31,7 +31,7 @@ menu:
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 25
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
@@ -79,7 +79,7 @@ languages:
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 25
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: 博客
|
||||
url: https://blog.gitea.io/
|
||||
@@ -122,7 +122,7 @@ languages:
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 25
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: 部落格
|
||||
url: https://blog.gitea.io/
|
||||
@@ -165,7 +165,7 @@ languages:
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 25
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
@@ -208,7 +208,7 @@ languages:
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 25
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
@@ -241,17 +241,17 @@ languages:
|
||||
menu:
|
||||
page:
|
||||
- name: Site
|
||||
url: /fr-fr/
|
||||
url: https://gitea.io/en-us/
|
||||
weight: 10
|
||||
pre: home
|
||||
post: active
|
||||
- name: Documentation
|
||||
url: https://docs.gitea.io/fr-fr/
|
||||
url: /fr-fr/
|
||||
weight: 20
|
||||
pre: question
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 25
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
|
@@ -73,3 +73,7 @@ using BasicAuth, as follows:
|
||||
$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
||||
[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
|
||||
```
|
||||
|
||||
## Sudo
|
||||
|
||||
The API allows admin users to sudo API requests as another user. Simply add either a `sudo=` parameter or `Sudo:` request header with the username of the user to sudo.
|
||||
|
71
docs/content/doc/advanced/api-usage.zh-cn.md
Normal file
71
docs/content/doc/advanced/api-usage.zh-cn.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
date: "2018-06-24:00:00+02:00"
|
||||
title: "API 使用指南"
|
||||
slug: "api-usage"
|
||||
weight: 40
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "API 使用指南"
|
||||
weight: 40
|
||||
identifier: "api-usage"
|
||||
---
|
||||
|
||||
# Gitea API 使用指南
|
||||
|
||||
## 开启/配置 API 访问
|
||||
|
||||
通常情况下, `ENABLE_SWAGGER_ENDPOINT` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat
|
||||
Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) 中获取更多配置相关信息。
|
||||
|
||||
## 通过 API 认证
|
||||
|
||||
Gitea 支持以下几种 API 认证方式:
|
||||
|
||||
- HTTP basic authentication 方式
|
||||
- 通过指定 `token=...` URL 查询参数方式
|
||||
- 通过指定 `access_token=...` URL 查询参数方式
|
||||
- 通过指定 `Authorization: token ...` HTTP header 方式
|
||||
|
||||
以上提及的认证方法接受相同的 apiKey token 类型,您可以在编码时通过查阅代码更好地理解这一点。
|
||||
Gitea 调用解析查询参数以及头部信息来获取 token 的代码可以在 [modules/auth/auth.go](https://github.com/go-gitea/gitea/blob/6efdcaed86565c91a3dc77631372a9cc45a58e89/modules/auth/auth.go#L47) 中找到。
|
||||
|
||||
您可以通过您的 gitea web 界面来创建 apiKey token:
|
||||
`Settings | Applications | Generate New Token`.
|
||||
|
||||
### 关于 `Authorization:` header
|
||||
|
||||
由于一些历史原因,Gitea 需要在 header 的 apiKey token 里引入前缀 `token`,类似于如下形式:
|
||||
|
||||
```
|
||||
Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675
|
||||
```
|
||||
|
||||
以 `curl` 命令为例,它会以如下形式携带在请求中:
|
||||
|
||||
```
|
||||
curl -X POST "http://localhost:4000/api/v1/repos/test1/test1/issues" \
|
||||
-H "accept: application/json" \
|
||||
-H "Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675" \
|
||||
-H "Content-Type: application/json" -d "{ \"body\": \"testing\", \"title\": \"test 20\"}" -i
|
||||
```
|
||||
|
||||
正如上例所示,您也可以在 GET 请求中使用同一个 token 并以 `token=` 的查询参数形式携带 token 来进行认证。
|
||||
|
||||
## 通过 API 列出您发布的令牌
|
||||
|
||||
`/users/:name/tokens` 是一个特殊的接口,需要您使用 basic authentication 进行认证,具体原因在 issue 中
|
||||
[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346) 有所提及,使用方法如下所示:
|
||||
|
||||
### 使用 Basic authentication 认证:
|
||||
|
||||
```
|
||||
$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
||||
[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
|
||||
```
|
||||
|
||||
## 使用 Sudo 方式请求 API
|
||||
|
||||
此 API 允许管理员借用其他用户身份进行 API 请求。只需在请求中指定查询参数 `sudo=` 或是指定 header 中的 `Sudo:` 为需要使用的用户 username 即可。
|
@@ -63,11 +63,17 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when
|
||||
default SSH port is used.
|
||||
|
||||
### Repository - Pull Request (`repository.pull-request`)
|
||||
- `WORK_IN_PROGRESS_PREFIXES`: **WIP:,\[WIP\]**: List of prefixes used in Pull Request
|
||||
title to mark them as Work In Progress
|
||||
|
||||
## UI (`ui`)
|
||||
|
||||
- `EXPLORE_PAGING_NUM`: **20**: Number of repositories that are shown in one explore page.
|
||||
- `ISSUE_PAGING_NUM`: **10**: Number of issues that are shown in one page (for all pages that list issues).
|
||||
- `FEED_MAX_COMMIT_NUM`: **5**: Number of maximum commits shown in one activity feed.
|
||||
- `GRAPH_MAX_COMMIT_NUM`: **100**: Number of maximum commits shown in the commit graph.
|
||||
- `DEFAULT_THEME`: **gitea**: \[gitea, arc-green\]: Set the default theme for the Gitea install.
|
||||
|
||||
### UI - Admin (`ui.admin`)
|
||||
|
||||
@@ -116,9 +122,13 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `LFS_CONTENT_PATH`: **./data/lfs**: Where to store LFS files.
|
||||
- `LFS_JWT_SECRET`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
||||
- `LFS_HTTP_AUTH_EXPIRY`: **20m**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, redirects http requests
|
||||
on another (https) port.
|
||||
- `PORT_TO_REDIRECT`: **80**: Port used when `REDIRECT_OTHER_PORT` is true.
|
||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
|
||||
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
|
||||
- `ENABLE_LETSENCRYPT`: **false**: If enabled you must set `DOMAIN` to valid internet facing domain (ensure DNS is set and port 80 is accessible by letsencrypt validation server).
|
||||
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
|
||||
- `LETSENCRYPT_ACCEPTTOS`: **false**: This is an explicit check that you accept the terms of service for Let's Encrypt.
|
||||
- `LETSENCRYPT_DIRECTORY`: **https**: Directory that Letsencrypt will use to cache information such as certs and private keys.
|
||||
- `LETSENCRYPT_EMAIL`: **email@example.com**: Email used by Letsencrypt to notify about problems with issued certificates. (No default)
|
||||
|
||||
## Database (`database`)
|
||||
|
||||
@@ -127,7 +137,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `NAME`: **gitea**: Database name.
|
||||
- `USER`: **root**: Database username.
|
||||
- `PASSWD`: **\<empty\>**: Database user password. Use \`your password\` for quoting if you use special characters in the password.
|
||||
- `SSL_MODE`: **disable**: For PostgreSQL only.
|
||||
- `SSL_MODE`: **disable**: For PostgreSQL and MySQL only.
|
||||
- `PATH`: **data/gitea.db**: For SQLite3 only, the database file path.
|
||||
- `LOG_SQL`: **true**: Log the executed SQL.
|
||||
|
||||
@@ -149,9 +159,11 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
information.
|
||||
- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: Header name for reverse proxy
|
||||
authentication.
|
||||
- `DISABLE_GIT_HOOKS`: **false**: Prevent all users (including admin) from creating custom
|
||||
- `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**: Header name for reverse proxy
|
||||
authentication provided email.
|
||||
- `DISABLE_GIT_HOOKS`: **false**: Set to `true` to prevent all users (including admin) from creating custom
|
||||
git hooks.
|
||||
- `IMPORT_LOCAL_PATHS`: **false**: 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.
|
||||
|
||||
## OpenID (`openid`)
|
||||
|
||||
@@ -177,7 +189,16 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: Enable this to allow reverse proxy authentication.
|
||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: **false**: Enable this to allow auto-registration
|
||||
for reverse authentication.
|
||||
- `ENABLE_CAPTCHA`: **true**: Enable this to use captcha validation for registration.
|
||||
- `ENABLE_REVERSE_PROXY_EMAIL`: **false**: Enable this to allow to auto-registration with a
|
||||
provided email rather than a generated email.
|
||||
- `ENABLE_CAPTCHA`: **false**: Enable this to use captcha validation for registration.
|
||||
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha\]
|
||||
- `RECAPTCHA_SECRET`: **""**: Go to https://www.google.com/recaptcha/admin to get a secret for recaptcha.
|
||||
- `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha.
|
||||
- `DEFAULT_ENABLE_DEPENDENCIES`: **true** Enable this to have dependencies enabled by default.
|
||||
- `ENABLE_USER_HEATMAP`: **true** Enable this to display the heatmap on users profiles.
|
||||
- `EMAIL_DOMAIN_WHITELIST`: **\<empty\>**: If non-empty, list of domain names that can only be used to register
|
||||
on this instance.
|
||||
|
||||
## Webhook (`webhook`)
|
||||
|
||||
@@ -202,8 +223,9 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
This is common on linux systems.
|
||||
- Note that enabling sendmail will ignore all other `mailer` settings except `ENABLED`,
|
||||
`FROM` and `SENDMAIL_PATH`.
|
||||
- `SENDMAIL_PATH`: **sendmail**: The location of sendmail on the operating system. (can be
|
||||
command or full path)
|
||||
- `SENDMAIL_PATH`: **sendmail**: The location of sendmail on the operating system (can be
|
||||
command or full path).
|
||||
- ``IS_TLS_ENABLED`` : **false** : Decide if SMTP connections should use TLS.
|
||||
|
||||
## Cache (`cache`)
|
||||
|
||||
@@ -227,7 +249,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
`http://cn.gravatar.com/avatar/`.
|
||||
- `DISABLE_GRAVATAR`: **false**: Enable this to use local avatars only.
|
||||
- `ENABLE_FEDERATED_AVATAR`: **false**: Enable support for federated avatars (see
|
||||
http://www.libravatar.org)
|
||||
[http://www.libravatar.org](http://www.libravatar.org)).
|
||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store local and cached files.
|
||||
|
||||
## Attachment (`attachment`)
|
||||
@@ -265,7 +287,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
|
||||
- `SCHEDULE`: **every 24h**: Cron syntax for scheduling repository health check.
|
||||
- `TIMEOUT`: **60s**: Time duration syntax for health check execution timeout.
|
||||
- `ARGS`: **\<empty\>**: Arguments for command `git fsck`, e.g. `--unreachable --tags`.
|
||||
- `ARGS`: **\<empty\>**: Arguments for command `git fsck`, e.g. `--unreachable --tags`. See more on http://git-scm.com/docs/git-fsck
|
||||
|
||||
### Cron - Repository Statistics Check (`cron.check_repo_stats`)
|
||||
|
||||
@@ -277,12 +299,24 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `MAX_GIT_DIFF_LINES`: **100**: Max number of lines allowed of a single file in diff view.
|
||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
||||
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
||||
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`.
|
||||
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
|
||||
|
||||
## Git - Timeout settings (`git.timeout`)
|
||||
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
|
||||
- `MIRROR`: **300**: Mirror external repositories timeout seconds.
|
||||
- `CLONE`: **300**: Git clone from internal repositories timeout seconds.
|
||||
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
|
||||
- `GC`: **60**: Git repository GC timeout seconds.
|
||||
|
||||
## Metrics (`metrics`)
|
||||
|
||||
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
|
||||
- `TOKEN`: **\<empty\>**: You need to specify the token, if you want to include in the authorization the metrics . The same token need to be used in prometheus parameters `bearer_token` or `bearer_token_file`.
|
||||
|
||||
## API (`api`)
|
||||
|
||||
- `ENABLE_SWAGGER_ENDPOINT`: **true**: Enables /api/swagger, /api/v1/swagger etc. endpoints. True or false; default is true.
|
||||
- `MAX_RESPONSE_ITEMS`: **50**: Max number of items in a page
|
||||
|
||||
- `ENABLE_SWAGGER_ENDPOINT`: **true**: Enables /api/swagger, /api/v1/swagger etc. endpoints. True or false; default is true.
|
||||
- `MAX_RESPONSE_ITEMS`: **50**: Max number of items in a page.
|
||||
|
||||
## i18n (`i18n`)
|
||||
|
||||
@@ -336,6 +370,10 @@ IS_INPUT_FILE = false
|
||||
- RENDER\_COMMAND: External command to render all matching extensions.
|
||||
- IS\_INPUT\_FILE: **false** Input is not a standard input but a file param followed `RENDER_COMMAND`.
|
||||
|
||||
Two special environment variables are passed to the render command:
|
||||
- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links.
|
||||
- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths.
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
|
||||
|
@@ -187,6 +187,13 @@ menu:
|
||||
- `MAX_GIT_DIFF_FILES`: 比较视图中的最大现实文件数目。
|
||||
- `GC_ARGS`: 执行 `git gc` 命令的参数, 比如: `--aggressive --auto`。
|
||||
|
||||
## Git - 超时设置 (`git.timeout`)
|
||||
- `MIGRATE`: **600**: 迁移外部仓库时的超时时间,单位秒
|
||||
- `MIRROR`: **300**: 镜像外部仓库的超时时间,单位秒
|
||||
- `CLONE`: **300**: 内部仓库间克隆的超时时间,单位秒
|
||||
- `PULL`: **300**: 内部仓库间拉取的超时时间,单位秒
|
||||
- `GC`: **60**: git仓库GC的超时时间,单位秒
|
||||
|
||||
## markup (`markup`)
|
||||
|
||||
外部渲染工具支持,你可以用你熟悉的文档渲染工具. 比如一下将新增一个名字为 `asciidoc` 的渲染工具which is followed `markup.` ini section. And there are some config items below.
|
||||
|
@@ -59,7 +59,7 @@ to override can be found in the `templates` directory of Gitea source. Override
|
||||
making a copy of the file under `custom/templates` using a full path structure
|
||||
matching source.
|
||||
|
||||
Any statement contained inside `{{` and `}}` are Gitea's templete syntax and
|
||||
Any statement contained inside `{{` and `}}` are Gitea's template syntax and
|
||||
shouldn't be touched without fully understanding these components.
|
||||
|
||||
### Adding links and tabs
|
||||
@@ -88,6 +88,14 @@ Apart from `extra_links.tmpl` and `extra_tabs.tmpl`, there are other useful temp
|
||||
- `body_outer_post.tmpl`, before the bottom `<footer>` element.
|
||||
- `footer.tmpl`, right before the end of the `<body>` tag, a good place for additional Javascript.
|
||||
|
||||
## Adding Analytics to Gitea
|
||||
|
||||
Google Analytics, Matomo (previously Piwik), and other analytics services can be added to Gitea. To add the tracking code, refer to the `Other additions to the page` section of this document, and add the JavaScript to the `custom/templates/custom/header.tmpl` file.
|
||||
|
||||
## Customizing gitignores, labels, licenses, locales, and readmes.
|
||||
|
||||
Place custom files in corresponding sub-folder under `custom/options`.
|
||||
|
||||
## Customizing the look of Gitea
|
||||
|
||||
As of version 1.6.0 Gitea has built-in themes. The two built-in themes are, the default theme `gitea`, and a dark theme `arc-green`. To change the look of your Gitea install change the value of `DEFAULT_THEME` in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini` to another one of the available options.
|
||||
|
88
docs/content/doc/advanced/customizing-gitea.zh-cn.md
Normal file
88
docs/content/doc/advanced/customizing-gitea.zh-cn.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
date: "2017-04-15T14:56:00+02:00"
|
||||
title: "自定义 Gitea 配置"
|
||||
slug: "customizing-gitea"
|
||||
weight: 9
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "自定义 Gitea 配置"
|
||||
weight: 9
|
||||
identifier: "customizing-gitea"
|
||||
---
|
||||
|
||||
# 自定义 Gitea 配置
|
||||
|
||||
Gitea 引用 `custom` 目录中的自定义配置文件来覆盖配置、模板等默认配置。
|
||||
|
||||
如果从二进制部署 Gitea ,则所有默认路径都将相对于该 gitea 二进制文件;如果从发行版安装,则可能会将这些路径修改为Linux文件系统标准。Gitea
|
||||
将会自动创建包括 `custom/` 在内的必要应用目录,应用本身的配置存放在
|
||||
`custom/conf/app.ini` 当中。在发行版中可能会以 `/etc/gitea/` 的形式为 `custom` 设置一个符号链接,查看配置详情请移步:
|
||||
|
||||
- [快速备忘单](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
||||
- [完整配置清单](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample)
|
||||
|
||||
如果您在 binary 同目录下无法找到 `custom` 文件夹,请检查您的 `GITEA_CUSTOM`
|
||||
环境变量配置, 因为它可能被配置到了其他地方(可能被一些启动脚本设置指定了目录)。
|
||||
|
||||
- [环境变量清单](https://docs.gitea.io/en-us/specific-variables/)
|
||||
|
||||
**注:** 必须完全重启 Gitea 以使配置生效。
|
||||
|
||||
## 使用自定义 /robots.txt
|
||||
|
||||
将 [想要展示的内容](http://www.robotstxt.org/) 存放在 `custom` 目录中的
|
||||
`robots.txt` 文件来让 Gitea 使用自定义的`/robots.txt` (默认:空 404)。
|
||||
|
||||
## 使用自定义的公共文件
|
||||
|
||||
将自定义的公共文件(比如页面和图片)作为 webroot 放在 `custom/public/` 中来让 Gitea 提供这些自定义内容(符号链接将被追踪)。
|
||||
|
||||
举例说明:`image.png` 存放在 `custom/public/`中,那么它可以通过链接 http://gitea.domain.tld/image.png 访问。
|
||||
|
||||
## 修改默认头像
|
||||
|
||||
替换以下目录中的 png 图片: `custom/public/img/avatar\_default.png`
|
||||
|
||||
## 自定义 Gitea 页面
|
||||
|
||||
您可以改变 Gitea `custom/templates` 的每个单页面。您可以在 Gitea 源码的 `templates` 目录中找到用于覆盖的模板文件,应用将根据
|
||||
`custom/templates` 目录下的路径结构进行匹配和覆盖。
|
||||
|
||||
包含在 `{{` 和 `}}` 中的任何语句都是 Gitea 的模板语法,如果您不完全理解这些组件,不建议您对它们进行修改。
|
||||
|
||||
### 添加链接和页签
|
||||
|
||||
如果您只是想添加额外的链接到顶部导航栏或额外的选项卡到存储库视图,您可以将它们放在您 `custom/templates/custom/` 目录下的 `extra_links.tmpl` 和 `extra_tabs.tmpl` 文件中。
|
||||
|
||||
举例说明:假设您需要在网站放置一个静态的“关于”页面,您只需将该页面放在您的
|
||||
"custom/public/"目录下(比如 `custom/public/impressum.html`)并且将它与 `custom/templates/custom/extra_links.tmpl` 链接起来即可。
|
||||
|
||||
这个链接应当使用一个名为“item”的 class 来匹配当前样式,您可以使用 `{{AppSubUrl}}` 来获取 base URL:
|
||||
`<a class="item" href="{{AppSubUrl}}/impressum.html">Impressum</a>`
|
||||
|
||||
同理,您可以将页签添加到 `extra_tabs.tmpl` 中,使用同样的方式来添加页签。它的具体样式需要与
|
||||
`templates/repo/header.tmpl` 中已有的其他选项卡的样式匹配
|
||||
([source in GitHub](https://github.com/go-gitea/gitea/blob/master/templates/repo/header.tmpl))
|
||||
|
||||
### 页面的其他新增内容
|
||||
|
||||
除了 `extra_links.tmpl` 和 `extra_tabs.tmpl`,您可以在您的 `custom/templates/custom/` 目录中存放一些其他有用的模板,例如:
|
||||
|
||||
- `header.tmpl`,在 `<head>` 标记结束之前的模板,例如添加自定义CSS文件
|
||||
- `body_outer_pre.tmpl`,在 `<body>` 标记开始处的模板
|
||||
- `body_inner_pre.tmpl`,在顶部导航栏之前,但在主 container 内部的模板,例如添加一个 `<div class="full height">`
|
||||
- `body_inner_post.tmpl`,在主 container 结束处的模板
|
||||
- `body_outer_post.tmpl`,在底部 `<footer>` 元素之前.
|
||||
- `footer.tmpl`,在 `<body>` 标签结束处的模板,可以在这里填写一些附加的 Javascript 脚本。
|
||||
|
||||
## 自定义 gitignores,labels, licenses, locales 以及 readmes
|
||||
|
||||
将自定义文件放在 `custom/options` 下相应子的文件夹中即可
|
||||
|
||||
## 更改 Gitea 外观
|
||||
|
||||
Gitea 目前由两种内置主题,分别为默认 `gitea` 主题和深色主题 `arc-green`,您可以通过修改
|
||||
`app.ini` [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) 部分的 `DEFAULT_THEME` 的值来变更至一个可用的 Gitea 外观。
|
70
docs/content/doc/advanced/external-renderers.en-us.md
Normal file
70
docs/content/doc/advanced/external-renderers.en-us.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
date: "2018-11-23:00:00+02:00"
|
||||
title: "External renderers"
|
||||
slug: "external-renderers"
|
||||
weight: 40
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "External renderers"
|
||||
weight: 40
|
||||
identifier: "external-renderers"
|
||||
---
|
||||
|
||||
# Custom files rendering configuration
|
||||
|
||||
Gitea supports custom file renderings (i.e., Jupyter notebooks, asciidoc, etc.) through external binaries,
|
||||
it is just matter of:
|
||||
* installing external binaries
|
||||
* add some configuration to your `app.ini` file
|
||||
* restart your gitea instance
|
||||
|
||||
## Installing external binaries
|
||||
|
||||
In order to get file rendering through external binaries, their associated packages must be installed.
|
||||
If you're using a Docker image, your `Dockerfile` should contain something along this lines:
|
||||
|
||||
```
|
||||
FROM gitea/gitea:1.6.0
|
||||
[...]
|
||||
|
||||
COPY custom/app.ini /data/gitea/conf/app.ini
|
||||
[...]
|
||||
|
||||
RUN apk --no-cache add asciidoctor freetype freetype-dev gcc g++ libpng python-dev py-pip python3-dev py3-pip
|
||||
# install any other package you need for your external renderers
|
||||
|
||||
RUN pip3 install --upgrade pip
|
||||
RUN pip3 install -U setuptools
|
||||
RUN pip3 install jupyter matplotlib docutils
|
||||
# add above any other python package you may need to install
|
||||
```
|
||||
|
||||
## `app.ini` file configuration
|
||||
|
||||
add one `[markup.XXXXX]` section per external renderer on your custom `app.ini`:
|
||||
|
||||
```
|
||||
[markup.asciidoc]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoctor --out-file=- -"
|
||||
; Input is not a standard input but a file
|
||||
IS_INPUT_FILE = false
|
||||
|
||||
[markup.jupyter]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .ipynb
|
||||
RENDER_COMMAND = "jupyter nbconvert --stdout --to html --template basic "
|
||||
IS_INPUT_FILE = true
|
||||
|
||||
[markup.restructuredtext]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .rst
|
||||
RENDER_COMMAND = rst2html.py
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
Once your configuration changes have been made, restart Gitea to have changes take effect.
|
@@ -17,7 +17,8 @@ menu:
|
||||
|
||||
首先你需要一些运行环境,这和 [从源代码安装]({{< relref "from-source.zh-cn.md" >}}) 相同,如果你还没有设置好,可以先阅读那个章节。
|
||||
|
||||
如果你想为 Gitea 贡献代码,你需要 Fork 这个项目并且以 `master` 为开发分支。Gitea使用Govendor来管理依赖,因此所有依赖项都被工具自动copy在vendor子目录下。用下面的命令来下载源码:
|
||||
如果你想为 Gitea 贡献代码,你需要 Fork 这个项目并且以 `master` 为开发分支。Gitea 使用 Govendor
|
||||
来管理依赖,因此所有依赖项都被工具自动 copy 在 vendor 子目录下。用下面的命令来下载源码:
|
||||
|
||||
```
|
||||
go get -d code.gitea.io/gitea
|
||||
@@ -39,4 +40,4 @@ git fetch --all --prune
|
||||
|
||||
然后你就可以开始开发了。你可以看一下 `Makefile` 的内容。`make test` 可以运行测试程序, `make build` 将生成一个 `gitea` 可运行文件在根目录。如果你的提交比较复杂,尽量多写一些单元测试代码。
|
||||
|
||||
好了,到这里你已经设置好了所有的开发Gitea所需的环境。欢迎成为 Gitea 的 Contributor。
|
||||
好了,到这里你已经设置好了所有的开发 Gitea 所需的环境。欢迎成为 Gitea 的 Contributor。
|
||||
|
45
docs/content/doc/advanced/make.zh-cn.md
Normal file
45
docs/content/doc/advanced/make.zh-cn.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
date: "2017-01-14T11:00:00-02:00"
|
||||
title: "Make 安装"
|
||||
slug: "make"
|
||||
weight: 10
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Make 安装"
|
||||
weight: 30
|
||||
identifier: "make"
|
||||
---
|
||||
|
||||
# 安装 Make
|
||||
|
||||
Gitea 大量使用了 Make 工具来自动执行任务并改进开发,本文将介绍如何安装 Make。
|
||||
|
||||
### 在 Linux 环境下
|
||||
|
||||
可以使用包管理工具来安装 Make。
|
||||
|
||||
Ubuntu/Debian 环境,执行以下命令:
|
||||
|
||||
```bash
|
||||
sudo apt-get install make
|
||||
```
|
||||
|
||||
Fedora/RHEL/CentOS,执行以下命令:
|
||||
|
||||
```bash
|
||||
sudo yum install make
|
||||
```
|
||||
|
||||
### 在 Windows 环境下
|
||||
|
||||
您可以参照以下三种方案在 Windows 环境安装 Make:
|
||||
|
||||
- 直接使用 [exe文件](http://www.equation.com/servlet/equation.cmd?fa=make):将适合您系统的exe文件拷贝到某处并添加至环境变量 `PATH` 中。
|
||||
- [32 位版本](ftp://ftp.equation.com/make/32/make.exe)
|
||||
- [64 位版本](ftp://ftp.equation.com/make/64/make.exe)
|
||||
- 使用 [MinGW](http://www.mingw.org/) 工具:
|
||||
- 此处使用二进制文件 `mingw32-make.exe` 替代前面提到的 `make.exe`文件。同样您需要将包含此exe文件的 `bin` 目录添加至环境变量 `PATH`中。
|
||||
- 通过 [Chocolatey](https://chocolatey.org/packages/make) 安装: 执行 `choco install make` 命令即可。
|
@@ -66,4 +66,3 @@ For documentation about each of the variables available, refer to the
|
||||
## Miscellaneous
|
||||
|
||||
* `SKIP_MINWINSVC`: If set to 1, do not run as a service on Windows.
|
||||
* `ZOOKEEPER_PATH`: [Zookeeper](http://zookeeper.apache.org/) jar file path
|
||||
|
62
docs/content/doc/advanced/specific-variables.zh-cn.md
Normal file
62
docs/content/doc/advanced/specific-variables.zh-cn.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
date: "2017-04-08T11:34:00+02:00"
|
||||
title: "环境变量清单"
|
||||
slug: "specific-variables"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "环境变量清单"
|
||||
weight: 20
|
||||
identifier: "specific-variables"
|
||||
---
|
||||
|
||||
# 环境变量清单
|
||||
|
||||
这里是用来控制 Gitea 行为表现的的环境变量清单,您需要在执行如下 Gitea 启动命令前设置它们来确保配置生效:
|
||||
|
||||
```
|
||||
GITEA_CUSTOM=/home/gitea/custom ./gitea web
|
||||
```
|
||||
|
||||
## Go 的配置
|
||||
|
||||
因为 Gitea 使用 Go 语言编写,因此它使用了一些相关的 Go 的配置参数:
|
||||
|
||||
* `GOOS`
|
||||
* `GOARCH`
|
||||
* [`GOPATH`](https://golang.org/cmd/go/#hdr-GOPATH_environment_variable)
|
||||
|
||||
您可以在[官方文档](https://golang.org/cmd/go/#hdr-Environment_variables)中查阅这些配置参数的详细信息。
|
||||
|
||||
## Gitea 的文件目录
|
||||
|
||||
* `GITEA_WORK_DIR`:工作目录的绝对路径
|
||||
* `GITEA_CUSTOM`:默认情况下 Gitea 使用默认目录 `GITEA_WORK_DIR`/custom,您可以使用这个参数来配置 *custom* 目录
|
||||
* `GOGS_WORK_DIR`: 已废弃,请使用 `GITEA_WORK_DIR` 替代
|
||||
* `GOGS_CUSTOM`: 已废弃,请使用 `GITEA_CUSTOM` 替代
|
||||
|
||||
## 操作系统配置
|
||||
|
||||
* `USER`:Gitea 运行时使用的系统用户,它将作为一些 repository 的访问地址的一部分
|
||||
* `USERNAME`: 如果没有配置 `USER`, Gitea 将使用 `USERNAME`
|
||||
* `HOME`: 用户的 home 目录,在 Windows 中会使用 `USERPROFILE` 环境变量
|
||||
|
||||
### 仅限于 Windows 的配置
|
||||
|
||||
* `USERPROFILE`: 用户的主目录,如果未配置则会使用 `HOMEDRIVE` + `HOMEPATH`
|
||||
* `HOMEDRIVE`: 用于访问 home 目录的主驱动器路径(C盘)
|
||||
* `HOMEPATH`:在指定主驱动器下的 home 目录相对路径
|
||||
|
||||
## Macaron(Gitea 使用的 web 框架)
|
||||
|
||||
* `HOST`:Macaron 监听的主机地址
|
||||
* `PORT`:Macaron 监听的端口地址
|
||||
* `MACARON_ENV`:为开发环境和生产环境提供特殊功能性配置的全局变量,当 MACARON_ENV 设置为 "" 或 "development"
|
||||
时,每次请求都会重编译页面模板。为了提高性能表现,可将它设置为 "production"。
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* `SKIP_MINWINSVC`:如果设置为 1,在 Windows 上不会以 service 的形式运行。
|
@@ -37,6 +37,9 @@ _Symbols used in table:_
|
||||
| Multiple OS support | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ |
|
||||
| Easy upgrade process | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ |
|
||||
| Markdown support | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Orgmode support | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | ? |
|
||||
| CSV support | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ? |
|
||||
| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | ? |
|
||||
| Static Git-powered pages | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Integrated Git-powered wiki | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Deploy Tokens | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
@@ -53,7 +56,7 @@ _Symbols used in table:_
|
||||
|---------|-------|------|-----------|-----------|-----------|-----------|--------------|
|
||||
| Repository topics | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Repository code search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Global code search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Global code search | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ |
|
||||
| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ⁄ | ✓ |
|
||||
| Group Milestones | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
@@ -74,7 +77,7 @@ _Symbols used in table:_
|
||||
| Issue templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Labels | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Time tracking | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Multiple assignees for issues | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Multiple assignees for issues | ✓ | ✘ | ✓ | ✘ | ✓ | ✘ | ✘ |
|
||||
| Related issues | ✘ | ✘ | ⁄ | ✘ | ✓ | ✘ | ✘ |
|
||||
| Confidential issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Comment reactions | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
@@ -84,6 +87,7 @@ _Symbols used in table:_
|
||||
| Create new branches from issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Global issue search | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Issue dependency | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
||||
|
||||
#### Pull/Merge requests
|
||||
|
||||
@@ -92,8 +96,8 @@ _Symbols used in table:_
|
||||
| Pull/Merge requests | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Squash merging | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ |
|
||||
| Rebase merging | ✓ | ✓ | ✓ | ✘ | ⁄ | ✘ | ✓ |
|
||||
| Pull/Merge request inline comments | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Pull/Merge request approval | ✘ | ✘ | ⁄ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Pull/Merge request inline comments | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Pull/Merge request approval | ✓ | ✘ | ⁄ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Merge conflict resolution | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Restrict push and merge access to certain users | ✓ | ✘ | ✓ | ⁄ | ✓ | ✓ | ✓ |
|
||||
| Revert specific commits or a merge request | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
@@ -115,5 +119,5 @@ _Symbols used in table:_
|
||||
| Act as OAuth 2.0 provider | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Two factor authentication (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Mattermost/Slack integration | ✓ | ✓ | ⁄ | ✓ | ✓ | ⁄ | ✓ |
|
||||
| Discord integration | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ |
|
||||
| Discord integration | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| External CI/CD status display | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
|
@@ -80,3 +80,17 @@ To migrate an repository *with* all tags you need to do two things
|
||||
```
|
||||
gitea admin repo-sync-releases
|
||||
```
|
||||
|
||||
## LFS Issues
|
||||
|
||||
For issues concerning LFS data upload
|
||||
|
||||
```
|
||||
batch response: Authentication required: Authorization error: <GITEA_LFS_URL>/info/lfs/objects/batch
|
||||
Check that you have proper access to the repository
|
||||
error: failed to push some refs to '<GIT_REPO_URL>'
|
||||
```
|
||||
Have you checked the value of `LFS_HTTP_AUTH_EXPIRY` in your `app.ini` file? By default your LFS token will expire after 20 minutes. If you have a slow connection or a large file (or both) it may not finish uploading within the time limit.
|
||||
|
||||
You may want to set this value to `60m` or `120m`.
|
||||
|
||||
|
@@ -21,10 +21,18 @@ the destination platform from the [downloads page](https://dl.gitea.io/gitea), c
|
||||
the URL and replace the URL within the commands below:
|
||||
|
||||
```sh
|
||||
wget -O gitea https://dl.gitea.io/gitea/1.4.2/gitea-1.4.2-linux-amd64
|
||||
wget -O gitea https://dl.gitea.io/gitea/1.5.0/gitea-1.5.0-linux-amd64
|
||||
chmod +x gitea
|
||||
```
|
||||
|
||||
## Verify GPG signature
|
||||
Gitea signs all binaries with a [GPG key](https://pgp.mit.edu/pks/lookup?op=vindex&fingerprint=on&search=0x2D9AE806EC1592E2) to prevent against unwanted modification of binaries. To validate the binary download the signature file which ends in `.asc` for the binary you downloaded and use the gpg command line tool.
|
||||
|
||||
```sh
|
||||
gpg --keyserver pgp.mit.edu --recv 7C9E68152594688862D62AF62D9AE806EC1592E2
|
||||
gpg --verify gitea-1.5.0-linux-amd64.asc gitea-1.5.0-linux-amd64
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
After getting a binary, it can be tested with `./gitea web` or moved to a permanent
|
||||
@@ -82,6 +90,20 @@ cp gitea /usr/local/bin/gitea
|
||||
|
||||
See how to create [Linux service]({{< relref "run-as-service-in-ubuntu.en-us.md" >}})
|
||||
|
||||
## Updating to a new version
|
||||
|
||||
You can update to a new version of gitea by stopping gitea, replacing the binary at `/usr/local/bin/gitea` and restarting the instance.
|
||||
The binary file name should not be changed during the update to avoid problems
|
||||
in existing repositories.
|
||||
|
||||
It is recommended you do a [backup]({{< relref "doc/usage/backup-and-restore.en-us.md" >}}) before updating your installation.
|
||||
|
||||
If you have carried out the installation steps as described above, the binary should
|
||||
have the generic name `gitea`. Do not change this, i.e. to include the version number.
|
||||
|
||||
See below for troubleshooting instructions to repair broken repositories after
|
||||
an update of your gitea version.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Old glibc versions
|
||||
@@ -99,3 +121,25 @@ For errors like `702 runWeb()] [E] Failed to start server: listen tcp 0.0.0.0:30
|
||||
bind: address already in use` gitea needs to be started on another free port. This
|
||||
is possible using `./gitea web -p $PORT`. It's possible another instance of gitea
|
||||
is already running.
|
||||
|
||||
### Git error after updating to a new version of gitea
|
||||
|
||||
If the binary file name has been changed during the update to a new version of gitea,
|
||||
git hooks in existing repositories will not work any more. In that case, a git
|
||||
error will be displayed when pushing to the repository.
|
||||
|
||||
```
|
||||
remote: ./hooks/pre-receive.d/gitea: line 2: [...]: No such file or directory
|
||||
```
|
||||
|
||||
The `[...]` part of the error message will contain the path to your previous gitea
|
||||
binary.
|
||||
|
||||
To solve this, go to the admin options and run the task `Resynchronize pre-receive,
|
||||
update and post-receive hooks of all repositories` to update all hooks to contain
|
||||
the new binary path. Please note that this overwrite all git hooks including ones
|
||||
with customizations made.
|
||||
|
||||
If you aren't using the built-in to Gitea ssh server you will also need to re-write
|
||||
the authorized key file by running the `Update the '.ssh/authorized_keys' file with
|
||||
Gitea SSH keys.` task in the admin options.
|
||||
|
@@ -64,3 +64,16 @@ bundled templates, options, plugins and themes are in `/usr/local/share/gitea`,
|
||||
is in `/usr/local/etc/rc.d/gitea`.
|
||||
|
||||
To enable Gitea to run as a service, run `sysrc gitea_enable=YES` and start it with `service gitea start`.
|
||||
|
||||
## Cloudron
|
||||
|
||||
Gitea is available as a 1-click install on [Cloudron](https://cloudron.io). For those unaware,
|
||||
Cloudron makes it easy to run apps like Gitea on your server and keep them up-to-date and secure.
|
||||
|
||||
[](https://cloudron.io/button.html?app=io.gitea.cloudronapp)
|
||||
|
||||
The Gitea package is maintained [here](https://git.cloudron.io/cloudron/gitea-app).
|
||||
|
||||
There is a [demo instance](https://my-demo.cloudron.me) (username: cloudron password: cloudron) where
|
||||
you can experiment with running Gitea.
|
||||
|
||||
|
@@ -66,7 +66,7 @@ provided to keep the build process as simple as possible.
|
||||
Depending on requirements, the following build tags can be included.
|
||||
|
||||
* `bindata`: Build a single monolithic binary, with all assets included.
|
||||
* `sqlite`: Enable support for a [SQLite3](https://sqlite.org/) database. Suggested only
|
||||
* `sqlite sqlite_unlock_notify`: Enable support for a [SQLite3](https://sqlite.org/) database. Suggested only
|
||||
for tiny installations.
|
||||
* `tidb`: Enable support for a [TiDB](https://github.com/pingcap/tidb) database.
|
||||
* `pam`: Enable support for PAM (Linux Pluggable Authentication Modules). Can be used to
|
||||
|
@@ -57,7 +57,7 @@ git checkout pr-xyz
|
||||
Comme nous regroupons déjà toutes les bibliothèques requises pour compiler Gitea, vous pouvez continuer avec le processus de compilation lui-même. Nous fournissons diverses [tâches Make](https://github.com/go-gitea/gitea/blob/master/Makefile) pour rendre le processus de construction aussi simple que possible. <a href='{{< relref "doc/advanced/make.fr-fr.md" >}}'>Voyez ici comment obtenir Make</a>. Selon vos besoins, vous pourrez éventuellement ajouter diverses options de compilation, vous pouvez choisir entre ces options :
|
||||
|
||||
* `bindata`: Intègre toutes les ressources nécessaires à l'exécution d'une instance de Gitea, ce qui rend un déploiement facile car il n'est pas nécessaire de se préoccuper des fichiers supplémentaires.
|
||||
* `sqlite`: Active la prise en charge d'une base de données [SQLite3](https://sqlite.org/), ceci n'est recommandé que pour les petites installations de Gitea.
|
||||
* `sqlite sqlite_unlock_notify`: Active la prise en charge d'une base de données [SQLite3](https://sqlite.org/), ceci n'est recommandé que pour les petites installations de Gitea.
|
||||
* `tidb`: Active la prise en charge d'une base de données [TiDB](https://github.com/pingcap/tidb), c'est une base de données simplet et basée sur des fichiers. Elle est comparable à SQLite.
|
||||
* `pam`: Active la prise en charge de PAM (mLinux Pluggable Authentication Modules), très utile si vos utilisateurs doivent être authentifiés avec les comptes du système.
|
||||
|
||||
|
@@ -47,7 +47,7 @@ git checkout v1.0.0
|
||||
我们已经将所有的依赖项拷贝到本工程,我们提供了一些 [编译选项](https://github.com/go-gitea/gitea/blob/master/Makefile) 来让编译更简单。你可以按照你的需求来设置编译开关,可用编译选项如下:
|
||||
|
||||
* `bindata`: 这个编译选项将会把运行Gitea所需的所有外部资源都打包到可执行文件中,这样部署将非常简单因为除了可执行程序将不再需要任何其他文件。
|
||||
* `sqlite`: 这个编译选项将启用SQLite3数据库的支持,建议只在少数人使用时使用这个模式。
|
||||
* `sqlite sqlite_unlock_notify`: 这个编译选项将启用SQLite3数据库的支持,建议只在少数人使用时使用这个模式。
|
||||
* `tidb`: 这个编译选项启用tidb嵌入式数据库的支持,他跟SQLite类似但是是用纯Go编写的。
|
||||
* `pam`: 这个编译选项将会启用 PAM (Linux Pluggable Authentication Modules) 认证,如果你使用这一认证模式的话需要开启这个选项。
|
||||
|
||||
|
@@ -47,7 +47,7 @@ git checkout v1.0.0
|
||||
完成設定相依性套件環境等工作後,您就可以開始編譯工作了。我們提供了不同的[編譯選項](https://github.com/go-gitea/gitea/blob/master/Makefile) ,讓編譯過程更加簡單。您可以根據需求來調整編譯選項,底下是可用的編譯選項說明:
|
||||
|
||||
* `bindata`: 使用此標籤來嵌入所有 Gitea 相關資源,您不用擔心其他額外檔案,對於部署來說非常方便。
|
||||
* `sqlite`: 使用此標籤來啟用 [SQLite3](https://sqlite.org/) 資料庫,建議只有少數人時才使用此模式。
|
||||
* `sqlite sqlite_unlock_notify`: 使用此標籤來啟用 [SQLite3](https://sqlite.org/) 資料庫,建議只有少數人時才使用此模式。
|
||||
* `tidb`: 使用此標籤來啟用 [TiDB](https://github.com/pingcap/tidb) 資料庫,它是檔案形式的資料庫,跟 SQLite 類似。
|
||||
* `pam`: 使用此標籤來啟用 PAM (Linux Pluggable Authentication Modules) 認證,對於系統使用者來說,此方式最方便了。
|
||||
|
||||
|
@@ -0,0 +1,63 @@
|
||||
---
|
||||
date: "2017-07-21T12:00:00+02:00"
|
||||
title: "在 Linux 中以 service 方式运行"
|
||||
slug: "linux-service"
|
||||
weight: 10
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "installation"
|
||||
name: "在Linux中以service方式运行"
|
||||
weight: 20
|
||||
identifier: "linux-service"
|
||||
---
|
||||
|
||||
### 在 Ubuntu 16.04 LTS 中以 service 方式运行
|
||||
|
||||
#### systemd 方式
|
||||
|
||||
在 terminal 中执行以下命令:
|
||||
```
|
||||
sudo vim /etc/systemd/system/gitea.service
|
||||
```
|
||||
|
||||
接着拷贝示例代码 [gitea.service](https://github.com/go-gitea/gitea/blob/master/contrib/systemd/gitea.service) 并取消对任何需要运行在主机上的服务部分的注释,譬如 MySQL。
|
||||
|
||||
修改 user,home 目录以及其他必须的初始化参数,如果使用自定义端口,则需修改 PORT 参数,反之如果使用默认端口则需删除 -p 标记。
|
||||
|
||||
激活 gitea 并将它作为系统自启动服务:
|
||||
```
|
||||
sudo systemctl enable gitea
|
||||
sudo systemctl start gitea
|
||||
```
|
||||
|
||||
|
||||
#### 使用 supervisor
|
||||
|
||||
在 terminal 中执行以下命令安装 supervisor:
|
||||
```
|
||||
sudo apt install supervisor
|
||||
```
|
||||
|
||||
为 supervisor 配置日志路径:
|
||||
```
|
||||
# assuming gitea is installed in /home/git/gitea/
|
||||
mkdir /home/git/gitea/log/supervisor
|
||||
```
|
||||
|
||||
在文件编辑器中打开 supervisor 的配置文件:
|
||||
```
|
||||
sudo vim /etc/supervisor/supervisord.conf
|
||||
```
|
||||
|
||||
增加如下示例配置
|
||||
[supervisord config](https://github.com/go-gitea/gitea/blob/master/contrib/supervisor/gitea)。
|
||||
|
||||
将 user(git) 和 home(/home/git) 设置为与上文部署中匹配的值。如果使用自定义端口,则需修改 PORT 参数,反之如果使用默认端口则需删除 -p 标记。
|
||||
|
||||
最后激活 supervisor 并将它作为系统自启动服务:
|
||||
```
|
||||
sudo systemctl enable supervisor
|
||||
sudo systemctl start supervisor
|
||||
```
|
@@ -19,8 +19,8 @@ Gitea provides automatically updated Docker images within its Docker Hub organiz
|
||||
possible to always use the latest stable tag or to use another service that handles updating
|
||||
Docker images.
|
||||
|
||||
This reference setup guides users through the setup based on `docker-compose`, the installation
|
||||
of `docker-compose` is out of scope of this documentation. To install `docker-compose` follow
|
||||
This reference setup guides users through the setup based on `docker-compose`, but the installation
|
||||
of `docker-compose` is out of scope of this documentation. To install `docker-compose` itself follow
|
||||
the official [install instructions](https://docs.docker.com/compose/install/).
|
||||
|
||||
## Basics
|
||||
@@ -30,6 +30,8 @@ image as a service. Since there is no database available one can be initialized
|
||||
Create a directory like `gitea` and paste the following content into a file named `docker-compose.yml`.
|
||||
Note that the volume should be owned by the user/group with the UID/GID specified in the config file.
|
||||
If you don't give the volume correct permissions, the container may not start.
|
||||
Also be aware that the tag `:latest` will install the current development version.
|
||||
For a stable release you can use `:1` or specify a certain release like `:1.5.1`.
|
||||
|
||||
```yaml
|
||||
version: "2"
|
||||
@@ -103,6 +105,11 @@ services:
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
+ - DB_TYPE=mysql
|
||||
+ - DB_HOST=db:3306
|
||||
+ - DB_NAME=gitea
|
||||
+ - DB_USER=gitea
|
||||
+ - DB_PASSWD=gitea
|
||||
restart: always
|
||||
networks:
|
||||
- gitea
|
||||
@@ -146,6 +153,11 @@ services:
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
+ - DB_TYPE=postgres
|
||||
+ - DB_HOST=db:5432
|
||||
+ - DB_NAME=gitea
|
||||
+ - DB_USER=gitea
|
||||
+ - DB_PASSWD=gitea
|
||||
restart: always
|
||||
networks:
|
||||
- gitea
|
||||
@@ -255,3 +267,16 @@ be placed in `/data/gitea` directory. If using host volumes it's quite easy to a
|
||||
files; for named volumes this is done through another container or by direct access at
|
||||
`/var/lib/docker/volumes/gitea_gitea/_data`. The configuration file will be saved at
|
||||
`/data/gitea/conf/app.ini` after the installation.
|
||||
|
||||
# Upgrading
|
||||
|
||||
:exclamation::exclamation: **Make sure you have volumed data to somewhere outside Docker container** :exclamation::exclamation:**
|
||||
|
||||
To upgrade your installation to the latest release:
|
||||
```
|
||||
# Edit `docker-compose.yml` to update the version, if you have one specified
|
||||
# Pull new images
|
||||
docker-compose pull
|
||||
# Start a new container, automatically removes old one
|
||||
docker-compose up -d
|
||||
```
|
||||
|
@@ -33,50 +33,53 @@ There are some basic steps to follow. On a Linux system run as the Gogs user:
|
||||
* Enter Gitea admin panel on the UI, run `Rewrite '.ssh/authorized_keys' file`.
|
||||
* If custom or config path was changed, run `Rewrite all update hook of repositories`.
|
||||
|
||||
### Change gogs specific information:
|
||||
## Change gogs specific information
|
||||
|
||||
* Rename `gogs-repositories/` to `gitea-repositories/`
|
||||
* Rename `gogs-data/` to `gitea-data/`
|
||||
* In `gitea/custom/conf/app.ini` change:
|
||||
|
||||
### Upgrading to most recent `gitea` version:
|
||||
FROM:
|
||||
|
||||
```ini
|
||||
[database]
|
||||
PATH = /home/:USER/gogs/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gogs-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gogs/log
|
||||
```
|
||||
|
||||
TO:
|
||||
|
||||
```ini
|
||||
[database]
|
||||
PATH = /home/:USER/gitea/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gitea-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gitea/log
|
||||
```
|
||||
|
||||
* Verify by starting Gitea with `gitea web`
|
||||
|
||||
## Upgrading to most recent `gitea` version
|
||||
|
||||
After successful migration from `gogs` to `gitea 1.0.x` it is possible to upgrade to the recent `gitea` version.
|
||||
Simply download the file matching the destination platform from the [downloads page](https://dl.gitea.io/gitea)
|
||||
and replace the binary.
|
||||
|
||||
FROM:
|
||||
```
|
||||
[database]
|
||||
PATH = /home/:USER/gogs/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gogs-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gogs/log
|
||||
```
|
||||
|
||||
TO:
|
||||
```
|
||||
[database]
|
||||
PATH = /home/:USER/gitea/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gitea-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gitea/log
|
||||
```
|
||||
|
||||
* Verify by starting Gitea with `gitea web`
|
||||
|
||||
### Troubleshooting
|
||||
## Troubleshooting
|
||||
|
||||
* If errors are encountered relating to custom templates in the `gitea/custom/templates`
|
||||
folder, try moving the templates causing the errors away one by one. They may not be
|
||||
compatible with Gitea or an update.
|
||||
|
||||
### Add Gitea to startup on Unix
|
||||
## Add Gitea to startup on Unix
|
||||
|
||||
Update the appropriate file from [gitea/contrib](https://github.com/go-gitea/gitea/tree/master/contrib)
|
||||
with the right environment variables.
|
||||
|
@@ -19,7 +19,7 @@ menu:
|
||||
|
||||
Veuillez suivre les étapes ci-dessous. Sur Unix, toute les commandes s'exécutent en tant que l'utilisateur utilisé pour votre installation de Gogs :
|
||||
|
||||
* Crééer une sauvegarde de Gogs avec la commande `gogs dump`. Le fichier nouvellement créé `gogs-dump-[timestamp].zip` contient toutes les données de votre instance de Gogs.
|
||||
* Crééer une sauvegarde de Gogs avec la commande `gogs dump`. Le fichier nouvellement créé `gogs-dump-[timestamp].zip` contient toutes les données de votre instance de Gogs.
|
||||
* Téléchargez le fichier correspondant à votre plateforme à partir de la [page de téléchargements](https://dl.gitea.io/gitea).
|
||||
* Mettez la binaire dans le répertoire d'installation souhaité.
|
||||
* Copiez le fichier `gogs/custom/conf/app.ini` vers `gitea/custom/conf/app.ini`.
|
||||
@@ -29,43 +29,45 @@ Veuillez suivre les étapes ci-dessous. Sur Unix, toute les commandes s'exécute
|
||||
* Vérifiez votre installation en exécutant Gitea avec la commande `gitea web`.
|
||||
* Connectez vous au panel d'administration de Gitea et exécutez l'action `Rewrite '.ssh/authorized_keys' file`, puis l'action `Rewrite all update hook of repositories` (obligatoire si le chemin menant à votre configuration personnalisée à changé).
|
||||
|
||||
### Modifier les informations spécifiques de gogs
|
||||
## Modifier les informations spécifiques de gogs
|
||||
|
||||
* Renommez `gogs-repositories/` vers `gitea-repositories/`
|
||||
* Renommez `gogs-data/` to `gitea-data/`
|
||||
* Dans votre fichier `gitea/custom/conf/app.ini`, modifiez les éléments suivants:
|
||||
|
||||
DE :
|
||||
```
|
||||
[database]
|
||||
PATH = /home/:USER/gogs/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gogs-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gogs/log
|
||||
```
|
||||
DE :
|
||||
|
||||
VERS :
|
||||
```
|
||||
[database]
|
||||
PATH = /home/:USER/gitea/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gitea-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gitea/log
|
||||
```
|
||||
```ini
|
||||
[database]
|
||||
PATH = /home/:USER/gogs/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gogs-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gogs/log
|
||||
```
|
||||
|
||||
VERS :
|
||||
|
||||
```ini
|
||||
[database]
|
||||
PATH = /home/:USER/gitea/data/:DATABASE.db
|
||||
[attachment]
|
||||
PATH = /home/:USER/gitea-data/attachments
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars
|
||||
[log]
|
||||
ROOT_PATH = /home/:USER/gitea/log
|
||||
```
|
||||
|
||||
* Vérifiez votre installation en exécutant Gitea avec la commande `gitea web`.
|
||||
|
||||
### Dépannage
|
||||
## Dépannage
|
||||
|
||||
* Si vous rencontrez des erreurs relatives à des modèles personnalisés dans le dossier `gitea/custom/templates`, essayez de déplacer un par un les modèles provoquant les erreurs. Il est possible qu'ils ne soient pas compatibles avec Gitea.
|
||||
|
||||
### Démarrer automatiquement Gitea (Unix)
|
||||
## Démarrer automatiquement Gitea (Unix)
|
||||
|
||||
Distributions utilisant systemd:
|
||||
|
||||
|
13
docs/content/doc/usage.zh-cn.md
Normal file
13
docs/content/doc/usage.zh-cn.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
date: "2016-12-27T16:00:00+02:00"
|
||||
title: "使用指南"
|
||||
slug: "usage"
|
||||
weight: 35
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "使用指南"
|
||||
weight: 35
|
||||
identifier: "usage"
|
||||
---
|
@@ -1,6 +1,6 @@
|
||||
---
|
||||
date: "2018-06-06T09:33:00+08:00"
|
||||
title: "使用: 备份与恢复"
|
||||
title: "使用:备份与恢复"
|
||||
slug: "backup-and-restore"
|
||||
weight: 11
|
||||
toc: true
|
||||
|
@@ -72,6 +72,50 @@ Admin operations:
|
||||
- Examples:
|
||||
- `gitea admin regenerate hooks`
|
||||
- `gitea admin regenerate keys`
|
||||
- `auth`:
|
||||
- `list`:
|
||||
- Description: lists all external authentication sources that exist
|
||||
- Options:
|
||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
||||
- Examples:
|
||||
- `gitea auth list`
|
||||
- `delete`:
|
||||
- Options:
|
||||
- `--id`: ID of source to be deleted. Required.
|
||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
||||
- Examples:
|
||||
- `gitea auth delete --id 1`
|
||||
- `add-oauth`:
|
||||
- Options:
|
||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
||||
- `--name`: Application Name.
|
||||
- `--provider`: OAuth2 Provider.
|
||||
- `--key`: Client ID (Key).
|
||||
- `--secret`: Client Secret.
|
||||
- `--auto-discover-url`: OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider).
|
||||
- `--use-custom-urls`: Use custom URLs for GitLab/GitHub OAuth endpoints.
|
||||
- `--custom-auth-url`: Use a custom Authorization URL (option for GitLab/GitHub).
|
||||
- `--custom-token-url`: Use a custom Token URL (option for GitLab/GitHub).
|
||||
- `--custom-profile-url`: Use a custom Profile URL (option for GitLab/GitHub).
|
||||
- `--custom-email-url`: Use a custom Email URL (option for GitHub).
|
||||
- Examples:
|
||||
- `gitea auth add-oauth --name external-github --provider github --key OBTAIN_FROM_SOURCE --secret OBTAIN_FROM_SOURCE`
|
||||
- `update-oauth`:
|
||||
- Options:
|
||||
- `--id`: ID of source to be updated. Required.
|
||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
||||
- `--name`: Application Name.
|
||||
- `--provider`: OAuth2 Provider.
|
||||
- `--key`: Client ID (Key).
|
||||
- `--secret`: Client Secret.
|
||||
- `--auto-discover-url`: OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider).
|
||||
- `--use-custom-urls`: Use custom URLs for GitLab/GitHub OAuth endpoints.
|
||||
- `--custom-auth-url`: Use a custom Authorization URL (option for GitLab/GitHub).
|
||||
- `--custom-token-url`: Use a custom Token URL (option for GitLab/GitHub).
|
||||
- `--custom-profile-url`: Use a custom Profile URL (option for GitLab/GitHub).
|
||||
- `--custom-email-url`: Use a custom Email URL (option for GitHub).
|
||||
- Examples:
|
||||
- `gitea auth update-oauth --id 1 --name external-github-updated`
|
||||
|
||||
#### cert
|
||||
|
||||
@@ -119,3 +163,24 @@ for automatic deployments.
|
||||
- `gitea generate secret INTERNAL_TOKEN`
|
||||
- `gitea generate secret LFS_JWT_SECRET`
|
||||
- `gitea generate secret SECRET_KEY`
|
||||
|
||||
#### keys
|
||||
|
||||
Provides an SSHD AuthorizedKeysCommand. Needs to be configured in the sshd config file:
|
||||
|
||||
```ini
|
||||
...
|
||||
# The value of -e and the AuthorizedKeysCommandUser should match the
|
||||
# username running gitea
|
||||
AuthorizedKeysCommandUser git
|
||||
AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k
|
||||
```
|
||||
|
||||
The command will return the appropriate authorized_keys line for the
|
||||
provided key. You should also set the value
|
||||
`SSH_CREATE_AUTHORIZED_KEYS_FILE=false` in the `[server]` section of
|
||||
`app.ini`.
|
||||
|
||||
NB: opensshd requires the gitea program to be owned by root and not
|
||||
writable by group or others. The program must be specified by an absolute
|
||||
path.
|
||||
|
@@ -30,6 +30,38 @@ HTTP_PORT = 3000
|
||||
CERT_FILE = cert.pem
|
||||
KEY_FILE = key.pem
|
||||
```
|
||||
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server).
|
||||
|
||||
### Setting-up HTTP redirection
|
||||
|
||||
The Gitea server is only able to listen to one port; to redirect HTTP requests to the HTTPS port, you will need to enable the HTTP redirection service:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
REDIRECT_OTHER_PORT = true
|
||||
; Port the redirection service should listen on
|
||||
PORT_TO_REDIRECT = 3080
|
||||
```
|
||||
|
||||
If you are using Docker, make sure that this port is configured in your `docker-compose.yml` file.
|
||||
|
||||
## Using Let's Encrypt
|
||||
|
||||
[Let's Encrypt](https://letsencrypt.org/) is a Certificate Authority that allows you to automatically request and renew SSL/TLS certificates. In addition to starting Gitea on your configured port, to request HTTPS certificates Gitea will also need to listed on port 80, and will set up an autoredirect to HTTPS for you. Let's Encrypt will need to be able to access Gitea via the Internet to verify your ownership of the domain.
|
||||
|
||||
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)
|
||||
|
||||
```ini
|
||||
[server]
|
||||
PROTOCOL=https
|
||||
DOMAIN=git.example.com
|
||||
ENABLE_LETSENCRYPT=true
|
||||
LETSENCRYPT_ACCEPTTOS=true
|
||||
LETSENCRYPT_DIRECTORY=https
|
||||
LETSENCRYPT_EMAIL=email@example.com
|
||||
```
|
||||
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server).
|
||||
|
||||
## Using reverse proxy
|
||||
|
37
docs/content/doc/usage/issue-pull-request-templates.zh-cn.md
Normal file
37
docs/content/doc/usage/issue-pull-request-templates.zh-cn.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
date: "2018-05-10T16:00:00+02:00"
|
||||
title: "使用:Issue 和 Pull Request 模板"
|
||||
slug: "issue-pull-request-templates"
|
||||
weight: 15
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "usage"
|
||||
name: "Issue 和 Pull Request 模板"
|
||||
weight: 15
|
||||
identifier: "issue-pull-request-templates"
|
||||
---
|
||||
|
||||
# 使用 Issue 和 Pull Request 模板
|
||||
|
||||
对于一些项目,在创建 issue 或 pull request 时有一个标准的询问列表需要提交者填写。Gitea 支持添加此类模板至 repository 的主分支,以便提交者在创建 issue 或 pull request 时可以自动生成一个需要完成的表单,这么做可以减少一些前期关于 issue 抑或 pull request 细节上的沟通成本。
|
||||
|
||||
以下罗列了一些可供参考的 issue 模板:
|
||||
|
||||
* ISSUE_TEMPLATE.md
|
||||
* issue_template.md
|
||||
* .gitea/ISSUE_TEMPLATE.md
|
||||
* .gitea/issue_template.md
|
||||
* .github/ISSUE_TEMPLATE.md
|
||||
* .github/issue_template.md
|
||||
|
||||
|
||||
以下罗列了一些可供参考的 PR 模板:
|
||||
|
||||
* PULL_REQUEST_TEMPLATE.md
|
||||
* pull_request_template.md
|
||||
* .gitea/PULL_REQUEST_TEMPLATE.md
|
||||
* .gitea/pull_request_template.md
|
||||
* .github/PULL_REQUEST_TEMPLATE.md
|
||||
* .github/pull_request_template.md
|
31
docs/content/doc/usage/pull-request.en-us.md
Normal file
31
docs/content/doc/usage/pull-request.en-us.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
date: "2018-06-01T19:00:00+02:00"
|
||||
title: "Usage: Pull Request"
|
||||
slug: "pull-request"
|
||||
weight: 13
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "usage"
|
||||
name: "Pull Request"
|
||||
weight: 13
|
||||
identifier: "pull-request"
|
||||
---
|
||||
|
||||
# Pull Request
|
||||
|
||||
## "Work In Progress" pull requests
|
||||
|
||||
Marking a pull request as being a work in progress will prevent that pull request from being accidentally merged. To mark a pull request as being a work in progress, you must prefix its title by `WIP:` or `[WIP]` (case insensitive). Those values are configurable in your `app.ini` file :
|
||||
|
||||
```
|
||||
[repository.pull-request]
|
||||
WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP]
|
||||
```
|
||||
|
||||
The first value of the list will be used in helpers.
|
||||
|
||||
## Pull Request Templates
|
||||
|
||||
You can find more information about pull request templates in the dedicated page : [Issue and Pull Request templates](../issue-pull-request-templates)
|
31
docs/content/doc/usage/pull-request.zh-cn.md
Normal file
31
docs/content/doc/usage/pull-request.zh-cn.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
date: "2018-06-01T19:00:00+02:00"
|
||||
title: "使用:Pull Request"
|
||||
slug: "pull-request"
|
||||
weight: 13
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "usage"
|
||||
name: "Pull Request"
|
||||
weight: 13
|
||||
identifier: "pull-request"
|
||||
---
|
||||
|
||||
# Pull Request
|
||||
|
||||
## 在 pull requests 使用“Work In Progress”标记
|
||||
|
||||
您可以通过在一个进行中的 pull request 的标题上添加前缀 `WIP:` 或者 `[WIP]`(此处大小写敏感)来防止它被意外合并,具体的前缀设置可以在配置文件 `app.ini` 中找到:
|
||||
|
||||
```
|
||||
[repository.pull-request]
|
||||
WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP]
|
||||
```
|
||||
|
||||
列表的第一个值将用于 helpers 程序。
|
||||
|
||||
## Pull Request 模板
|
||||
|
||||
有关 pull request 模板的更多信息请您移步 : [Issue and Pull Request templates](../issue-pull-request-templates)
|
@@ -81,7 +81,7 @@ Then set `[server] ROOT_URL = http://git.example.com/git/` in your configuration
|
||||
|
||||
Note: The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`
|
||||
|
||||
## Using Caddy with a Sub-path as a reverse proxy
|
||||
## Using Caddy as a reverse proxy
|
||||
|
||||
If you want Caddy to serve your Gitea instance you can add the following server block to your Caddyfile:
|
||||
|
||||
|
105
docs/content/doc/usage/reverse-proxies.zh-cn.md
Normal file
105
docs/content/doc/usage/reverse-proxies.zh-cn.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
date: "2018-05-22T11:00:00+00:00"
|
||||
title: "使用:反向代理"
|
||||
slug: "reverse-proxies"
|
||||
weight: 17
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "usage"
|
||||
name: "反向代理"
|
||||
weight: 16
|
||||
identifier: "reverse-proxies"
|
||||
---
|
||||
|
||||
## 使用 Nginx 作为反向代理服务
|
||||
|
||||
如果您想使用 Nginx 作为 Gitea 的反向代理服务,您可以参照以下 `nginx.conf` 配置中 `server` 的 `http` 部分:
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
server_name git.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 使用 Nginx 作为反向代理服务并将 Gitea 路由至一个子路径
|
||||
|
||||
如果您已经有一个域名并且想与 Gitea 共享该域名,您可以增加以下 `nginx.conf` 配置中 `server` 的 `http` 部分,为 Gitea 添加路由规则:
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
server_name git.example.com;
|
||||
|
||||
location /git/ { # Note: Trailing slash
|
||||
proxy_pass http://localhost:3000/; # Note: Trailing slash
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
然后在您的 Gitea 配置文件中添加 `[server] ROOT_URL = http://git.example.com/git/`。
|
||||
|
||||
## 使用 Apache HTTPD 作为反向代理服务
|
||||
|
||||
如果您想使用 Apache HTTPD 作为 Gitea 的反向代理服务,您可以为您的 Apache HTTPD 作如下配置(在 Ubuntu 中,配置文件通常在 `/etc/apache2/httpd.conf` 目录下):
|
||||
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
...
|
||||
ProxyPreserveHost On
|
||||
ProxyRequests off
|
||||
ProxyPass / http://localhost:3000/
|
||||
ProxyPassReverse / http://localhost:3000/
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
注:必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`
|
||||
|
||||
## 使用 Apache HTTPD 作为反向代理服务并将 Gitea 路由至一个子路径
|
||||
|
||||
如果您已经有一个域名并且想与 Gitea 共享该域名,您可以增加以下配置为 Gitea 添加路由规则(在 Ubuntu 中,配置文件通常在 `/etc/apache2/httpd.conf` 目录下):
|
||||
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
...
|
||||
<Proxy *>
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Proxy>
|
||||
|
||||
ProxyPass /git http://localhost:3000 # Note: no trailing slash after either /git or port
|
||||
ProxyPassReverse /git http://localhost:3000 # Note: no trailing slash after either /git or port
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
然后在您的 Gitea 配置文件中添加 `[server] ROOT_URL = http://git.example.com/git/`。
|
||||
|
||||
注:必须启用以下 Apache HTTPD 组件:`proxy`, `proxy_http`
|
||||
|
||||
## 使用 Caddy 作为反向代理服务
|
||||
|
||||
如果您想使用 Caddy 作为 Gitea 的反向代理服务,您可以在 `Caddyfile` 中添加如下配置:
|
||||
|
||||
```
|
||||
git.example.com {
|
||||
proxy / http://localhost:3000
|
||||
}
|
||||
```
|
||||
|
||||
## 使用 Caddy 作为反向代理服务并将 Gitea 路由至一个子路径
|
||||
|
||||
如果您已经有一个域名并且想与 Gitea 共享该域名,您可以在您的 `Caddyfile` 文件中增加以下配置,为 Gitea 添加路由规则:
|
||||
|
||||
```
|
||||
git.example.com {
|
||||
proxy /git/ http://localhost:3000 # Note: Trailing Slash after /git/
|
||||
}
|
||||
```
|
||||
|
||||
然后在您的 Gitea 配置文件中添加 `[server] ROOT_URL = http://git.example.com/git/`。
|
@@ -1,44 +0,0 @@
|
||||
:80 {
|
||||
root /srv/www
|
||||
|
||||
locale en-US zh-CN zh-TW pt-BR nl-NL fr-FR {
|
||||
detect header
|
||||
}
|
||||
|
||||
redir 301 {
|
||||
if {path} match ^/$
|
||||
/ /{>Detected-Locale}/
|
||||
}
|
||||
|
||||
rewrite /en-US/ {
|
||||
regexp (.*)
|
||||
to /en-us/{1}
|
||||
}
|
||||
|
||||
rewrite /zh-CN/ {
|
||||
regexp (.*)
|
||||
to /zh-cn/{1}
|
||||
}
|
||||
|
||||
rewrite /zh-TW/ {
|
||||
regexp (.*)
|
||||
to /zh-tw/{1}
|
||||
}
|
||||
|
||||
rewrite /pt-BR/ {
|
||||
regexp (.*)
|
||||
to /pt-br/{1}
|
||||
}
|
||||
|
||||
rewrite /nl-NL/ {
|
||||
regexp (.*)
|
||||
to /nl-nl/{1}
|
||||
}
|
||||
|
||||
rewrite /fr-FR/ {
|
||||
regexp (.*)
|
||||
to /fr-fr/{1}
|
||||
}
|
||||
|
||||
header / Vary "Accept-Language"
|
||||
}
|
0
docs/static/.gitkeep
vendored
0
docs/static/.gitkeep
vendored
6
docs/static/_headers
vendored
Normal file
6
docs/static/_headers
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' https://fonts.googleapis.com https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com https://fonts.gstatic.com
|
||||
X-Frame-Options: DENY
|
||||
X-Xss-Protection: 1; mode=block
|
||||
X-Content-Type-Options: nosniff
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
8
docs/static/_redirects
vendored
Normal file
8
docs/static/_redirects
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
https://gitea-docs.netlify.com/* https://docs.gitea.io/:splat 302!
|
||||
|
||||
/ /fr-fr/ 302! Language=fr
|
||||
/ /nl-nl/ 302! Language=nl
|
||||
/ /pt-br/ 302! Language=pt-br
|
||||
/ /zh-cn/ 302! Language=zh-cn
|
||||
/ /zh-tw/ 302! Language=zh-tw
|
||||
/ /en-us/ 302!
|
@@ -2,14 +2,16 @@
|
||||
|
||||
Integration tests can be run with make commands for the
|
||||
appropriate backends, namely:
|
||||
|
||||
make test-mysql
|
||||
make test-pgsql
|
||||
make test-sqlite
|
||||
```shell
|
||||
make test-mysql
|
||||
make test-pgsql
|
||||
make test-sqlite
|
||||
```
|
||||
|
||||
Make sure to perform a clean build before running tests:
|
||||
|
||||
make clean build
|
||||
```
|
||||
make clean build
|
||||
```
|
||||
|
||||
## Run all tests via local drone
|
||||
```
|
||||
@@ -45,7 +47,6 @@ TEST_PGSQL_HOST=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAdd
|
||||
## Running individual tests
|
||||
|
||||
Example command to run GPG test with sqlite backend:
|
||||
|
||||
```
|
||||
go test -c code.gitea.io/gitea/integrations \
|
||||
-o integrations.sqlite.test -tags 'sqlite' &&
|
||||
|
56
integrations/README_ZH.md
Normal file
56
integrations/README_ZH.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 关于集成测试
|
||||
|
||||
使用如下 make 命令可以运行指定的集成测试:
|
||||
```shell
|
||||
make test-mysql
|
||||
make test-pgsql
|
||||
make test-sqlite
|
||||
```
|
||||
|
||||
在执行集成测试命令前请确保清理了之前的构建环境,清理命令如下:
|
||||
```
|
||||
make clean build
|
||||
```
|
||||
|
||||
## 如何在本地 drone 服务器上运行所有测试
|
||||
```
|
||||
drone exec --local --build-event "pull_request"
|
||||
```
|
||||
|
||||
## 如何使用 sqlite 数据库进行集成测试
|
||||
使用该命令执行集成测试
|
||||
```
|
||||
make test-sqlite
|
||||
```
|
||||
|
||||
## 如何使用 mysql 数据库进行集成测试
|
||||
首先在docker容器里部署一个 mysql 数据库
|
||||
```
|
||||
docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" --rm --name mysql mysql:5.7 #(just ctrl-c to stop db and clean the container)
|
||||
```
|
||||
之后便可以基于这个数据库进行集成测试
|
||||
```
|
||||
TEST_MYSQL_HOST="$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql):3306" TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-mysql
|
||||
```
|
||||
|
||||
## 如何使用 pgsql 数据库进行集成测试
|
||||
同上,首先在 docker 容器里部署一个 pgsql 数据库
|
||||
```
|
||||
docker run -e "POSTGRES_DB=test" --rm --name pgsql postgres:9.5 #(just ctrl-c to stop db and clean the container)
|
||||
```
|
||||
之后便可以基于这个数据库进行集成测试
|
||||
```
|
||||
TEST_PGSQL_HOST=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' pgsql) TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-pgsql
|
||||
```
|
||||
|
||||
## 如何进行自定义的集成测试
|
||||
|
||||
下面的示例展示了怎样基于 sqlite 数据库进行 GPG 测试:
|
||||
```
|
||||
go test -c code.gitea.io/gitea/integrations \
|
||||
-o integrations.sqlite.test -tags 'sqlite' &&
|
||||
GITEA_ROOT="$GOPATH/src/code.gitea.io/gitea" \
|
||||
GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test \
|
||||
-test.v -test.run GPG
|
||||
```
|
||||
|
@@ -11,6 +11,8 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
@@ -19,7 +21,8 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
session := loginUser(t, "user1")
|
||||
keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", keyOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", keyOwner.Name, token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n",
|
||||
"title": "test-key",
|
||||
@@ -36,8 +39,8 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
OwnerID: keyOwner.ID,
|
||||
})
|
||||
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d",
|
||||
keyOwner.Name, newPublicKey.ID)
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
|
||||
keyOwner.Name, newPublicKey.ID, token)
|
||||
session.MakeRequest(t, req, http.StatusNoContent)
|
||||
models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID})
|
||||
}
|
||||
@@ -47,7 +50,8 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
|
||||
// user1 is an admin user
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d", models.NonexistentID)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token=%s", models.NonexistentID, token)
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
@@ -57,7 +61,8 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, adminUsername)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", adminUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", adminUsername, token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n",
|
||||
"title": "test-key",
|
||||
@@ -67,7 +72,37 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
|
||||
DecodeJSON(t, resp, &newPublicKey)
|
||||
|
||||
session = loginUser(t, normalUsername)
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d",
|
||||
adminUsername, newPublicKey.ID)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
|
||||
adminUsername, newPublicKey.ID, token)
|
||||
session.MakeRequest(t, req, http.StatusForbidden)
|
||||
}
|
||||
|
||||
func TestAPISudoUser(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, adminUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", normalUsername, token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var user api.User
|
||||
DecodeJSON(t, resp, &user)
|
||||
|
||||
assert.Equal(t, normalUsername, user.UserName)
|
||||
}
|
||||
|
||||
func TestAPISudoUserForbidden(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
|
||||
session := loginUser(t, normalUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/user?sudo=%s&token=%s", adminUsername, token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
session.MakeRequest(t, req, http.StatusForbidden)
|
||||
}
|
||||
|
@@ -17,7 +17,8 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s", branchName)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s?token=%s", branchName, token)
|
||||
resp := session.MakeRequest(t, req, NoExpectedStatus)
|
||||
if !exists {
|
||||
assert.EqualValues(t, http.StatusNotFound, resp.Code)
|
||||
|
@@ -69,8 +69,9 @@ func TestAPICreateComment(t *testing.T) {
|
||||
repoOwner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments",
|
||||
repoOwner.Name, repo.Name, issue.Index)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments?token=%s",
|
||||
repoOwner.Name, repo.Name, issue.Index, token)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
"body": commentBody,
|
||||
})
|
||||
@@ -93,8 +94,9 @@ func TestAPIEditComment(t *testing.T) {
|
||||
repoOwner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d",
|
||||
repoOwner.Name, repo.Name, comment.ID)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, token)
|
||||
req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
|
||||
"body": newCommentBody,
|
||||
})
|
||||
@@ -117,8 +119,9 @@ func TestAPIDeleteComment(t *testing.T) {
|
||||
repoOwner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d",
|
||||
repoOwner.Name, repo.Name, comment.ID)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
|
||||
repoOwner.Name, repo.Name, comment.ID, token)
|
||||
session.MakeRequest(t, req, http.StatusNoContent)
|
||||
|
||||
models.AssertNotExistsBean(t, &models.Comment{ID: comment.ID})
|
||||
|
@@ -20,16 +20,18 @@ type makeRequestFunc func(testing.TB, *http.Request, int) *httptest.ResponseReco
|
||||
func TestGPGKeys(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
makeRequest makeRequestFunc
|
||||
token string
|
||||
results []int
|
||||
}{
|
||||
{name: "NoLogin", makeRequest: MakeRequest,
|
||||
{name: "NoLogin", makeRequest: MakeRequest, token: "",
|
||||
results: []int{http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized},
|
||||
},
|
||||
{name: "LoggedAsUser2", makeRequest: session.MakeRequest,
|
||||
{name: "LoggedAsUser2", makeRequest: session.MakeRequest, token: token,
|
||||
results: []int{http.StatusOK, http.StatusOK, http.StatusNotFound, http.StatusNoContent, http.StatusInternalServerError, http.StatusInternalServerError, http.StatusCreated, http.StatusCreated}},
|
||||
}
|
||||
|
||||
@@ -38,29 +40,29 @@ func TestGPGKeys(t *testing.T) {
|
||||
//Basic test on result code
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Run("ViewOwnGPGKeys", func(t *testing.T) {
|
||||
testViewOwnGPGKeys(t, tc.makeRequest, tc.results[0])
|
||||
testViewOwnGPGKeys(t, tc.makeRequest, tc.token, tc.results[0])
|
||||
})
|
||||
t.Run("ViewGPGKeys", func(t *testing.T) {
|
||||
testViewGPGKeys(t, tc.makeRequest, tc.results[1])
|
||||
testViewGPGKeys(t, tc.makeRequest, tc.token, tc.results[1])
|
||||
})
|
||||
t.Run("GetGPGKey", func(t *testing.T) {
|
||||
testGetGPGKey(t, tc.makeRequest, tc.results[2])
|
||||
testGetGPGKey(t, tc.makeRequest, tc.token, tc.results[2])
|
||||
})
|
||||
t.Run("DeleteGPGKey", func(t *testing.T) {
|
||||
testDeleteGPGKey(t, tc.makeRequest, tc.results[3])
|
||||
testDeleteGPGKey(t, tc.makeRequest, tc.token, tc.results[3])
|
||||
})
|
||||
|
||||
t.Run("CreateInvalidGPGKey", func(t *testing.T) {
|
||||
testCreateInvalidGPGKey(t, tc.makeRequest, tc.results[4])
|
||||
testCreateInvalidGPGKey(t, tc.makeRequest, tc.token, tc.results[4])
|
||||
})
|
||||
t.Run("CreateNoneRegistredEmailGPGKey", func(t *testing.T) {
|
||||
testCreateNoneRegistredEmailGPGKey(t, tc.makeRequest, tc.results[5])
|
||||
testCreateNoneRegistredEmailGPGKey(t, tc.makeRequest, tc.token, tc.results[5])
|
||||
})
|
||||
t.Run("CreateValidGPGKey", func(t *testing.T) {
|
||||
testCreateValidGPGKey(t, tc.makeRequest, tc.results[6])
|
||||
testCreateValidGPGKey(t, tc.makeRequest, tc.token, tc.results[6])
|
||||
})
|
||||
t.Run("CreateValidSecondaryEmailGPGKey", func(t *testing.T) {
|
||||
testCreateValidSecondaryEmailGPGKey(t, tc.makeRequest, tc.results[7])
|
||||
testCreateValidSecondaryEmailGPGKey(t, tc.makeRequest, tc.token, tc.results[7])
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -70,7 +72,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
|
||||
var keys []*api.GPGKey
|
||||
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys") //GET all keys
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys?token="+token) //GET all keys
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &keys)
|
||||
|
||||
@@ -91,7 +93,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
assert.EqualValues(t, false, primaryKey2.Emails[0].Verified)
|
||||
|
||||
var key api.GPGKey
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(primaryKey1.ID, 10)) //Primary key 1
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(primaryKey1.ID, 10)+"?token="+token) //Primary key 1
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &key)
|
||||
assert.EqualValues(t, "38EA3BCED732982C", key.KeyID)
|
||||
@@ -99,13 +101,13 @@ func TestGPGKeys(t *testing.T) {
|
||||
assert.EqualValues(t, "user2@example.com", key.Emails[0].Email)
|
||||
assert.EqualValues(t, true, key.Emails[0].Verified)
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(subKey.ID, 10)) //Subkey of 38EA3BCED732982C
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(subKey.ID, 10)+"?token="+token) //Subkey of 38EA3BCED732982C
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &key)
|
||||
assert.EqualValues(t, "70D7C694D17D03AD", key.KeyID)
|
||||
assert.EqualValues(t, 0, len(key.Emails))
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(primaryKey2.ID, 10)) //Primary key 2
|
||||
req = NewRequest(t, "GET", "/api/v1/user/gpg_keys/"+strconv.FormatInt(primaryKey2.ID, 10)+"?token="+token) //Primary key 2
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &key)
|
||||
assert.EqualValues(t, "FABF39739FE1E927", key.KeyID)
|
||||
@@ -119,7 +121,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
t.Run("CheckCommits", func(t *testing.T) {
|
||||
t.Run("NotSigned", func(t *testing.T) {
|
||||
var branch api.Branch
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo16/branches/not-signed")
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo16/branches/not-signed?token="+token)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &branch)
|
||||
assert.EqualValues(t, false, branch.Commit.Verification.Verified)
|
||||
@@ -127,7 +129,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
|
||||
t.Run("SignedWithNotValidatedEmail", func(t *testing.T) {
|
||||
var branch api.Branch
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo16/branches/good-sign-not-yet-validated")
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo16/branches/good-sign-not-yet-validated?token="+token)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &branch)
|
||||
assert.EqualValues(t, false, branch.Commit.Verification.Verified)
|
||||
@@ -135,7 +137,7 @@ func TestGPGKeys(t *testing.T) {
|
||||
|
||||
t.Run("SignedWithValidEmail", func(t *testing.T) {
|
||||
var branch api.Branch
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo16/branches/good-sign")
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo16/branches/good-sign?token="+token)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &branch)
|
||||
assert.EqualValues(t, true, branch.Commit.Verification.Verified)
|
||||
@@ -143,39 +145,39 @@ func TestGPGKeys(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func testViewOwnGPGKeys(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys")
|
||||
func testViewOwnGPGKeys(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys?token="+token)
|
||||
makeRequest(t, req, expected)
|
||||
}
|
||||
|
||||
func testViewGPGKeys(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
req := NewRequest(t, "GET", "/api/v1/users/user2/gpg_keys")
|
||||
func testViewGPGKeys(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
req := NewRequest(t, "GET", "/api/v1/users/user2/gpg_keys?token="+token)
|
||||
makeRequest(t, req, expected)
|
||||
}
|
||||
|
||||
func testGetGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys/1")
|
||||
func testGetGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
req := NewRequest(t, "GET", "/api/v1/user/gpg_keys/1?token="+token)
|
||||
makeRequest(t, req, expected)
|
||||
}
|
||||
|
||||
func testDeleteGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
req := NewRequest(t, "DELETE", "/api/v1/user/gpg_keys/1")
|
||||
func testDeleteGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
req := NewRequest(t, "DELETE", "/api/v1/user/gpg_keys/1?token="+token)
|
||||
makeRequest(t, req, expected)
|
||||
}
|
||||
|
||||
func testCreateGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int, publicKey string) {
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/gpg_keys", api.CreateGPGKeyOption{
|
||||
func testCreateGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int, publicKey string) {
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/gpg_keys?token="+token, api.CreateGPGKeyOption{
|
||||
ArmoredKey: publicKey,
|
||||
})
|
||||
makeRequest(t, req, expected)
|
||||
}
|
||||
|
||||
func testCreateInvalidGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
testCreateGPGKey(t, makeRequest, expected, "invalid_key")
|
||||
func testCreateInvalidGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
testCreateGPGKey(t, makeRequest, token, expected, "invalid_key")
|
||||
}
|
||||
|
||||
func testCreateNoneRegistredEmailGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
testCreateGPGKey(t, makeRequest, expected, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
func testCreateNoneRegistredEmailGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
testCreateGPGKey(t, makeRequest, token, expected, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFmGUygBCACjCNbKvMGgp0fd5vyFW9olE1CLCSyyF9gQN2hSuzmZLuAZF2Kh
|
||||
dCMCG2T1UwzUB/yWUFWJ2BtCwSjuaRv+cGohqEy6bhEBV90peGA33lHfjx7wP25O
|
||||
@@ -194,9 +196,9 @@ INx/MmBfmtCq05FqNclvU+sj2R3N1JJOtBOjZrJHQbJhzoILou8AkxeX1A+q9OAz
|
||||
-----END PGP PUBLIC KEY BLOCK-----`)
|
||||
}
|
||||
|
||||
func testCreateValidGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
func testCreateValidGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
//User2 <user2@example.com> //primary & activated
|
||||
testCreateGPGKey(t, makeRequest, expected, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
testCreateGPGKey(t, makeRequest, token, expected, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFmGVsMBCACuxgZ7W7rI9xN08Y4M7B8yx/6/I4Slm94+wXf8YNRvAyqj30dW
|
||||
VJhyBcnfNRDLKSQp5o/hhfDkCgdqBjLa1PnHlGS3PXJc0hP/FyYPD2BFvNMPpCYS
|
||||
@@ -228,9 +230,9 @@ uy6MA3VSB99SK9ducGmE1Jv8mcziREroz2TEGr0zPs6h
|
||||
-----END PGP PUBLIC KEY BLOCK-----`)
|
||||
}
|
||||
|
||||
func testCreateValidSecondaryEmailGPGKey(t *testing.T, makeRequest makeRequestFunc, expected int) {
|
||||
func testCreateValidSecondaryEmailGPGKey(t *testing.T, makeRequest makeRequestFunc, token string, expected int) {
|
||||
//User2 <user21@example.com> //secondary and not activated
|
||||
testCreateGPGKey(t, makeRequest, expected, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
testCreateGPGKey(t, makeRequest, token, expected, `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFmGWN4BCAC18V4tVGO65VLCV7p14FuXJlUtZ5CuYMvgEkcOqrvRaBSW9ao4
|
||||
PGESOhJpfWpnW3QgJniYndLzPpsmdHEclEER6aZjiNgReWPOjHD5tykWocZAJqXD
|
||||
|
152
integrations/api_helper_for_declarative_test.go
Normal file
152
integrations/api_helper_for_declarative_test.go
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type APITestContext struct {
|
||||
Reponame string
|
||||
Session *TestSession
|
||||
Token string
|
||||
Username string
|
||||
ExpectedCode int
|
||||
}
|
||||
|
||||
func NewAPITestContext(t *testing.T, username, reponame string) APITestContext {
|
||||
session := loginUser(t, username)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
return APITestContext{
|
||||
Session: session,
|
||||
Token: token,
|
||||
Username: username,
|
||||
Reponame: reponame,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx APITestContext) GitPath() string {
|
||||
return fmt.Sprintf("%s/%s.git", ctx.Username, ctx.Reponame)
|
||||
}
|
||||
|
||||
func doAPICreateRepository(ctx APITestContext, empty bool, callback ...func(*testing.T, api.Repository)) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
createRepoOption := &api.CreateRepoOption{
|
||||
AutoInit: !empty,
|
||||
Description: "Temporary repo",
|
||||
Name: ctx.Reponame,
|
||||
Private: true,
|
||||
Gitignores: "",
|
||||
License: "WTFPL",
|
||||
Readme: "Default",
|
||||
}
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos?token="+ctx.Token, createRepoOption)
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
return
|
||||
}
|
||||
resp := ctx.Session.MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
var repository api.Repository
|
||||
DecodeJSON(t, resp, &repository)
|
||||
if len(callback) > 0 {
|
||||
callback[0](t, repository)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func doAPIGetRepository(ctx APITestContext, callback ...func(*testing.T, api.Repository)) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", ctx.Username, ctx.Reponame, ctx.Token)
|
||||
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
return
|
||||
}
|
||||
resp := ctx.Session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var repository api.Repository
|
||||
DecodeJSON(t, resp, &repository)
|
||||
if len(callback) > 0 {
|
||||
callback[0](t, repository)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func doAPIDeleteRepository(ctx APITestContext) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", ctx.Username, ctx.Reponame, ctx.Token)
|
||||
|
||||
req := NewRequest(t, "DELETE", urlStr)
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
return
|
||||
}
|
||||
ctx.Session.MakeRequest(t, req, http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
func doAPICreateUserKey(ctx APITestContext, keyname, keyFile string, callback ...func(*testing.T, api.PublicKey)) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
urlStr := fmt.Sprintf("/api/v1/user/keys?token=%s", ctx.Token)
|
||||
|
||||
dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
|
||||
assert.NoError(t, err)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateKeyOption{
|
||||
Title: keyname,
|
||||
Key: string(dataPubKey),
|
||||
})
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
return
|
||||
}
|
||||
resp := ctx.Session.MakeRequest(t, req, http.StatusCreated)
|
||||
var publicKey api.PublicKey
|
||||
DecodeJSON(t, resp, &publicKey)
|
||||
if len(callback) > 0 {
|
||||
callback[0](t, publicKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func doAPIDeleteUserKey(ctx APITestContext, keyID int64) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
urlStr := fmt.Sprintf("/api/v1/user/keys/%d?token=%s", keyID, ctx.Token)
|
||||
|
||||
req := NewRequest(t, "DELETE", urlStr)
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
return
|
||||
}
|
||||
ctx.Session.MakeRequest(t, req, http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
func doAPICreateDeployKey(ctx APITestContext, keyname, keyFile string, readOnly bool) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", ctx.Username, ctx.Reponame, ctx.Token)
|
||||
|
||||
dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
|
||||
assert.NoError(t, err)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, api.CreateKeyOption{
|
||||
Title: keyname,
|
||||
Key: string(dataPubKey),
|
||||
ReadOnly: readOnly,
|
||||
})
|
||||
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
return
|
||||
}
|
||||
ctx.Session.MakeRequest(t, req, http.StatusCreated)
|
||||
}
|
||||
}
|
@@ -23,12 +23,13 @@ func TestAPIAddIssueLabels(t *testing.T) {
|
||||
label := models.AssertExistsAndLoadBean(t, &models.Label{RepoID: repo.ID}).(*models.Label)
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels",
|
||||
owner.Name, repo.Name, issue.Index)
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
||||
owner.Name, repo.Name, issue.Index, token)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{
|
||||
Labels: []int64{label.ID},
|
||||
})
|
||||
session := loginUser(t, owner.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiLabels []*api.Label
|
||||
DecodeJSON(t, resp, &apiLabels)
|
||||
@@ -45,12 +46,13 @@ func TestAPIReplaceIssueLabels(t *testing.T) {
|
||||
label := models.AssertExistsAndLoadBean(t, &models.Label{RepoID: repo.ID}).(*models.Label)
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels",
|
||||
owner.Name, repo.Name, issue.Index)
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels?token=%s",
|
||||
owner.Name, repo.Name, issue.Index, token)
|
||||
req := NewRequestWithJSON(t, "PUT", urlStr, &api.IssueLabelsOption{
|
||||
Labels: []int64{label.ID},
|
||||
})
|
||||
session := loginUser(t, owner.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiLabels []*api.Label
|
||||
DecodeJSON(t, resp, &apiLabels)
|
||||
|
@@ -5,13 +5,13 @@
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -22,8 +22,9 @@ func TestAPIListIssues(t *testing.T) {
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues?state=all",
|
||||
owner.Name, repo.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues?state=all&token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiIssues []*api.Issue
|
||||
DecodeJSON(t, resp, &apiIssues)
|
||||
@@ -41,8 +42,8 @@ func TestAPICreateIssue(t *testing.T) {
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all", owner.Name, repo.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repo.Name, token)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
|
||||
Body: body,
|
||||
Title: title,
|
||||
|
@@ -7,8 +7,11 @@ package integrations
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
)
|
||||
@@ -46,8 +49,8 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
|
||||
repoOwner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys", repoOwner.Name, repo.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
||||
rawKeyBody := api.CreateKeyOption{
|
||||
Title: "read-only",
|
||||
Key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n",
|
||||
@@ -72,8 +75,8 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||
repoOwner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys", repoOwner.Name, repo.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", repoOwner.Name, repo.Name, token)
|
||||
rawKeyBody := api.CreateKeyOption{
|
||||
Title: "read-write",
|
||||
Key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsufOCrDDlT8DLkodnnJtbq7uGflcPae7euTfM+Laq4So+v4WeSV362Rg0O/+Sje1UthrhN6lQkfRkdWIlCRQEXg+LMqr6RhvDfZquE2Xwqv/itlz7LjbdAUdYoO1iH7rMSmYvQh4WEnC/DAacKGbhdGIM/ZBz0z6tHm7bPgbI9ykEKekTmPwQFP1Qebvf5NYOFMWqQ2sCEAI9dBMVLoojsIpV+KADf+BotiIi8yNfTG2rzmzpxBpW9fYjd1Sy1yd4NSUpoPbEJJYJ1TrjiSWlYOVq9Ar8xW1O87i6gBjL/3zN7ANeoYhaAXupdOS6YL22YOK/yC0tJtXwwdh/eSrh",
|
||||
@@ -90,3 +93,102 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||
Mode: models.AccessModeWrite,
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateUserKey(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{Name: "user1"}).(*models.User)
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
token := url.QueryEscape(getTokenForLoggedInUser(t, session))
|
||||
keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
|
||||
keyType := "ssh-rsa"
|
||||
keyContent := "AAAAB3NzaC1yc2EAAAADAQABAAABAQCyTiPTeHJl6Gs5D1FyHT0qTWpVkAy9+LIKjctQXklrePTvUNVrSpt4r2exFYXNMPeA8V0zCrc3Kzs1SZw3jWkG3i53te9onCp85DqyatxOD2pyZ30/gPn1ZUg40WowlFM8gsUFMZqaH7ax6d8nsBKW7N/cRyqesiOQEV9up3tnKjIB8XMTVvC5X4rBWgywz7AFxSv8mmaTHnUgVW4LgMPwnTWo0pxtiIWbeMLyrEE4hIM74gSwp6CRQYo6xnG3fn4yWkcK2X2mT9adQ241IDdwpENJHcry/T6AJ8dNXduEZ67egnk+rVlQ2HM4LpymAv9DAAFFeaQK0hT+3aMDoumV"
|
||||
rawKeyBody := api.CreateKeyOption{
|
||||
Title: "test-key",
|
||||
Key: keyType + " " + keyContent,
|
||||
}
|
||||
req := NewRequestWithJSON(t, "POST", keysURL, rawKeyBody)
|
||||
resp := session.MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
var newPublicKey api.PublicKey
|
||||
DecodeJSON(t, resp, &newPublicKey)
|
||||
models.AssertExistsAndLoadBean(t, &models.PublicKey{
|
||||
ID: newPublicKey.ID,
|
||||
OwnerID: user.ID,
|
||||
Name: rawKeyBody.Title,
|
||||
Content: rawKeyBody.Key,
|
||||
Mode: models.AccessModeWrite,
|
||||
})
|
||||
|
||||
// Search by fingerprint
|
||||
fingerprintURL := fmt.Sprintf("/api/v1/user/keys?token=%s&fingerprint=%s", token, newPublicKey.Fingerprint)
|
||||
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var fingerprintPublicKeys []api.PublicKey
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Equal(t, newPublicKey.Fingerprint, fingerprintPublicKeys[0].Fingerprint)
|
||||
assert.Equal(t, newPublicKey.ID, fingerprintPublicKeys[0].ID)
|
||||
assert.Equal(t, user.ID, fingerprintPublicKeys[0].Owner.ID)
|
||||
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/users/%s/keys?token=%s&fingerprint=%s", user.Name, token, newPublicKey.Fingerprint)
|
||||
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Equal(t, newPublicKey.Fingerprint, fingerprintPublicKeys[0].Fingerprint)
|
||||
assert.Equal(t, newPublicKey.ID, fingerprintPublicKeys[0].ID)
|
||||
assert.Equal(t, user.ID, fingerprintPublicKeys[0].Owner.ID)
|
||||
|
||||
// Fail search by fingerprint
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/user/keys?token=%s&fingerprint=%sA", token, newPublicKey.Fingerprint)
|
||||
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Len(t, fingerprintPublicKeys, 0)
|
||||
|
||||
// Fail searching for wrong users key
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/users/%s/keys?token=%s&fingerprint=%s", "user2", token, newPublicKey.Fingerprint)
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Len(t, fingerprintPublicKeys, 0)
|
||||
|
||||
// Now login as user 2
|
||||
session2 := loginUser(t, "user2")
|
||||
token2 := url.QueryEscape(getTokenForLoggedInUser(t, session2))
|
||||
|
||||
// Should find key even though not ours, but we shouldn't know whose it is
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/user/keys?token=%s&fingerprint=%s", token2, newPublicKey.Fingerprint)
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Equal(t, newPublicKey.Fingerprint, fingerprintPublicKeys[0].Fingerprint)
|
||||
assert.Equal(t, newPublicKey.ID, fingerprintPublicKeys[0].ID)
|
||||
assert.Nil(t, fingerprintPublicKeys[0].Owner)
|
||||
|
||||
// Should find key even though not ours, but we shouldn't know whose it is
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/users/%s/keys?token=%s&fingerprint=%s", user.Name, token2, newPublicKey.Fingerprint)
|
||||
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Equal(t, newPublicKey.Fingerprint, fingerprintPublicKeys[0].Fingerprint)
|
||||
assert.Equal(t, newPublicKey.ID, fingerprintPublicKeys[0].ID)
|
||||
assert.Nil(t, fingerprintPublicKeys[0].Owner)
|
||||
|
||||
// Fail when searching for key if it is not ours
|
||||
fingerprintURL = fmt.Sprintf("/api/v1/users/%s/keys?token=%s&fingerprint=%s", "user2", token2, newPublicKey.Fingerprint)
|
||||
req = NewRequest(t, "GET", fingerprintURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &fingerprintPublicKeys)
|
||||
assert.Len(t, fingerprintPublicKeys, 0)
|
||||
}
|
||||
|
48
integrations/api_org_test.go
Normal file
48
integrations/api_org_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAPIOrg(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
var org = api.CreateOrgOption{
|
||||
UserName: "user1_org",
|
||||
FullName: "User1's organization",
|
||||
Description: "This organization created by user1",
|
||||
Website: "https://try.gitea.io",
|
||||
Location: "Shanghai",
|
||||
}
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs?token="+token, &org)
|
||||
resp := session.MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
var apiOrg api.Organization
|
||||
DecodeJSON(t, resp, &apiOrg)
|
||||
|
||||
assert.Equal(t, org.UserName, apiOrg.UserName)
|
||||
assert.Equal(t, org.FullName, apiOrg.FullName)
|
||||
assert.Equal(t, org.Description, apiOrg.Description)
|
||||
assert.Equal(t, org.Website, apiOrg.Website)
|
||||
assert.Equal(t, org.Location, apiOrg.Location)
|
||||
|
||||
models.AssertExistsAndLoadBean(t, &models.User{
|
||||
Name: org.UserName,
|
||||
LowerName: strings.ToLower(org.UserName),
|
||||
FullName: org.FullName,
|
||||
})
|
||||
}
|
@@ -5,10 +5,13 @@
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -20,7 +23,8 @@ func TestAPIViewPulls(t *testing.T) {
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/pulls?state=all", owner.Name, repo.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/pulls?state=all&token="+token, owner.Name, repo.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var pulls []*api.PullRequest
|
||||
@@ -28,3 +32,27 @@ func TestAPIViewPulls(t *testing.T) {
|
||||
expectedLen := models.GetCount(t, &models.Issue{RepoID: repo.ID}, models.Cond("is_pull = ?", true))
|
||||
assert.Len(t, pulls, expectedLen)
|
||||
}
|
||||
|
||||
// TestAPIMergePullWIP ensures that we can't merge a WIP pull request
|
||||
func TestAPIMergePullWIP(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{Status: models.PullRequestStatusMergeable}, models.Cond("has_merged = ?", false)).(*models.PullRequest)
|
||||
pr.LoadIssue()
|
||||
pr.Issue.ChangeTitle(owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title)
|
||||
|
||||
// force reload
|
||||
pr.LoadAttributes()
|
||||
|
||||
assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0])
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge?token=%s", owner.Name, repo.Name, pr.Index, token), &auth.MergePullRequestForm{
|
||||
MergeMessageField: pr.Issue.Title,
|
||||
Do: string(models.MergeStyleMerge),
|
||||
})
|
||||
|
||||
session.MakeRequest(t, req, http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ func TestAPICreateRelease(t *testing.T) {
|
||||
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
session := loginUser(t, owner.LowerName)
|
||||
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -32,8 +32,8 @@ func TestAPICreateRelease(t *testing.T) {
|
||||
commitID, err := gitRepo.GetTagCommitID("v0.0.1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases",
|
||||
owner.Name, repo.Name)
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases?token=%s",
|
||||
owner.Name, repo.Name, token)
|
||||
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateReleaseOption{
|
||||
TagName: "v0.0.1",
|
||||
Title: "v0.0.1",
|
||||
@@ -53,8 +53,8 @@ func TestAPICreateRelease(t *testing.T) {
|
||||
Note: newRelease.Note,
|
||||
})
|
||||
|
||||
urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d",
|
||||
owner.Name, repo.Name, newRelease.ID)
|
||||
urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d?token=%s",
|
||||
owner.Name, repo.Name, newRelease.ID, token)
|
||||
req = NewRequest(t, "GET", urlStr)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
|
34
integrations/api_repo_git_ref_test.go
Normal file
34
integrations/api_repo_git_ref_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
)
|
||||
|
||||
func TestAPIReposGitRefs(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
for _, ref := range [...]string{
|
||||
"refs/heads/master", // Branch
|
||||
"refs/tags/v1.1", // Tag
|
||||
} {
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/%s?token="+token, user.Name, ref)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
// Test getting all refs
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/refs?token="+token, user.Name)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
// Test getting non-existent refs
|
||||
req = NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/git/refs/heads/unknown?token="+token, user.Name)
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
@@ -16,16 +16,17 @@ func TestAPIReposRaw(t *testing.T) {
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
for _, ref := range [...]string{
|
||||
"master", // Branch
|
||||
"v1.1", // Tag
|
||||
"65f1bf27bc3bf70f64657658635e66094edbcb4d", // Commit
|
||||
} {
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/%s/README.md", user.Name, ref)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/%s/README.md?token="+token, user.Name, ref)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
// Test default branch
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/README.md", user.Name)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/README.md?token="+token, user.Name)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
@@ -67,16 +67,16 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
expectedResults
|
||||
}{
|
||||
{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
|
||||
nil: {count: 16},
|
||||
user: {count: 16},
|
||||
user2: {count: 16}},
|
||||
nil: {count: 19},
|
||||
user: {count: 19},
|
||||
user2: {count: 19}},
|
||||
},
|
||||
{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
|
||||
nil: {count: 10},
|
||||
user: {count: 10},
|
||||
user2: {count: 10}},
|
||||
},
|
||||
{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search", expectedResults: expectedResults{
|
||||
{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search?default", expectedResults: expectedResults{
|
||||
nil: {count: 10},
|
||||
user: {count: 10},
|
||||
user2: {count: 10}},
|
||||
@@ -143,9 +143,11 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
var session *TestSession
|
||||
var testName string
|
||||
var userID int64
|
||||
var token string
|
||||
if userToLogin != nil && userToLogin.ID > 0 {
|
||||
testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||
session = loginUser(t, userToLogin.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
userID = userToLogin.ID
|
||||
} else {
|
||||
testName = "AnonymousUser"
|
||||
@@ -153,7 +155,7 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
request := NewRequest(t, "GET", testCase.requestURL)
|
||||
request := NewRequest(t, "GET", testCase.requestURL+"&token="+token)
|
||||
response := session.MakeRequest(t, request, http.StatusOK)
|
||||
|
||||
var body api.SearchResults
|
||||
@@ -162,7 +164,7 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
assert.Len(t, body.Data, expected.count)
|
||||
for _, repo := range body.Data {
|
||||
r := getRepo(t, repo.ID)
|
||||
hasAccess, err := models.HasAccess(userID, r, models.AccessModeRead)
|
||||
hasAccess, err := models.HasAccess(userID, r)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, hasAccess)
|
||||
|
||||
@@ -210,28 +212,104 @@ func TestAPIViewRepo(t *testing.T) {
|
||||
func TestAPIOrgRepos(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
|
||||
user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User)
|
||||
// User3 is an Org. Check their repos.
|
||||
sourceOrg := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", sourceOrg.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
expectedResults := map[*models.User]struct {
|
||||
count int
|
||||
includesPrivate bool
|
||||
}{
|
||||
nil: {count: 1},
|
||||
user: {count: 2, includesPrivate: true},
|
||||
user2: {count: 3, includesPrivate: true},
|
||||
user3: {count: 1},
|
||||
}
|
||||
|
||||
var apiRepos []*api.Repository
|
||||
DecodeJSON(t, resp, &apiRepos)
|
||||
expectedLen := models.GetCount(t, models.Repository{OwnerID: sourceOrg.ID},
|
||||
models.Cond("is_private = ?", false))
|
||||
assert.Len(t, apiRepos, expectedLen)
|
||||
for _, repo := range apiRepos {
|
||||
assert.False(t, repo.Private)
|
||||
for userToLogin, expected := range expectedResults {
|
||||
var session *TestSession
|
||||
var testName string
|
||||
var token string
|
||||
if userToLogin != nil && userToLogin.ID > 0 {
|
||||
testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||
session = loginUser(t, userToLogin.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
} else {
|
||||
testName = "AnonymousUser"
|
||||
session = emptyTestSession(t)
|
||||
}
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiRepos []*api.Repository
|
||||
DecodeJSON(t, resp, &apiRepos)
|
||||
assert.Len(t, apiRepos, expected.count)
|
||||
for _, repo := range apiRepos {
|
||||
if !expected.includesPrivate {
|
||||
assert.False(t, repo.Private)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)
|
||||
sess := loginUser(t, user.Name)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repositories/2")
|
||||
sess.MakeRequest(t, req, http.StatusNotFound)
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repositories/2?token="+token)
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func TestAPIRepoMigrate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ctxUserID, userID int64
|
||||
cloneURL, repoName string
|
||||
expectedStatus int
|
||||
}{
|
||||
{ctxUserID: 1, userID: 2, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-admin", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, userID: 2, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-own", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, userID: 1, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-bad", expectedStatus: http.StatusForbidden},
|
||||
{ctxUserID: 2, userID: 3, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-org", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, userID: 6, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-bad-org", expectedStatus: http.StatusForbidden},
|
||||
}
|
||||
|
||||
prepareTestEnv(t)
|
||||
for _, testCase := range testCases {
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: testCase.ctxUserID}).(*models.User)
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOption{
|
||||
CloneAddr: testCase.cloneURL,
|
||||
UID: int(testCase.userID),
|
||||
RepoName: testCase.repoName,
|
||||
})
|
||||
session.MakeRequest(t, req, testCase.expectedStatus)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIOrgRepoCreate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ctxUserID int64
|
||||
orgName, repoName string
|
||||
expectedStatus int
|
||||
}{
|
||||
{ctxUserID: 1, orgName: "user3", repoName: "repo-admin", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, orgName: "user3", repoName: "repo-own", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, orgName: "user6", repoName: "repo-bad-org", expectedStatus: http.StatusForbidden},
|
||||
}
|
||||
|
||||
prepareTestEnv(t)
|
||||
for _, testCase := range testCases {
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: testCase.ctxUserID}).(*models.User)
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos?token="+token, testCase.orgName), &api.CreateRepoOption{
|
||||
Name: testCase.repoName,
|
||||
})
|
||||
session.MakeRequest(t, req, testCase.expectedStatus)
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,8 @@ func TestAPITeam(t *testing.T) {
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser.UID}).(*models.User)
|
||||
|
||||
session := loginUser(t, user.Name)
|
||||
req := NewRequestf(t, "GET", "/api/v1/teams/%d", teamUser.TeamID)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiTeam api.Team
|
||||
|
50
integrations/api_token_test.go
Normal file
50
integrations/api_token_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
// TestAPICreateAndDeleteToken tests that token that was just created can be deleted
|
||||
func TestAPICreateAndDeleteToken(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
|
||||
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", map[string]string{
|
||||
"name": "test-key-1",
|
||||
})
|
||||
req = AddBasicAuthHeader(req, user.Name)
|
||||
resp := MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
var newAccessToken api.AccessToken
|
||||
DecodeJSON(t, resp, &newAccessToken)
|
||||
models.AssertExistsAndLoadBean(t, &models.AccessToken{
|
||||
ID: newAccessToken.ID,
|
||||
Name: newAccessToken.Name,
|
||||
Sha1: newAccessToken.Sha1,
|
||||
UID: user.ID,
|
||||
})
|
||||
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", newAccessToken.ID)
|
||||
req = AddBasicAuthHeader(req, user.Name)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
||||
models.AssertNotExistsBean(t, &models.AccessToken{ID: newAccessToken.ID})
|
||||
}
|
||||
|
||||
// TestAPIDeleteMissingToken ensures that error is thrown when token not found
|
||||
func TestAPIDeleteMissingToken(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
|
||||
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", models.NonexistentID)
|
||||
req = AddBasicAuthHeader(req, user.Name)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
30
integrations/api_user_heatmap_test.go
Normal file
30
integrations/api_user_heatmap_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.package models
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserHeatmap(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, adminUsername)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/users/%s/heatmap", normalUsername)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var heatmap []*models.UserHeatmapData
|
||||
DecodeJSON(t, resp, &heatmap)
|
||||
var dummyheatmap []*models.UserHeatmapData
|
||||
dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1540080000, Contributions: 1})
|
||||
|
||||
assert.Equal(t, dummyheatmap, heatmap)
|
||||
}
|
63
integrations/api_user_orgs_test.go
Normal file
63
integrations/api_user_orgs_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.package models
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUserOrgs(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
adminUsername := "user1"
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, adminUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/users/%s/orgs?token=%s", normalUsername, token)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var orgs []*api.Organization
|
||||
DecodeJSON(t, resp, &orgs)
|
||||
|
||||
assert.Equal(t, []*api.Organization{
|
||||
{
|
||||
ID: 3,
|
||||
UserName: "user3",
|
||||
FullName: "User Three",
|
||||
AvatarURL: "https://secure.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?d=identicon",
|
||||
Description: "",
|
||||
Website: "",
|
||||
Location: "",
|
||||
},
|
||||
}, orgs)
|
||||
}
|
||||
|
||||
func TestMyOrgs(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
normalUsername := "user2"
|
||||
session := loginUser(t, normalUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequest(t, "GET", "/api/v1/user/orgs?token="+token)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var orgs []*api.Organization
|
||||
DecodeJSON(t, resp, &orgs)
|
||||
|
||||
assert.Equal(t, []*api.Organization{
|
||||
{
|
||||
ID: 3,
|
||||
UserName: "user3",
|
||||
FullName: "User Three",
|
||||
AvatarURL: "https://secure.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?d=identicon",
|
||||
Description: "",
|
||||
Website: "",
|
||||
Location: "",
|
||||
},
|
||||
}, orgs)
|
||||
}
|
@@ -43,6 +43,7 @@ var gitLDAPUsers = []ldapUser{
|
||||
SSHKeys: []string{
|
||||
"SHA256:qLY06smKfHoW/92yXySpnxFR10QFrLdRjf/GNPvwcW8",
|
||||
"SHA256:QlVTuM5OssDatqidn2ffY+Lc4YA5Fs78U+0KOHI51jQ",
|
||||
"SHA256:DXdeUKYOJCSSmClZuwrb60hUq7367j4fA+udNC3FdRI",
|
||||
},
|
||||
IsAdmin: true,
|
||||
},
|
||||
|
@@ -102,7 +102,7 @@ func BenchmarkRepoBranchCommit(b *testing.B) {
|
||||
branchCount := len(branches)
|
||||
b.ResetTimer() //We measure from here
|
||||
for i := 0; i < b.N; i++ {
|
||||
req := NewRequestf(b, "GET", "/%s/%s/commits/%s", owner.Name, repo.Name, branches[i%branchCount])
|
||||
req := NewRequestf(b, "GET", "/%s/%s/commits/%s", owner.Name, repo.Name, branches[i%branchCount].Name)
|
||||
session.MakeRequest(b, req, http.StatusOK)
|
||||
}
|
||||
})
|
||||
|
24
integrations/download_test.go
Normal file
24
integrations/download_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDownloadByID(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
// Request raw blob
|
||||
req := NewRequest(t, "GET", "/user2/repo1/raw/blob/4b4851ad51df6a7d9f25c979345979eaeb5b349f")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Equal(t, "# repo1\n\nDescription for repo1", resp.Body.String())
|
||||
}
|
127
integrations/git_helper_for_declarative_test.go
Normal file
127
integrations/git_helper_for_declarative_test.go
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func withKeyFile(t *testing.T, keyname string, callback func(string)) {
|
||||
keyFile := filepath.Join(setting.AppDataPath, keyname)
|
||||
err := exec.Command("ssh-keygen", "-f", keyFile, "-t", "rsa", "-N", "").Run()
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Setup ssh wrapper
|
||||
os.Setenv("GIT_SSH_COMMAND",
|
||||
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "+
|
||||
filepath.Join(setting.AppWorkPath, keyFile))
|
||||
os.Setenv("GIT_SSH_VARIANT", "ssh")
|
||||
|
||||
callback(keyFile)
|
||||
|
||||
defer os.RemoveAll(keyFile)
|
||||
defer os.RemoveAll(keyFile + ".pub")
|
||||
}
|
||||
|
||||
func createSSHUrl(gitPath string, u *url.URL) *url.URL {
|
||||
u2 := *u
|
||||
u2.Scheme = "ssh"
|
||||
u2.User = url.User("git")
|
||||
u2.Host = fmt.Sprintf("%s:%d", setting.SSH.ListenHost, setting.SSH.ListenPort)
|
||||
u2.Path = gitPath
|
||||
return &u2
|
||||
}
|
||||
|
||||
func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
|
||||
prepareTestEnv(t)
|
||||
s := http.Server{
|
||||
Handler: mac,
|
||||
}
|
||||
|
||||
u, err := url.Parse(setting.AppURL)
|
||||
assert.NoError(t, err)
|
||||
listener, err := net.Listen("tcp", u.Host)
|
||||
assert.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
s.Shutdown(ctx)
|
||||
cancel()
|
||||
}()
|
||||
|
||||
go s.Serve(listener)
|
||||
//Started by config go ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
|
||||
|
||||
callback(t, u)
|
||||
}
|
||||
|
||||
func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
assert.NoError(t, git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{}))
|
||||
assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
|
||||
}
|
||||
}
|
||||
|
||||
func doGitCloneFail(dstLocalPath string, u *url.URL) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
assert.Error(t, git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{}))
|
||||
assert.False(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
|
||||
}
|
||||
}
|
||||
|
||||
func doGitInitTestRepository(dstPath string) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
// Init repository in dstPath
|
||||
assert.NoError(t, git.InitRepository(dstPath, false))
|
||||
assert.NoError(t, ioutil.WriteFile(filepath.Join(dstPath, "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", dstPath)), 0644))
|
||||
assert.NoError(t, git.AddChanges(dstPath, true))
|
||||
signature := git.Signature{
|
||||
Email: "test@example.com",
|
||||
Name: "test",
|
||||
When: time.Now(),
|
||||
}
|
||||
assert.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &signature,
|
||||
Author: &signature,
|
||||
Message: "Initial Commit",
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
func doGitAddRemote(dstPath, remoteName string, u *url.URL) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
_, err := git.NewCommand("remote", "add", remoteName, u.String()).RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func doGitPushTestRepository(dstPath, remoteName, branch string) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
_, err := git.NewCommand("push", "-u", remoteName, branch).RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func doGitPushTestRepositoryFail(dstPath, remoteName, branch string) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
_, err := git.NewCommand("push", "-u", remoteName, branch).RunInDir(dstPath)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
}
|
@@ -5,25 +5,17 @@
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -32,157 +24,86 @@ const (
|
||||
bigSize = 128 * 1024 * 1024 //128Mo
|
||||
)
|
||||
|
||||
func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
|
||||
prepareTestEnv(t)
|
||||
s := http.Server{
|
||||
Handler: mac,
|
||||
}
|
||||
|
||||
u, err := url.Parse(setting.AppURL)
|
||||
assert.NoError(t, err)
|
||||
listener, err := net.Listen("tcp", u.Host)
|
||||
assert.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
s.Shutdown(ctx)
|
||||
cancel()
|
||||
}()
|
||||
|
||||
go s.Serve(listener)
|
||||
//Started by config go ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
|
||||
|
||||
callback(t, u)
|
||||
func TestGit(t *testing.T) {
|
||||
onGiteaRun(t, testGit)
|
||||
}
|
||||
|
||||
func TestGit(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
u.Path = "user2/repo1.git"
|
||||
func testGit(t *testing.T, u *url.URL) {
|
||||
username := "user2"
|
||||
baseAPITestContext := NewAPITestContext(t, username, "repo1")
|
||||
|
||||
t.Run("HTTP", func(t *testing.T) {
|
||||
dstPath, err := ioutil.TempDir("", "repo-tmp-17")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstPath)
|
||||
t.Run("Standard", func(t *testing.T) {
|
||||
t.Run("CloneNoLogin", func(t *testing.T) {
|
||||
dstLocalPath, err := ioutil.TempDir("", "repo1")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstLocalPath)
|
||||
err = git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
|
||||
})
|
||||
u.Path = baseAPITestContext.GitPath()
|
||||
|
||||
t.Run("CreateRepo", func(t *testing.T) {
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", &api.CreateRepoOption{
|
||||
AutoInit: true,
|
||||
Description: "Temporary repo",
|
||||
Name: "repo-tmp-17",
|
||||
Private: false,
|
||||
Gitignores: "",
|
||||
License: "WTFPL",
|
||||
Readme: "Default",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusCreated)
|
||||
})
|
||||
t.Run("HTTP", func(t *testing.T) {
|
||||
httpContext := baseAPITestContext
|
||||
httpContext.Reponame = "repo-tmp-17"
|
||||
|
||||
u.Path = "user2/repo-tmp-17.git"
|
||||
u.User = url.UserPassword("user2", userPassword)
|
||||
t.Run("Clone", func(t *testing.T) {
|
||||
err = git.Clone(u.String(), dstPath, git.CloneRepoOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md")))
|
||||
})
|
||||
dstPath, err := ioutil.TempDir("", httpContext.Reponame)
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstPath)
|
||||
t.Run("Standard", func(t *testing.T) {
|
||||
ensureAnonymousClone(t, u)
|
||||
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
t.Run("Little", func(t *testing.T) {
|
||||
commitAndPush(t, littleSize, dstPath)
|
||||
})
|
||||
t.Run("Big", func(t *testing.T) {
|
||||
commitAndPush(t, bigSize, dstPath)
|
||||
})
|
||||
})
|
||||
})
|
||||
t.Run("LFS", func(t *testing.T) {
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
//Setup git LFS
|
||||
_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("track", "data-file-*").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
err = git.AddChanges(dstPath, false, ".gitattributes")
|
||||
assert.NoError(t, err)
|
||||
t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
|
||||
|
||||
t.Run("Little", func(t *testing.T) {
|
||||
commitAndPush(t, littleSize, dstPath)
|
||||
})
|
||||
t.Run("Big", func(t *testing.T) {
|
||||
commitAndPush(t, bigSize, dstPath)
|
||||
})
|
||||
u.Path = httpContext.GitPath()
|
||||
u.User = url.UserPassword(username, userPassword)
|
||||
|
||||
t.Run("Clone", doGitClone(dstPath, u))
|
||||
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
t.Run("Little", func(t *testing.T) {
|
||||
commitAndPush(t, littleSize, dstPath)
|
||||
})
|
||||
t.Run("Locks", func(t *testing.T) {
|
||||
lockTest(t, u.String(), dstPath)
|
||||
t.Run("Big", func(t *testing.T) {
|
||||
commitAndPush(t, bigSize, dstPath)
|
||||
})
|
||||
})
|
||||
})
|
||||
t.Run("SSH", func(t *testing.T) {
|
||||
//Setup remote link
|
||||
u.Scheme = "ssh"
|
||||
u.User = url.User("git")
|
||||
u.Host = fmt.Sprintf("%s:%d", setting.SSH.ListenHost, setting.SSH.ListenPort)
|
||||
u.Path = "user2/repo-tmp-18.git"
|
||||
t.Run("LFS", func(t *testing.T) {
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
//Setup git LFS
|
||||
_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("track", "data-file-*").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
err = git.AddChanges(dstPath, false, ".gitattributes")
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Setup key
|
||||
keyFile := filepath.Join(setting.AppDataPath, "my-testing-key")
|
||||
err := exec.Command("ssh-keygen", "-f", keyFile, "-t", "rsa", "-N", "").Run()
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(keyFile)
|
||||
defer os.RemoveAll(keyFile + ".pub")
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", keyOwner.Name)
|
||||
|
||||
dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
|
||||
assert.NoError(t, err)
|
||||
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||
"key": string(dataPubKey),
|
||||
"title": "test-key",
|
||||
t.Run("Little", func(t *testing.T) {
|
||||
commitAndPush(t, littleSize, dstPath)
|
||||
})
|
||||
t.Run("Big", func(t *testing.T) {
|
||||
commitAndPush(t, bigSize, dstPath)
|
||||
})
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusCreated)
|
||||
t.Run("Locks", func(t *testing.T) {
|
||||
lockTest(t, u.String(), dstPath)
|
||||
})
|
||||
})
|
||||
})
|
||||
t.Run("SSH", func(t *testing.T) {
|
||||
sshContext := baseAPITestContext
|
||||
sshContext.Reponame = "repo-tmp-18"
|
||||
keyname := "my-testing-key"
|
||||
//Setup key the user ssh key
|
||||
withKeyFile(t, keyname, func(keyFile string) {
|
||||
t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile))
|
||||
|
||||
//Setup ssh wrapper
|
||||
os.Setenv("GIT_SSH_COMMAND",
|
||||
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "+
|
||||
filepath.Join(setting.AppWorkPath, keyFile))
|
||||
os.Setenv("GIT_SSH_VARIANT", "ssh")
|
||||
//Setup remote link
|
||||
sshURL := createSSHUrl(sshContext.GitPath(), u)
|
||||
|
||||
//Setup clone folder
|
||||
dstPath, err := ioutil.TempDir("", "repo-tmp-18")
|
||||
dstPath, err := ioutil.TempDir("", sshContext.Reponame)
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstPath)
|
||||
|
||||
t.Run("Standard", func(t *testing.T) {
|
||||
t.Run("CreateRepo", func(t *testing.T) {
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", &api.CreateRepoOption{
|
||||
AutoInit: true,
|
||||
Description: "Temporary repo",
|
||||
Name: "repo-tmp-18",
|
||||
Private: false,
|
||||
Gitignores: "",
|
||||
License: "WTFPL",
|
||||
Readme: "Default",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusCreated)
|
||||
})
|
||||
t.Run("CreateRepo", doAPICreateRepository(sshContext, false))
|
||||
|
||||
//TODO get url from api
|
||||
t.Run("Clone", func(t *testing.T) {
|
||||
_, err = git.NewCommand("clone").AddArguments(u.String(), dstPath).Run()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md")))
|
||||
})
|
||||
t.Run("Clone", doGitClone(dstPath, sshURL))
|
||||
|
||||
//time.Sleep(5 * time.Minute)
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
t.Run("Little", func(t *testing.T) {
|
||||
@@ -214,10 +135,20 @@ func TestGit(t *testing.T) {
|
||||
lockTest(t, u.String(), dstPath)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func ensureAnonymousClone(t *testing.T, u *url.URL) {
|
||||
dstLocalPath, err := ioutil.TempDir("", "repo1")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstLocalPath)
|
||||
t.Run("CloneAnonymous", doGitClone(dstLocalPath, u))
|
||||
|
||||
}
|
||||
|
||||
func lockTest(t *testing.T, remote, repoPath string) {
|
||||
_, err := git.NewCommand("remote").AddArguments("set-url", "origin", remote).RunInDir(repoPath) //TODO add test ssh git-lfs-creds
|
||||
assert.NoError(t, err)
|
||||
|
1
integrations/gitea-repositories-meta/user2/utf8.git/HEAD
Normal file
1
integrations/gitea-repositories-meta/user2/utf8.git/HEAD
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
@@ -0,0 +1,4 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message taken by
|
||||
# applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit. The hook is
|
||||
# allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "applypatch-msg".
|
||||
|
||||
. git-sh-setup
|
||||
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
|
||||
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
|
||||
:
|
24
integrations/gitea-repositories-meta/user2/utf8.git/hooks/commit-msg.sample
Executable file
24
integrations/gitea-repositories-meta/user2/utf8.git/hooks/commit-msg.sample
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message.
|
||||
# Called by "git commit" with one argument, the name of the file
|
||||
# that has the commit message. The hook should exit with non-zero
|
||||
# status after issuing an appropriate message if it wants to stop the
|
||||
# commit. The hook is allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "commit-msg".
|
||||
|
||||
# Uncomment the below to add a Signed-off-by line to the message.
|
||||
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
|
||||
# hook is more suited to it.
|
||||
#
|
||||
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
||||
|
||||
# This example catches duplicate Signed-off-by lines.
|
||||
|
||||
test "" = "$(grep '^Signed-off-by: ' "$1" |
|
||||
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
|
||||
echo >&2 Duplicate Signed-off-by lines.
|
||||
exit 1
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user