Compare commits
6 Commits
v1.0.0
...
options-bi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a46834168 | ||
|
|
8596ea5519 | ||
|
|
608b1ce642 | ||
|
|
d97b9cf0c2 | ||
|
|
dd5464e1f2 | ||
|
|
c06db22b24 |
51
.drone.yml
51
.drone.yml
@@ -8,12 +8,11 @@ pipeline:
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite bindata
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- apk -U add openssh-client
|
||||
- make clean
|
||||
- make generate
|
||||
- make vet
|
||||
- make lint
|
||||
- make test
|
||||
@@ -26,7 +25,7 @@ pipeline:
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite bindata
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test-mysql
|
||||
@@ -38,7 +37,7 @@ pipeline:
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite bindata
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test-pgsql
|
||||
@@ -50,13 +49,13 @@ pipeline:
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite bindata
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make release
|
||||
when:
|
||||
event: [ push, tag ]
|
||||
branch: [ master, release/*, refs/tags/* ]
|
||||
branch: [ master, refs/tags/* ]
|
||||
|
||||
coverage:
|
||||
image: plugins/coverage
|
||||
@@ -67,19 +66,11 @@ pipeline:
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
tags: [ '${DRONE_TAG##v}' ]
|
||||
tags: [ '${TAG}' ]
|
||||
when:
|
||||
event: [ tag ]
|
||||
branch: [ refs/tags/* ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
tags: [ '${DRONE_BRANCH##release/v}' ]
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ release/* ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
@@ -88,26 +79,6 @@ pipeline:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /gitea/${DRONE_TAG##v}
|
||||
when:
|
||||
event: [ tag ]
|
||||
branch: [ refs/tags/* ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /gitea/${DRONE_BRANCH##release/v}
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ release/* ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
@@ -118,6 +89,16 @@ pipeline:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /gitea/$$TAG
|
||||
when:
|
||||
event: [ tag ]
|
||||
branch: [ refs/tags/* ]
|
||||
|
||||
github:
|
||||
image: plugins/github-release
|
||||
files:
|
||||
|
||||
@@ -1 +1 @@
|
||||
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9zcnYvYXBwCiAgcGF0aDogc3JjL2NvZGUuZ2l0ZWEuaW8vZ2l0ZWEKCnBpcGVsaW5lOgogIHRlc3Q6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlIGJpbmRhdGEKICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gYXBrIC1VIGFkZCBvcGVuc3NoLWNsaWVudAogICAgICAtIG1ha2UgY2xlYW4KICAgICAgLSBtYWtlIGdlbmVyYXRlCiAgICAgIC0gbWFrZSB2ZXQKICAgICAgLSBtYWtlIGxpbnQKICAgICAgLSBtYWtlIHRlc3QKICAgICAgLSBtYWtlIGJ1aWxkCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIHRlc3QtbXlzcWw6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlIGJpbmRhdGEKICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gbWFrZSB0ZXN0LW15c3FsCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KCiAgdGVzdC1wZ3NxbDoKICAgIGltYWdlOiB3ZWJoaXBwaWUvZ29sYW5nOmVkZ2UKICAgIHB1bGw6IHRydWUKICAgIGVudmlyb25tZW50OgogICAgICBDR09fRU5BQkxFRDogMQogICAgICBUQUdTOiBzcWxpdGUgYmluZGF0YQogICAgICBHT1BBVEg6IC9zcnYvYXBwCiAgICBjb21tYW5kczoKICAgICAgLSBtYWtlIHRlc3QtcGdzcWwKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2ggXQoKICB1cGRhdGVyOgogICAgaW1hZ2U6IGthcmFsYWJlL3hnby1sYXRlc3Q6bGF0ZXN0CiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlIGJpbmRhdGEKICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gbWFrZSByZWxlYXNlCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcgXQogICAgICBicmFuY2g6IFsgbWFzdGVyLCByZWxlYXNlLyosIHJlZnMvdGFncy8qIF0KCiAgY292ZXJhZ2U6CiAgICBpbWFnZTogcGx1Z2lucy9jb3ZlcmFnZQogICAgc2VydmVyOiBodHRwczovL2NvdmVyYWdlLmdpdGVhLmlvCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIGRvY2tlcjoKICAgIGltYWdlOiBwbHVnaW5zL2RvY2tlcgogICAgcmVwbzogZ2l0ZWEvZ2l0ZWEKICAgIHRhZ3M6IFsgJyR7RFJPTkVfVEFHIyN2fScgXQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZG9ja2VyOgogICAgaW1hZ2U6IHBsdWdpbnMvZG9ja2VyCiAgICByZXBvOiBnaXRlYS9naXRlYQogICAgdGFnczogWyAnJHtEUk9ORV9CUkFOQ0gjI3JlbGVhc2Uvdn0nIF0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2ggXQogICAgICBicmFuY2g6IFsgcmVsZWFzZS8qIF0KCiAgZG9ja2VyOgogICAgaW1hZ2U6IHBsdWdpbnMvZG9ja2VyCiAgICByZXBvOiBnaXRlYS9naXRlYQogICAgdGFnczogWyAnbGF0ZXN0JyBdCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8ke0RST05FX1RBRyMjdn0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHRhZyBdCiAgICAgIGJyYW5jaDogWyByZWZzL3RhZ3MvKiBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8ke0RST05FX0JSQU5DSCMjcmVsZWFzZS92fQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCiAgICAgIGJyYW5jaDogWyByZWxlYXNlLyogXQoKICByZWxlYXNlOgogICAgaW1hZ2U6IHBsdWdpbnMvczMKICAgIHBhdGhfc3R5bGU6IHRydWUKICAgIHN0cmlwX3ByZWZpeDogZGlzdC9yZWxlYXNlLwogICAgc291cmNlOiBkaXN0L3JlbGVhc2UvKgogICAgdGFyZ2V0OiAvZ2l0ZWEvbWFzdGVyCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIGdpdGh1YjoKICAgIGltYWdlOiBwbHVnaW5zL2dpdGh1Yi1yZWxlYXNlCiAgICBmaWxlczoKICAgICAgLSBkaXN0L3JlbGVhc2UvKgogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZ2l0dGVyOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0dGVyCgpzZXJ2aWNlczoKICBteXNxbDoKICAgIGltYWdlOiBteXNxbDo1LjcKICAgIGVudmlyb25tZW50OgogICAgICAtIE1ZU1FMX0RBVEFCQVNFPXRlc3QKICAgICAgLSBNWVNRTF9BTExPV19FTVBUWV9QQVNTV09SRD15ZXMKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2ggXQoKICBwZ3NxbDoKICAgIGltYWdlOiBwb3N0Z3Jlczo5LjUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX0RCPXRlc3QKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2ggXQo._4feZQfrP_lA1JxSLtj7CDpAN-uB4n4nJKR1R2UcxHg
|
||||
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9zcnYvYXBwCiAgcGF0aDogc3JjL2NvZGUuZ2l0ZWEuaW8vZ2l0ZWEKCnBpcGVsaW5lOgogIHRlc3Q6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIGFwayAtVSBhZGQgb3BlbnNzaC1jbGllbnQKICAgICAgLSBtYWtlIGNsZWFuCiAgICAgIC0gbWFrZSB2ZXQKICAgICAgLSBtYWtlIGxpbnQKICAgICAgLSBtYWtlIHRlc3QKICAgICAgLSBtYWtlIGJ1aWxkCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIHRlc3QtbXlzcWw6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIG1ha2UgdGVzdC1teXNxbAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHRlc3QtcGdzcWw6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIG1ha2UgdGVzdC1wZ3NxbAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHVwZGF0ZXI6CiAgICBpbWFnZToga2FyYWxhYmUveGdvLWxhdGVzdDpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGVudmlyb25tZW50OgogICAgICBDR09fRU5BQkxFRDogMQogICAgICBUQUdTOiBzcWxpdGUKICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gbWFrZSByZWxlYXNlCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcgXQogICAgICBicmFuY2g6IFsgbWFzdGVyLCByZWZzL3RhZ3MvKiBdCgogIGNvdmVyYWdlOgogICAgaW1hZ2U6IHBsdWdpbnMvY292ZXJhZ2UKICAgIHNlcnZlcjogaHR0cHM6Ly9jb3ZlcmFnZS5naXRlYS5pbwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCwgdGFnLCBwdWxsX3JlcXVlc3QgXQoKICBkb2NrZXI6CiAgICBpbWFnZTogcGx1Z2lucy9kb2NrZXIKICAgIHJlcG86IGdpdGVhL2dpdGVhCiAgICB0YWdzOiBbICcke1RBR30nIF0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHRhZyBdCiAgICAgIGJyYW5jaDogWyByZWZzL3RhZ3MvKiBdCgogIGRvY2tlcjoKICAgIGltYWdlOiBwbHVnaW5zL2RvY2tlcgogICAgcmVwbzogZ2l0ZWEvZ2l0ZWEKICAgIHRhZ3M6IFsgJ2xhdGVzdCcgXQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCiAgICAgIGJyYW5jaDogWyBtYXN0ZXIgXQoKICByZWxlYXNlOgogICAgaW1hZ2U6IHBsdWdpbnMvczMKICAgIHBhdGhfc3R5bGU6IHRydWUKICAgIHN0cmlwX3ByZWZpeDogZGlzdC9yZWxlYXNlLwogICAgc291cmNlOiBkaXN0L3JlbGVhc2UvKgogICAgdGFyZ2V0OiAvZ2l0ZWEvbWFzdGVyCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8kJFRBRwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZ2l0aHViOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICAgIGZpbGVzOgogICAgICAtIGRpc3QvcmVsZWFzZS8qCiAgICB3aGVuOgogICAgICBldmVudDogWyB0YWcgXQogICAgICBicmFuY2g6IFsgcmVmcy90YWdzLyogXQoKICBnaXR0ZXI6CiAgICBpbWFnZTogcGx1Z2lucy9naXR0ZXIKCnNlcnZpY2VzOgogIG15c3FsOgogICAgaW1hZ2U6IG15c3FsOjUuNwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTVlTUUxfREFUQUJBU0U9dGVzdAogICAgICAtIE1ZU1FMX0FMTE9XX0VNUFRZX1BBU1NXT1JEPXllcwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHBnc3FsOgogICAgaW1hZ2U6IHBvc3RncmVzOjkuNQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUE9TVEdSRVNfREI9dGVzdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCg.LjU9u_DQ4fD2CytUu9RwwSimdcS3-KzR6nO4ff4edNU
|
||||
4
.github/issue_template.md
vendored
4
.github/issue_template.md
vendored
@@ -12,10 +12,6 @@
|
||||
- [ ] PostgreSQL
|
||||
- [ ] MySQL
|
||||
- [ ] SQLite
|
||||
- Can you reproduce the bug at https://try.gitea.io:
|
||||
- [ ] Yes (provide example URL)
|
||||
- [ ] No
|
||||
- [ ] Not relevant
|
||||
- Log gist:
|
||||
|
||||
## Description
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,7 +30,6 @@ coverage.out
|
||||
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
/modules/templates/bindata.go
|
||||
|
||||
*.db
|
||||
*.log
|
||||
|
||||
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,43 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## [1.0.0](https://github.com/go-gitea/gitea/releases/tag/v1.0.0) - 2016-12-23
|
||||
|
||||
* BREAKING
|
||||
* We have various changes on the API, scripting against API must be updated
|
||||
* FEATURE
|
||||
* Show last login for admins [#121](https://github.com/go-gitea/gitea/pull/121)
|
||||
* BUGFIXES
|
||||
* Fixed sender of notifications [#2](https://github.com/go-gitea/gitea/pull/2)
|
||||
* Fixed keyword hijacking vulnerability [#20](https://github.com/go-gitea/gitea/pull/20)
|
||||
* Fixed non-markdown readme rendering [#95](https://github.com/go-gitea/gitea/pull/95)
|
||||
* Allow updating draft releases [#169](https://github.com/go-gitea/gitea/pull/169)
|
||||
* GitHub API compliance [#227](https://github.com/go-gitea/gitea/pull/227)
|
||||
* Added commit SHA to tag webhook [#286](https://github.com/go-gitea/gitea/issues/286)
|
||||
* Secured links via noopener [#315](https://github.com/go-gitea/gitea/issues/315)
|
||||
* Replace tabs with spaces on wiki title [#371](https://github.com/go-gitea/gitea/pull/371)
|
||||
* Fixed vulnerability on labels and releases [#409](https://github.com/go-gitea/gitea/pull/409)
|
||||
* Fixed issue comment API [#449](https://github.com/go-gitea/gitea/pull/449)
|
||||
* ENHANCEMENT
|
||||
* Use proper import path for libravatar [#3](https://github.com/go-gitea/gitea/pull/3)
|
||||
* Integrated DroneCI for tests and builds [#24](https://github.com/go-gitea/gitea/issues/24)
|
||||
* Integrated dependency manager [#29](https://github.com/go-gitea/gitea/issues/29)
|
||||
* Embedded bindata optionally [#30](https://github.com/go-gitea/gitea/issues/30)
|
||||
* Integrated pagination for releases [#73](https://github.com/go-gitea/gitea/pull/73)
|
||||
* Autogenerate version on every build [#91](https://github.com/go-gitea/gitea/issues/91)
|
||||
* Refactored Docker container [#104](https://github.com/go-gitea/gitea/issues/104)
|
||||
* Added short-hash support for downloads [#211](https://github.com/go-gitea/gitea/issues/211)
|
||||
* Display tooltip for downloads [#221](https://github.com/go-gitea/gitea/issues/221)
|
||||
* Improved HTTP headers for issue attachments [#270](https://github.com/go-gitea/gitea/pull/270)
|
||||
* Integrate public as bindata optionally [#293](https://github.com/go-gitea/gitea/pull/293)
|
||||
* Integrate templates as bindata optionally [#314](https://github.com/go-gitea/gitea/pull/314)
|
||||
* Inject more ENV variables into custom hooks [#316](https://github.com/go-gitea/gitea/issues/316)
|
||||
* Correct LDAP login validation [#342](https://github.com/go-gitea/gitea/pull/342)
|
||||
* Integrate conf as bindata optionally [#354](https://github.com/go-gitea/gitea/pull/354)
|
||||
* Serve video files in browser [#418](https://github.com/go-gitea/gitea/pull/418)
|
||||
* Configurable SSH host binding [#431](https://github.com/go-gitea/gitea/issues/431)
|
||||
* MISC
|
||||
* Forked from Gogs and renamed to Gitea
|
||||
* Catching more errors with logs
|
||||
* Fixed all linting errors
|
||||
* Made the go linter entirely happy
|
||||
* Really integrated vendoring
|
||||
@@ -26,8 +26,7 @@ RUN apk update && \
|
||||
-s /bin/bash \
|
||||
-u 1000 \
|
||||
-G git \
|
||||
git && \
|
||||
echo "git:$(date +%s | sha256sum | base64 | head -c 32)" | chpasswd
|
||||
git
|
||||
|
||||
ENV USER git
|
||||
ENV GITEA_CUSTOM /data/gitea
|
||||
@@ -39,4 +38,7 @@ ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY docker /
|
||||
|
||||
COPY public /app/gitea/public
|
||||
COPY templates /app/gitea/templates
|
||||
COPY gitea /app/gitea/gitea
|
||||
|
||||
22
Makefile
22
Makefile
@@ -2,23 +2,25 @@ DIST := dist
|
||||
EXECUTABLE := gitea
|
||||
IMPORT := code.gitea.io/gitea
|
||||
|
||||
BINDATA := modules/{options,public,templates}/bindata.go
|
||||
SHA := $(shell git rev-parse --short HEAD)
|
||||
DATE := $(shell date -u '+%Y-%m-%d %I:%M:%S %Z')
|
||||
|
||||
STYLESHEETS := $(wildcard public/less/index.less public/less/_*.less)
|
||||
JAVASCRIPTS :=
|
||||
|
||||
LDFLAGS += -X "main.Version=$(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')"
|
||||
LDFLAGS += -X "code.gitea.io/gitea/modules/setting.BuildTime=$(DATE)"
|
||||
LDFLAGS += -X "code.gitea.io/gitea/modules/setting.BuildGitHash=$(SHA)"
|
||||
|
||||
TARGETS ?= linux/*,darwin/*,windows/*
|
||||
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||
|
||||
TAGS ?=
|
||||
|
||||
ifneq ($(DRONE_TAG),)
|
||||
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||
VERSION ?= $(DRONE_TAG)
|
||||
else
|
||||
ifneq ($(DRONE_BRANCH),)
|
||||
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||
VERSION ?= $(DRONE_BRANCH)
|
||||
else
|
||||
VERSION ?= master
|
||||
endif
|
||||
@@ -30,7 +32,7 @@ all: build
|
||||
.PHONY: clean
|
||||
clean:
|
||||
go clean -i ./...
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA)
|
||||
rm -rf $(EXECUTABLE) $(DIST)
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
@@ -83,14 +85,10 @@ install: $(wildcard *.go)
|
||||
.PHONY: build
|
||||
build: $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(SOURCES)
|
||||
.PHONY: $(EXECUTABLE)
|
||||
$(EXECUTABLE): $(wildcard *.go)
|
||||
go build -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="$(TAGS)" webhippie/golang:edge make clean generate build
|
||||
docker build -t gitea/gitea:latest .
|
||||
|
||||
.PHONY: release
|
||||
release: release-dirs release-build release-copy release-check
|
||||
|
||||
|
||||
124
README.md
124
README.md
@@ -1,5 +1,3 @@
|
||||
[简体中文](https://github.com/go-gitea/gitea/blob/master/README_ZH.md)
|
||||
|
||||
# Gitea - Git with a cup of tea
|
||||
|
||||
[](http://drone.gitea.io/go-gitea/gitea)
|
||||
@@ -8,28 +6,122 @@
|
||||
[](https://coverage.gitea.io/go-gitea/gitea)
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea)
|
||||
[](https://godoc.org/code.gitea.io/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
|
||||
||||
|
||||
[](https://github.com/go-gitea/gitea)
|
||||
|
||||
##### Status
|
||||
|
||||
**Current version**: (see [Releases](https://github.com/go-gitea/gitea/releases))
|
||||
|
||||
| Web | UI | Preview |
|
||||
|:-------------:|:-------:|:-------:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
||||
### Important Notes
|
||||
|
||||
1. **YOU MUST READ THE [Contributors Guide](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST**.
|
||||
2. If you think there are vulnerabilities in the project, please talk privately to **security@gitea.io**. Thanks!
|
||||
3. If you're interested in using APIs, we have experimental support with [documentation](https://godoc.org/github.com/go-gitea/go-sdk).
|
||||
|
||||
## Purpose
|
||||
|
||||
The goal of this project is to make the easiest, fastest, and most painless way of setting up a self-hosted Git service. With Go, this can be done with an independent binary distribution across **all platforms** that Go supports, including Linux, macOS, and Windows on x86, amd64, ARM and PowerPC architectures. Want to try it before doing anything else? Do it [online](https://try.gitea.io/)!
|
||||
The goal of this project is to make the easiest, fastest, and most painless way of setting up a self-hosted Git service. With Go, this can be done with an independent binary distribution across **ALL platforms** that Go supports, including Linux, Mac OS X, Windows and ARM.
|
||||
|
||||
## Notes
|
||||
## Features
|
||||
|
||||
1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
||||
2. If you found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
||||
3. If you're interested in using our APIs, we have experimental support with [documentation](https://godoc.org/code.gitea.io/sdk/gitea).
|
||||
- Activity timeline
|
||||
- SSH and HTTP/HTTPS protocols
|
||||
- SMTP/LDAP/Reverse proxy authentication
|
||||
- Reverse proxy with sub-path
|
||||
- Account/Organization/Repository management
|
||||
- Add/Remove repository collaborators
|
||||
- Repository/Organization webhooks (including Slack)
|
||||
- Repository Git hooks/deploy keys
|
||||
- Repository issues, pull requests and wiki
|
||||
- Migrate and mirror repository and its wiki
|
||||
- Web editor for repository files and wiki
|
||||
- Gravatar and Federated avatar with custom source
|
||||
- Mail service
|
||||
- Administration panel
|
||||
- Supports MySQL, PostgreSQL, SQLite3 and [TiDB](https://github.com/pingcap/tidb) (experimental)
|
||||
- Multi-language support ([20 languages](https://crowdin.com/project/gogs))
|
||||
|
||||
## Docs
|
||||
## System Requirements
|
||||
|
||||
- A cheap Raspberry Pi is powerful enough for basic functionality.
|
||||
- 2 CPU cores and 1GB RAM would be the baseline for teamwork.
|
||||
|
||||
## Browser Support
|
||||
|
||||
- Please see [Semantic UI](https://github.com/Semantic-Org/Semantic-UI#browser-support) for specific versions of supported browsers.
|
||||
- The official support minimal size is **1024*768**, UI may still looks right in smaller size but no promises and fixes.
|
||||
|
||||
## Installation
|
||||
|
||||
**Note: As Gitea is a [Gogs](https://github.com/gogits/gogs) fork, tutorials and documentation related to gogs applies to Gitea too**
|
||||
|
||||
How to install Gitea:
|
||||
|
||||
- go get code.gitea.io/gitea
|
||||
- [Ship with Docker](https://github.com/go-gitea/gitea/tree/master/docker)
|
||||
- [Install with Vagrant](https://github.com/go-gitea/examples/tree/master/vagrant)
|
||||
|
||||
**Note: binary release will be available soon**
|
||||
|
||||
### Tutorials
|
||||
|
||||
- [How To Set Up Gogs on Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-set-up-gogs-on-ubuntu-14-04)
|
||||
- [Run your own GitHub-like service with the help of Docker](http://blog.hypriot.com/post/run-your-own-github-like-service-with-docker/)
|
||||
- [Dockerized Gogs git server and alpine postgres in 20 minutes or less](http://garthwaite.org/docker-gogs.html)
|
||||
- [Host Your Own Private GitHub with Gogs.io](https://eladnava.com/host-your-own-private-github-with-gogs-io/)
|
||||
- [使用 Gogs 搭建自己的 Git 服务器](https://mynook.info/blog/post/host-your-own-git-server-using-gogs) (Chinese)
|
||||
- [阿里云上 Ubuntu 14.04 64 位安装 Gogs](http://my.oschina.net/luyao/blog/375654) (Chinese)
|
||||
- [Installing Gogs on FreeBSD](https://www.codejam.info/2015/03/installing-gogs-on-freebsd.html)
|
||||
- [Gogs on Raspberry Pi](http://blog.meinside.pe.kr/Gogs-on-Raspberry-Pi/)
|
||||
- [Cloudflare Full SSL with GOGS (Go Git Service) using NGINX](http://www.listekconsulting.com/articles/cloudflare-full-ssl-with-gogs-go-git-service-using-nginx/)
|
||||
|
||||
### Screencasts
|
||||
|
||||
- [How to install Gogs on a Linux Server (DigitalOcean)](https://www.youtube.com/watch?v=deSfX0gqefE)
|
||||
- [Instalando Gogs no Ubuntu](https://www.youtube.com/watch?v=4UkHAR1F7ZA) (Português)
|
||||
|
||||
### Deploy to Cloud
|
||||
|
||||
- [OpenShift](https://github.com/tkisme/gogs-openshift)
|
||||
- [Cloudron](https://cloudron.io/appstore.html#io.gogs.cloudronapp)
|
||||
- [Scaleway](https://www.scaleway.com/imagehub/gogs/)
|
||||
- [Portal](https://portaldemo.xyz/cloud/)
|
||||
- [Sandstorm](https://github.com/cem/gogs-sandstorm)
|
||||
- [sloppy.io](https://github.com/sloppyio/quickstarters/tree/master/gogs)
|
||||
- [YunoHost](https://github.com/mbugeia/gogs_ynh)
|
||||
- [DPlatform](https://github.com/j8r/DPlatform)
|
||||
|
||||
## Software and Service Support
|
||||
|
||||
- [Drone](https://github.com/drone/drone) (CI)
|
||||
- [Fabric8](http://fabric8.io/) (DevOps)
|
||||
- [Taiga](https://taiga.io/) (Project Management)
|
||||
- [Puppet](https://forge.puppetlabs.com/Siteminds/gogs) (IT)
|
||||
- [Kanboard](http://kanboard.net/plugin/gogs-webhook) (Project Management)
|
||||
- [BearyChat](https://bearychat.com/) (Team Communication)
|
||||
- [HiWork](http://www.hiwork.cc/) (Team Communication)
|
||||
|
||||
### Product Support
|
||||
|
||||
- [Synology](https://www.synology.com) (Docker)
|
||||
- [One Space](http://www.onespace.cc) (App Store)
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- Router and middleware mechanism of [Macaron](https://github.com/go-macaron/macaron).
|
||||
- System Monitor Status is inspired by [GoBlog](https://github.com/fuxiaohei/goblog).
|
||||
- Thanks [Rocker](http://weibo.com/rocker1989) for designing Logo.
|
||||
- Thanks [Crowdin](https://crowdin.com/project/gogs) for providing open source translation plan.
|
||||
- Thanks [DigitalOcean](https://www.digitalocean.com) for hosting home and demo sites.
|
||||
- Thanks [KeyCDN](https://www.keycdn.com/) and [QiNiu](http://www.qiniu.com/) for providing CDN service.
|
||||
|
||||
For further information or instructions how to install Gitea please take a look at our [documentation](https://docs.gitea.io/en-us/), if you can not find some specific information just head over to our [Gitter](https://gitter.im/go-gitea/gitea) channel to have a chat with us.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -39,7 +131,7 @@ Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
* [Maintainers](https://github.com/orgs/go-gitea/people)
|
||||
* [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
|
||||
* [Translators](options/locale/TRANSLATORS)
|
||||
* [Translators](conf/locale/TRANSLATORS)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
48
README_ZH.md
48
README_ZH.md
@@ -1,48 +0,0 @@
|
||||
[English](https://github.com/go-gitea/gitea/blob/master/README.md)
|
||||
|
||||
# Gitea - Git with a cup of tea
|
||||
|
||||
[](http://drone.gitea.io/go-gitea/gitea)
|
||||
[](https://gitter.im/go-gitea/gitea?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](http://microbadger.com/images/gitea/gitea "Get your own image badge on microbadger.com")
|
||||
[](https://coverage.gitea.io/go-gitea/gitea)
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea)
|
||||
[](https://godoc.org/code.gitea.io/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
|
||||
||||
|
||||
|:-------------:|:-------:|:-------:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
||||
## 目标
|
||||
|
||||
Gitea的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用Go作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了x86,amd64,还包括 ARM 和 PowerPC。
|
||||
|
||||
如果您想试用一下,请访问 [在线Demo](https://try.gitea.io/)!
|
||||
|
||||
## 提示
|
||||
|
||||
1. **开始贡献代码之前请确保你已经看过了 [贡献者向导(英文)](CONTRIBUTING.md)**.
|
||||
2. 所有的安全问题,请私下发送邮件给 **security@gitea.io**。谢谢!
|
||||
3. 如果你要使用API,请参见 [API 文档](https://godoc.org/code.gitea.io/sdk/gitea).
|
||||
|
||||
## 文档
|
||||
|
||||
关于如何安装请访问我们的 [文档站](https://docs.gitea.io/zh-cn/),如果没有找到对应的文档,你也可以通过 [Gitter - 英文](https://gitter.im/go-gitea/gitea) 和 QQ群 328432459 来和我们交流。
|
||||
|
||||
## 贡献流程
|
||||
|
||||
Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## 作者
|
||||
|
||||
* [Maintainers](https://github.com/orgs/go-gitea/people)
|
||||
* [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
|
||||
* [Translators](options/locale/TRANSLATORS)
|
||||
|
||||
## 授权许可
|
||||
|
||||
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/go-gitea/gitea/blob/master/LICENSE) 文件中。
|
||||
@@ -1,5 +1,4 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -19,7 +18,7 @@ var (
|
||||
CmdAdmin = cli.Command{
|
||||
Name: "admin",
|
||||
Usage: "Preform admin operations on command line",
|
||||
Description: `Allow using internal logic of Gitea without hacking into the source code
|
||||
Description: `Allow using internal logic of Gogs without hacking into the source code
|
||||
to make automatic initialization process more smoothly`,
|
||||
Subcommands: []cli.Command{
|
||||
subcmdCreateUser,
|
||||
|
||||
@@ -137,7 +137,7 @@ func runCert(ctx *cli.Context) error {
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"Acme Co"},
|
||||
CommonName: "Gitea",
|
||||
CommonName: "Gogs",
|
||||
},
|
||||
NotBefore: notBefore,
|
||||
NotAfter: notAfter,
|
||||
|
||||
21
cmd/dump.go
21
cmd/dump.go
@@ -1,5 +1,4 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -22,9 +21,9 @@ import (
|
||||
// CmdDump represents the available dump sub-command.
|
||||
var CmdDump = cli.Command{
|
||||
Name: "dump",
|
||||
Usage: "Dump Gitea files and database",
|
||||
Usage: "Dump Gogs files and database",
|
||||
Description: `Dump compresses all related files and database into zip file.
|
||||
It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
It can be used for backup and capture Gogs server image to send to maintainer`,
|
||||
Action: runDump,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
@@ -56,14 +55,14 @@ func runDump(ctx *cli.Context) error {
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
log.Fatalf("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
TmpWorkDir, err := ioutil.TempDir(tmpDir, "gitea-dump-")
|
||||
TmpWorkDir, err := ioutil.TempDir(tmpDir, "gogs-dump-")
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to create tmp work directory: %v", err)
|
||||
}
|
||||
log.Printf("Creating tmp work dir: %s", TmpWorkDir)
|
||||
|
||||
reposDump := path.Join(TmpWorkDir, "gitea-repo.zip")
|
||||
dbDump := path.Join(TmpWorkDir, "gitea-db.sql")
|
||||
reposDump := path.Join(TmpWorkDir, "gogs-repo.zip")
|
||||
dbDump := path.Join(TmpWorkDir, "gogs-db.sql")
|
||||
|
||||
log.Printf("Dumping local repositories...%s", setting.RepoRootPath)
|
||||
zip.Verbose = ctx.Bool("verbose")
|
||||
@@ -76,18 +75,18 @@ func runDump(ctx *cli.Context) error {
|
||||
log.Fatalf("Fail to dump database: %v", err)
|
||||
}
|
||||
|
||||
fileName := fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix())
|
||||
fileName := fmt.Sprintf("gogs-dump-%d.zip", time.Now().Unix())
|
||||
log.Printf("Packing dump files...")
|
||||
z, err := zip.Create(fileName)
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to create %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
if err := z.AddFile("gitea-repo.zip", reposDump); err != nil {
|
||||
log.Fatalf("Fail to include gitea-repo.zip: %v", err)
|
||||
if err := z.AddFile("gogs-repo.zip", reposDump); err != nil {
|
||||
log.Fatalf("Fail to include gogs-repo.zip: %v", err)
|
||||
}
|
||||
if err := z.AddFile("gitea-db.sql", dbDump); err != nil {
|
||||
log.Fatalf("Fail to include gitea-db.sql: %v", err)
|
||||
if err := z.AddFile("gogs-db.sql", dbDump); err != nil {
|
||||
log.Fatalf("Fail to include gogs-db.sql: %v", err)
|
||||
}
|
||||
customDir, err := os.Stat(setting.CustomPath)
|
||||
if err == nil && customDir.IsDir() {
|
||||
|
||||
15
cmd/serve.go
15
cmd/serve.go
@@ -1,5 +1,4 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -77,7 +76,7 @@ var (
|
||||
)
|
||||
|
||||
func fail(userMessage, logMessage string, args ...interface{}) {
|
||||
fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
|
||||
fmt.Fprintln(os.Stderr, "Gogs:", userMessage)
|
||||
|
||||
if len(logMessage) > 0 {
|
||||
if !setting.ProdMode {
|
||||
@@ -121,7 +120,7 @@ func handleUpdateTask(uuid string, user, repoUser *models.User, reponame string,
|
||||
|
||||
// Ask for running deliver hook and test pull request tasks.
|
||||
reqURL := setting.LocalURL + repoUser.Name + "/" + reponame + "/tasks/trigger?branch=" +
|
||||
strings.TrimPrefix(task.RefName, git.BranchPrefix) + "&secret=" + base.EncodeMD5(repoUser.Salt) + "&pusher=" + com.ToStr(user.ID)
|
||||
strings.TrimPrefix(task.RefName, git.BRANCH_PREFIX) + "&secret=" + base.EncodeMD5(repoUser.Salt) + "&pusher=" + com.ToStr(user.ID)
|
||||
log.GitLogger.Trace("Trigger task: %s", reqURL)
|
||||
|
||||
resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
|
||||
@@ -145,7 +144,7 @@ func runServ(c *cli.Context) error {
|
||||
setup("serv.log")
|
||||
|
||||
if setting.SSH.Disabled {
|
||||
println("Gitea: SSH has been disabled")
|
||||
println("Gogs: SSH has been disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -155,8 +154,8 @@ func runServ(c *cli.Context) error {
|
||||
|
||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||
if len(cmd) == 0 {
|
||||
println("Hi there, You've successfully authenticated, but Gitea does not provide shell access.")
|
||||
println("If this is unexpected, please log in with password and setup Gitea under another user.")
|
||||
println("Hi there, You've successfully authenticated, but Gogs does not provide shell access.")
|
||||
println("If this is unexpected, please log in with password and setup Gogs under another user.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -256,11 +255,11 @@ func runServ(c *cli.Context) error {
|
||||
"User %s does not have level %v access to repository %s",
|
||||
user.Name, requestedMode, repoPath)
|
||||
}
|
||||
|
||||
os.Setenv("GITEA_PUSHER_NAME", user.Name)
|
||||
}
|
||||
}
|
||||
|
||||
os.Setenv("GITEA_PUSHER_NAME", user.Name)
|
||||
|
||||
uuid := gouuid.NewV4().String()
|
||||
os.Setenv("GITEA_UUID", uuid)
|
||||
// Keep the old env variable name for backward compability
|
||||
|
||||
62
cmd/web.go
62
cmd/web.go
@@ -7,6 +7,7 @@ package cmd
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
@@ -21,7 +23,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/public"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/template"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/admin"
|
||||
apiv1 "code.gitea.io/gitea/routers/api/v1"
|
||||
@@ -37,15 +39,18 @@ import (
|
||||
"github.com/go-macaron/i18n"
|
||||
"github.com/go-macaron/session"
|
||||
"github.com/go-macaron/toolbox"
|
||||
"github.com/go-xorm/xorm"
|
||||
version "github.com/mcuadros/go-version"
|
||||
"github.com/urfave/cli"
|
||||
ini "gopkg.in/ini.v1"
|
||||
macaron "gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
// CmdWeb represents the available web sub-command.
|
||||
var CmdWeb = cli.Command{
|
||||
Name: "web",
|
||||
Usage: "Start Gitea web server",
|
||||
Description: `Gitea web server is the only thing you need to run,
|
||||
Usage: "Start Gogs web server",
|
||||
Description: `Gogs web server is the only thing you need to run,
|
||||
and it takes care of all the other things for you`,
|
||||
Action: runWeb,
|
||||
Flags: []cli.Flag{
|
||||
@@ -69,6 +74,45 @@ type VerChecker struct {
|
||||
Expected string
|
||||
}
|
||||
|
||||
// checkVersion checks if binary matches the version of templates files.
|
||||
func checkVersion() {
|
||||
// Templates.
|
||||
data, err := ioutil.ReadFile(setting.StaticRootPath + "/templates/.VERSION")
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to read 'templates/.VERSION': %v", err)
|
||||
}
|
||||
tplVer := string(data)
|
||||
if tplVer != setting.AppVer {
|
||||
if version.Compare(tplVer, setting.AppVer, ">") {
|
||||
log.Fatal(4, "Binary version is lower than template file version, did you forget to recompile Gogs?")
|
||||
} else {
|
||||
log.Fatal(4, "Binary version is higher than template file version, did you forget to update template files?")
|
||||
}
|
||||
}
|
||||
|
||||
// Check dependency version.
|
||||
checkers := []VerChecker{
|
||||
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.5.5"},
|
||||
{"github.com/go-macaron/binding", binding.Version, "0.3.2"},
|
||||
{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
|
||||
{"github.com/go-macaron/csrf", csrf.Version, "0.1.0"},
|
||||
{"github.com/go-macaron/i18n", i18n.Version, "0.3.0"},
|
||||
{"github.com/go-macaron/session", session.Version, "0.1.6"},
|
||||
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
|
||||
{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
|
||||
{"gopkg.in/macaron.v1", macaron.Version, "1.1.7"},
|
||||
{"code.gitea.io/git", git.Version, "0.4.1"},
|
||||
}
|
||||
for _, c := range checkers {
|
||||
if !version.Compare(c.Version(), c.Expected, ">=") {
|
||||
log.Fatal(4, `Dependency outdated!
|
||||
Package '%s' current version (%s) is below requirement (%s),
|
||||
please use following command to update this package and recompile Gogs:
|
||||
go get -u %[1]s`, c.ImportPath, c.Version(), c.Expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// newMacaron initializes Macaron instance.
|
||||
func newMacaron() *macaron.Macaron {
|
||||
m := macaron.New()
|
||||
@@ -96,8 +140,15 @@ func newMacaron() *macaron.Macaron {
|
||||
},
|
||||
))
|
||||
|
||||
m.Use(templates.Renderer())
|
||||
models.InitMailRender(templates.Mailer())
|
||||
funcMap := template.NewFuncMap()
|
||||
m.Use(macaron.Renderer(macaron.RenderOptions{
|
||||
Directory: path.Join(setting.StaticRootPath, "templates"),
|
||||
AppendDirectories: []string{path.Join(setting.CustomPath, "templates")},
|
||||
Funcs: funcMap,
|
||||
IndentJSON: macaron.Env != macaron.PROD,
|
||||
}))
|
||||
models.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
|
||||
path.Join(setting.CustomPath, "templates/mail"), funcMap)
|
||||
|
||||
localeNames, err := options.Dir("locale")
|
||||
|
||||
@@ -156,6 +207,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
routers.GlobalInit()
|
||||
checkVersion()
|
||||
|
||||
m := newMacaron()
|
||||
|
||||
|
||||
14
conf/app.ini
14
conf/app.ini
@@ -1,3 +1,6 @@
|
||||
# NEVER EVER MODIFY THIS FILE
|
||||
# PLEASE MAKE CHANGES ON CORRESPONDING CUSTOM CONFIG FILE
|
||||
|
||||
; App name that shows on every page title
|
||||
APP_NAME = Gitea: Git with a cup of tea
|
||||
; Change it if you run locally
|
||||
@@ -54,7 +57,7 @@ FEED_MAX_COMMIT_NUM = 5
|
||||
; Value of `theme-color` meta tag, used by Android >= 5.0
|
||||
; An invalid color like "none" or "disable" will have the default style
|
||||
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||
THEME_COLOR_META_TAG = `#6cc644`
|
||||
THEME_COLOR_META_TAG = `#ff5343`
|
||||
; Max size of files to be displayed (defaults is 8MiB)
|
||||
MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
|
||||
@@ -100,8 +103,6 @@ DISABLE_SSH = false
|
||||
START_SSH_SERVER = false
|
||||
; Domain name to be exposed in clone URL
|
||||
SSH_DOMAIN = %(DOMAIN)s
|
||||
; Network interface builtin SSH server listens on
|
||||
SSH_LISTEN_HOST =
|
||||
; Port number to be exposed in clone URL
|
||||
SSH_PORT = 22
|
||||
; Port number builtin SSH server listens on
|
||||
@@ -335,7 +336,7 @@ HOST =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
PASSWD =
|
||||
; Receivers, can be one or more, e.g. 1@example.com,2@example.com
|
||||
; Receivers, can be one or more, e.g. ["1@example.com","2@example.com"]
|
||||
RECEIVERS =
|
||||
|
||||
; For "database" mode only
|
||||
@@ -399,8 +400,8 @@ DEFAULT_INTERVAL = 8
|
||||
MAX_RESPONSE_ITEMS = 50
|
||||
|
||||
[i18n]
|
||||
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
|
||||
NAMES = English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska,한국어
|
||||
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE
|
||||
NAMES = English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska
|
||||
|
||||
; Used for datetimepicker
|
||||
[i18n.datelang]
|
||||
@@ -424,7 +425,6 @@ tr-TR = tr
|
||||
cs-CZ = cs-CZ
|
||||
sr-SP = sr
|
||||
sv-SE = sv
|
||||
ko-KR = ko
|
||||
|
||||
; Extension mapping to highlight class
|
||||
; e.g. .toml=ini
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
[[ -f ./setup ]] && source ./setup
|
||||
|
||||
pushd /root > /dev/null
|
||||
exec su-exec root /usr/sbin/sshd -D
|
||||
exec su-exec root /usr/sbin/sshd -E /var/log/sshd.log -D
|
||||
popd
|
||||
|
||||
@@ -18,6 +18,7 @@ UseDNS no
|
||||
AllowAgentForwarding no
|
||||
AllowTcpForwarding no
|
||||
PrintMotd no
|
||||
PrintLastLog no
|
||||
|
||||
PermitUserEnvironment yes
|
||||
PermitRootLogin no
|
||||
|
||||
4
main.go
4
main.go
@@ -1,5 +1,5 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// Version holds the current Gitea version
|
||||
var Version = "1.0.0+dev"
|
||||
const Version = "0.9.99.0915"
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
|
||||
@@ -494,12 +494,12 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
isNewBranch := false
|
||||
opType := ActionCommitRepo
|
||||
// Check it's tag push or branch.
|
||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
|
||||
opType = ActionPushTag
|
||||
opts.Commits = &PushCommits{}
|
||||
} else {
|
||||
// if not the first commit, set the compare URL.
|
||||
if opts.OldCommitID == git.EmptySHA {
|
||||
if opts.OldCommitID == git.EMPTY_SHA {
|
||||
isNewBranch = true
|
||||
} else {
|
||||
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID)
|
||||
@@ -539,7 +539,7 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
}()
|
||||
|
||||
apiPusher := pusher.APIFormat()
|
||||
apiRepo := repo.APIFormat(AccessModeNone)
|
||||
apiRepo := repo.APIFormat(nil)
|
||||
|
||||
var shaSum string
|
||||
switch opType {
|
||||
@@ -562,7 +562,7 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
if err != nil {
|
||||
log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
|
||||
}
|
||||
shaSum, err = gitRepo.GetBranchCommitID(refName)
|
||||
shaSum, err = gitRepo.GetBranchCommitID(opts.RefFullName)
|
||||
if err != nil {
|
||||
log.Error(4, "GetBranchCommitID[%s]: %v", opts.RefFullName, err)
|
||||
}
|
||||
@@ -580,7 +580,7 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
if err != nil {
|
||||
log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
|
||||
}
|
||||
shaSum, err = gitRepo.GetTagCommitID(refName)
|
||||
shaSum, err = gitRepo.GetTagCommitID(opts.RefFullName)
|
||||
if err != nil {
|
||||
log.Error(4, "GetTagCommitID[%s]: %v", opts.RefFullName, err)
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ import (
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/highlight"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/template/highlight"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/sergi/go-diff/diffmatchpatch"
|
||||
"golang.org/x/net/html/charset"
|
||||
|
||||
@@ -87,20 +87,13 @@ func (issue *Issue) AfterSet(colName string, _ xorm.Cell) {
|
||||
}
|
||||
}
|
||||
|
||||
func (issue *Issue) loadRepo(e Engine) (err error) {
|
||||
func (issue *Issue) loadAttributes(e Engine) (err error) {
|
||||
if issue.Repo == nil {
|
||||
issue.Repo, err = getRepositoryByID(e, issue.RepoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getRepositoryByID [%d]: %v", issue.RepoID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (issue *Issue) loadAttributes(e Engine) (err error) {
|
||||
if err := issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if issue.Poster == nil {
|
||||
issue.Poster, err = getUserByID(e, issue.PosterID)
|
||||
@@ -272,7 +265,7 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Index: issue.Index,
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
})
|
||||
}
|
||||
@@ -329,16 +322,6 @@ func (issue *Issue) removeLabel(e *xorm.Session, label *Label) error {
|
||||
|
||||
// RemoveLabel removes a label from issue by given ID.
|
||||
func (issue *Issue) RemoveLabel(doer *User, label *Label) error {
|
||||
if err := issue.loadRepo(x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if has, err := HasAccess(doer, issue.Repo, AccessModeWrite); err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return ErrLabelNotExist{}
|
||||
}
|
||||
|
||||
if err := DeleteIssueLabel(issue, label); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -370,16 +353,6 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := issue.loadRepo(sess); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if has, err := hasAccess(sess, doer, issue.Repo, AccessModeWrite); err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return ErrLabelNotExist{}
|
||||
}
|
||||
|
||||
if err = issue.clearLabels(sess); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -398,7 +371,7 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
|
||||
Action: api.HookIssueLabelCleared,
|
||||
Index: issue.Index,
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
})
|
||||
}
|
||||
@@ -520,7 +493,7 @@ func (issue *Issue) ChangeStatus(doer *User, repo *Repository, isClosed bool) (e
|
||||
apiPullRequest := &api.PullRequestPayload{
|
||||
Index: issue.Index,
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: repo.APIFormat(AccessModeNone),
|
||||
Repository: repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
}
|
||||
if isClosed {
|
||||
@@ -558,7 +531,7 @@ func (issue *Issue) ChangeTitle(doer *User, title string) (err error) {
|
||||
},
|
||||
},
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
})
|
||||
}
|
||||
@@ -590,7 +563,7 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
|
||||
},
|
||||
},
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
})
|
||||
}
|
||||
@@ -623,7 +596,7 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
|
||||
apiPullRequest := &api.PullRequestPayload{
|
||||
Index: issue.Index,
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
}
|
||||
if isRemoveAssignee {
|
||||
@@ -915,10 +888,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
||||
}
|
||||
|
||||
if len(opts.Labels) > 0 && opts.Labels != "0" {
|
||||
labelIDs, err := base.StringsToInt64s(strings.Split(opts.Labels, ","))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
|
||||
if len(labelIDs) > 0 {
|
||||
sess.
|
||||
Join("INNER", "issue_label", "issue.id = issue_label.issue_id").
|
||||
@@ -1085,7 +1055,7 @@ func GetIssueUserPairsByMode(uid, rid int64, isClosed bool, page, filterMode int
|
||||
|
||||
// UpdateIssueMentions extracts mentioned people from content and
|
||||
// updates issue-user relations for them.
|
||||
func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
|
||||
func UpdateIssueMentions(issueID int64, mentions []string) error {
|
||||
if len(mentions) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -1095,7 +1065,7 @@ func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
|
||||
}
|
||||
users := make([]*User, 0, len(mentions))
|
||||
|
||||
if err := e.In("lower_name", mentions).Asc("lower_name").Find(&users); err != nil {
|
||||
if err := x.In("lower_name", mentions).Asc("lower_name").Find(&users); err != nil {
|
||||
return fmt.Errorf("find mentioned users: %v", err)
|
||||
}
|
||||
|
||||
@@ -1119,7 +1089,7 @@ func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
|
||||
ids = append(ids, memberIDs...)
|
||||
}
|
||||
|
||||
if err := UpdateIssueUsersByMentions(e, issueID, ids); err != nil {
|
||||
if err := UpdateIssueUsersByMentions(issueID, ids); err != nil {
|
||||
return fmt.Errorf("UpdateIssueUsersByMentions: %v", err)
|
||||
}
|
||||
|
||||
@@ -1174,11 +1144,10 @@ func GetIssueStats(opts *IssueStatsOptions) *IssueStats {
|
||||
And("is_pull = ?", opts.IsPull)
|
||||
|
||||
if len(opts.Labels) > 0 && opts.Labels != "0" {
|
||||
labelIDs, err := base.StringsToInt64s(strings.Split(opts.Labels, ","))
|
||||
if err != nil {
|
||||
log.Warn("Malformed Labels argument: %s", opts.Labels)
|
||||
} else if len(labelIDs) > 0 {
|
||||
sess.Join("INNER", "issue_label", "issue.id = issue_id").
|
||||
labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
|
||||
if len(labelIDs) > 0 {
|
||||
sess.
|
||||
Join("INNER", "issue_label", "issue.id = issue_id").
|
||||
In("label_id", labelIDs)
|
||||
}
|
||||
}
|
||||
@@ -1361,22 +1330,22 @@ func UpdateIssueUserByRead(uid, issueID int64) error {
|
||||
}
|
||||
|
||||
// UpdateIssueUsersByMentions updates issue-user pairs by mentioning.
|
||||
func UpdateIssueUsersByMentions(e Engine, issueID int64, uids []int64) error {
|
||||
func UpdateIssueUsersByMentions(issueID int64, uids []int64) error {
|
||||
for _, uid := range uids {
|
||||
iu := &IssueUser{
|
||||
UID: uid,
|
||||
IssueID: issueID,
|
||||
}
|
||||
has, err := e.Get(iu)
|
||||
has, err := x.Get(iu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
iu.IsMentioned = true
|
||||
if has {
|
||||
_, err = e.Id(iu.ID).AllCols().Update(iu)
|
||||
_, err = x.Id(iu.ID).AllCols().Update(iu)
|
||||
} else {
|
||||
_, err = e.Insert(iu)
|
||||
_, err = x.Insert(iu)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -123,55 +123,14 @@ func (c *Comment) AfterDelete() {
|
||||
}
|
||||
}
|
||||
|
||||
// HTMLURL formats a URL-string to the issue-comment
|
||||
func (c *Comment) HTMLURL() string {
|
||||
issue, err := GetIssueByID(c.IssueID)
|
||||
if err != nil { // Silently dropping errors :unamused:
|
||||
log.Error(4, "GetIssueByID(%d): %v", c.IssueID, err)
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s#issuecomment-%d", issue.HTMLURL(), c.ID)
|
||||
}
|
||||
|
||||
// IssueURL formats a URL-string to the issue
|
||||
func (c *Comment) IssueURL() string {
|
||||
issue, err := GetIssueByID(c.IssueID)
|
||||
if err != nil { // Silently dropping errors :unamused:
|
||||
log.Error(4, "GetIssueByID(%d): %v", c.IssueID, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
if issue.IsPull {
|
||||
return ""
|
||||
}
|
||||
return issue.HTMLURL()
|
||||
}
|
||||
|
||||
// PRURL formats a URL-string to the pull-request
|
||||
func (c *Comment) PRURL() string {
|
||||
issue, err := GetIssueByID(c.IssueID)
|
||||
if err != nil { // Silently dropping errors :unamused:
|
||||
log.Error(4, "GetIssueByID(%d): %v", c.IssueID, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
if !issue.IsPull {
|
||||
return ""
|
||||
}
|
||||
return issue.HTMLURL()
|
||||
}
|
||||
|
||||
// APIFormat converts a Comment to the api.Comment format
|
||||
func (c *Comment) APIFormat() *api.Comment {
|
||||
return &api.Comment{
|
||||
ID: c.ID,
|
||||
Poster: c.Poster.APIFormat(),
|
||||
HTMLURL: c.HTMLURL(),
|
||||
IssueURL: c.IssueURL(),
|
||||
PRURL: c.PRURL(),
|
||||
Body: c.Content,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
ID: c.ID,
|
||||
Poster: c.Poster.APIFormat(),
|
||||
Body: c.Content,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,9 +146,9 @@ func (c *Comment) EventTag() string {
|
||||
|
||||
// MailParticipants sends new comment emails to repository watchers
|
||||
// and mentioned people.
|
||||
func (c *Comment) MailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
|
||||
func (c *Comment) MailParticipants(opType ActionType, issue *Issue) (err error) {
|
||||
mentions := markdown.FindAllMentions(c.Content)
|
||||
if err = UpdateIssueMentions(e, c.IssueID, mentions); err != nil {
|
||||
if err = UpdateIssueMentions(c.IssueID, mentions); err != nil {
|
||||
return fmt.Errorf("UpdateIssueMentions [%d]: %v", c.IssueID, err)
|
||||
}
|
||||
|
||||
@@ -303,9 +262,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
||||
if err = notifyWatchers(e, act); err != nil {
|
||||
log.Error(4, "notifyWatchers: %v", err)
|
||||
}
|
||||
if err = comment.MailParticipants(e, act.OpType, opts.Issue); err != nil {
|
||||
log.Error(4, "MailParticipants: %v", err)
|
||||
}
|
||||
comment.MailParticipants(act.OpType, opts.Issue)
|
||||
}
|
||||
|
||||
return comment, nil
|
||||
@@ -418,15 +375,6 @@ func getCommentsByIssueIDSince(e Engine, issueID, since int64) ([]*Comment, erro
|
||||
return comments, sess.Find(&comments)
|
||||
}
|
||||
|
||||
func getCommentsByRepoIDSince(e Engine, repoID, since int64) ([]*Comment, error) {
|
||||
comments := make([]*Comment, 0, 10)
|
||||
sess := e.Where("issue.repo_id = ?", repoID).Join("INNER", "issue", "issue.id = comment.issue_id", repoID).Asc("created_unix")
|
||||
if since > 0 {
|
||||
sess.And("updated_unix >= ?", since)
|
||||
}
|
||||
return comments, sess.Find(&comments)
|
||||
}
|
||||
|
||||
func getCommentsByIssueID(e Engine, issueID int64) ([]*Comment, error) {
|
||||
return getCommentsByIssueIDSince(e, issueID, -1)
|
||||
}
|
||||
@@ -441,11 +389,6 @@ func GetCommentsByIssueIDSince(issueID, since int64) ([]*Comment, error) {
|
||||
return getCommentsByIssueIDSince(x, issueID, since)
|
||||
}
|
||||
|
||||
// GetCommentsByRepoIDSince returns a list of comments for all issues in a repo since a given time point.
|
||||
func GetCommentsByRepoIDSince(repoID, since int64) ([]*Comment, error) {
|
||||
return getCommentsByRepoIDSince(x, repoID, since)
|
||||
}
|
||||
|
||||
// UpdateComment updates information of comment.
|
||||
func UpdateComment(c *Comment) error {
|
||||
_, err := x.Id(c.ID).AllCols().Update(c)
|
||||
|
||||
@@ -69,7 +69,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
|
||||
// and mentioned people.
|
||||
func (issue *Issue) MailParticipants() (err error) {
|
||||
mentions := markdown.FindAllMentions(issue.Content)
|
||||
if err = UpdateIssueMentions(x, issue.ID, mentions); err != nil {
|
||||
if err = UpdateIssueMentions(issue.ID, mentions); err != nil {
|
||||
return fmt.Errorf("UpdateIssueMentions [%d]: %v", issue.ID, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -548,9 +548,9 @@ func ExternalUserLogin(user *User, login, password string, source *LoginSource,
|
||||
func UserSignIn(username, password string) (*User, error) {
|
||||
var user *User
|
||||
if strings.Contains(username, "@") {
|
||||
user = &User{Email: strings.ToLower(strings.TrimSpace(username))}
|
||||
user = &User{Email: strings.ToLower(username)}
|
||||
} else {
|
||||
user = &User{LowerName: strings.ToLower(strings.TrimSpace(username))}
|
||||
user = &User{LowerName: strings.ToLower(username)}
|
||||
}
|
||||
|
||||
hasUser, err := x.Get(user)
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"path"
|
||||
|
||||
"gopkg.in/gomail.v2"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/mailer"
|
||||
"code.gitea.io/gitea/modules/markdown"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"gopkg.in/gomail.v2"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -31,16 +31,32 @@ const (
|
||||
mailNotifyCollaborator base.TplName = "notify/collaborator"
|
||||
)
|
||||
|
||||
var templates *template.Template
|
||||
type mailRenderInterface interface {
|
||||
HTMLString(string, interface{}, ...macaron.HTMLOptions) (string, error)
|
||||
}
|
||||
|
||||
var mailRender mailRenderInterface
|
||||
|
||||
// InitMailRender initializes the macaron mail renderer
|
||||
func InitMailRender(tmpls *template.Template) {
|
||||
templates = tmpls
|
||||
func InitMailRender(dir, appendDir string, funcMap []template.FuncMap) {
|
||||
opt := &macaron.RenderOptions{
|
||||
Directory: dir,
|
||||
AppendDirectories: []string{appendDir},
|
||||
Funcs: funcMap,
|
||||
Extensions: []string{".tmpl", ".html"},
|
||||
}
|
||||
ts := macaron.NewTemplateSet()
|
||||
ts.Set(macaron.DEFAULT_TPL_SET_NAME, opt)
|
||||
|
||||
mailRender = &macaron.TplRender{
|
||||
TemplateSet: ts,
|
||||
Opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
// SendTestMail sends a test mail
|
||||
func SendTestMail(email string) error {
|
||||
return gomail.Send(&mailer.Sender{}, mailer.NewMessage([]string{email}, "Gitea Test Email!", "Gitea Test Email!").Message)
|
||||
return gomail.Send(&mailer.Sender{}, mailer.NewMessage([]string{email}, "Gogs Test Email!", "Gogs Test Email!").Message)
|
||||
}
|
||||
|
||||
// SendUserMail sends a mail to the user
|
||||
@@ -51,15 +67,13 @@ func SendUserMail(c *macaron.Context, u *User, tpl base.TplName, code, subject,
|
||||
"ResetPwdCodeLives": setting.Service.ResetPwdCodeLives / 60,
|
||||
"Code": code,
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
|
||||
if err := templates.ExecuteTemplate(&content, string(tpl), data); err != nil {
|
||||
log.Error(3, "Template: %v", err)
|
||||
body, err := mailRender.HTMLString(string(tpl), data)
|
||||
if err != nil {
|
||||
log.Error(3, "HTMLString: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{u.Email}, subject, content.String())
|
||||
msg := mailer.NewMessage([]string{u.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
@@ -83,15 +97,13 @@ func SendActivateEmailMail(c *macaron.Context, u *User, email *EmailAddress) {
|
||||
"Code": u.GenerateEmailActivateCode(email.Email),
|
||||
"Email": email.Email,
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
|
||||
if err := templates.ExecuteTemplate(&content, string(mailAuthActivateEmail), data); err != nil {
|
||||
log.Error(3, "Template: %v", err)
|
||||
body, err := mailRender.HTMLString(string(mailAuthActivateEmail), data)
|
||||
if err != nil {
|
||||
log.Error(3, "HTMLString: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), content.String())
|
||||
msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
@@ -102,15 +114,13 @@ func SendRegisterNotifyMail(c *macaron.Context, u *User) {
|
||||
data := map[string]interface{}{
|
||||
"Username": u.DisplayName(),
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
|
||||
if err := templates.ExecuteTemplate(&content, string(mailAuthRegisterNotify), data); err != nil {
|
||||
log.Error(3, "Template: %v", err)
|
||||
body, err := mailRender.HTMLString(string(mailAuthRegisterNotify), data)
|
||||
if err != nil {
|
||||
log.Error(3, "HTMLString: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), content.String())
|
||||
msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
@@ -126,15 +136,13 @@ func SendCollaboratorMail(u, doer *User, repo *Repository) {
|
||||
"RepoName": repoName,
|
||||
"Link": repo.HTMLURL(),
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
|
||||
if err := templates.ExecuteTemplate(&content, string(mailNotifyCollaborator), data); err != nil {
|
||||
log.Error(3, "Template: %v", err)
|
||||
body, err := mailRender.HTMLString(string(mailNotifyCollaborator), data)
|
||||
if err != nil {
|
||||
log.Error(3, "HTMLString: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{u.Email}, subject, content.String())
|
||||
msg := mailer.NewMessage([]string{u.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
@@ -153,14 +161,11 @@ func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []s
|
||||
body := string(markdown.RenderSpecialLink([]byte(issue.Content), issue.Repo.HTMLURL(), issue.Repo.ComposeMetas()))
|
||||
data := composeTplData(subject, body, issue.HTMLURL())
|
||||
data["Doer"] = doer
|
||||
|
||||
var content bytes.Buffer
|
||||
|
||||
if err := templates.ExecuteTemplate(&content, string(tplName), data); err != nil {
|
||||
log.Error(3, "Template: %v", err)
|
||||
content, err := mailRender.HTMLString(string(tplName), data)
|
||||
if err != nil {
|
||||
log.Error(3, "HTMLString (%s): %v", tplName, err)
|
||||
}
|
||||
|
||||
msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content.String())
|
||||
msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content)
|
||||
msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info)
|
||||
return msg
|
||||
}
|
||||
|
||||
@@ -457,12 +457,8 @@ func generateOrgRandsAndSalt(x *xorm.Engine) (err error) {
|
||||
}
|
||||
|
||||
for _, org := range orgs {
|
||||
if org.Rands, err = base.GetRandomString(10); err != nil {
|
||||
return err
|
||||
}
|
||||
if org.Salt, err = base.GetRandomString(10); err != nil {
|
||||
return err
|
||||
}
|
||||
org.Rands = base.GetRandomString(10)
|
||||
org.Salt = base.GetRandomString(10)
|
||||
if _, err = sess.Id(org.ID).Update(org); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -109,12 +109,8 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||
}
|
||||
|
||||
org.LowerName = strings.ToLower(org.Name)
|
||||
if org.Rands, err = GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
if org.Salt, err = GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
org.Rands = GetUserSalt()
|
||||
org.Salt = GetUserSalt()
|
||||
org.UseCustomAvatar = true
|
||||
org.MaxRepoCreation = -1
|
||||
org.NumTeams = 1
|
||||
|
||||
@@ -160,14 +160,14 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
||||
Ref: pr.BaseBranch,
|
||||
Sha: baseCommit.ID.String(),
|
||||
RepoID: pr.BaseRepoID,
|
||||
Repository: pr.BaseRepo.APIFormat(AccessModeNone),
|
||||
Repository: pr.BaseRepo.APIFormat(nil),
|
||||
}
|
||||
apiHeadBranchInfo := &api.PRBranchInfo{
|
||||
Name: pr.HeadBranch,
|
||||
Ref: pr.HeadBranch,
|
||||
Sha: headCommit.ID.String(),
|
||||
RepoID: pr.HeadRepoID,
|
||||
Repository: pr.HeadRepo.APIFormat(AccessModeNone),
|
||||
Repository: pr.HeadRepo.APIFormat(nil),
|
||||
}
|
||||
apiPullRequest := &api.PullRequest{
|
||||
ID: pr.ID,
|
||||
@@ -355,7 +355,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
Action: api.HookIssueClosed,
|
||||
Index: pr.Index,
|
||||
PullRequest: pr.APIFormat(),
|
||||
Repository: pr.Issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: pr.Issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
}); err != nil {
|
||||
log.Error(4, "PrepareWebhooks: %v", err)
|
||||
@@ -380,12 +380,12 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
l.PushFront(mergeCommit)
|
||||
|
||||
p := &api.PushPayload{
|
||||
Ref: git.BranchPrefix + pr.BaseBranch,
|
||||
Ref: git.BRANCH_PREFIX + pr.BaseBranch,
|
||||
Before: pr.MergeBase,
|
||||
After: pr.MergedCommitID,
|
||||
CompareURL: setting.AppURL + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
|
||||
Commits: ListToPushCommits(l).ToAPIPayloadCommits(pr.BaseRepo.HTMLURL()),
|
||||
Repo: pr.BaseRepo.APIFormat(AccessModeNone),
|
||||
Repo: pr.BaseRepo.APIFormat(nil),
|
||||
Pusher: pr.HeadRepo.MustOwner().APIFormat(),
|
||||
Sender: doer.APIFormat(),
|
||||
}
|
||||
@@ -404,6 +404,7 @@ var patchConflicts = []string{
|
||||
}
|
||||
|
||||
// testPatch checks if patch can be merged to base repository without conflict.
|
||||
// FIXME: make a mechanism to clean up stable local copies.
|
||||
func (pr *PullRequest) testPatch() (err error) {
|
||||
if pr.BaseRepo == nil {
|
||||
pr.BaseRepo, err = GetRepositoryByID(pr.BaseRepoID)
|
||||
@@ -428,9 +429,6 @@ func (pr *PullRequest) testPatch() (err error) {
|
||||
|
||||
log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
|
||||
|
||||
// Delete old temp local copy before we create a new temp local copy
|
||||
RemoveAllWithNotice("Deleting old local copy", pr.BaseRepo.LocalCopyPath())
|
||||
|
||||
if err := pr.BaseRepo.UpdateLocalCopyBranch(pr.BaseBranch); err != nil {
|
||||
return fmt.Errorf("UpdateLocalCopy: %v", err)
|
||||
}
|
||||
@@ -516,7 +514,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
||||
Action: api.HookIssueOpened,
|
||||
Index: pull.Index,
|
||||
PullRequest: pr.APIFormat(),
|
||||
Repository: repo.APIFormat(AccessModeNone),
|
||||
Repository: repo.APIFormat(nil),
|
||||
Sender: pull.Poster.APIFormat(),
|
||||
}); err != nil {
|
||||
log.Error(4, "PrepareWebhooks: %v", err)
|
||||
@@ -842,7 +840,7 @@ func AddTestPullRequestTask(doer *User, repoID int64, branch string, isSync bool
|
||||
Action: api.HookIssueSynchronized,
|
||||
Index: pr.Issue.Index,
|
||||
PullRequest: pr.Issue.PullRequest.APIFormat(),
|
||||
Repository: pr.Issue.Repo.APIFormat(AccessModeNone),
|
||||
Repository: pr.Issue.Repo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
}); err != nil {
|
||||
log.Error(4, "PrepareWebhooks [pull_id: %v]: %v", pr.ID, err)
|
||||
@@ -929,7 +927,7 @@ func TestPullRequests() {
|
||||
|
||||
pr, err := GetPullRequestByID(com.StrTo(prID).MustInt64())
|
||||
if err != nil {
|
||||
log.Error(4, "GetPullRequestByID[%s]: %v", prID, err)
|
||||
log.Error(4, "GetPullRequestByID[%d]: %v", prID, err)
|
||||
continue
|
||||
} else if err = pr.testPatch(); err != nil {
|
||||
log.Error(4, "testPatch[%d]: %v", pr.ID, err)
|
||||
|
||||
@@ -189,7 +189,7 @@ func UpdateRelease(gitRepo *git.Repository, rel *Release) (err error) {
|
||||
}
|
||||
|
||||
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
|
||||
func DeleteReleaseByID(id int64, u *User) error {
|
||||
func DeleteReleaseByID(id int64) error {
|
||||
rel, err := GetReleaseByID(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetReleaseByID: %v", err)
|
||||
@@ -200,13 +200,6 @@ func DeleteReleaseByID(id int64, u *User) error {
|
||||
return fmt.Errorf("GetRepositoryByID: %v", err)
|
||||
}
|
||||
|
||||
has, err := HasAccess(u, repo, AccessModeWrite)
|
||||
if err != nil {
|
||||
return fmt.Errorf("HasAccess: %v", err)
|
||||
} else if !has {
|
||||
return fmt.Errorf("DeleteReleaseByID: permission denied")
|
||||
}
|
||||
|
||||
_, stderr, err := process.ExecDir(-1, repo.RepoPath(),
|
||||
fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
|
||||
"git", "tag", "-d", rel.TagName)
|
||||
|
||||
@@ -276,13 +276,9 @@ func (repo *Repository) HTMLURL() string {
|
||||
}
|
||||
|
||||
// APIFormat converts a Repository to api.Repository
|
||||
func (repo *Repository) APIFormat(mode AccessMode) *api.Repository {
|
||||
// Arguments that are allowed to be nil: permission
|
||||
func (repo *Repository) APIFormat(permission *api.Permission) *api.Repository {
|
||||
cloneLink := repo.CloneLink()
|
||||
permission := &api.Permission{
|
||||
Admin: mode >= AccessModeAdmin,
|
||||
Push: mode >= AccessModeWrite,
|
||||
Pull: mode >= AccessModeRead,
|
||||
}
|
||||
return &api.Repository{
|
||||
ID: repo.ID,
|
||||
Owner: repo.Owner.APIFormat(),
|
||||
@@ -510,7 +506,7 @@ func (repo *Repository) DescriptionHTML() template.HTML {
|
||||
|
||||
// LocalCopyPath returns the local repository copy path
|
||||
func (repo *Repository) LocalCopyPath() string {
|
||||
return path.Join(setting.AppDataPath, "tmp/local-repo", com.ToStr(repo.ID))
|
||||
return path.Join(setting.AppDataPath, "tmp/local-rpeo", com.ToStr(repo.ID))
|
||||
}
|
||||
|
||||
// UpdateLocalCopyBranch pulls latest changes of given branch from repoPath to localPath.
|
||||
@@ -843,8 +839,6 @@ func getRepoInitFile(tp, name string) ([]byte, error) {
|
||||
return options.Gitignore(cleanedName)
|
||||
case "license":
|
||||
return options.License(cleanedName)
|
||||
case "label":
|
||||
return options.Labels(cleanedName)
|
||||
default:
|
||||
return []byte{}, fmt.Errorf("Invalid init file type")
|
||||
}
|
||||
|
||||
@@ -158,13 +158,13 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
|
||||
}
|
||||
oldCommitID := opts.LastCommitID
|
||||
if opts.NewBranch != opts.OldBranch {
|
||||
oldCommitID = git.EmptySHA
|
||||
oldCommitID = git.EMPTY_SHA
|
||||
}
|
||||
if err := CommitRepoAction(CommitRepoActionOptions{
|
||||
PusherName: doer.Name,
|
||||
RepoOwnerID: repo.MustOwner().ID,
|
||||
RepoName: repo.Name,
|
||||
RefFullName: git.BranchPrefix + opts.NewBranch,
|
||||
RefFullName: git.BRANCH_PREFIX + opts.NewBranch,
|
||||
OldCommitID: oldCommitID,
|
||||
NewCommitID: commit.ID.String(),
|
||||
Commits: pushCommits,
|
||||
@@ -297,7 +297,7 @@ func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (
|
||||
PusherName: doer.Name,
|
||||
RepoOwnerID: repo.MustOwner().ID,
|
||||
RepoName: repo.Name,
|
||||
RefFullName: git.BranchPrefix + opts.NewBranch,
|
||||
RefFullName: git.BRANCH_PREFIX + opts.NewBranch,
|
||||
OldCommitID: opts.LastCommitID,
|
||||
NewCommitID: commit.ID.String(),
|
||||
Commits: pushCommits,
|
||||
@@ -533,7 +533,7 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
|
||||
PusherName: doer.Name,
|
||||
RepoOwnerID: repo.MustOwner().ID,
|
||||
RepoName: repo.Name,
|
||||
RefFullName: git.BranchPrefix + opts.NewBranch,
|
||||
RefFullName: git.BRANCH_PREFIX + opts.NewBranch,
|
||||
OldCommitID: opts.LastCommitID,
|
||||
NewCommitID: commit.ID.String(),
|
||||
Commits: pushCommits,
|
||||
|
||||
@@ -231,7 +231,7 @@ func SyncMirrors() {
|
||||
|
||||
m, err := GetMirrorByRepoID(com.StrTo(repoID).MustInt64())
|
||||
if err != nil {
|
||||
log.Error(4, "GetMirrorByRepoID [%s]: %v", repoID, err)
|
||||
log.Error(4, "GetMirrorByRepoID [%d]: %v", repoID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ func SyncMirrors() {
|
||||
|
||||
m.ScheduleNextUpdate()
|
||||
if err = UpdateMirror(m); err != nil {
|
||||
log.Error(4, "UpdateMirror [%s]: %v", repoID, err)
|
||||
log.Error(4, "UpdateMirror [%d]: %v", repoID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,14 +88,7 @@ func UpdateAccessToken(t *AccessToken) error {
|
||||
}
|
||||
|
||||
// DeleteAccessTokenByID deletes access token by given ID.
|
||||
func DeleteAccessTokenByID(id, userID int64) error {
|
||||
cnt, err := x.Id(id).Delete(&AccessToken{
|
||||
UID: userID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if cnt != 1 {
|
||||
return ErrAccessTokenNotExist{}
|
||||
}
|
||||
return nil
|
||||
func DeleteAccessTokenByID(id int64) error {
|
||||
_, err := x.Id(id).Delete(new(AccessToken))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -91,10 +91,10 @@ type PushUpdateOptions struct {
|
||||
// PushUpdate must be called for any push actions in order to
|
||||
// generates necessary push action history feeds.
|
||||
func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
isNewRef := opts.OldCommitID == git.EmptySHA
|
||||
isDelRef := opts.NewCommitID == git.EmptySHA
|
||||
isNewRef := opts.OldCommitID == git.EMPTY_SHA
|
||||
isDelRef := opts.NewCommitID == git.EMPTY_SHA
|
||||
if isNewRef && isDelRef {
|
||||
return fmt.Errorf("Old and new revisions are both %s", git.EmptySHA)
|
||||
return fmt.Errorf("Old and new revisions are both %s", git.EMPTY_SHA)
|
||||
}
|
||||
|
||||
repoPath := RepoPath(opts.RepoUserName, opts.RepoName)
|
||||
@@ -106,7 +106,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
}
|
||||
|
||||
if isDelRef {
|
||||
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s",
|
||||
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %d",
|
||||
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
|
||||
return nil
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
}
|
||||
|
||||
// Push tags.
|
||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
|
||||
if err := CommitRepoAction(CommitRepoActionOptions{
|
||||
PusherName: opts.PusherName,
|
||||
RepoOwnerID: owner.ID,
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/nfnt/resize"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
|
||||
"code.gitea.io/git"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
@@ -362,7 +361,7 @@ func (u *User) NewGitSig() *git.Signature {
|
||||
|
||||
// EncodePasswd encodes password to safe format.
|
||||
func (u *User) EncodePasswd() {
|
||||
newPasswd := pbkdf2.Key([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
|
||||
newPasswd := base.PBKDF2([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
|
||||
u.Passwd = fmt.Sprintf("%x", newPasswd)
|
||||
}
|
||||
|
||||
@@ -532,7 +531,7 @@ func IsUserExist(uid int64, name string) (bool, error) {
|
||||
}
|
||||
|
||||
// GetUserSalt returns a ramdom user salt token.
|
||||
func GetUserSalt() (string, error) {
|
||||
func GetUserSalt() string {
|
||||
return base.GetRandomString(10)
|
||||
}
|
||||
|
||||
@@ -604,12 +603,8 @@ func CreateUser(u *User) (err error) {
|
||||
u.LowerName = strings.ToLower(u.Name)
|
||||
u.AvatarEmail = u.Email
|
||||
u.Avatar = base.HashEmail(u.AvatarEmail)
|
||||
if u.Rands, err = GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
if u.Salt, err = GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
u.Rands = GetUserSalt()
|
||||
u.Salt = GetUserSalt()
|
||||
u.EncodePasswd()
|
||||
u.MaxRepoCreation = -1
|
||||
|
||||
|
||||
@@ -5,16 +5,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrEmailAddressNotExist email address not exist
|
||||
ErrEmailAddressNotExist = errors.New("Email address does not exist")
|
||||
)
|
||||
|
||||
// EmailAddress is the list of all email addresses of a user. Can contain the
|
||||
// primary email address, but is not obligatory.
|
||||
type EmailAddress struct {
|
||||
@@ -122,9 +116,7 @@ func (email *EmailAddress) Activate() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user.Rands, err = GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
user.Rands = GetUserSalt()
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
@@ -147,25 +139,14 @@ func (email *EmailAddress) Activate() error {
|
||||
|
||||
// DeleteEmailAddress deletes an email address of given user.
|
||||
func DeleteEmailAddress(email *EmailAddress) (err error) {
|
||||
var deleted int64
|
||||
// ask to check UID
|
||||
var address = EmailAddress{
|
||||
UID: email.UID,
|
||||
}
|
||||
if email.ID > 0 {
|
||||
deleted, err = x.Id(email.ID).Delete(&address)
|
||||
_, err = x.Id(email.ID).Delete(new(EmailAddress))
|
||||
} else {
|
||||
deleted, err = x.
|
||||
_, err = x.
|
||||
Where("email=?", email.Email).
|
||||
Delete(&address)
|
||||
Delete(new(EmailAddress))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if deleted != 1 {
|
||||
return ErrEmailAddressNotExist
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteEmailAddresses deletes multiple email addresses
|
||||
|
||||
@@ -634,7 +634,7 @@ func DeliverHooks() {
|
||||
|
||||
tasks = make([]*HookTask, 0, 5)
|
||||
if err := x.Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
|
||||
log.Error(4, "Get repository [%s] hook tasks: %v", repoID, err)
|
||||
log.Error(4, "Get repository [%d] hook tasks: %v", repoID, err)
|
||||
continue
|
||||
}
|
||||
for _, t := range tasks {
|
||||
|
||||
@@ -33,7 +33,6 @@ func ToWikiPageURL(name string) string {
|
||||
// that are not belong to wiki repository.
|
||||
func ToWikiPageName(urlString string) string {
|
||||
name, _ := url.QueryUnescape(strings.Replace(urlString, "-", " ", -1))
|
||||
name = strings.Replace(name, "\t", " ", -1)
|
||||
return strings.Replace(strings.TrimLeft(name, "./"), "/", " ", -1)
|
||||
}
|
||||
|
||||
|
||||
@@ -151,11 +151,6 @@ func bindUser(l *ldap.Conn, userDN, passwd string) error {
|
||||
|
||||
// SearchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter
|
||||
func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, string, string, string, bool, bool) {
|
||||
// See https://tools.ietf.org/search/rfc4513#section-5.1.2
|
||||
if len(passwd) == 0 {
|
||||
log.Debug("Auth. failed for %s, password cannot be empty")
|
||||
return "", "", "", "", false, false
|
||||
}
|
||||
l, err := dial(ls)
|
||||
if err != nil {
|
||||
log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err)
|
||||
|
||||
@@ -5,15 +5,16 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
"html/template"
|
||||
"math"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -56,9 +57,6 @@ func DetectEncoding(content []byte) (string, error) {
|
||||
}
|
||||
|
||||
result, err := chardet.NewTextDetector().DetectBest(content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if result.Charset != "UTF-8" && len(setting.Repository.AnsiCharset) > 0 {
|
||||
log.Debug("Using default AnsiCharset: %s", setting.Repository.AnsiCharset)
|
||||
return setting.Repository.AnsiCharset, err
|
||||
@@ -85,31 +83,57 @@ func BasicAuthEncode(username, password string) string {
|
||||
}
|
||||
|
||||
// GetRandomString generate random string by specify chars.
|
||||
func GetRandomString(n int) (string, error) {
|
||||
func GetRandomString(n int, alphabets ...byte) string {
|
||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
buffer := make([]byte, n)
|
||||
max := big.NewInt(int64(len(alphanum)))
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
index, err := randomInt(max)
|
||||
if err != nil {
|
||||
return "", err
|
||||
var bytes = make([]byte, n)
|
||||
rand.Read(bytes)
|
||||
for i, b := range bytes {
|
||||
if len(alphabets) == 0 {
|
||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
||||
} else {
|
||||
bytes[i] = alphabets[b%byte(len(alphabets))]
|
||||
}
|
||||
|
||||
buffer[i] = alphanum[index]
|
||||
}
|
||||
|
||||
return string(buffer), nil
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func randomInt(max *big.Int) (int, error) {
|
||||
rand, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// PBKDF2 http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto
|
||||
// FIXME: use https://godoc.org/golang.org/x/crypto/pbkdf2?
|
||||
func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
|
||||
prf := hmac.New(h, password)
|
||||
hashLen := prf.Size()
|
||||
numBlocks := (keyLen + hashLen - 1) / hashLen
|
||||
|
||||
return int(rand.Int64()), nil
|
||||
var buf [4]byte
|
||||
dk := make([]byte, 0, numBlocks*hashLen)
|
||||
U := make([]byte, hashLen)
|
||||
for block := 1; block <= numBlocks; block++ {
|
||||
// N.B.: || means concatenation, ^ means XOR
|
||||
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
||||
// U_1 = PRF(password, salt || uint(i))
|
||||
prf.Reset()
|
||||
prf.Write(salt)
|
||||
buf[0] = byte(block >> 24)
|
||||
buf[1] = byte(block >> 16)
|
||||
buf[2] = byte(block >> 8)
|
||||
buf[3] = byte(block)
|
||||
prf.Write(buf[:4])
|
||||
dk = prf.Sum(dk)
|
||||
T := dk[len(dk)-hashLen:]
|
||||
copy(U, T)
|
||||
|
||||
// U_n = PRF(password, U_(n-1))
|
||||
for n := 2; n <= iter; n++ {
|
||||
prf.Reset()
|
||||
prf.Write(U)
|
||||
U = U[:0]
|
||||
U = prf.Sum(U)
|
||||
for x := range U {
|
||||
T[x] ^= U[x]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dk[:keyLen]
|
||||
}
|
||||
|
||||
// VerifyTimeLimitCode verify time limit code
|
||||
@@ -259,25 +283,19 @@ func computeTimeDiff(diff int64) (int64, string) {
|
||||
diffStr = "1 year"
|
||||
default:
|
||||
diffStr = fmt.Sprintf("%d years", diff/Year)
|
||||
diff -= (diff / Year) * Year
|
||||
diff = 0
|
||||
}
|
||||
return diff, diffStr
|
||||
}
|
||||
|
||||
// TimeSincePro calculates the time interval and generate full user-friendly string.
|
||||
func TimeSincePro(then time.Time) string {
|
||||
return timeSincePro(then, time.Now())
|
||||
}
|
||||
|
||||
func timeSincePro(then, now time.Time) string {
|
||||
now := time.Now()
|
||||
diff := now.Unix() - then.Unix()
|
||||
|
||||
if then.After(now) {
|
||||
return "future"
|
||||
}
|
||||
if diff == 0 {
|
||||
return "now"
|
||||
}
|
||||
|
||||
var timeStr, diffStr string
|
||||
for {
|
||||
@@ -291,7 +309,9 @@ func timeSincePro(then, now time.Time) string {
|
||||
return strings.TrimPrefix(timeStr, ", ")
|
||||
}
|
||||
|
||||
func timeSince(then, now time.Time, lang string) string {
|
||||
func timeSince(then time.Time, lang string) string {
|
||||
now := time.Now()
|
||||
|
||||
lbl := i18n.Tr(lang, "tool.ago")
|
||||
diff := now.Unix() - then.Unix()
|
||||
if then.After(now) {
|
||||
@@ -302,7 +322,7 @@ func timeSince(then, now time.Time, lang string) string {
|
||||
switch {
|
||||
case diff <= 0:
|
||||
return i18n.Tr(lang, "tool.now")
|
||||
case diff <= 1:
|
||||
case diff <= 2:
|
||||
return i18n.Tr(lang, "tool.1s", lbl)
|
||||
case diff < 1*Minute:
|
||||
return i18n.Tr(lang, "tool.seconds", diff, lbl)
|
||||
@@ -341,18 +361,12 @@ func timeSince(then, now time.Time, lang string) string {
|
||||
|
||||
// RawTimeSince retrieves i18n key of time since t
|
||||
func RawTimeSince(t time.Time, lang string) string {
|
||||
return timeSince(t, time.Now(), lang)
|
||||
return timeSince(t, lang)
|
||||
}
|
||||
|
||||
// TimeSince calculates the time interval and generate user-friendly string.
|
||||
func TimeSince(then time.Time, lang string) template.HTML {
|
||||
return htmlTimeSince(then, time.Now(), lang)
|
||||
}
|
||||
|
||||
func htmlTimeSince(then, now time.Time, lang string) template.HTML {
|
||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`,
|
||||
then.Format(setting.TimeFormat),
|
||||
timeSince(then, now, lang)))
|
||||
func TimeSince(t time.Time, lang string) template.HTML {
|
||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`, t.Format(setting.TimeFormat), timeSince(t, lang)))
|
||||
}
|
||||
|
||||
// Storage space size types
|
||||
@@ -437,10 +451,10 @@ func Subtract(left interface{}, right interface{}) interface{} {
|
||||
case int64:
|
||||
rright = right.(int64)
|
||||
case float32:
|
||||
fright = float64(right.(float32))
|
||||
fright = float64(left.(float32))
|
||||
isInt = false
|
||||
case float64:
|
||||
fright = right.(float64)
|
||||
fleft = left.(float64)
|
||||
isInt = false
|
||||
}
|
||||
|
||||
@@ -472,16 +486,12 @@ func TruncateString(str string, limit int) string {
|
||||
}
|
||||
|
||||
// StringsToInt64s converts a slice of string to a slice of int64.
|
||||
func StringsToInt64s(strs []string) ([]int64, error) {
|
||||
func StringsToInt64s(strs []string) []int64 {
|
||||
ints := make([]int64, len(strs))
|
||||
for i := range strs {
|
||||
n, err := com.StrTo(strs[i]).Int64()
|
||||
if err != nil {
|
||||
return ints, err
|
||||
}
|
||||
ints[i] = n
|
||||
ints[i] = com.StrTo(strs[i]).MustInt64()
|
||||
}
|
||||
return ints, nil
|
||||
return ints
|
||||
}
|
||||
|
||||
// Int64sToStrings converts a slice of int64 to a slice of string.
|
||||
@@ -525,8 +535,3 @@ func IsImageFile(data []byte) bool {
|
||||
func IsPDFFile(data []byte) bool {
|
||||
return strings.Index(http.DetectContentType(data), "application/pdf") != -1
|
||||
}
|
||||
|
||||
// IsVideoFile detectes if data is an video format
|
||||
func IsVideoFile(data []byte) bool {
|
||||
return strings.Index(http.DetectContentType(data), "video/") != -1
|
||||
}
|
||||
|
||||
@@ -4,40 +4,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/Unknwon/i18n"
|
||||
macaroni18n "github.com/go-macaron/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"strk.kbt.io/projects/go/libravatar"
|
||||
"time"
|
||||
)
|
||||
|
||||
var BaseDate time.Time
|
||||
|
||||
// time durations
|
||||
const (
|
||||
DayDur = 24 * time.Hour
|
||||
WeekDur = 7 * DayDur
|
||||
MonthDur = 30 * DayDur
|
||||
YearDur = 12 * MonthDur
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// setup
|
||||
macaroni18n.I18n(macaroni18n.Options{
|
||||
Directory: "../../options/locale/",
|
||||
DefaultLang: "en-US",
|
||||
Langs: []string{"en-US"},
|
||||
Names: []string{"english"},
|
||||
})
|
||||
BaseDate = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
// run the tests
|
||||
retVal := m.Run()
|
||||
|
||||
os.Exit(retVal)
|
||||
}
|
||||
|
||||
func TestEncodeMD5(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
"3858f62230ac3c915f300c664312c63f",
|
||||
@@ -56,41 +26,7 @@ func TestShortSha(t *testing.T) {
|
||||
assert.Equal(t, "veryverylo", ShortSha("veryverylong"))
|
||||
}
|
||||
|
||||
func TestDetectEncoding(t *testing.T) {
|
||||
testSuccess := func(b []byte, expected string) {
|
||||
encoding, err := DetectEncoding(b)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, encoding)
|
||||
}
|
||||
// utf-8
|
||||
b := []byte("just some ascii")
|
||||
testSuccess(b, "UTF-8")
|
||||
|
||||
// utf-8-sig: "hey" (with BOM)
|
||||
b = []byte{0xef, 0xbb, 0xbf, 0x68, 0x65, 0x79}
|
||||
testSuccess(b, "UTF-8")
|
||||
|
||||
// utf-16: "hey<accented G>"
|
||||
b = []byte{0xff, 0xfe, 0x68, 0x00, 0x65, 0x00, 0x79, 0x00, 0xf4, 0x01}
|
||||
testSuccess(b, "UTF-16LE")
|
||||
|
||||
// iso-8859-1: d<accented e>cor<newline>
|
||||
b = []byte{0x44, 0xe9, 0x63, 0x6f, 0x72, 0x0a}
|
||||
encoding, err := DetectEncoding(b)
|
||||
assert.NoError(t, err)
|
||||
// due to a race condition in `chardet` library, it could either detect
|
||||
// "ISO-8859-1" or "IS0-8859-2" here. Technically either is correct, so
|
||||
// we accept either.
|
||||
assert.Contains(t, encoding, "ISO-8859")
|
||||
|
||||
setting.Repository.AnsiCharset = "placeholder"
|
||||
testSuccess(b, "placeholder")
|
||||
|
||||
// invalid bytes
|
||||
b = []byte{0xfa}
|
||||
_, err = DetectEncoding(b)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
// TODO: Test DetectEncoding()
|
||||
|
||||
func TestBasicAuthDecode(t *testing.T) {
|
||||
_, _, err := BasicAuthDecode("?")
|
||||
@@ -107,9 +43,7 @@ func TestBasicAuthEncode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetRandomString(t *testing.T) {
|
||||
randomString, err := GetRandomString(4)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, randomString, 4)
|
||||
assert.Len(t, GetRandomString(4), 4)
|
||||
}
|
||||
|
||||
// TODO: Test PBKDF2()
|
||||
@@ -152,112 +86,11 @@ func TestAvatarLink(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func TestComputeTimeDiff(t *testing.T) {
|
||||
// test that for each offset in offsets,
|
||||
// computeTimeDiff(base + offset) == (offset, str)
|
||||
test := func(base int64, str string, offsets ...int64) {
|
||||
for _, offset := range offsets {
|
||||
diff, diffStr := computeTimeDiff(base + offset)
|
||||
assert.Equal(t, offset, diff)
|
||||
assert.Equal(t, str, diffStr)
|
||||
}
|
||||
}
|
||||
test(0, "now", 0)
|
||||
test(1, "1 second", 0)
|
||||
test(2, "2 seconds", 0)
|
||||
test(Minute, "1 minute", 0, 1, 30, Minute-1)
|
||||
test(2*Minute, "2 minutes", 0, Minute-1)
|
||||
test(Hour, "1 hour", 0, 1, Hour-1)
|
||||
test(5*Hour, "5 hours", 0, Hour-1)
|
||||
test(Day, "1 day", 0, 1, Day-1)
|
||||
test(5*Day, "5 days", 0, Day-1)
|
||||
test(Week, "1 week", 0, 1, Week-1)
|
||||
test(3*Week, "3 weeks", 0, 4*Day+25000)
|
||||
test(Month, "1 month", 0, 1, Month-1)
|
||||
test(10*Month, "10 months", 0, Month-1)
|
||||
test(Year, "1 year", 0, Year-1)
|
||||
test(3*Year, "3 years", 0, Year-1)
|
||||
}
|
||||
|
||||
func TestTimeSince(t *testing.T) {
|
||||
assert.Equal(t, "now", timeSince(BaseDate, BaseDate, "en"))
|
||||
|
||||
// test that each diff in `diffs` yields the expected string
|
||||
test := func(expected string, diffs ...time.Duration) {
|
||||
ago := i18n.Tr("en", "tool.ago")
|
||||
fromNow := i18n.Tr("en", "tool.from_now")
|
||||
for _, diff := range diffs {
|
||||
actual := timeSince(BaseDate, BaseDate.Add(diff), "en")
|
||||
assert.Equal(t, expected+" "+ago, actual)
|
||||
actual = timeSince(BaseDate.Add(diff), BaseDate, "en")
|
||||
assert.Equal(t, expected+" "+fromNow, actual)
|
||||
}
|
||||
}
|
||||
test("1 second", time.Second, time.Second+50*time.Millisecond)
|
||||
test("2 seconds", 2*time.Second, 2*time.Second+50*time.Millisecond)
|
||||
test("1 minute", time.Minute, time.Minute+30*time.Second)
|
||||
test("2 minutes", 2*time.Minute, 2*time.Minute+30*time.Second)
|
||||
test("1 hour", time.Hour, time.Hour+30*time.Minute)
|
||||
test("2 hours", 2*time.Hour, 2*time.Hour+30*time.Minute)
|
||||
test("1 day", DayDur, DayDur+12*time.Hour)
|
||||
test("2 days", 2*DayDur, 2*DayDur+12*time.Hour)
|
||||
test("1 week", WeekDur, WeekDur+3*DayDur)
|
||||
test("2 weeks", 2*WeekDur, 2*WeekDur+3*DayDur)
|
||||
test("1 month", MonthDur, MonthDur+15*DayDur)
|
||||
test("2 months", 2*MonthDur, 2*MonthDur+15*DayDur)
|
||||
test("1 year", YearDur, YearDur+6*MonthDur)
|
||||
test("2 years", 2*YearDur, 2*YearDur+6*MonthDur)
|
||||
}
|
||||
|
||||
func TestTimeSincePro(t *testing.T) {
|
||||
assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate))
|
||||
|
||||
// test that a difference of `diff` yields the expected string
|
||||
test := func(expected string, diff time.Duration) {
|
||||
actual := timeSincePro(BaseDate, BaseDate.Add(diff))
|
||||
assert.Equal(t, expected, actual)
|
||||
assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate))
|
||||
}
|
||||
test("1 second", time.Second)
|
||||
test("2 seconds", 2*time.Second)
|
||||
test("1 minute", time.Minute)
|
||||
test("1 minute, 1 second", time.Minute+time.Second)
|
||||
test("1 minute, 59 seconds", time.Minute+59*time.Second)
|
||||
test("2 minutes", 2*time.Minute)
|
||||
test("1 hour", time.Hour)
|
||||
test("1 hour, 1 second", time.Hour+time.Second)
|
||||
test("1 hour, 59 minutes, 59 seconds", time.Hour+59*time.Minute+59*time.Second)
|
||||
test("2 hours", 2*time.Hour)
|
||||
test("1 day", DayDur)
|
||||
test("1 day, 23 hours, 59 minutes, 59 seconds",
|
||||
DayDur+23*time.Hour+59*time.Minute+59*time.Second)
|
||||
test("2 days", 2*DayDur)
|
||||
test("1 week", WeekDur)
|
||||
test("2 weeks", 2*WeekDur)
|
||||
test("1 month", MonthDur)
|
||||
test("3 months", 3*MonthDur)
|
||||
test("1 year", YearDur)
|
||||
test("2 years, 3 months, 1 week, 2 days, 4 hours, 12 minutes, 17 seconds",
|
||||
2*YearDur+3*MonthDur+WeekDur+2*DayDur+4*time.Hour+
|
||||
12*time.Minute+17*time.Second)
|
||||
}
|
||||
|
||||
func TestHtmlTimeSince(t *testing.T) {
|
||||
setting.TimeFormat = time.UnixDate
|
||||
// test that `diff` yields a result containing `expected`
|
||||
test := func(expected string, diff time.Duration) {
|
||||
actual := htmlTimeSince(BaseDate, BaseDate.Add(diff), "en")
|
||||
assert.Contains(t, actual, `title="Sat Jan 1 00:00:00 UTC 2000"`)
|
||||
assert.Contains(t, actual, expected)
|
||||
}
|
||||
test("1 second", time.Second)
|
||||
test("3 minutes", 3*time.Minute+5*time.Second)
|
||||
test("1 day", DayDur+18*time.Hour)
|
||||
test("1 week", WeekDur+6*DayDur)
|
||||
test("3 months", 3*MonthDur+3*WeekDur)
|
||||
test("2 years", 2*YearDur)
|
||||
test("3 years", 3*YearDur+11*MonthDur+4*WeekDur)
|
||||
}
|
||||
// TODO: computeTimeDiff()
|
||||
// TODO: TimeSincePro()
|
||||
// TODO: timeSince()
|
||||
// TODO: RawTimeSince()
|
||||
// TODO: TimeSince()
|
||||
|
||||
func TestFileSize(t *testing.T) {
|
||||
var size int64
|
||||
@@ -273,48 +106,11 @@ func TestFileSize(t *testing.T) {
|
||||
assert.Equal(t, "512TB", FileSize(size))
|
||||
size = size * 1024
|
||||
assert.Equal(t, "512PB", FileSize(size))
|
||||
size = size * 4
|
||||
assert.Equal(t, "2.0EB", FileSize(size))
|
||||
//size = size * 1024 TODO: Fix bug for EB
|
||||
//assert.Equal(t, "512EB", FileSize(size))
|
||||
}
|
||||
|
||||
func TestSubtract(t *testing.T) {
|
||||
toFloat64 := func(n interface{}) float64 {
|
||||
switch n.(type) {
|
||||
case int:
|
||||
return float64(n.(int))
|
||||
case int8:
|
||||
return float64(n.(int8))
|
||||
case int16:
|
||||
return float64(n.(int16))
|
||||
case int32:
|
||||
return float64(n.(int32))
|
||||
case int64:
|
||||
return float64(n.(int64))
|
||||
case float32:
|
||||
return float64(n.(float32))
|
||||
case float64:
|
||||
return n.(float64)
|
||||
default:
|
||||
return 0.0
|
||||
}
|
||||
}
|
||||
values := []interface{}{
|
||||
int(-3),
|
||||
int8(14),
|
||||
int16(81),
|
||||
int32(-156),
|
||||
int64(1528),
|
||||
float32(3.5),
|
||||
float64(-15.348),
|
||||
}
|
||||
for _, left := range values {
|
||||
for _, right := range values {
|
||||
expected := toFloat64(left) - toFloat64(right)
|
||||
sub := Subtract(left, right)
|
||||
assert.InDelta(t, expected, sub, 1e-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Subtract()
|
||||
|
||||
func TestEllipsisString(t *testing.T) {
|
||||
assert.Equal(t, "...", EllipsisString("foobar", 0))
|
||||
@@ -339,18 +135,14 @@ func TestTruncateString(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStringsToInt64s(t *testing.T) {
|
||||
testSuccess := func(input []string, expected []int64) {
|
||||
result, err := StringsToInt64s(input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
testSuccess([]string{}, []int64{})
|
||||
testSuccess([]string{"-1234"}, []int64{-1234})
|
||||
testSuccess([]string{"1", "4", "16", "64", "256"},
|
||||
[]int64{1, 4, 16, 64, 256})
|
||||
assert.Equal(t, []int64{}, StringsToInt64s([]string{}))
|
||||
assert.Equal(t,
|
||||
[]int64{1, 4, 16, 64, 256},
|
||||
StringsToInt64s([]string{"1", "4", "16", "64", "256"}),
|
||||
)
|
||||
|
||||
_, err := StringsToInt64s([]string{"-1", "a", "$"})
|
||||
assert.Error(t, err)
|
||||
// TODO: StringsToInt64s should return ([]int64, error)
|
||||
assert.Equal(t, []int64{-1, 0, 0}, StringsToInt64s([]string{"-1", "a", "$"}))
|
||||
}
|
||||
|
||||
func TestInt64sToStrings(t *testing.T) {
|
||||
|
||||
@@ -76,11 +76,6 @@ func License(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("license", name))
|
||||
}
|
||||
|
||||
// Labels eads the content of a specific labels from static or custom path.
|
||||
func Labels(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("label", name))
|
||||
}
|
||||
|
||||
// fileFromDir is a helper to read files from static or custom path.
|
||||
func fileFromDir(name string) ([]byte, error) {
|
||||
customPath := path.Join(setting.CustomPath, "options", name)
|
||||
|
||||
@@ -72,11 +72,6 @@ func License(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("license", name))
|
||||
}
|
||||
|
||||
// Labels eads the content of a specific labels from static or custom path.
|
||||
func Labels(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("label", name))
|
||||
}
|
||||
|
||||
// fileFromDir is a helper to read files from bindata or custom path.
|
||||
func fileFromDir(name string) ([]byte, error) {
|
||||
customPath := path.Join(setting.CustomPath, "options", name)
|
||||
|
||||
@@ -6,8 +6,6 @@ package public
|
||||
|
||||
//go:generate go-bindata -tags "bindata" -ignore "\\.go|\\.less" -pkg "public" -o "bindata.go" ../../public/...
|
||||
//go:generate go fmt bindata.go
|
||||
//go:generate sed -i.bak s/..\/..\/public\/// bindata.go
|
||||
//go:generate rm -f bindata.go.bak
|
||||
|
||||
// Options represents the available options to configure the macaron handler.
|
||||
type Options struct {
|
||||
|
||||
@@ -22,7 +22,7 @@ func Static(opts *Options) macaron.Handler {
|
||||
AssetDir: AssetDir,
|
||||
AssetInfo: AssetInfo,
|
||||
AssetNames: AssetNames,
|
||||
Prefix: "",
|
||||
Prefix: "../../public",
|
||||
}),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package setting
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultLangs = strings.Split("en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR", ",")
|
||||
defaultLangNames = strings.Split("English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska,한국어", ",")
|
||||
)
|
||||
@@ -51,6 +51,10 @@ const (
|
||||
|
||||
// settings
|
||||
var (
|
||||
// BuildTime information should only be set by -ldflags.
|
||||
BuildTime string
|
||||
BuildGitHash string
|
||||
|
||||
// AppVer settings
|
||||
AppVer string
|
||||
AppName string
|
||||
@@ -80,7 +84,6 @@ var (
|
||||
StartBuiltinServer bool `ini:"START_SSH_SERVER"`
|
||||
Domain string `ini:"SSH_DOMAIN"`
|
||||
Port int `ini:"SSH_PORT"`
|
||||
ListenHost string `ini:"SSH_LISTEN_HOST"`
|
||||
ListenPort int `ini:"SSH_LISTEN_PORT"`
|
||||
RootPath string `ini:"SSH_ROOT_PATH"`
|
||||
KeyTestPath string `ini:"SSH_KEY_TEST_PATH"`
|
||||
@@ -104,21 +107,16 @@ var (
|
||||
UseTiDB bool
|
||||
|
||||
// Webhook settings
|
||||
Webhook = struct {
|
||||
Webhook struct {
|
||||
QueueLength int
|
||||
DeliverTimeout int
|
||||
SkipTLSVerify bool
|
||||
Types []string
|
||||
PagingNum int
|
||||
}{
|
||||
QueueLength: 1000,
|
||||
DeliverTimeout: 5,
|
||||
SkipTLSVerify: false,
|
||||
PagingNum: 10,
|
||||
}
|
||||
|
||||
// Repository settings
|
||||
Repository = struct {
|
||||
Repository struct {
|
||||
AnsiCharset string
|
||||
ForcePrivate bool
|
||||
MaxCreationLimit int
|
||||
@@ -141,44 +139,12 @@ var (
|
||||
FileMaxSize int64
|
||||
MaxFiles int
|
||||
} `ini:"-"`
|
||||
}{
|
||||
AnsiCharset: "",
|
||||
ForcePrivate: false,
|
||||
MaxCreationLimit: -1,
|
||||
MirrorQueueLength: 1000,
|
||||
PullRequestQueueLength: 1000,
|
||||
PreferredLicenses: []string{"Apache License 2.0,MIT License"},
|
||||
DisableHTTPGit: false,
|
||||
|
||||
// Repository editor settings
|
||||
Editor: struct {
|
||||
LineWrapExtensions []string
|
||||
PreviewableFileModes []string
|
||||
}{
|
||||
LineWrapExtensions: strings.Split(".txt,.md,.markdown,.mdown,.mkd,", ","),
|
||||
PreviewableFileModes: []string{"markdown"},
|
||||
},
|
||||
|
||||
// Repository upload settings
|
||||
Upload: struct {
|
||||
Enabled bool
|
||||
TempPath string
|
||||
AllowedTypes []string `delim:"|"`
|
||||
FileMaxSize int64
|
||||
MaxFiles int
|
||||
}{
|
||||
Enabled: true,
|
||||
TempPath: "data/tmp/uploads",
|
||||
AllowedTypes: []string{},
|
||||
FileMaxSize: 3,
|
||||
MaxFiles: 5,
|
||||
},
|
||||
}
|
||||
RepoRootPath string
|
||||
ScriptType = "bash"
|
||||
ScriptType string
|
||||
|
||||
// UI settings
|
||||
UI = struct {
|
||||
UI struct {
|
||||
ExplorePagingNum int
|
||||
IssuePagingNum int
|
||||
FeedMaxCommitNum int
|
||||
@@ -194,38 +160,13 @@ var (
|
||||
User struct {
|
||||
RepoPagingNum int
|
||||
} `ini:"ui.user"`
|
||||
}{
|
||||
ExplorePagingNum: 20,
|
||||
IssuePagingNum: 10,
|
||||
FeedMaxCommitNum: 5,
|
||||
ThemeColorMetaTag: `#6cc644`,
|
||||
MaxDisplayFileSize: 8388608,
|
||||
Admin: struct {
|
||||
UserPagingNum int
|
||||
RepoPagingNum int
|
||||
NoticePagingNum int
|
||||
OrgPagingNum int
|
||||
}{
|
||||
UserPagingNum: 50,
|
||||
RepoPagingNum: 50,
|
||||
NoticePagingNum: 25,
|
||||
OrgPagingNum: 50,
|
||||
},
|
||||
User: struct {
|
||||
RepoPagingNum int
|
||||
}{
|
||||
RepoPagingNum: 15,
|
||||
},
|
||||
}
|
||||
|
||||
// Markdown sttings
|
||||
Markdown = struct {
|
||||
Markdown struct {
|
||||
EnableHardLineBreak bool
|
||||
CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"`
|
||||
FileExtensions []string
|
||||
}{
|
||||
EnableHardLineBreak: false,
|
||||
FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd", ","),
|
||||
}
|
||||
|
||||
// Picture settings
|
||||
@@ -260,7 +201,7 @@ var (
|
||||
CSRFCookieName = "_csrf"
|
||||
|
||||
// Cron tasks
|
||||
Cron = struct {
|
||||
Cron struct {
|
||||
UpdateMirror struct {
|
||||
Enabled bool
|
||||
RunAtStart bool
|
||||
@@ -278,37 +219,10 @@ var (
|
||||
RunAtStart bool
|
||||
Schedule string
|
||||
} `ini:"cron.check_repo_stats"`
|
||||
}{
|
||||
UpdateMirror: struct {
|
||||
Enabled bool
|
||||
RunAtStart bool
|
||||
Schedule string
|
||||
}{
|
||||
Schedule: "@every 10m",
|
||||
},
|
||||
RepoHealthCheck: struct {
|
||||
Enabled bool
|
||||
RunAtStart bool
|
||||
Schedule string
|
||||
Timeout time.Duration
|
||||
Args []string `delim:" "`
|
||||
}{
|
||||
Schedule: "@every 24h",
|
||||
Timeout: 60 * time.Second,
|
||||
Args: []string{},
|
||||
},
|
||||
CheckRepoStats: struct {
|
||||
Enabled bool
|
||||
RunAtStart bool
|
||||
Schedule string
|
||||
}{
|
||||
RunAtStart: true,
|
||||
Schedule: "@every 24h",
|
||||
},
|
||||
}
|
||||
|
||||
// Git settings
|
||||
Git = struct {
|
||||
Git struct {
|
||||
DisableDiffHighlight bool
|
||||
MaxGitDiffLines int
|
||||
MaxGitDiffLineCharacters int
|
||||
@@ -321,39 +235,16 @@ var (
|
||||
Pull int
|
||||
GC int `ini:"GC"`
|
||||
} `ini:"git.timeout"`
|
||||
}{
|
||||
DisableDiffHighlight: false,
|
||||
MaxGitDiffLines: 1000,
|
||||
MaxGitDiffLineCharacters: 500,
|
||||
MaxGitDiffFiles: 100,
|
||||
GCArgs: []string{},
|
||||
Timeout: struct {
|
||||
Migrate int
|
||||
Mirror int
|
||||
Clone int
|
||||
Pull int
|
||||
GC int `ini:"GC"`
|
||||
}{
|
||||
Migrate: 600,
|
||||
Mirror: 300,
|
||||
Clone: 300,
|
||||
Pull: 300,
|
||||
GC: 60,
|
||||
},
|
||||
}
|
||||
|
||||
// Mirror settings
|
||||
Mirror = struct {
|
||||
Mirror struct {
|
||||
DefaultInterval int
|
||||
}{
|
||||
DefaultInterval: 8,
|
||||
}
|
||||
|
||||
// API settings
|
||||
API = struct {
|
||||
API struct {
|
||||
MaxResponseItems int
|
||||
}{
|
||||
MaxResponseItems: 50,
|
||||
}
|
||||
|
||||
// I18n settings
|
||||
@@ -461,10 +352,6 @@ func NewContext() {
|
||||
|
||||
Cfg = ini.Empty()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to parse 'app.ini': %v", err)
|
||||
}
|
||||
|
||||
CustomPath = os.Getenv("GITEA_CUSTOM")
|
||||
if len(CustomPath) == 0 {
|
||||
// For backward compatibility
|
||||
@@ -555,10 +442,6 @@ please consider changing to GITEA_CUSTOM`)
|
||||
if err = Cfg.Section("server").MapTo(&SSH); err != nil {
|
||||
log.Fatal(4, "Fail to map SSH settings: %v", err)
|
||||
}
|
||||
|
||||
SSH.KeygenPath = sec.Key("SSH_KEYGEN_PATH").MustString("ssh-keygen")
|
||||
SSH.Port = sec.Key("SSH_PORT").MustInt(22)
|
||||
|
||||
// When disable SSH, start builtin server value is ignored.
|
||||
if SSH.Disabled {
|
||||
SSH.StartBuiltinServer = false
|
||||
@@ -582,11 +465,11 @@ please consider changing to GITEA_CUSTOM`)
|
||||
}
|
||||
|
||||
sec = Cfg.Section("security")
|
||||
InstallLock = sec.Key("INSTALL_LOCK").MustBool(false)
|
||||
SecretKey = sec.Key("SECRET_KEY").MustString("!#@FDEWREWR&*(")
|
||||
LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7)
|
||||
CookieUserName = sec.Key("COOKIE_USERNAME").MustString("gitea_awesome")
|
||||
CookieRememberName = sec.Key("COOKIE_REMEMBER_NAME").MustString("gitea_incredible")
|
||||
InstallLock = sec.Key("INSTALL_LOCK").MustBool()
|
||||
SecretKey = sec.Key("SECRET_KEY").String()
|
||||
LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt()
|
||||
CookieUserName = sec.Key("COOKIE_USERNAME").String()
|
||||
CookieRememberName = sec.Key("COOKIE_REMEMBER_NAME").String()
|
||||
ReverseProxyAuthUser = sec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER")
|
||||
|
||||
sec = Cfg.Section("attachment")
|
||||
@@ -617,7 +500,7 @@ please consider changing to GITEA_CUSTOM`)
|
||||
"StampNano": time.StampNano,
|
||||
}[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")]
|
||||
|
||||
RunUser = Cfg.Section("").Key("RUN_USER").MustString(user.CurrentUsername())
|
||||
RunUser = Cfg.Section("").Key("RUN_USER").String()
|
||||
// Does not check run user when the install lock is off.
|
||||
if InstallLock {
|
||||
currentUser, match := IsRunUserMatchCurrentUser(RunUser)
|
||||
@@ -660,8 +543,6 @@ please consider changing to GITEA_CUSTOM`)
|
||||
GravatarSource = "http://gravatar.duoshuo.com/avatar/"
|
||||
case "gravatar":
|
||||
GravatarSource = "https://secure.gravatar.com/avatar/"
|
||||
case "libravatar":
|
||||
GravatarSource = "https://seccdn.libravatar.org/avatar/"
|
||||
default:
|
||||
GravatarSource = source
|
||||
}
|
||||
@@ -708,18 +589,12 @@ please consider changing to GITEA_CUSTOM`)
|
||||
}
|
||||
|
||||
Langs = Cfg.Section("i18n").Key("LANGS").Strings(",")
|
||||
if len(Langs) == 0 {
|
||||
Langs = defaultLangs
|
||||
}
|
||||
Names = Cfg.Section("i18n").Key("NAMES").Strings(",")
|
||||
if len(Names) == 0 {
|
||||
Names = defaultLangNames
|
||||
}
|
||||
dateLangs = Cfg.Section("i18n.datelang").KeysHash()
|
||||
|
||||
ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool(false)
|
||||
ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool(true)
|
||||
ShowFooterTemplateLoadTime = Cfg.Section("other").Key("SHOW_FOOTER_TEMPLATE_LOAD_TIME").MustBool(true)
|
||||
ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool()
|
||||
ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool()
|
||||
ShowFooterTemplateLoadTime = Cfg.Section("other").Key("SHOW_FOOTER_TEMPLATE_LOAD_TIME").MustBool()
|
||||
|
||||
HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt"))
|
||||
}
|
||||
@@ -760,18 +635,21 @@ var logLevels = map[string]string{
|
||||
}
|
||||
|
||||
func newLogService() {
|
||||
log.Info("Gitea v%s", AppVer)
|
||||
log.Info("%s %s", AppName, AppVer)
|
||||
|
||||
if len(BuildTime) > 0 {
|
||||
log.Info("Build Time: %s", BuildTime)
|
||||
log.Info("Build Git Hash: %s", BuildGitHash)
|
||||
}
|
||||
|
||||
// Get and check log mode.
|
||||
LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",")
|
||||
LogConfigs = make([]string, len(LogModes))
|
||||
|
||||
for i, mode := range LogModes {
|
||||
mode = strings.TrimSpace(mode)
|
||||
|
||||
sec, err := Cfg.GetSection("log." + mode)
|
||||
|
||||
if err != nil {
|
||||
sec, _ = Cfg.NewSection("log." + mode)
|
||||
log.Fatal(4, "Unknown log mode: %s", mode)
|
||||
}
|
||||
|
||||
validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
|
||||
@@ -809,11 +687,11 @@ func newLogService() {
|
||||
sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}),
|
||||
sec.Key("ADDR").MustString(":7020"))
|
||||
case "smtp":
|
||||
LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":["%s"],"subject":"%s"}`, level,
|
||||
LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":"%s","subject":"%s"}`, level,
|
||||
sec.Key("USER").MustString("example@example.com"),
|
||||
sec.Key("PASSWD").MustString("******"),
|
||||
sec.Key("HOST").MustString("127.0.0.1:25"),
|
||||
strings.Replace(sec.Key("RECEIVERS").MustString("example@example.com"), ",", "\",\"", -1),
|
||||
sec.Key("RECEIVERS").MustString("[]"),
|
||||
sec.Key("SUBJECT").MustString("Diagnostic message from serve"))
|
||||
case "database":
|
||||
LogConfigs[i] = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level,
|
||||
@@ -846,7 +724,7 @@ func newSessionService() {
|
||||
SessionConfig.ProviderConfig = strings.Trim(Cfg.Section("session").Key("PROVIDER_CONFIG").String(), "\" ")
|
||||
SessionConfig.CookieName = Cfg.Section("session").Key("COOKIE_NAME").MustString("i_like_gogits")
|
||||
SessionConfig.CookiePath = AppSubURL
|
||||
SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool(false)
|
||||
SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool()
|
||||
SessionConfig.Gclifetime = Cfg.Section("session").Key("GC_INTERVAL_TIME").MustInt64(86400)
|
||||
SessionConfig.Maxlifetime = Cfg.Section("session").Key("SESSION_LIFE_TIME").MustInt64(86400)
|
||||
|
||||
|
||||
@@ -110,10 +110,10 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) {
|
||||
}
|
||||
}
|
||||
|
||||
func listen(config *ssh.ServerConfig, host string, port int) {
|
||||
listener, err := net.Listen("tcp", host+":"+com.ToStr(port))
|
||||
func listen(config *ssh.ServerConfig, port int) {
|
||||
listener, err := net.Listen("tcp", "0.0.0.0:"+com.ToStr(port))
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to start SSH server: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
for {
|
||||
// Once a ServerConfig has been configured, connections can be accepted.
|
||||
@@ -148,7 +148,7 @@ func listen(config *ssh.ServerConfig, host string, port int) {
|
||||
}
|
||||
|
||||
// Listen starts a SSH server listens on given port.
|
||||
func Listen(host string, port int) {
|
||||
func Listen(port int) {
|
||||
config := &ssh.ServerConfig{
|
||||
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key))))
|
||||
@@ -185,5 +185,5 @@ func Listen(host string, port int) {
|
||||
}
|
||||
config.AddHostKey(private)
|
||||
|
||||
go listen(config, host, port)
|
||||
go listen(config, port)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package templates
|
||||
package template
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
@@ -1,103 +0,0 @@
|
||||
// +build !bindata
|
||||
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/Unknwon/com"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
templates = template.New("")
|
||||
)
|
||||
|
||||
// Renderer implements the macaron handler for serving the templates.
|
||||
func Renderer() macaron.Handler {
|
||||
return macaron.Renderer(macaron.RenderOptions{
|
||||
Funcs: NewFuncMap(),
|
||||
Directory: path.Join(setting.StaticRootPath, "templates"),
|
||||
AppendDirectories: []string{
|
||||
path.Join(setting.CustomPath, "templates"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Mailer provides the templates required for sending notification mails.
|
||||
func Mailer() *template.Template {
|
||||
for _, funcs := range NewFuncMap() {
|
||||
templates.Funcs(funcs)
|
||||
}
|
||||
|
||||
staticDir := path.Join(setting.StaticRootPath, "templates", "mail")
|
||||
|
||||
if com.IsDir(staticDir) {
|
||||
files, err := com.StatDir(staticDir)
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read %s templates dir. %v", staticDir, err)
|
||||
} else {
|
||||
for _, filePath := range files {
|
||||
if !strings.HasSuffix(filePath, ".tmpl") {
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(path.Join(staticDir, filePath))
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read static %s template. %v", filePath, err)
|
||||
continue
|
||||
}
|
||||
|
||||
templates.New(
|
||||
strings.TrimSuffix(
|
||||
filePath,
|
||||
".tmpl",
|
||||
),
|
||||
).Parse(string(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customDir := path.Join(setting.CustomPath, "templates", "mail")
|
||||
|
||||
if com.IsDir(customDir) {
|
||||
files, err := com.StatDir(customDir)
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read %s templates dir. %v", customDir, err)
|
||||
} else {
|
||||
for _, filePath := range files {
|
||||
if !strings.HasSuffix(filePath, ".tmpl") {
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(path.Join(customDir, filePath))
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read custom %s template. %v", filePath, err)
|
||||
continue
|
||||
}
|
||||
|
||||
templates.New(
|
||||
strings.TrimSuffix(
|
||||
filePath,
|
||||
".tmpl",
|
||||
),
|
||||
).Parse(string(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return templates
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
// +build bindata
|
||||
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-macaron/bindata"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
templates = template.New("")
|
||||
)
|
||||
|
||||
// Renderer implements the macaron handler for serving the templates.
|
||||
func Renderer() macaron.Handler {
|
||||
return macaron.Renderer(macaron.RenderOptions{
|
||||
Funcs: NewFuncMap(),
|
||||
AppendDirectories: []string{
|
||||
path.Join(setting.CustomPath, "templates"),
|
||||
},
|
||||
TemplateFileSystem: bindata.Templates(
|
||||
bindata.Options{
|
||||
Asset: Asset,
|
||||
AssetDir: AssetDir,
|
||||
AssetInfo: AssetInfo,
|
||||
AssetNames: AssetNames,
|
||||
Prefix: "",
|
||||
},
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
// Mailer provides the templates required for sending notification mails.
|
||||
func Mailer() *template.Template {
|
||||
for _, funcs := range NewFuncMap() {
|
||||
templates.Funcs(funcs)
|
||||
}
|
||||
|
||||
for _, assetPath := range AssetNames() {
|
||||
if !strings.HasPrefix(assetPath, "mail/") {
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(assetPath, ".tmpl") {
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := Asset(assetPath)
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read embedded %s template. %v", assetPath, err)
|
||||
continue
|
||||
}
|
||||
|
||||
templates.New(
|
||||
strings.TrimPrefix(
|
||||
strings.TrimSuffix(
|
||||
assetPath,
|
||||
".tmpl",
|
||||
),
|
||||
"mail/",
|
||||
),
|
||||
).Parse(string(content))
|
||||
}
|
||||
|
||||
customDir := path.Join(setting.CustomPath, "templates", "mail")
|
||||
|
||||
if com.IsDir(customDir) {
|
||||
files, err := com.StatDir(customDir)
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read %s templates dir. %v", customDir, err)
|
||||
} else {
|
||||
for _, filePath := range files {
|
||||
if !strings.HasSuffix(filePath, ".tmpl") {
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(path.Join(customDir, filePath))
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Failed to read custom %s template. %v", filePath, err)
|
||||
continue
|
||||
}
|
||||
|
||||
templates.New(
|
||||
strings.TrimSuffix(
|
||||
filePath,
|
||||
".tmpl",
|
||||
),
|
||||
).Parse(string(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return templates
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package templates
|
||||
|
||||
//go:generate go-bindata -tags "bindata" -ignore "\\.go" -pkg "templates" -o "bindata.go" ../../templates/...
|
||||
//go:generate go fmt bindata.go
|
||||
//go:generate sed -i.bak s/..\/..\/templates\/// bindata.go
|
||||
//go:generate rm -f bindata.go.bak
|
||||
@@ -17,7 +17,6 @@ Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com>
|
||||
Camille Baronnet <gogs AT camillebaronnet DOT fr>
|
||||
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
|
||||
Cysioland
|
||||
Damaris Padieu <damizx AT hotmail DOT fr>
|
||||
Daniel Speichert <daniel AT speichert DOT pl>
|
||||
David Yzaguirre <dvdyzag AT gmail DOT com>
|
||||
Dmitriy Nogay <me AT catwhocode DOT ga>
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Потребителско име
|
||||
admin_password=Парола
|
||||
confirm_password=Потвърждение на паролата
|
||||
admin_email=Ел. поща
|
||||
install_btn_confirm=Инсталирай Gitea
|
||||
install_gogs=Инсталирай Gitea
|
||||
test_git_failed=Неуспешно тестването на "git" команда: %v
|
||||
sqlite3_not_available=Вашата версия не поддържа SQLite3, моля, изтеглете официалната двоична версия от %s, а не gobuild версията.
|
||||
invalid_db_setting=Настройките на базата данни са некоректни: %v
|
||||
|
||||
@@ -96,8 +96,8 @@ offline_mode=Zapnout režim offline
|
||||
offline_mode_popup=Vypnout síť doručování obsahu (CDN) i v produkčním režimu, vše bude obslouženo místně.
|
||||
disable_gravatar=Vypnout službu Gravatar
|
||||
disable_gravatar_popup=Vypnout službu Gravatar a ostatní zdroje. Všechny ikony uživatelů budou nahrány uživateli nebo výchozí.
|
||||
federated_avatar_lookup=Povolit vyhledání avatarů z veřejných zdrojů
|
||||
federated_avatar_lookup_popup=Povolte vyhledání avatarů z veřejných zdrojů pro využití služeb založených na libravatar.
|
||||
federated_avatar_lookup=Enable Federated Avatars Lookup
|
||||
federated_avatar_lookup_popup=Enable federated avatars lookup to use federated open source service based on libravatar.
|
||||
disable_registration=Vypnout možnost se zaregistrovat
|
||||
disable_registration_popup=Vypnout možnost registrace, pouze správce může vytvořit účty.
|
||||
enable_captcha=Povolit službu CAPTCHA
|
||||
@@ -110,7 +110,7 @@ admin_name=Uživatelské jméno
|
||||
admin_password=Heslo
|
||||
confirm_password=Potvrdit heslo
|
||||
admin_email=E-mailová adresa správce
|
||||
install_btn_confirm=Nainstalovat Gitea
|
||||
install_gogs=Nainstalovat Gitea
|
||||
test_git_failed=Chyba při testu příkazu 'git': %v
|
||||
sqlite3_not_available=Vaše verze vydání Gitea nepodporuje SQLite3, prosíme stáhněte si oficiální binární balíček z %s, ne gobuild verzi.
|
||||
invalid_db_setting=Nastavení databáze není správné: %v
|
||||
@@ -162,7 +162,7 @@ reset_password=Obnova vašeho hesla
|
||||
invalid_code=Omlouváme se, ale kód potvrzení vašeho účtu vypršel nebo není správný.
|
||||
reset_password_helper=Klikněte zde pro obnovu vašeho hesla
|
||||
password_too_short=Délka hesla musí být minimálně 6 znaků.
|
||||
non_local_account=Externí účty nemohou měnit hesla přes Gitea.
|
||||
non_local_account=Non-local accounts cannot change passwords through Gitea.
|
||||
|
||||
[mail]
|
||||
activate_account=Prosíme, aktivujte si váš účet
|
||||
@@ -270,7 +270,7 @@ continue=Pokračovat
|
||||
cancel=Zrušit
|
||||
|
||||
lookup_avatar_by_mail=Vyhledávat uživatelskou ikonu podle emailu
|
||||
federated_avatar_lookup=Vyhledání Avatarů ve veřejných zdrojích
|
||||
federated_avatar_lookup=Federated Avatar Lookup
|
||||
enable_custom_avatar=Povolit uživatelskou ikonu uživatele
|
||||
choose_new_avatar=Vybrat novou ikonu uživatele
|
||||
update_avatar=Aktualizovat nastavení ikony uživatele
|
||||
@@ -366,7 +366,7 @@ auto_init=Inicializovat tento repositář s vybranými soubory a šablonou
|
||||
create_repo=Vytvořit repositář
|
||||
default_branch=Výchozí větev
|
||||
mirror_prune=Vyčistit
|
||||
mirror_prune_desc=Odstranit vzdálené odkazy, které již ve vzdáleném repozitáři neexistují
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_interval=Odstup zrcadlení (hodina)
|
||||
mirror_address=Adresa zrcadla
|
||||
mirror_address_desc=Prosím, přidejte do adresy potřebné přihlašovací údaje.
|
||||
@@ -439,7 +439,7 @@ editor.delete_this_file=Odstranit tento soubor
|
||||
editor.must_have_write_access=Musíte mít přístup pro zápis pro dělání či navrhování změn tohoto souboru
|
||||
editor.file_delete_success=Soubor '%s' byl úspěšně odstraněn!
|
||||
editor.name_your_file=Pojmenujte váš soubor...
|
||||
editor.filename_help=Pro vložení adresáře prostě napište jméno a přidejte /. K odstranění adresáře běžte na začátek pole a stiskněte backspace.
|
||||
editor.filename_help=To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
|
||||
editor.or=nebo
|
||||
editor.cancel_lower=zrušit
|
||||
editor.commit_changes=Uložit změny revize
|
||||
@@ -454,13 +454,13 @@ editor.new_branch_name_desc=Nový název větve...
|
||||
editor.cancel=Zrušit
|
||||
editor.filename_cannot_be_empty=Název souboru nemůže být prázdný.
|
||||
editor.branch_already_exists=Repositář větev '%s' již obsahuje.
|
||||
editor.directory_is_a_file=Položka '%s' v nadřazené cestě je v tomto repozitáři soubor, ne adresář.
|
||||
editor.filename_is_a_directory=Jméno souboru '%s' koliduje v tomto repozitáři se jménem adresáře.
|
||||
editor.file_editing_no_longer_exists=Soubor '%s', který upravujete, již neexistuje v tomto repozitáři.
|
||||
editor.file_changed_while_editing=Obsah souboru se změnil od začátku úprav. <a target="_blank" href="%s"> Klepnutím sem</a> zobrazíte, co se změnilo, nebo <strong>stiskněte potvrdit znovu</strong> pro přepsání změn.
|
||||
editor.file_already_exists=Soubor '%s' již existuje v tomto repozitáři.
|
||||
editor.no_changes_to_show=Žádné změny k zobrazení.
|
||||
editor.fail_to_update_file=Vytvoření nebo změna souboru '%s' skončilo chybou: %v
|
||||
editor.directory_is_a_file=Entry '%s' in the parent path is a file not a directory in this repository.
|
||||
editor.filename_is_a_directory=The filename '%s' is an existing directory in this repository.
|
||||
editor.file_editing_no_longer_exists=The file '%s' you are editing no longer exists in the repository.
|
||||
editor.file_changed_while_editing=Obsah souboru se změnil od začátku úprav. <a target="_blank" rel="noopener" href="%s"> Klepnutím sem</a> zobrazíte, co se změnilo, nebo <strong>stiskněte potvrdit znovu</strong> pro přepsání změn.
|
||||
editor.file_already_exists=A file with name '%s' already exists in this repository.
|
||||
editor.no_changes_to_show=There are no changes to show.
|
||||
editor.fail_to_update_file=Failed to update/create file '%s' with error: %v
|
||||
editor.add_subdir=Přidat podadresář...
|
||||
editor.unable_to_upload_files=Nepodařilo se nahrát soubor '%s'. Chyba: %v
|
||||
editor.upload_files_to_dir=Nahrát soubory do '%s'
|
||||
@@ -673,7 +673,7 @@ settings.delete=Smazat tento repositář
|
||||
settings.delete_desc=Jakmile smažete repositář, není možné se vrátit. Buďte si, prosím, jist.
|
||||
settings.delete_notices_1=- Tuto operaci <strong>nelze</strong> zvrátit.
|
||||
settings.delete_notices_2=Tato operace permanentně smaže vše v tomto repositáři, včetně dat Gitu, úkolů, komentářů a přístupu spolupracovníků.
|
||||
settings.delete_notices_fork_1=- Po smazání se všechny forky se stanou nezávislé.
|
||||
settings.delete_notices_fork_1=- All forks will become independent after deletion.
|
||||
settings.deletion_success=Repositář byl úspěšně smazán!
|
||||
settings.update_settings_success=Možnosti repositáře byly úspěšně změněny.
|
||||
settings.transfer_owner=Nový vlastník
|
||||
@@ -721,7 +721,7 @@ settings.event_choose=Nech mne vybrat, co potřebuji.
|
||||
settings.event_create=Vytvořit
|
||||
settings.event_create_desc=Větev nebo značka byla vytvořena
|
||||
settings.event_pull_request=Požadavek na stažení
|
||||
settings.event_pull_request_desc=Pull request byl otevřen, uzavřen, znovu-otevřen, upraven, přiřazen, zrušeno přiřazení, popis upraven, smazán nebo synchronizován.
|
||||
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
|
||||
settings.event_push=Nahrát
|
||||
settings.event_push_desc=Nahrání pomocí Gitu do repositáře
|
||||
settings.active=Aktivní
|
||||
@@ -759,7 +759,7 @@ diff.show_unified_view=Jednotný pohled
|
||||
diff.stats_desc=<strong> %d změnil soubory</strong>, kde provedl <strong>%d přidání</strong> a <strong>%d odebrání</strong>
|
||||
diff.bin=binární
|
||||
diff.view_file=Zobrazit soubor
|
||||
diff.file_suppressed=Diff nebyl zobrazen, protože je příliš veliký
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=Některé soubory nejsou zobrazny, neboť je v této revizi změněno mnoho souborů
|
||||
|
||||
release.releases=Vydání
|
||||
@@ -860,7 +860,7 @@ teams.owners_permission_desc=Vlastníci mají plný přístup do <strong>všech
|
||||
teams.members=Členové týmu
|
||||
teams.update_settings=Upravit nastavení
|
||||
teams.delete_team=Smazat tento tým
|
||||
teams.add_team_member=Přidat člena týmu
|
||||
teams.add_team_member=Přidát člena týmu
|
||||
teams.delete_team_title=Smazání týmu
|
||||
teams.delete_team_desc=Jelikož bude tento tým smazán, jeho členové mohou ztratit přístup do některých repositářů. Chcete pokračovat?
|
||||
teams.delete_team_success=Daný tým byl úspěšně smazán.
|
||||
@@ -1182,13 +1182,13 @@ now=nyní
|
||||
1w=%s 1 týdnem
|
||||
1mon=%s 1 měsícem
|
||||
1y=%s 1 rokem
|
||||
seconds=%[2]s %[1]d sekundami
|
||||
minutes=%[2]s %[1]d minutami
|
||||
hours=%[2]s %[1]d hodinami
|
||||
days=%[2]s %[1]d dny
|
||||
weeks=%[2]s %[1]d týdny
|
||||
months=%[2]s %[1]d měsíci
|
||||
years=%[2]s %[1]d roky
|
||||
seconds=%s %d sekundami
|
||||
minutes=%s %d minutami
|
||||
hours=%s %d hodinami
|
||||
days=%s %d dny
|
||||
weeks=%s %d týdny
|
||||
months=%s %d měsíci
|
||||
years=%s %d roky
|
||||
raw_seconds=sekund
|
||||
raw_minutes=minut
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Benutzername
|
||||
admin_password=Passwort
|
||||
confirm_password=Passwort bestätigen
|
||||
admin_email=Administrator E-Mail
|
||||
install_btn_confirm=Gitea installieren
|
||||
install_gogs=Gitea installieren
|
||||
test_git_failed=Fehler beim Test des 'git' Kommandos: %v
|
||||
sqlite3_not_available=Ihre Gitea-Version unterstützt SQLite3 nicht. Bitte laden Sie die offizielle binäre Version von %s herunter, NICHT die gobuild-Version.
|
||||
invalid_db_setting=Datenbankeinstellungen sind nicht korrekt: %v
|
||||
@@ -401,7 +401,6 @@ watch=Beobachten
|
||||
unstar=Favorit entfernen
|
||||
star=Favorit hinzufügen
|
||||
fork=Fork
|
||||
download_archive=Dieses Repository herunterladen
|
||||
|
||||
no_desc=Keine Beschreibung
|
||||
quick_guide=Kurzanleitung
|
||||
@@ -456,7 +455,6 @@ editor.cancel=Abbrechen
|
||||
editor.filename_cannot_be_empty=Der Dateiname darf nicht leer sein.
|
||||
editor.branch_already_exists=Branch '%s' existiert bereits in diesem Repository.
|
||||
editor.directory_is_a_file='%s' im übergeordneten Verzeichnis ist eine Datei und kein Verzeichnis.
|
||||
editor.file_is_a_symlink=Die Datei '%s' ist ein Symlink der nicht über den Web Editor bearbeitet werden kann.
|
||||
editor.filename_is_a_directory=Die Datei '%s' existiert bereits als Verzeichnis in diesem Repository.
|
||||
editor.file_editing_no_longer_exists=Die Datei '%s', welche Sie bearbeiten, existiert in diesem Repository nicht mehr.
|
||||
editor.file_changed_while_editing=Seit dem Start der Bearbeitung hat sich die Datei geändert. <a target="_blank" rel="noopener" href="%s">Hier klicken</a> um die Änderungen zu sehen, oder nochmals <strong>Commit drücken</strong> um die Änderungen zu überschreiben.
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name = Username
|
||||
admin_password = Password
|
||||
confirm_password = Confirm Password
|
||||
admin_email = Admin Email
|
||||
install_btn_confirm = Install Gitea
|
||||
install_gogs = Install Gitea
|
||||
test_git_failed = Fail to test 'git' command: %v
|
||||
sqlite3_not_available = Your release version does not support SQLite3, please download the official binary version from %s, NOT the gobuild version.
|
||||
invalid_db_setting = Database setting is not correct: %v
|
||||
@@ -405,7 +405,6 @@ watch = Watch
|
||||
unstar = Unstar
|
||||
star = Star
|
||||
fork = Fork
|
||||
download_archive = Download this repository
|
||||
|
||||
no_desc = No Description
|
||||
quick_guide = Quick Guide
|
||||
@@ -431,7 +430,6 @@ file_history = History
|
||||
file_view_raw = View Raw
|
||||
file_permalink = Permalink
|
||||
file_too_large = This file is too large to be shown
|
||||
video_not_supported_in_browser = Your browser doesn't support HTML5 video tag.
|
||||
|
||||
editor.new_file = New file
|
||||
editor.upload_file = Upload file
|
||||
@@ -461,7 +459,6 @@ editor.cancel = Cancel
|
||||
editor.filename_cannot_be_empty = Filename cannot be empty.
|
||||
editor.branch_already_exists = Branch '%s' already exists in this repository.
|
||||
editor.directory_is_a_file = Entry '%s' in the parent path is a file not a directory in this repository.
|
||||
editor.file_is_a_symlink = The file '%s' is a symlink that cannot be modified from the web editor
|
||||
editor.filename_is_a_directory = The filename '%s' is an existing directory in this repository.
|
||||
editor.file_editing_no_longer_exists = The file '%s' you are editing no longer exists in the repository.
|
||||
editor.file_changed_while_editing = File content has been changed since you started editing. <a target="_blank" rel="noopener" href="%s">Click here</a> to see what have been changed or <strong>press commit again</strong> to overwrite those changes.
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Nombre de usuario
|
||||
admin_password=Contraseña
|
||||
confirm_password=Confirmar Contraseña
|
||||
admin_email=Correo electrónico del administrador
|
||||
install_btn_confirm=Instalar Gitea
|
||||
install_gogs=Instalar Gitea
|
||||
test_git_failed=Fallo al probar el comando 'git': %v
|
||||
sqlite3_not_available=Tu versión no soporta SQLite3, por favor descarga el binario oficial desde %s, NO la versión de gobuild.
|
||||
invalid_db_setting=La configuración de la base de datos no es correcta: %v
|
||||
@@ -401,7 +401,6 @@ watch=Seguir
|
||||
unstar=Eliminar destacado
|
||||
star=Destacar
|
||||
fork=Fork
|
||||
download_archive=Descargar este repositorio
|
||||
|
||||
no_desc=Sin descripción
|
||||
quick_guide=Guía Rápida
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Käyttäjätunnus
|
||||
admin_password=Salasana
|
||||
confirm_password=Varmista salasana
|
||||
admin_email=Ylläpito sähköposti
|
||||
install_btn_confirm=Asenna Gitea
|
||||
install_gogs=Asenna Gitea
|
||||
test_git_failed=Epäonnistui testata 'git' komentoa: %v
|
||||
sqlite3_not_available=Julkaisu versiosi ei tue SQLite3, ole hyvä ja lataa virallinen binääri versio osoitteesta %s, EI gobuild versiota.
|
||||
invalid_db_setting=Tietokanta asetus ei ole oikea: %v
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Nom d'utilisateur
|
||||
admin_password=Mot de passe
|
||||
confirm_password=Confirmez le mot de passe
|
||||
admin_email=E-mail de l'administrateur
|
||||
install_btn_confirm=Installer Gitea
|
||||
install_gogs=Installer Gitea
|
||||
test_git_failed=Le test de la commande "git" a échoué : %v
|
||||
sqlite3_not_available=Votre version publiée ne prend pas en charge SQLite3. Veuillez télécharger la version binaire officielle à cette adresse %s.
|
||||
invalid_db_setting=Paramètres de base de données incorrects : %v
|
||||
@@ -455,7 +455,6 @@ editor.cancel=Annuler
|
||||
editor.filename_cannot_be_empty=Nom de fichier ne peut pas être vide.
|
||||
editor.branch_already_exists=La branche '%s' existe déjà dans ce dépôt.
|
||||
editor.directory_is_a_file=L'entrée '%s' dans le chemin d’accès parent est un fichier pas un répertoire dans ce dépôt.
|
||||
editor.file_is_a_symlink=Le fichier '%s' est un lien symbolique qui ne peut pas être modifié par l'éditeur web
|
||||
editor.filename_is_a_directory=Le nom de fichier '%s' existe déjà dans ce dépot.
|
||||
editor.file_editing_no_longer_exists=Le fichier '%s' que vous modifiez n'existe plus dans le dépôt.
|
||||
editor.file_changed_while_editing=Le contenu du fichier à changé depuis que vous avez commencé à l'éditer. <a target="_blank" rel="noopener" href="%s">Cliquez ici</a> pour voir ce qui à été modifié ou <strong>appuyez sur commit encore une fois</strong> pour remplacer ces changements.
|
||||
@@ -531,7 +530,7 @@ issues.close_comment_issue=Commenter et fermer
|
||||
issues.reopen_issue=Réouvrir
|
||||
issues.reopen_comment_issue=Commenter et réouvrir
|
||||
issues.create_comment=Créer un commentaire
|
||||
issues.closed_at=`fermé à <a id="%[1]s"href="#%[1]s"> %[2]s</a>`
|
||||
issues.closed_at=`fermé à <a id="%[1]s"href="#%[1]s"> %[2]s"</a>`
|
||||
issues.reopened_at=`réouvert à <a id="%[1]s" href="#%[1]s"> %[2]s</a>`
|
||||
issues.commit_ref_at=`a référencé ce problème à partir d'un commit <a id="%[1]s" href="#%[1]s"> %[2]s</a>`
|
||||
issues.poster=Publier
|
||||
@@ -1159,7 +1158,7 @@ notices.delete_success=Notifications système supprimées avec succès.
|
||||
[action]
|
||||
create_repo=a créé le dépôt <a href="%s">%s</a>
|
||||
rename_repo=a rebaptisé le dépôt de <code>%[1]s</code> vers <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=a commité dans <a href="%[1]s/src/%[2]s">%[3]s</a> sur <a href="%[1]s">%[4]s</a>
|
||||
commit_repo=a soumis à <a href="%[1]s/src/%[2]s">%[3]s</a> sur <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`a ouvert un problème <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
close_issue=`tickets clos <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
reopen_issue=`tickets ré-ouverts <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Nome utente
|
||||
admin_password=Password
|
||||
confirm_password=Conferma Password
|
||||
admin_email=E-mail dell'Admin
|
||||
install_btn_confirm=Installare Gitea
|
||||
install_gogs=Installare Gitea
|
||||
test_git_failed=Fallito il test del comando git: %v
|
||||
sqlite3_not_available=Questa versione non supporta SQLite3, si prega di scaricare la versione binaria ufficiale da %s, NON la versione gobuild.
|
||||
invalid_db_setting=La configurazione del database non è corretta: %v
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=ユーザ名
|
||||
admin_password=パスワード
|
||||
confirm_password=パスワード確認
|
||||
admin_email=管理者の電子メール
|
||||
install_btn_confirm=Gitea をインストール
|
||||
install_gogs=Gitea をインストール
|
||||
test_git_failed='Git' コマンドテストに失敗: %v
|
||||
sqlite3_not_available=このリリース バージョンは SQLite3 をサポートしていません。gobuild バージョンではない、公式のバイナリ バージョンを %s からダウンロードしてください。
|
||||
invalid_db_setting=データベースの設定が正しくありません: %v
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -110,7 +110,7 @@ admin_name=Lietotājvārds
|
||||
admin_password=Parole
|
||||
confirm_password=Apstipriniet paroli
|
||||
admin_email=Administratora e-pasts
|
||||
install_btn_confirm=Instalēt Gitea
|
||||
install_gogs=Instalēt Gitea
|
||||
test_git_failed=Kļūda pārbaudot 'git' komandu: %v
|
||||
sqlite3_not_available=Jūsu versija neatbalsta SQLite3, lūdzu lejupielādējiet oficiālo bināro versiju no %s, NEVIS gobuild versiju.
|
||||
invalid_db_setting=Datu bāzes iestatījums nav pareizs: %v
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Gebruikersnaam
|
||||
admin_password=Wachtwoord
|
||||
confirm_password=Verifieer wachtwoord
|
||||
admin_email=Beheerder E-mail
|
||||
install_btn_confirm=Installeer Gitea
|
||||
install_gogs=Installeer Gitea
|
||||
test_git_failed=Git test niet gelukt: 'git' commando %v
|
||||
sqlite3_not_available=Uw versie biedt geen ondersteuning voor SQLite3, download de officiële binaire versie van %s, niet de gobuild versie.
|
||||
invalid_db_setting=Uw database instellingen zijn niet correct: %v
|
||||
|
||||
@@ -60,7 +60,7 @@ ssl_mode=Tryb SSL
|
||||
path=Ścieżka
|
||||
sqlite_helper=Ścieżka do pliku bazy danych SQLite3 lub TiDB. <br>Proszę użyć ścieżki bezwzględnej podczas uruchamiania usługi.
|
||||
err_empty_db_path=Ścieżka do bazy danych SQLite3 lub TiDB nie może być pusta.
|
||||
err_invalid_tidb_name=Nazwa bazy danych TiDB nie może zawierać znaków „.” i „-”.
|
||||
err_invalid_tidb_name=Nazwa bazy danych TiDB nie może zawierać znaków "." i "-".
|
||||
no_admin_and_disable_registration=Rejestracji nie można wyłączyć bez tworzenia konta admina.
|
||||
err_empty_admin_password=Hasło admina nie może być puste.
|
||||
|
||||
@@ -86,7 +86,7 @@ optional_title=Ustawienia opcjonalne
|
||||
email_title=Ustawienia serwera e-mail
|
||||
smtp_host=Serwer SMTP
|
||||
smtp_from=Od
|
||||
smtp_from_helper=Adres w polu „Od”, zgodnie z RFC 5322. Może być to po prostu adres email, bądź adres w formacie „Nazwa” <email@example.com>.
|
||||
smtp_from_helper=Adres w polu "Od", zgodnie z RFC 5322. Może być to po prostu adres email, bądź adres w formacie "Nazwa" <email@example.com>.
|
||||
mailer_user=E-mail nadawcy
|
||||
mailer_password=Hasło nadawcy
|
||||
register_confirm=Włącz potwierdzenia rejestracji
|
||||
@@ -110,8 +110,8 @@ admin_name=Nazwa Użytkownika
|
||||
admin_password=Hasło
|
||||
confirm_password=Potwierdź hasło
|
||||
admin_email=E-mail administratora
|
||||
install_btn_confirm=Zainstaluj Gitea
|
||||
test_git_failed=Nie udało się przetestować polecenia „git”: %v
|
||||
install_gogs=Zainstaluj Gitea
|
||||
test_git_failed=Nie udało się przetestować polecenia "git": %v
|
||||
sqlite3_not_available=Twoje wydanie nie obsługuje SQLite3, proszę pobrać oficjalne wydanie z %s, a NIE wersję z gobuild.
|
||||
invalid_db_setting=Ustawienia bazy danych nie są poprawne: %v
|
||||
invalid_repo_path=Ścieżka repozytoriów nie jest poprawna: %v
|
||||
@@ -190,11 +190,11 @@ AuthName=Nazwa autoryzacji
|
||||
AdminEmail=E-mail administratora
|
||||
|
||||
NewBranchName=Nazwa nowej gałęzi
|
||||
CommitSummary=Podsumowanie commitu
|
||||
CommitMessage=Wiadomość commitu
|
||||
CommitChoice=Wybór commitu
|
||||
CommitSummary=Commit summary
|
||||
CommitMessage=Commit message
|
||||
CommitChoice=Commit choice
|
||||
TreeName=Ścieżka pliku
|
||||
Content=Treść
|
||||
Content=Content
|
||||
|
||||
require_error=` nie może być puste.`
|
||||
alpha_dash_error=` musi się składać z prawidłowych znaków alfanumerycznych, myślników oraz podkreśleń.`
|
||||
@@ -242,13 +242,13 @@ following=Obserwowani
|
||||
follow=Obserwuj
|
||||
unfollow=Przestań obserwować
|
||||
|
||||
form.name_reserved=Nazwa użytkownika „%s” jest zarezerwowana.
|
||||
form.name_pattern_not_allowed=Wzorzec nazwy użytkownika „%s” jest niedozwolony.
|
||||
form.name_reserved=Nazwa użytkownika "%s" jest zarezerwowana.
|
||||
form.name_pattern_not_allowed=Wzorzec nazwy użytkownika "%s" jest niedozwolony.
|
||||
|
||||
[settings]
|
||||
profile=Profil
|
||||
password=Hasło
|
||||
avatar=Awatar
|
||||
avatar=Avatar
|
||||
ssh_keys=Klucze SSH
|
||||
social=Konta społecznościowe
|
||||
applications=Aplikacje
|
||||
@@ -269,7 +269,7 @@ change_username_prompt=Ta zmiana wpłynie na sposób w jaki łącza odnoszą si
|
||||
continue=Kontynuuj
|
||||
cancel=Anuluj
|
||||
|
||||
lookup_avatar_by_mail=Wyszukaj Avatar po mailu
|
||||
lookup_avatar_by_mail=Lookup Avatar by mail
|
||||
federated_avatar_lookup=Federated Avatar Lookup
|
||||
enable_custom_avatar=Włącz niestandardowe awatary
|
||||
choose_new_avatar=Wybierz nowy avatar
|
||||
@@ -357,7 +357,7 @@ fork_from=Forkuj z
|
||||
fork_visiblity_helper=Fork nie może zmieniać swojej widoczności
|
||||
repo_desc=Opis
|
||||
repo_lang=Język
|
||||
repo_gitignore_helper=Wybierz szablony pliku .gitignore
|
||||
repo_gitignore_helper=Select .gitignore templates
|
||||
license=Licencja
|
||||
license_helper=Wybierz plik licencji
|
||||
readme=Readme
|
||||
@@ -370,14 +370,14 @@ mirror_prune_desc=Usuń wszystkie śledzone odwołania które nie istnieją w zd
|
||||
mirror_interval=Częstotliwość kopiowania (godziny)
|
||||
mirror_address=Adres kopii lustrzanej
|
||||
mirror_address_desc=Proszę podać wymagane poświadczenia użytkownika w adresie.
|
||||
mirror_last_synced=Ostatnia synchronizacja
|
||||
mirror_last_synced=Last Synced
|
||||
watchers=Obserwujący
|
||||
stargazers=Polubienia
|
||||
forks=Forki
|
||||
|
||||
form.reach_limit_of_creation=Właściciel osiągnął limit maksymalnej ilości repozytoriów %d.
|
||||
form.name_reserved=Nazwa repozytorium „%s” jest zarezerwowana.
|
||||
form.name_pattern_not_allowed=Wzorzec nazwy repozytorium „%s” jest niedozwolony.
|
||||
form.name_reserved=Nazwa repozytorium "%s" jest zarezerwowana.
|
||||
form.name_pattern_not_allowed=Wzorzec nazwy repozytorium "%s" jest niedozwolony.
|
||||
|
||||
need_auth=Wymaga autoryzacji
|
||||
migrate_type=Typ migracji
|
||||
@@ -427,43 +427,43 @@ file_view_raw=Zobacz czysty
|
||||
file_permalink=Bezpośredni odnośnik
|
||||
file_too_large=Ten plik jest zbyt duży, aby go wyświetlić
|
||||
|
||||
editor.new_file=Nowy plik
|
||||
editor.upload_file=Załaduj plik
|
||||
editor.edit_file=Edytuj plik
|
||||
editor.preview_changes=Podgląd zmian
|
||||
editor.cannot_edit_non_text_files=Nie można edytować plików nietekstowych
|
||||
editor.edit_this_file=Edytuj ten plik
|
||||
editor.must_be_on_a_branch=Musisz być na gałęzi aby zgłosić lub zaproponować zmiany do tego pliku
|
||||
editor.new_file=New file
|
||||
editor.upload_file=Upload file
|
||||
editor.edit_file=Edit file
|
||||
editor.preview_changes=Preview Changes
|
||||
editor.cannot_edit_non_text_files=Cannot edit non-text files
|
||||
editor.edit_this_file=Edit this file
|
||||
editor.must_be_on_a_branch=You must be on a branch to make or propose changes to this file
|
||||
editor.fork_before_edit=Musisz sforkować to repozytorium przed edycją tego pliku
|
||||
editor.delete_this_file=Usuń ten plik
|
||||
editor.must_have_write_access=Musisz mieć uprawnienia do zapisu aby zgłosić lub zaproponować zmiany do tego pliku
|
||||
editor.file_delete_success=Plik '%s' został usunięty pomyślnie!
|
||||
editor.name_your_file=Nazwij plik...
|
||||
editor.filename_help=Aby dodać katalog, wpisz nazwę i naciśnij przycisk /. Aby usunąć katalog, przejdź do początku pola i naciśnij klawisz backspace.
|
||||
editor.or=lub
|
||||
editor.cancel_lower=anuluj
|
||||
editor.commit_changes=Zatwierdź zmiany
|
||||
editor.add_tmpl=Dodaj '%s/<filename>'
|
||||
editor.add=Dodaj '%s'
|
||||
editor.update=Zaktualizuj '%s'
|
||||
editor.delete=Usuń '%s'
|
||||
editor.commit_message_desc=Dodaj dodatkowy rozszerzony opis...
|
||||
editor.commit_directly_to_this_branch=Commituj bezpośrednio do gałęzi <strong class="branch-name">%s</strong>.
|
||||
editor.create_new_branch=Stwórz <strong>nową gałąź</strong> dla tego commita i rozpocznij pull request.
|
||||
editor.new_branch_name_desc=Nazwa nowej gałęzi...
|
||||
editor.cancel=Anuluj
|
||||
editor.filename_cannot_be_empty=Nazwa pliku nie może być pusta.
|
||||
editor.branch_already_exists=Gałąź '%s' już istnieje w tym repozytorium.
|
||||
editor.delete_this_file=Delete this file
|
||||
editor.must_have_write_access=You must have write access to make or propose changes to this file
|
||||
editor.file_delete_success=File '%s' has been deleted successfully!
|
||||
editor.name_your_file=Name your file...
|
||||
editor.filename_help=To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
|
||||
editor.or=or
|
||||
editor.cancel_lower=cancel
|
||||
editor.commit_changes=Commit Changes
|
||||
editor.add_tmpl=Add '%s/<filename>'
|
||||
editor.add=Add '%s'
|
||||
editor.update=Update '%s'
|
||||
editor.delete=Delete '%s'
|
||||
editor.commit_message_desc=Add an optional extended description...
|
||||
editor.commit_directly_to_this_branch=Commit directly to the <strong class="branch-name">%s</strong> branch.
|
||||
editor.create_new_branch=Create a <strong>new branch</strong> for this commit and start a pull request.
|
||||
editor.new_branch_name_desc=New branch name...
|
||||
editor.cancel=Cancel
|
||||
editor.filename_cannot_be_empty=Filename cannot be empty.
|
||||
editor.branch_already_exists=Branch '%s' already exists in this repository.
|
||||
editor.directory_is_a_file=Entry '%s' in the parent path is a file not a directory in this repository.
|
||||
editor.filename_is_a_directory=The filename '%s' is an existing directory in this repository.
|
||||
editor.file_editing_no_longer_exists=Plik '%s' który edytujesz nie istnieje już w tym repozytorium.
|
||||
editor.file_changed_while_editing=Zawartość pliku została zmieniona od rozpoczęcia edycji. <a target="_blank" href="%s">Kliknij tutaj</a> aby zobaczyć, co zostało zmienione lub <strong>naciśnij commit ponownie</strong> aby nadpisać te zmiany.
|
||||
editor.file_already_exists=Nazwa pliku '%s' już istnieje w tym repozytorium.
|
||||
editor.no_changes_to_show=Brak zmian do pokazania.
|
||||
editor.fail_to_update_file=Tworzenie/aktualizacja pliku '%s' nie powiodła się z błędem: %v
|
||||
editor.add_subdir=Dodaj podkatalog...
|
||||
editor.unable_to_upload_files=Wysyłanie plików do '%s' nie powiodło się z błędem: %v
|
||||
editor.upload_files_to_dir=Prześlij pliki do '%s'
|
||||
editor.file_editing_no_longer_exists=The file '%s' you are editing no longer exists in the repository.
|
||||
editor.file_changed_while_editing=File content has been changed since you started editing. <a target="_blank" rel="noopener" href="%s">Click here</a> to see what have been changed or <strong>press commit again</strong> to overwrite those changes.
|
||||
editor.file_already_exists=A file with name '%s' already exists in this repository.
|
||||
editor.no_changes_to_show=There are no changes to show.
|
||||
editor.fail_to_update_file=Failed to update/create file '%s' with error: %v
|
||||
editor.add_subdir=Add subdirectory...
|
||||
editor.unable_to_upload_files=Failed to upload files to '%s' with error: %v
|
||||
editor.upload_files_to_dir=Upload files to '%s'
|
||||
|
||||
commits.commits=Commity
|
||||
commits.search=Przeszukaj commity
|
||||
@@ -490,11 +490,11 @@ issues.create=Utwórz problem
|
||||
issues.new_label=Nowa etykieta
|
||||
issues.new_label_placeholder=Etykieta...
|
||||
issues.create_label=Utwórz etykietę
|
||||
issues.label_templates.title=Załaduj wstępnie przygotowany zestaw etykiet
|
||||
issues.label_templates.info=Nie ma jeszcze żadnych etykiet. Kliknij na przycisk „Nowa etykieta” powyżej, aby utworzyć lub użyć poniższego zestawu wstępnie zdefiniowanego.
|
||||
issues.label_templates.helper=Wybierz zestaw etykiet
|
||||
issues.label_templates.title=Load a predefined set of labels
|
||||
issues.label_templates.info=There aren’t any labels yet. You can click on the "New Label" button above to create one or use a predefined set below.
|
||||
issues.label_templates.helper=Select a label set
|
||||
issues.label_templates.use=Użyj ten zestaw etykiet
|
||||
issues.label_templates.fail_to_load_file=Ładowanie pliku szablonu etykiety '%s' nie powiodło się: %v
|
||||
issues.label_templates.fail_to_load_file=Failed to load label template file '%s': %v
|
||||
issues.open_tab=Otwarte %d
|
||||
issues.close_tab=Zamknięte %d
|
||||
issues.filter_label=Etykieta
|
||||
@@ -551,8 +551,8 @@ issues.label_deletion=Usunięcie etykiety
|
||||
issues.label_deletion_desc=Usunięcie tej etykiety spowoduje usuniecie jej ze wszystkich powiązanych problemów. Czy na pewno chcesz kontynuować?
|
||||
issues.label_deletion_success=Etykieta została usunięta pomyślnie!
|
||||
issues.num_participants=%d uczestników
|
||||
issues.attachment.open_tab=`Kliknij, aby zobaczyć „%s” w nowej karcie`
|
||||
issues.attachment.download=`Kliknij, aby pobrać „%s”`
|
||||
issues.attachment.open_tab=`Kliknij, aby zobaczyć "%s" w nowej karcie`
|
||||
issues.attachment.download=`Kliknij, aby pobrać "%s"`
|
||||
|
||||
pulls.new=Nowy pull request
|
||||
pulls.compare_changes=Porównaj zmiany
|
||||
@@ -594,7 +594,7 @@ milestones.desc=Opis
|
||||
milestones.due_date=Termin realizacji (opcjonalnie)
|
||||
milestones.clear=Wyczyść
|
||||
milestones.invalid_due_date_format=Format daty realizacji jest nieprawidłowy, musi być "rrrr-mm-dd".
|
||||
milestones.create_success=Kamień milowy „%s” został utworzony pomyślnie!
|
||||
milestones.create_success=Kamień milowy "%s" został utworzony pomyślnie!
|
||||
milestones.edit=Edytuj kamień milowy
|
||||
milestones.edit_subheader=Użyj lepszego opisu, tak aby nie wprowadzać w błąd użytkowników.
|
||||
milestones.cancel=Anuluj
|
||||
@@ -617,7 +617,7 @@ wiki.last_commit_info=%s edytuje tę stronę %s
|
||||
wiki.edit_page_button=Edytuj
|
||||
wiki.new_page_button=Nowa strona
|
||||
wiki.delete_page_button=Usuń stronę
|
||||
wiki.delete_page_notice_1=Strona zostanie usunięta <code>„%s”</code>. Bądź ostrożny.
|
||||
wiki.delete_page_notice_1=Strona zostanie usunięta <code>"%s"</code>. Bądź ostrożny.
|
||||
wiki.page_already_exists=Strona Wiki o tej samej nazwie już istnieje.
|
||||
wiki.pages=Strony
|
||||
wiki.last_updated=Ostatnia aktualizacja %s
|
||||
@@ -632,9 +632,9 @@ settings.collaboration.undefined=Niezdefiniowany
|
||||
settings.hooks=Webhooki
|
||||
settings.githooks=Hooki Git
|
||||
settings.basic_settings=Ustawienia podstawowe
|
||||
settings.mirror_settings=Kopia lustrzana ustawień
|
||||
settings.mirror_settings=Mirror Settings
|
||||
settings.sync_mirror=Synchronizuj teraz
|
||||
settings.mirror_sync_in_progress=Synchronizacja kopii lustrzanej jest w toku, odśwież stronę w ciągu minuty.
|
||||
settings.mirror_sync_in_progress=Mirror syncing is in progress, please refresh page in about a minute.
|
||||
settings.site=Oficjalna Strona
|
||||
settings.update_settings=Aktualizuj ustawienia
|
||||
settings.change_reponame_prompt=Zmiana nazwy repozytorium wpłynie na linki do niego.
|
||||
@@ -644,8 +644,8 @@ settings.use_internal_wiki=Użyj wbudowanego wiki
|
||||
settings.use_external_wiki=Użyj zewnętrznego Wiki
|
||||
settings.external_wiki_url=Adres URL zewnętrznego Wiki
|
||||
settings.external_wiki_url_desc=Odwiedzający zostaną przekierowani do adresu URL po kliknięciu zakładki.
|
||||
settings.issues_desc=Włącz system zgłaszania problemów
|
||||
settings.use_internal_issue_tracker=Użyj wbudowany lekki system zgłaszania problemów
|
||||
settings.issues_desc=Enable issue tracker
|
||||
settings.use_internal_issue_tracker=Use builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Użyj zewnętrznego systemu zgłaszania problemów
|
||||
settings.tracker_url_format=Format dla adresu URL zewnętrznego systemu
|
||||
settings.tracker_issue_style=Styl nazw zewnętrznego systemu zgłaszania problemów:
|
||||
@@ -721,7 +721,7 @@ settings.event_choose=Pozwól mi wybrać, czego potrzebuję.
|
||||
settings.event_create=Utwórz
|
||||
settings.event_create_desc=Utworzono gałąź lub tag
|
||||
settings.event_pull_request=Pull Request
|
||||
settings.event_pull_request_desc=Otworzono żądanie pull, zamknięto, otwarto ponownie, zaktualizowano, przypisano, nieprzypisano, zaktualizowano etykietę, wyczyszczono etykietę lub zsynchronizowano.
|
||||
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
|
||||
settings.event_push=Wypchnięcie
|
||||
settings.event_push_desc=Wypchnięcie (push) do repozytorium Git
|
||||
settings.active=Aktywny
|
||||
@@ -813,8 +813,8 @@ team_name_helper=Będziesz używał tej nazwy do wywoływania tego zespołu w dy
|
||||
team_desc_helper=Czym zajmuje się ten zespół?
|
||||
team_permission_desc=Jaki poziom uprawnień powinien mieć ten zespół?
|
||||
|
||||
form.name_reserved=Nazwa organizacji „%s” jest zarezerwowana.
|
||||
form.name_pattern_not_allowed=Wzorzec nazwy organizacji „%s” jest niedozwolony.
|
||||
form.name_reserved=Nazwa organizacji "%s" jest zarezerwowana.
|
||||
form.name_pattern_not_allowed=Wzorzec nazwy organizacji "%s" jest niedozwolony.
|
||||
|
||||
settings=Ustawienia
|
||||
settings.options=Opcje
|
||||
@@ -1062,9 +1062,9 @@ config.db_host=Host
|
||||
config.db_name=Nazwa
|
||||
config.db_user=Użytkownik
|
||||
config.db_ssl_mode=Tryb SSL
|
||||
config.db_ssl_mode_helper=(tylko dla „postgres”)
|
||||
config.db_ssl_mode_helper=(tylko dla "postgres")
|
||||
config.db_path=Ścieżka
|
||||
config.db_path_helper=(dla „sqlite3” i „tidb”)
|
||||
config.db_path_helper=(dla "sqlite3" i "tidb")
|
||||
|
||||
config.service_config=Konfiguracja usługi
|
||||
config.register_email_confirm=Wymagaj potwierdzenia e-mail
|
||||
@@ -1116,16 +1116,16 @@ config.disable_gravatar=Wyłącz Gravatara
|
||||
config.enable_federated_avatar=Enable Federated Avatars
|
||||
|
||||
config.git_config=Konfiguracja Git
|
||||
config.git_disable_diff_highlight=Wyłączyć wyróżnianie składni diff
|
||||
config.git_max_diff_lines=Maksymalna ilość linii diff (dla pojedynczego pliku)
|
||||
config.git_max_diff_line_characters=Maksymalna ilość znaków diff (dla pojedynczego pliku)
|
||||
config.git_max_diff_files=Maksymalna ilość plików diff (które zostaną wyświetlone)
|
||||
config.git_gc_args=Argumenty GC
|
||||
config.git_disable_diff_highlight=Disable Diff Syntax Highlight
|
||||
config.git_max_diff_lines=Max Diff Lines (for a single file)
|
||||
config.git_max_diff_line_characters=Max Diff Characters (for a single line)
|
||||
config.git_max_diff_files=Max Diff Files (to be shown)
|
||||
config.git_gc_args=GC Arguments
|
||||
config.git_migrate_timeout=Limit czasu migracji
|
||||
config.git_mirror_timeout=Limit czasu aktualizacji kopii lustrzanej
|
||||
config.git_clone_timeout=Limit czasu operacji klonowania
|
||||
config.git_pull_timeout=Limit czasu dla operacji pull
|
||||
config.git_gc_timeout=Limit czasu odśmiecania pamięci
|
||||
config.git_mirror_timeout=Mirror Update Timeout
|
||||
config.git_clone_timeout=Clone Operation Timeout
|
||||
config.git_pull_timeout=Pull Operation Timeout
|
||||
config.git_gc_timeout=GC Operation Timeout
|
||||
|
||||
config.log_config=Konfiguracja dziennika
|
||||
config.log_mode=Tryb dziennika
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Nome de usuário
|
||||
admin_password=Senha
|
||||
confirm_password=Confirmar senha
|
||||
admin_email=E-mail do administrador
|
||||
install_btn_confirm=Instalar Gitea
|
||||
install_gogs=Instalar Gitea
|
||||
test_git_failed=Falha ao testar o comando 'git': %v
|
||||
sqlite3_not_available=Sua versão não suporta SQLite3, por favor faça o download da versão binária oficial em %s, NÃO da versão gobuild.
|
||||
invalid_db_setting=Configuração do banco de dados não está correta: %v
|
||||
@@ -1197,3 +1197,4 @@ default_message=Arraste e solte arquivos aqui, ou clique para selecioná-los.
|
||||
invalid_input_type=Você não pode enviar arquivos deste tipo.
|
||||
file_too_big=O tamanho do arquivo ({{filesize}} MB) excede o limite máximo ({{maxFilesize}} MB).
|
||||
remove_file=Remover
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ home=Главная
|
||||
dashboard=Панель управления
|
||||
explore=Обзор
|
||||
help=Помощь
|
||||
sign_in=Вход
|
||||
sign_in=Войти
|
||||
sign_out=Выход
|
||||
sign_up=Регистрация
|
||||
register=Регистрация
|
||||
@@ -24,10 +24,10 @@ re_type=Введите повторно
|
||||
captcha=Капча
|
||||
|
||||
repository=Репозиторий
|
||||
organization=Организация
|
||||
organization=Группа
|
||||
mirror=Зеркало
|
||||
new_repo=Новый репозиторий
|
||||
new_migrate=Новая миграция
|
||||
new_migrate=Новая Миграция
|
||||
new_mirror=Новое зеркало
|
||||
new_fork=Новое ответвление репозитория
|
||||
new_org=Новая организация
|
||||
@@ -97,7 +97,7 @@ offline_mode_popup=Отключить CDN даже в производствен
|
||||
disable_gravatar=Отключить службу Gravatar
|
||||
disable_gravatar_popup=Отключить Gravatar и пользовательские источники, все аватары по-умолчанию загружаются пользователями.
|
||||
federated_avatar_lookup=Включить поиск внешних Аватаров
|
||||
federated_avatar_lookup_popup=Включите Поиск федеративного аватара для использования федеративной службы с открытым исходным кодом на основе libravatar.
|
||||
federated_avatar_lookup_popup=Enable federated avatars lookup to use federated open source service based on libravatar.
|
||||
disable_registration=Отключить самостоятельную регистрацию
|
||||
disable_registration_popup=Запретить пользователям самостоятельную регистрацию, только администратор может создавать аккаунты.
|
||||
enable_captcha=Включить капчу
|
||||
@@ -110,7 +110,7 @@ admin_name=Имя пользователя
|
||||
admin_password=Пароль
|
||||
confirm_password=Подтвердить пароль
|
||||
admin_email=Электронная почта администратора
|
||||
install_btn_confirm=Установить Gitea
|
||||
install_gogs=Установить Gitea
|
||||
test_git_failed=Не удалось проверить 'git' команду: %v
|
||||
sqlite3_not_available=Ваша версия не поддерживает SQLite3, пожалуйста скачайте официальную бинарную версию от %s, а не версию gobuild.
|
||||
invalid_db_setting=Настройки базы данных не правильные: %v
|
||||
@@ -190,9 +190,9 @@ AuthName=Имя авторизации
|
||||
AdminEmail=Электронная почта администратора
|
||||
|
||||
NewBranchName=Новая ветка
|
||||
CommitSummary=Резюме коммита
|
||||
CommitSummary=Commit summary
|
||||
CommitMessage=Зафиксировать сообщение
|
||||
CommitChoice=Выбор коммита
|
||||
CommitChoice=Commit choice
|
||||
TreeName=Путь к файлу
|
||||
Content=Содержимое
|
||||
|
||||
@@ -366,7 +366,7 @@ auto_init=Инициализировать этот репозиторий вы
|
||||
create_repo=Создать репозиторий
|
||||
default_branch=Ветка по умолчанию
|
||||
mirror_prune=Очистить
|
||||
mirror_prune_desc=Удалите ссылки на удаленно отслеживаемые объекты, которых больше нет на удаленном сервере
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_interval=Интервал зеркалирования (час)
|
||||
mirror_address=Адрес зеркала
|
||||
mirror_address_desc=Укажите необходимые учетные данные в адрес.
|
||||
@@ -433,13 +433,13 @@ editor.edit_file=Редактировать файл
|
||||
editor.preview_changes=Просмотр изменений
|
||||
editor.cannot_edit_non_text_files=Возможно редактировать только текстовые файлы
|
||||
editor.edit_this_file=Отредактируйте этот файл
|
||||
editor.must_be_on_a_branch=Чтобы сделать или предложить изменения вы должны выбрать ветку
|
||||
editor.must_be_on_a_branch=You must be on a branch to make or propose changes to this file
|
||||
editor.fork_before_edit=Создайте ветку репозитория перед редактированием файла
|
||||
editor.delete_this_file=Удалить файл
|
||||
editor.must_have_write_access=Вам необходимо иметь доступ на запись, чтобы вносить или предлагать правки этого файла
|
||||
editor.file_delete_success=Файл «%s» был успешно удален!
|
||||
editor.file_delete_success=File '%s' has been deleted successfully!
|
||||
editor.name_your_file=Назовите свой файл...
|
||||
editor.filename_help=Чтобы добавить каталог, просто наберите название и нажмите /. Чтобы удалить каталог, перейдите к началу поля и нажмите клавишу backspace.
|
||||
editor.filename_help=To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
|
||||
editor.or=или
|
||||
editor.cancel_lower=отмена
|
||||
editor.commit_changes=Фиксация изменений
|
||||
@@ -447,17 +447,17 @@ editor.add_tmpl=Добавить '%s/<filename>'
|
||||
editor.add=Добавить '%s'
|
||||
editor.update=Обновить '%s'
|
||||
editor.delete=Удалить '%s'
|
||||
editor.commit_message_desc=Добавьте необязательное расширенное описание...
|
||||
editor.commit_directly_to_this_branch=Сделайте коммит прямо в ветку <strong class="branch-name">%s</strong>.
|
||||
editor.create_new_branch=Создайте <strong>новую ветвь</strong> для этого коммита, и сделайте пул запрос.
|
||||
editor.commit_message_desc=Add an optional extended description...
|
||||
editor.commit_directly_to_this_branch=Commit directly to the <strong class="branch-name">%s</strong> branch.
|
||||
editor.create_new_branch=Create a <strong>new branch</strong> for this commit and start a pull request.
|
||||
editor.new_branch_name_desc=Новое название ветки...
|
||||
editor.cancel=Отмена
|
||||
editor.filename_cannot_be_empty=Имя файла не может быть пустым.
|
||||
editor.branch_already_exists=Ветка «%s» уже существует в этом репозитории.
|
||||
editor.directory_is_a_file=Запись «%s» в пути на верх является файлом, а не каталогом этого репозитория.
|
||||
editor.filename_is_a_directory=Файл «%s» является каталогом в этом репозитории.
|
||||
editor.file_editing_no_longer_exists=Редактируемый вами файл «%s» больше не существует в репозитории.
|
||||
editor.file_changed_while_editing=Содержимое файла изменилось со времени начала редактирования. <a target="_blank" href="%s"> нажмите здесь,</a> чтобы увидеть, что было изменено, или <strong>нажмите кнопку commit снова</strong>, чтобы перезаписать эти изменения.
|
||||
editor.directory_is_a_file=Entry '%s' in the parent path is a file not a directory in this repository.
|
||||
editor.filename_is_a_directory=The filename '%s' is an existing directory in this repository.
|
||||
editor.file_editing_no_longer_exists=The file '%s' you are editing no longer exists in the repository.
|
||||
editor.file_changed_while_editing=File content has been changed since you started editing. <a target="_blank" rel="noopener" href="%s">Click here</a> to see what have been changed or <strong>press commit again</strong> to overwrite those changes.
|
||||
editor.file_already_exists=Файл с именем «%s» уже существует в этом репозитории.
|
||||
editor.no_changes_to_show=Нет изменений.
|
||||
editor.fail_to_update_file=Не удалось обновить/создать файл «%s» из-за ошибки: %v
|
||||
@@ -491,10 +491,10 @@ issues.new_label=Новая метка
|
||||
issues.new_label_placeholder=Имя метки...
|
||||
issues.create_label=Добавить метку
|
||||
issues.label_templates.title=Загрузить набор предопределённых меток
|
||||
issues.label_templates.info=Меток пока нет. Вы можете нажать на кнопку «Создать метку», чтобы создать новую или использовать одну из готового набора ниже.
|
||||
issues.label_templates.info=There aren’t any labels yet. You can click on the "New Label" button above to create one or use a predefined set below.
|
||||
issues.label_templates.helper=Выберите метку
|
||||
issues.label_templates.use=Использовать ярлык
|
||||
issues.label_templates.fail_to_load_file=Не удалось загрузить файл шаблона метки «%s»: %v
|
||||
issues.label_templates.fail_to_load_file=Failed to load label template file '%s': %v
|
||||
issues.open_tab=%d открыто(ы)
|
||||
issues.close_tab=%d закрыто(ы)
|
||||
issues.filter_label=Метка
|
||||
@@ -522,7 +522,7 @@ issues.next=Следующая страница
|
||||
issues.open_title=Открыто
|
||||
issues.closed_title=Закрыто
|
||||
issues.num_comments=комментариев: %d
|
||||
issues.commented_at=«прокомментировал <a href="#%s"> %s</a>»
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Вы уверены, что хотите удалить этот комментарий?
|
||||
issues.no_content=Пока нет содержимого.
|
||||
issues.close_issue=Закрыть
|
||||
@@ -721,7 +721,7 @@ settings.event_choose=Позвольте мне выбрать то, что ну
|
||||
settings.event_create=Создать
|
||||
settings.event_create_desc=Ветка или тэг созданы
|
||||
settings.event_pull_request=Запросы на слияние
|
||||
settings.event_pull_request_desc=Запрос слияния открыт, закрыт, переоткрыт, изменён, назначен, снят, метка обновлена, метка убрана, или синхронизирован.
|
||||
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
|
||||
settings.event_push=Push
|
||||
settings.event_push_desc=Push в репозиторий
|
||||
settings.active=Активен
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Корисничко име
|
||||
admin_password=Лозинка
|
||||
confirm_password=Потврдите лозинку
|
||||
admin_email=Адреса е-поште адмниистратора
|
||||
install_btn_confirm=Успостави Gitea
|
||||
install_gogs=Успостави Gitea
|
||||
test_git_failed=Команда 'git' није успела: %v
|
||||
sqlite3_not_available=Ваша верзија не подржава SQLite3, молимо вас преузмите званичну бинарну верзију од %s, а не верзију gobuild.
|
||||
invalid_db_setting=Подешавања базе података су неправилна: %v
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Användarnamn
|
||||
admin_password=Lösenord
|
||||
confirm_password=Bekräfta lösenord
|
||||
admin_email=Administratörs Epost
|
||||
install_btn_confirm=Installera Gogs
|
||||
install_gogs=Installera Gogs
|
||||
test_git_failed=Misslyckades att testa 'git' kommando: %v
|
||||
sqlite3_not_available=Din release stödjer ej SQLite3, ladda vänligen ner den officiella binären via %s, inte gobuild varianten.
|
||||
invalid_db_setting=Databas inställningen är inkorrekt: %v
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=Kullanıcı Adı
|
||||
admin_password=Parola
|
||||
confirm_password=Parolayı Doğrula
|
||||
admin_email=Yönetici E-Postası
|
||||
install_btn_confirm=Gogs'u Kur
|
||||
install_gogs=Gogs'u Kur
|
||||
test_git_failed='git' komut testi başarısız: %v
|
||||
sqlite3_not_available=Yayın sürümünüz SQLite3'ü desteklemiyor, lütfen %s'den resmi sürümü (gobuild sürümünü DEĞİL) indirin.
|
||||
invalid_db_setting=Veritabanı ayarları geçersiz: %v
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=管理员用户名
|
||||
admin_password=管理员密码
|
||||
confirm_password=确认密码
|
||||
admin_email=管理员邮箱
|
||||
install_btn_confirm=立即安装
|
||||
install_gogs=立即安装
|
||||
test_git_failed=无法识别 'git' 命令:%v
|
||||
sqlite3_not_available=您所使用的发行版不支持 SQLite3,请从 %s 下载官方构建版,而不是 gobuild 版本。
|
||||
invalid_db_setting=数据库设置不正确:%v
|
||||
@@ -459,7 +459,6 @@ editor.cancel=取消
|
||||
editor.filename_cannot_be_empty=文件名不能为空。
|
||||
editor.branch_already_exists=此仓库已存在名为 '%s' 的分支。
|
||||
editor.directory_is_a_file=路径 '%s' 的父路径中包含此仓库已存在的文件名。
|
||||
editor.file_is_a_symlink = '%s'数据是网页编辑器不能改变的符号链接。
|
||||
editor.filename_is_a_directory=文件名 '%s' 是此仓库中已存在的目录名。
|
||||
editor.file_editing_no_longer_exists=您编辑的文件 '%s' 已经不存在于此仓库中。
|
||||
editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。<a target="_blank" rel="noopener" href="%s">单击此处</a> 查看变动的具体内容,或者 <strong>再次提交</strong> 覆盖已发生的变动。
|
||||
|
||||
@@ -110,7 +110,7 @@ admin_name=管理員用戶名
|
||||
admin_password=管理員密碼
|
||||
confirm_password=確認密碼
|
||||
admin_email=管理員郵箱
|
||||
install_btn_confirm=立即安裝
|
||||
install_gogs=立即安裝
|
||||
test_git_failed=無法識別 'git' 命令:%v
|
||||
sqlite3_not_available=您所使用的發行版本不支持 SQLite3,請從 %s 下載官方構建版,而不是 gobuild 版本。
|
||||
invalid_db_setting=數據庫設置不正確:%v
|
||||
|
||||
@@ -96,8 +96,8 @@ offline_mode=啓用離線模式
|
||||
offline_mode_popup=在部署模式下也禁用從 CDN 獲取文件,所有的資源將從本地伺服器獲取。
|
||||
disable_gravatar=禁用 Gravatar 服務
|
||||
disable_gravatar_popup=禁用 Gravatar 和自定義源,僅使用由用戶上傳或默認的頭像。
|
||||
federated_avatar_lookup=開啟聯合頭像查詢
|
||||
federated_avatar_lookup_popup=開啟聯合頭像查詢並使用基於開放源碼的 libravatar 服務
|
||||
federated_avatar_lookup=Enable Federated Avatars Lookup
|
||||
federated_avatar_lookup_popup=Enable federated avatars lookup to use federated open source service based on libravatar.
|
||||
disable_registration=禁止用戶自主註冊
|
||||
disable_registration_popup=禁止用戶自主註冊功能,只有管理員可以添加帳號。
|
||||
enable_captcha=啟用驗證碼服務
|
||||
@@ -110,7 +110,7 @@ admin_name=管理員用戶名
|
||||
admin_password=管理員密碼
|
||||
confirm_password=確認密碼
|
||||
admin_email=管理員郵箱
|
||||
install_btn_confirm=立即安裝
|
||||
install_gogs=立即安裝
|
||||
test_git_failed=無法識別 'git' 命令:%v
|
||||
sqlite3_not_available=您所使用的發行版本不支持 SQLite3,請從 %s 下載官方構建版,而不是 gobuild 版本。
|
||||
invalid_db_setting=數據庫設置不正確:%v
|
||||
@@ -152,7 +152,7 @@ sign_up_now=還沒帳戶?馬上註冊。
|
||||
confirmation_mail_sent_prompt=一封新的確認郵件已經被發送至 <b>%s</b>,請檢查您的收件箱並在 %d 小時內完成確認註冊操作。
|
||||
active_your_account=激活您的帳戶
|
||||
prohibit_login=禁止登錄
|
||||
prohibit_login_desc=您的帳戶被停用,請聯繫網站管理員。
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
resent_limit_prompt=對不起,您請求發送激活郵件過於頻繁,請等待 3 分鐘後再試!
|
||||
has_unconfirmed_mail=%s 您好,您有一封發送至( <b>%s</b>) 但未被確認的郵件。如果您未收到激活郵件,或需要重新發送,請單擊下方的按鈕。
|
||||
resend_mail=單擊此處重新發送確認郵件
|
||||
@@ -190,9 +190,9 @@ AuthName=認證名稱
|
||||
AdminEmail=管理員郵箱
|
||||
|
||||
NewBranchName=新的分支名稱
|
||||
CommitSummary=提交摘要
|
||||
CommitSummary=Commit summary
|
||||
CommitMessage=提交訊息
|
||||
CommitChoice=提交選擇
|
||||
CommitChoice=Commit choice
|
||||
TreeName=檔案路徑
|
||||
Content=內容
|
||||
|
||||
@@ -248,7 +248,7 @@ form.name_pattern_not_allowed=用戶名不允許 '%s' 的格式。
|
||||
[settings]
|
||||
profile=個人信息
|
||||
password=修改密碼
|
||||
avatar=頭像
|
||||
avatar=Avatar
|
||||
ssh_keys=管理 SSH 密鑰
|
||||
social=社交帳號綁定
|
||||
applications=管理授權應用
|
||||
@@ -269,8 +269,8 @@ change_username_prompt=該操作將會影響到所有與您帳戶有關的鏈接
|
||||
continue=繼續操作
|
||||
cancel=取消操作
|
||||
|
||||
lookup_avatar_by_mail=通過信箱查找頭像
|
||||
federated_avatar_lookup=Federated Avatar 查詢
|
||||
lookup_avatar_by_mail=Lookup Avatar by mail
|
||||
federated_avatar_lookup=Federated Avatar Lookup
|
||||
enable_custom_avatar=啟動自定義頭像
|
||||
choose_new_avatar=選擇新的頭像
|
||||
update_avatar=更新頭像設置
|
||||
@@ -357,7 +357,7 @@ fork_from=派生自
|
||||
fork_visiblity_helper=派生倉庫無法修改可見性。
|
||||
repo_desc=倉庫描述
|
||||
repo_lang=倉庫語言
|
||||
repo_gitignore_helper=選擇 .gitignore 主題
|
||||
repo_gitignore_helper=Select .gitignore templates
|
||||
license=授權許可
|
||||
license_helper=請選擇授權許可文件
|
||||
readme=Readme
|
||||
@@ -370,7 +370,7 @@ mirror_prune_desc=當遠程追蹤的引用被刪除時本地也會同步刪除
|
||||
mirror_interval=鏡像同步周期(小時)
|
||||
mirror_address=鏡像地址
|
||||
mirror_address_desc=請在位址中包括必要的使用者憑據。
|
||||
mirror_last_synced=上次同步
|
||||
mirror_last_synced=Last Synced
|
||||
watchers=關注者
|
||||
stargazers=稱讚者
|
||||
forks=派生倉庫
|
||||
@@ -425,45 +425,45 @@ file_raw=原始文件
|
||||
file_history=文件歷史
|
||||
file_view_raw=查看原始文件
|
||||
file_permalink=永久連結
|
||||
file_too_large=檔案太大,無法顯示
|
||||
file_too_large=This file is too large to be shown
|
||||
|
||||
editor.new_file=開新檔案
|
||||
editor.upload_file=上傳檔案
|
||||
editor.edit_file=編輯文件
|
||||
editor.preview_changes=預覽更改
|
||||
editor.preview_changes=Preview Changes
|
||||
editor.cannot_edit_non_text_files=不能編輯非文字檔
|
||||
editor.edit_this_file=編輯此文件
|
||||
editor.must_be_on_a_branch=你必須在一個分支或提出對此檔的更改
|
||||
editor.fork_before_edit=你必須在編輯檔案之前備份此檔案
|
||||
editor.must_be_on_a_branch=You must be on a branch to make or propose changes to this file
|
||||
editor.fork_before_edit=You must fork this repository before editing the file
|
||||
editor.delete_this_file=刪除此文件
|
||||
editor.must_have_write_access=您必須具有寫存取權限,或提出對此檔案的更改
|
||||
editor.file_delete_success=已成功刪除 '%s' !
|
||||
editor.name_your_file=命名您的檔...
|
||||
editor.filename_help=輸入名稱後按下 / 鍵即可新增資料夾,或將滑鼠移至輸入格最左側按下Backspace移除資料夾。
|
||||
editor.must_have_write_access=You must have write access to make or propose changes to this file
|
||||
editor.file_delete_success=File '%s' has been deleted successfully!
|
||||
editor.name_your_file=Name your file...
|
||||
editor.filename_help=To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
|
||||
editor.or=或
|
||||
editor.cancel_lower=取消
|
||||
editor.commit_changes=提交更改嗎?
|
||||
editor.add_tmpl=添加%s/<filename>'
|
||||
editor.commit_changes=Commit Changes
|
||||
editor.add_tmpl=Add '%s/<filename>'
|
||||
editor.add=新增 '%s'
|
||||
editor.update=更新 '%s'
|
||||
editor.delete=刪除 '%s'
|
||||
editor.commit_message_desc=添加一個可選的擴展描述...
|
||||
editor.commit_directly_to_this_branch=直接提交到 <strong class="branch-name">%s</strong> 分支。
|
||||
editor.create_new_branch=創建 <strong>新的分支</strong> 為此提交和開始合併請求。
|
||||
editor.commit_message_desc=Add an optional extended description...
|
||||
editor.commit_directly_to_this_branch=Commit directly to the <strong class="branch-name">%s</strong> branch.
|
||||
editor.create_new_branch=Create a <strong>new branch</strong> for this commit and start a pull request.
|
||||
editor.new_branch_name_desc=新的分支名稱...
|
||||
editor.cancel=取消
|
||||
editor.filename_cannot_be_empty=檔案名不能為空。
|
||||
editor.branch_already_exists='%s' 已存在於此存儲庫。
|
||||
editor.directory_is_a_file='%s' 在此倉庫中的路徑是檔案而不是目錄。
|
||||
editor.filename_is_a_directory=檔案名 '%s' 是此資料庫中的現有目錄。
|
||||
editor.file_editing_no_longer_exists=檔 '%s' 您正在編輯不再存在於資料庫。
|
||||
editor.file_changed_while_editing=從您開始編輯已更改檔的內容。<a target="_blank"href="%s"> 按一下此處</a> 以查看什麼發生了更改或 <strong>按提交再</strong> 覆蓋這些更改。
|
||||
editor.file_already_exists=帶有名稱 '%s' 的檔已經存在在這個資料庫中。
|
||||
editor.filename_cannot_be_empty=Filename cannot be empty.
|
||||
editor.branch_already_exists=Branch '%s' already exists in this repository.
|
||||
editor.directory_is_a_file=Entry '%s' in the parent path is a file not a directory in this repository.
|
||||
editor.filename_is_a_directory=The filename '%s' is an existing directory in this repository.
|
||||
editor.file_editing_no_longer_exists=The file '%s' you are editing no longer exists in the repository.
|
||||
editor.file_changed_while_editing=File content has been changed since you started editing. <a target="_blank" rel="noopener" href="%s">Click here</a> to see what have been changed or <strong>press commit again</strong> to overwrite those changes.
|
||||
editor.file_already_exists=A file with name '%s' already exists in this repository.
|
||||
editor.no_changes_to_show=沒有可以顯示的變更。
|
||||
editor.fail_to_update_file=上傳/創建檔案 '%s' 失敗, 錯誤訊息: %v
|
||||
editor.fail_to_update_file=Failed to update/create file '%s' with error: %v
|
||||
editor.add_subdir=新增子目錄...
|
||||
editor.unable_to_upload_files=上傳檔案失敗到 '%s', 錯誤訊息: %v
|
||||
editor.upload_files_to_dir=上傳檔案到 '%s'
|
||||
editor.unable_to_upload_files=Failed to upload files to '%s' with error: %v
|
||||
editor.upload_files_to_dir=Upload files to '%s'
|
||||
|
||||
commits.commits=次代碼提交
|
||||
commits.search=搜索提交歷史
|
||||
@@ -490,11 +490,11 @@ issues.create=創建問題
|
||||
issues.new_label=創建標籤
|
||||
issues.new_label_placeholder=標籤名稱...
|
||||
issues.create_label=創建標籤
|
||||
issues.label_templates.title=載入一組預定義的標籤
|
||||
issues.label_templates.info=沒有任何標籤。你可以點選上面創建一個或按下面"新建標籤"按鈕來使用一組預定義。
|
||||
issues.label_templates.helper=選擇一個標籤集
|
||||
issues.label_templates.use=使用此標籤集
|
||||
issues.label_templates.fail_to_load_file=載入標籤範本檔案 '%s' 失敗: %v
|
||||
issues.label_templates.title=Load a predefined set of labels
|
||||
issues.label_templates.info=There aren’t any labels yet. You can click on the "New Label" button above to create one or use a predefined set below.
|
||||
issues.label_templates.helper=Select a label set
|
||||
issues.label_templates.use=Use this label set
|
||||
issues.label_templates.fail_to_load_file=Failed to load label template file '%s': %v
|
||||
issues.open_tab=%d 個開啓中
|
||||
issues.close_tab=%d 個已關閉
|
||||
issues.filter_label=標籤篩選
|
||||
@@ -522,7 +522,7 @@ issues.next=下一頁
|
||||
issues.open_title=開啟中
|
||||
issues.closed_title=已關閉
|
||||
issues.num_comments=%d 條評論
|
||||
issues.commented_at=` 評論 <a href="#%s"> %s'</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=您確定要刪除該條評論嗎?
|
||||
issues.no_content=尚未有任何內容
|
||||
issues.close_issue=關閉
|
||||
@@ -536,7 +536,7 @@ issues.commit_ref_at=`在代碼提交 <a id="%[1]s" href="#%[1]s">%[2]s</a> 中
|
||||
issues.poster=發佈者
|
||||
issues.collaborator=協同者
|
||||
issues.owner=所有者
|
||||
issues.sign_in_require_desc=<a href="%s"> 登入</a> 才能加入這對話。
|
||||
issues.sign_in_require_desc=<a href="%s">Sign in</a> to join this conversation.
|
||||
issues.edit=編輯
|
||||
issues.cancel=取消
|
||||
issues.save=保存
|
||||
@@ -633,24 +633,24 @@ settings.hooks=管理 Web 鉤子
|
||||
settings.githooks=管理 Git 鉤子
|
||||
settings.basic_settings=基本設置
|
||||
settings.mirror_settings=鏡像設定
|
||||
settings.sync_mirror=立即同步
|
||||
settings.mirror_sync_in_progress=鏡像同步正在進行中,請大約一分鐘後刷新頁面。
|
||||
settings.sync_mirror=Sync Now
|
||||
settings.mirror_sync_in_progress=Mirror syncing is in progress, please refresh page in about a minute.
|
||||
settings.site=官方網站
|
||||
settings.update_settings=更新倉庫設置
|
||||
settings.change_reponame_prompt=該操作將會影響到所有與該倉庫有關的鏈接
|
||||
settings.advanced_settings=高級設置
|
||||
settings.wiki_desc=啓用 Wiki 系統
|
||||
settings.use_internal_wiki=使用內建 wiki
|
||||
settings.use_internal_wiki=Use builtin wiki
|
||||
settings.use_external_wiki=使用外部 wiki
|
||||
settings.external_wiki_url=外部 Wiki 連結
|
||||
settings.external_wiki_url_desc=當分頁上按一下,訪客將會重新導到 URL。
|
||||
settings.issues_desc=啟用問題追蹤
|
||||
settings.use_internal_issue_tracker=使用內建輕量級問題追蹤
|
||||
settings.issues_desc=Enable issue tracker
|
||||
settings.use_internal_issue_tracker=Use builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=使用外部的問題管理系統
|
||||
settings.tracker_url_format=外部問題管理系統的 URL 格式
|
||||
settings.tracker_issue_style=外部公單管理系統命名風格:
|
||||
settings.tracker_issue_style.numeric=數字
|
||||
settings.tracker_issue_style.alphanumeric=字母及數字
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
|
||||
settings.pulls_desc=啟用合併請求以接受社區貢獻
|
||||
settings.danger_zone=危險操作區
|
||||
@@ -721,7 +721,7 @@ settings.event_choose=讓我選擇我的需要
|
||||
settings.event_create=創建
|
||||
settings.event_create_desc=創建分支或標籤
|
||||
settings.event_pull_request=合併請求
|
||||
settings.event_pull_request_desc=請求打開,關閉,重新打開,編輯,分配,未分配,標籤更新,標籤清除,或同步。
|
||||
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
|
||||
settings.event_push=推送
|
||||
settings.event_push_desc=Git 倉庫推送
|
||||
settings.active=是否激活
|
||||
@@ -759,7 +759,7 @@ diff.show_unified_view=統一視圖
|
||||
diff.stats_desc=共有 <strong> %d 個文件被更改</strong>,包括 <strong>%d 次插入</strong> 和 <strong>%d 次删除</strong>
|
||||
diff.bin=二進制
|
||||
diff.view_file=查看文件
|
||||
diff.file_suppressed=文件差異過大導致無法顯示
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=部分文件因文件數量過多而無法顯示
|
||||
|
||||
release.releases=版本發佈
|
||||
@@ -791,7 +791,7 @@ release.deletion=刪除版本發布操作
|
||||
release.deletion_desc=刪除該版本發布將會移除相應的 Git 標籤。是否繼續?
|
||||
release.deletion_success=版本發布刪除成功!
|
||||
release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。
|
||||
release.tag_name_invalid=標記名稱不是有效的。
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=下載附件
|
||||
|
||||
[org]
|
||||
@@ -959,7 +959,7 @@ users.edit_account=編輯用戶信息
|
||||
users.max_repo_creation=最大儲存庫新增限制
|
||||
users.max_repo_creation_desc=(設定 -1 使用全域預設限制)
|
||||
users.is_activated=該用戶已被激活
|
||||
users.prohibit_login=此帳戶禁止登錄
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.is_admin=該用戶具有管理員權限
|
||||
users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限
|
||||
users.allow_import_local=該用戶具有導入本地倉庫的權限
|
||||
@@ -1113,19 +1113,19 @@ config.cookie_life_time=Cookie 生命周期
|
||||
config.picture_config=圖片配置
|
||||
config.picture_service=圖片服務
|
||||
config.disable_gravatar=禁用 Gravatar 頭像
|
||||
config.enable_federated_avatar=開啟聯合頭像
|
||||
config.enable_federated_avatar=Enable Federated Avatars
|
||||
|
||||
config.git_config=Git 配置
|
||||
config.git_disable_diff_highlight=禁用比較語法高亮
|
||||
config.git_max_diff_lines=Max Diff 線 (對於單個檔)
|
||||
config.git_max_diff_line_characters=最大比較的字元 (單行)
|
||||
config.git_max_diff_files=Max Diff 檔 (顯示)
|
||||
config.git_gc_args=GC 參數
|
||||
config.git_migrate_timeout=移動超時
|
||||
config.git_mirror_timeout=鏡像更新超時
|
||||
config.git_clone_timeout=複製操作超時
|
||||
config.git_pull_timeout=操作超時
|
||||
config.git_gc_timeout=GC 操作超時
|
||||
config.git_config=Git Configuration
|
||||
config.git_disable_diff_highlight=Disable Diff Syntax Highlight
|
||||
config.git_max_diff_lines=Max Diff Lines (for a single file)
|
||||
config.git_max_diff_line_characters=Max Diff Characters (for a single line)
|
||||
config.git_max_diff_files=Max Diff Files (to be shown)
|
||||
config.git_gc_args=GC Arguments
|
||||
config.git_migrate_timeout=Migration Timeout
|
||||
config.git_mirror_timeout=Mirror Update Timeout
|
||||
config.git_clone_timeout=Clone Operation Timeout
|
||||
config.git_pull_timeout=Pull Operation Timeout
|
||||
config.git_gc_timeout=GC Operation Timeout
|
||||
|
||||
config.log_config=日誌配置
|
||||
config.log_mode=日誌模式
|
||||
|
||||
@@ -1089,7 +1089,7 @@ function searchUsers() {
|
||||
if (response.ok && response.data.length) {
|
||||
var html = '';
|
||||
$.each(response.data, function (i, item) {
|
||||
html += '<div class="item"><img class="ui avatar image" src="' + item.avatar_url + '"><span class="username">' + item.login + '</span>';
|
||||
html += '<div class="item"><img class="ui avatar image" src="' + item.avatar_url + '"><span class="username">' + item.username + '</span>';
|
||||
if (notEmpty(item.full_name)) {
|
||||
html += ' (' + item.full_name + ')';
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
|
||||
ctx.Handle(500, "UpdateSource", err)
|
||||
return
|
||||
}
|
||||
log.Trace("Authentication changed by admin(%s): %d", ctx.User.Name, source.ID)
|
||||
log.Trace("Authentication changed by admin(%s): %s", ctx.User.Name, source.ID)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("admin.auths.update_success"))
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/auths/" + com.ToStr(form.ID))
|
||||
|
||||
@@ -197,11 +197,7 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
|
||||
|
||||
if len(form.Password) > 0 {
|
||||
u.Passwd = form.Password
|
||||
var err error
|
||||
if u.Salt, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
}
|
||||
u.Salt = models.GetUserSalt()
|
||||
u.EncodePasswd()
|
||||
}
|
||||
|
||||
|
||||
@@ -87,11 +87,7 @@ func EditUser(ctx *context.APIContext, form api.EditUserOption) {
|
||||
|
||||
if len(form.Password) > 0 {
|
||||
u.Passwd = form.Password
|
||||
var err error
|
||||
if u.Salt, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Error(500, "UpdateUser", err)
|
||||
return
|
||||
}
|
||||
u.Salt = models.GetUserSalt()
|
||||
u.EncodePasswd()
|
||||
}
|
||||
|
||||
|
||||
@@ -280,17 +280,12 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
})
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("").Get(repo.ListIssues).Post(bind(api.CreateIssueOption{}), repo.CreateIssue)
|
||||
m.Group("/comments", func() {
|
||||
m.Get("", repo.ListRepoIssueComments)
|
||||
m.Combo("/:id").Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueComment)
|
||||
})
|
||||
m.Group("/:index", func() {
|
||||
m.Combo("").Get(repo.GetIssue).Patch(bind(api.EditIssueOption{}), repo.EditIssue)
|
||||
|
||||
m.Group("/comments", func() {
|
||||
m.Combo("").Get(repo.ListIssueComments).Post(bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment)
|
||||
m.Combo("/:id").Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueComment).
|
||||
Delete(repo.DeleteIssueComment)
|
||||
m.Combo("/:id").Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueComment)
|
||||
})
|
||||
|
||||
m.Group("/labels", func() {
|
||||
|
||||
@@ -102,8 +102,7 @@ func CreateHook(ctx *context.APIContext, form api.CreateHookOption) {
|
||||
// EditHook modify a hook of a repository
|
||||
// see https://github.com/gogits/go-gogs-client/wiki/Repositories#edit-a-hook
|
||||
func EditHook(ctx *context.APIContext, form api.EditHookOption) {
|
||||
hookID := ctx.ParamsInt64(":id")
|
||||
w, err := models.GetWebhookByRepoID(ctx.Repo.Repository.ID, hookID)
|
||||
w, err := models.GetWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if models.IsErrWebhookNotExist(err) {
|
||||
ctx.Status(404)
|
||||
@@ -166,12 +165,7 @@ func EditHook(ctx *context.APIContext, form api.EditHookOption) {
|
||||
return
|
||||
}
|
||||
|
||||
updated, err := models.GetWebhookByRepoID(ctx.Repo.Repository.ID, hookID)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetWebhookByRepoID", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(200, convert.ToHook(ctx.Repo.RepoLink, updated))
|
||||
ctx.JSON(200, convert.ToHook(ctx.Repo.RepoLink, w))
|
||||
}
|
||||
|
||||
// DeleteHook delete a hook of a repository
|
||||
|
||||
@@ -40,26 +40,6 @@ func ListIssueComments(ctx *context.APIContext) {
|
||||
ctx.JSON(200, &apiComments)
|
||||
}
|
||||
|
||||
// ListRepoIssueComments returns all issue-comments for an issue
|
||||
func ListRepoIssueComments(ctx *context.APIContext) {
|
||||
var since time.Time
|
||||
if len(ctx.Query("since")) > 0 {
|
||||
since, _ = time.Parse(time.RFC3339, ctx.Query("since"))
|
||||
}
|
||||
|
||||
comments, err := models.GetCommentsByRepoIDSince(ctx.Repo.Repository.ID, since.Unix())
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetCommentsByRepoIDSince", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiComments := make([]*api.Comment, len(comments))
|
||||
for i := range comments {
|
||||
apiComments[i] = comments[i].APIFormat()
|
||||
}
|
||||
ctx.JSON(200, &apiComments)
|
||||
}
|
||||
|
||||
// CreateIssueComment create a comment for an issue
|
||||
func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOption) {
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
@@ -104,30 +84,3 @@ func EditIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
|
||||
}
|
||||
ctx.JSON(200, comment.APIFormat())
|
||||
}
|
||||
|
||||
// DeleteIssueComment delete a comment from an issue
|
||||
func DeleteIssueComment(ctx *context.APIContext) {
|
||||
comment, err := models.GetCommentByID(ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if models.IsErrCommentNotExist(err) {
|
||||
ctx.Error(404, "GetCommentByID", err)
|
||||
} else {
|
||||
ctx.Error(500, "GetCommentByID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
|
||||
ctx.Status(403)
|
||||
return
|
||||
} else if comment.Type != models.CommentTypeComment {
|
||||
ctx.Status(204)
|
||||
return
|
||||
}
|
||||
|
||||
if err = models.DeleteCommentByID(comment.ID); err != nil {
|
||||
ctx.Error(500, "DeleteCommentByID", err)
|
||||
return
|
||||
}
|
||||
ctx.Status(204)
|
||||
}
|
||||
|
||||
@@ -95,12 +95,16 @@ func ListMyRepos(ctx *context.APIContext) {
|
||||
|
||||
repos := make([]*api.Repository, numOwnRepos+len(accessibleRepos))
|
||||
for i := range ownRepos {
|
||||
repos[i] = ownRepos[i].APIFormat(models.AccessModeOwner)
|
||||
repos[i] = ownRepos[i].APIFormat(&api.Permission{true, true, true})
|
||||
}
|
||||
i := numOwnRepos
|
||||
|
||||
for repo, access := range accessibleRepos {
|
||||
repos[i] = repo.APIFormat(access)
|
||||
repos[i] = repo.APIFormat(&api.Permission{
|
||||
Admin: access >= models.AccessModeAdmin,
|
||||
Push: access >= models.AccessModeWrite,
|
||||
Pull: true,
|
||||
})
|
||||
i++
|
||||
}
|
||||
|
||||
@@ -134,7 +138,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(201, repo.APIFormat(models.AccessModeOwner))
|
||||
ctx.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
// Create one repository of mine
|
||||
@@ -237,19 +241,14 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||
}
|
||||
|
||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
|
||||
ctx.JSON(201, repo.APIFormat(models.AccessModeAdmin))
|
||||
ctx.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
// Get one repository
|
||||
// see https://github.com/gogits/go-gogs-client/wiki/Repositories#get
|
||||
func Get(ctx *context.APIContext) {
|
||||
repo := ctx.Repo.Repository
|
||||
access, err := models.AccessLevel(ctx.User, repo)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetRepository", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(200, repo.APIFormat(access))
|
||||
ctx.JSON(200, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
// GetByID returns a single Repository
|
||||
@@ -264,12 +263,7 @@ func GetByID(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
access, err := models.AccessLevel(ctx.User, repo)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetRepositoryByID", err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(200, repo.APIFormat(access))
|
||||
ctx.JSON(200, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
// Delete one repository
|
||||
|
||||
@@ -73,7 +73,6 @@ func DeleteEmail(ctx *context.APIContext, form api.CreateEmailOption) {
|
||||
for i := range form.Emails {
|
||||
emails[i] = &models.EmailAddress{
|
||||
Email: form.Emails[i],
|
||||
UID: ctx.User.ID,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,17 +18,9 @@ func getStarredRepos(userID int64, private bool) ([]*api.Repository, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user, err := models.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repos := make([]*api.Repository, len(starredRepos))
|
||||
for i, starred := range starredRepos {
|
||||
access, err := models.AccessLevel(user, starred)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repos[i] = starred.APIFormat(access)
|
||||
repos[i] = starred.APIFormat(&api.Permission{true, true, true})
|
||||
}
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ import (
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/cron"
|
||||
"code.gitea.io/gitea/modules/highlight"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/mailer"
|
||||
"code.gitea.io/gitea/modules/markdown"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/ssh"
|
||||
"code.gitea.io/gitea/modules/template/highlight"
|
||||
macaron "gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
@@ -73,7 +73,7 @@ func GlobalInit() {
|
||||
checkRunMode()
|
||||
|
||||
if setting.InstallLock && setting.SSH.StartBuiltinServer {
|
||||
ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort)
|
||||
log.Info("SSH server started on %s:%v", setting.SSH.ListenHost, setting.SSH.ListenPort)
|
||||
ssh.Listen(setting.SSH.ListenPort)
|
||||
log.Info("SSH server started on :%v", setting.SSH.ListenPort)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,6 @@ func Install(ctx *context.Context) {
|
||||
|
||||
// InstallPost response for submit install items
|
||||
func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
var err error
|
||||
ctx.Data["CurDbOption"] = form.DbType
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -132,7 +131,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = exec.LookPath("git"); err != nil {
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
@@ -162,7 +161,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
|
||||
// Set test engine.
|
||||
var x *xorm.Engine
|
||||
if err = models.NewTestEngine(x); err != nil {
|
||||
if err := models.NewTestEngine(x); err != nil {
|
||||
if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
|
||||
ctx.Data["Err_DbType"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://docs.gitea.io/installation/install_from_binary.html"), tplInstall, &form)
|
||||
@@ -175,7 +174,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
|
||||
// Test repository root path.
|
||||
form.RepoRootPath = strings.Replace(form.RepoRootPath, "\\", "/", -1)
|
||||
if err = os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
|
||||
if err := os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
|
||||
ctx.Data["Err_RepoRootPath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), tplInstall, &form)
|
||||
return
|
||||
@@ -183,7 +182,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
|
||||
// Test log root path.
|
||||
form.LogRootPath = strings.Replace(form.LogRootPath, "\\", "/", -1)
|
||||
if err = os.MkdirAll(form.LogRootPath, os.ModePerm); err != nil {
|
||||
if err := os.MkdirAll(form.LogRootPath, os.ModePerm); err != nil {
|
||||
ctx.Data["Err_LogRootPath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_log_root_path", err), tplInstall, &form)
|
||||
return
|
||||
@@ -226,7 +225,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
cfg := ini.Empty()
|
||||
if com.IsFile(setting.CustomConf) {
|
||||
// Keeps custom settings if there is already something.
|
||||
if err = cfg.Append(setting.CustomConf); err != nil {
|
||||
if err := cfg.Append(setting.CustomConf); err != nil {
|
||||
log.Error(4, "Fail to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
}
|
||||
}
|
||||
@@ -280,20 +279,15 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath)
|
||||
|
||||
cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
|
||||
var secretKey string
|
||||
if secretKey, err = base.GetRandomString(10); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
cfg.Section("security").Key("SECRET_KEY").SetValue(secretKey)
|
||||
cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15))
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
|
||||
err := os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
|
||||
if err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
|
||||
if err = cfg.SaveTo(setting.CustomConf); err != nil {
|
||||
if err := cfg.SaveTo(setting.CustomConf); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
@@ -309,7 +303,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
IsAdmin: true,
|
||||
IsActive: true,
|
||||
}
|
||||
if err = models.CreateUser(u); err != nil {
|
||||
if err := models.CreateUser(u); err != nil {
|
||||
if !models.IsErrUserAlreadyExist(err) {
|
||||
setting.InstallLock = false
|
||||
ctx.Data["Err_AdminName"] = true
|
||||
@@ -322,11 +316,11 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
}
|
||||
|
||||
// Auto-login for admin
|
||||
if err = ctx.Session.Set("uid", u.ID); err != nil {
|
||||
if err := ctx.Session.Set("uid", u.ID); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
if err = ctx.Session.Set("uname", u.Name); err != nil {
|
||||
if err := ctx.Session.Set("uname", u.Name); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/template"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -74,7 +74,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
|
||||
|
||||
d, _ := ioutil.ReadAll(dataRc)
|
||||
buf = append(buf, d...)
|
||||
if content, err := templates.ToUTF8WithErr(buf); err != nil {
|
||||
if content, err := template.ToUTF8WithErr(buf); err != nil {
|
||||
if err != nil {
|
||||
log.Error(4, "ToUTF8WithErr: %v", err)
|
||||
}
|
||||
@@ -186,11 +186,6 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if entry.IsLink() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", part), tplEditFile, &form)
|
||||
return
|
||||
}
|
||||
if entry.IsDir() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", part), tplEditFile, &form)
|
||||
|
||||
@@ -208,7 +208,7 @@ func HTTP(ctx *context.Context) {
|
||||
RepoUserName: username,
|
||||
RepoName: reponame,
|
||||
}); err == nil {
|
||||
go models.AddTestPullRequestTask(authUser, repo.ID, strings.TrimPrefix(refFullName, git.BranchPrefix), true)
|
||||
go models.AddTestPullRequestTask(authUser, repo.ID, strings.TrimPrefix(refFullName, git.BRANCH_PREFIX), true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -374,10 +374,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
||||
}
|
||||
|
||||
// Check labels.
|
||||
labelIDs, err := base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
|
||||
if err != nil {
|
||||
return nil, 0, 0
|
||||
}
|
||||
labelIDs := base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
|
||||
labelIDMark := base.Int64sToMap(labelIDs)
|
||||
hasSelected := false
|
||||
for i := range labels {
|
||||
|
||||
@@ -296,7 +296,7 @@ func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) {
|
||||
|
||||
// DeleteRelease delete a release
|
||||
func DeleteRelease(ctx *context.Context) {
|
||||
if err := models.DeleteReleaseByID(ctx.QueryInt64("id"), ctx.User); err != nil {
|
||||
if err := models.DeleteReleaseByID(ctx.QueryInt64("id")); err != nil {
|
||||
ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("repo.release.deletion_success"))
|
||||
|
||||
@@ -16,11 +16,11 @@ import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/highlight"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markdown"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/template"
|
||||
"code.gitea.io/gitea/modules/template/highlight"
|
||||
"github.com/Unknwon/paginater"
|
||||
)
|
||||
|
||||
@@ -164,7 +164,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
||||
} else {
|
||||
// Building code view blocks with line number on server side.
|
||||
var fileContent string
|
||||
if content, err := templates.ToUTF8WithErr(buf); err != nil {
|
||||
if content, err := template.ToUTF8WithErr(buf); err != nil {
|
||||
if err != nil {
|
||||
log.Error(4, "ToUTF8WithErr: %s", err)
|
||||
}
|
||||
@@ -198,8 +198,6 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
||||
|
||||
case base.IsPDFFile(buf):
|
||||
ctx.Data["IsPDFFile"] = true
|
||||
case base.IsVideoFile(buf):
|
||||
ctx.Data["IsVideoFile"] = true
|
||||
case base.IsImageFile(buf):
|
||||
ctx.Data["IsImageFile"] = true
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ func TestWebhook(ctx *context.Context) {
|
||||
if commit == nil {
|
||||
ghost := models.NewGhostUser()
|
||||
commit = &git.Commit{
|
||||
ID: git.MustIDFromString(git.EmptySHA),
|
||||
ID: git.MustIDFromString(git.EMPTY_SHA),
|
||||
Author: ghost.NewGitSig(),
|
||||
Committer: ghost.NewGitSig(),
|
||||
CommitMessage: "This is a fake commit",
|
||||
@@ -370,7 +370,7 @@ func TestWebhook(ctx *context.Context) {
|
||||
|
||||
apiUser := ctx.User.APIFormat()
|
||||
p := &api.PushPayload{
|
||||
Ref: git.BranchPrefix + ctx.Repo.Repository.DefaultBranch,
|
||||
Ref: git.BRANCH_PREFIX + ctx.Repo.Repository.DefaultBranch,
|
||||
Before: commit.ID.String(),
|
||||
After: commit.ID.String(),
|
||||
Commits: []*api.PayloadCommit{
|
||||
@@ -388,7 +388,7 @@ func TestWebhook(ctx *context.Context) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone),
|
||||
Repo: ctx.Repo.Repository.APIFormat(nil),
|
||||
Pusher: apiUser,
|
||||
Sender: apiUser,
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, str
|
||||
}
|
||||
pages := make([]PageMeta, 0, len(entries))
|
||||
for i := range entries {
|
||||
if entries[i].Type == git.ObjectBlob && strings.HasSuffix(entries[i].Name(), ".md") {
|
||||
if entries[i].Type == git.OBJECT_BLOB && strings.HasSuffix(entries[i].Name(), ".md") {
|
||||
name := strings.TrimSuffix(entries[i].Name(), ".md")
|
||||
pages = append(pages, PageMeta{
|
||||
Name: name,
|
||||
@@ -171,7 +171,7 @@ func WikiPages(ctx *context.Context) {
|
||||
}
|
||||
pages := make([]PageMeta, 0, len(entries))
|
||||
for i := range entries {
|
||||
if entries[i].Type == git.ObjectBlob && strings.HasSuffix(entries[i].Name(), ".md") {
|
||||
if entries[i].Type == git.OBJECT_BLOB && strings.HasSuffix(entries[i].Name(), ".md") {
|
||||
c, err := wikiRepo.GetCommitByPath(entries[i].Name())
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetCommit", err)
|
||||
|
||||
@@ -289,11 +289,7 @@ func Activate(ctx *context.Context) {
|
||||
// Verify code.
|
||||
if user := models.VerifyUserActiveCode(code); user != nil {
|
||||
user.IsActive = true
|
||||
var err error
|
||||
if user.Rands, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
}
|
||||
user.Rands = models.GetUserSalt()
|
||||
if err := models.UpdateUser(user); err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(404)
|
||||
@@ -432,15 +428,8 @@ func ResetPasswdPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
u.Passwd = passwd
|
||||
var err error
|
||||
if u.Rands, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
}
|
||||
if u.Salt, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
}
|
||||
u.Rands = models.GetUserSalt()
|
||||
u.Salt = models.GetUserSalt()
|
||||
u.EncodePasswd()
|
||||
if err := models.UpdateUser(u); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
|
||||
@@ -250,9 +250,6 @@ func Issues(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
ctx.Data["Repos"] = showRepos
|
||||
if len(repoIDs) == 0 {
|
||||
repoIDs = []int64{-1}
|
||||
}
|
||||
|
||||
issueStats := models.GetUserIssueStats(repoID, ctxUser.ID, repoIDs, filterMode, isPullList)
|
||||
issueStats.AllCount = int64(allCount)
|
||||
|
||||
@@ -197,11 +197,7 @@ func SettingsPasswordPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
||||
ctx.Flash.Error(ctx.Tr("form.password_not_match"))
|
||||
} else {
|
||||
ctx.User.Passwd = form.Password
|
||||
var err error
|
||||
if ctx.User.Salt, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
}
|
||||
ctx.User.Salt = models.GetUserSalt()
|
||||
ctx.User.EncodePasswd()
|
||||
if err := models.UpdateUser(ctx.User); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
@@ -291,7 +287,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
||||
|
||||
// DeleteEmail response for delete user's email
|
||||
func DeleteEmail(ctx *context.Context) {
|
||||
if err := models.DeleteEmailAddress(&models.EmailAddress{ID: ctx.QueryInt64("id"), UID: ctx.User.ID}); err != nil {
|
||||
if err := models.DeleteEmailAddress(&models.EmailAddress{ID: ctx.QueryInt64("id")}); err != nil {
|
||||
ctx.Handle(500, "DeleteEmail", err)
|
||||
return
|
||||
}
|
||||
@@ -426,7 +422,7 @@ func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm
|
||||
|
||||
// SettingsDeleteApplication response for delete user access token
|
||||
func SettingsDeleteApplication(ctx *context.Context) {
|
||||
if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil {
|
||||
if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id")); err != nil {
|
||||
ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
DIR=/home/git/gitea
|
||||
USER=git
|
||||
|
||||
start_stop_daemon_args="--user ${USER} --chdir ${DIR}"
|
||||
command="${DIR}/gitea"
|
||||
command_args="web"
|
||||
command_background=yes
|
||||
pidfile=/var/run/gitea.pid
|
||||
|
||||
depend()
|
||||
{
|
||||
need net
|
||||
}
|
||||
1
templates/.VERSION
Normal file
1
templates/.VERSION
Normal file
@@ -0,0 +1 @@
|
||||
0.9.99.0915
|
||||
@@ -20,7 +20,7 @@
|
||||
<i class="octicon octicon-flame"></i> Einfach zu installieren
|
||||
</h1>
|
||||
<p class="large">
|
||||
Starte einfach <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-binary/">die Anwendung</a> für deine Plattform. Gitea gibt es auch für <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a>, <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a> oder als <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-package/">Installationspaket</a>.
|
||||
Starte einfach <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">die Anwendung</a> für deine Plattform. Gitea gibt es auch für <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a>, <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a> oder als <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">Installationspaket</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
@@ -57,7 +57,7 @@
|
||||
<i class="octicon octicon-flame"></i> 易安装
|
||||
</h1>
|
||||
<p class="large">
|
||||
您除了可以根据操作系统平台通过 <a target="_blank" rel="noopener" href="https://docs.gitea.io/zh-cn/install-from-binary/">二进制运行</a>,还可以通过 <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> 或 <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>,以及 <a target="_blank" rel="noopener" href="https://docs.gitea.io/zh-cn/install-from-package/">包管理</a> 安装。
|
||||
您除了可以根据操作系统平台通过 <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">二进制运行</a>,还可以通过 <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> 或 <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>,以及 <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">包管理</a> 安装。
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
@@ -94,10 +94,10 @@
|
||||
<i class="octicon octicon-flame"></i> Facile à installer
|
||||
</h1>
|
||||
<p class="large">
|
||||
Il suffit de <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-binary/">lancer l'exécutable</a> correspondant à votre système.
|
||||
Il suffit de <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">lancer l'exécutable</a> correspondant à votre système.
|
||||
Ou d'utiliser Gitea avec <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> ou
|
||||
<a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>
|
||||
ou en l'installant depuis un <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-package/">package</a>.
|
||||
ou en l'installant depuis un <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">package</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
@@ -134,7 +134,7 @@
|
||||
<i class="octicon octicon-flame"></i> Fácil de instalar
|
||||
</h1>
|
||||
<p class="large">
|
||||
Simplemente <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-binary/">arranca el binario</a> para tu plataforma. O usa Gitea con <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> o <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, o utilice el <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-package/">paquete</a>.
|
||||
Simplemente <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">arranca el binario</a> para tu plataforma. O usa Gitea con <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> o <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, o utilice el <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">paquete</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
@@ -171,7 +171,7 @@
|
||||
<i class="octicon octicon-flame"></i> Fácil de instalar
|
||||
</h1>
|
||||
<p class="large">
|
||||
Simplesmente <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-binary/">rode o executável</a> para o seu sistema operacional. Ou obtenha o Gitea com o <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> ou <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, ou baixe o <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-package/">pacote</a>.
|
||||
Simplesmente <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">rode o executável</a> para o seu sistema operacional. Ou obtenha o Gitea com o <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> ou <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, ou baixe o <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">pacote</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
@@ -208,7 +208,7 @@
|
||||
<i class="octicon octicon-flame"></i> Простой в установке
|
||||
</h1>
|
||||
<p class="large">
|
||||
Просто <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-binary/">запустите исполняемый файл</a> для вашей платформы. Изпользуйте Gitea с <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> или <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, или загрузите <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-package/">пакет</a>.
|
||||
Просто <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">запустите исполняемый файл</a> для вашей платформы. Изпользуйте Gitea с <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> или <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, или загрузите <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">пакет</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
@@ -245,7 +245,7 @@
|
||||
<i class="octicon octicon-flame"></i> Easy to install
|
||||
</h1>
|
||||
<p class="large">
|
||||
Simply <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-binary/">run the binary</a> for your platform. Or ship Gitea with <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> or <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, or get it <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/install-from-package/">packaged</a>.
|
||||
Simply <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_binary.html">run the binary</a> for your platform. Or ship Gitea with <a target="_blank" rel="noopener" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> or <a target="_blank" rel="noopener" href="https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs">Vagrant</a>, or get it <a target="_blank" rel="noopener" href="https://docs.gitea.io/installation/install_from_packages.html">packaged</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="eight wide center column">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user