Compare commits
47 Commits
templates-
...
options-bi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a46834168 | ||
|
|
8596ea5519 | ||
|
|
608b1ce642 | ||
|
|
d97b9cf0c2 | ||
|
|
dd5464e1f2 | ||
|
|
c06db22b24 | ||
|
|
cd0ce9f3d8 | ||
|
|
70134323d1 | ||
|
|
8a28130540 | ||
|
|
e52b24ad5d | ||
|
|
947d2ee21b | ||
|
|
d07c955e2a | ||
|
|
edae0f134c | ||
|
|
db29855d2d | ||
|
|
e6cb9a7397 | ||
|
|
dc14d0c046 | ||
|
|
0118b275b6 | ||
|
|
c8f300b2cd | ||
|
|
db6a4e9fbf | ||
|
|
b21bf80dd4 | ||
|
|
0f05470cb8 | ||
|
|
d7ed78a919 | ||
|
|
e8e0539b45 | ||
|
|
e6cfccdd40 | ||
|
|
71bb6df75a | ||
|
|
bea9d55da6 | ||
|
|
d93429af8b | ||
|
|
7e09f80ee3 | ||
|
|
baf60bf603 | ||
|
|
4ff0db0246 | ||
|
|
79bd7648b0 | ||
|
|
b78d3f5865 | ||
|
|
5ab85372da | ||
|
|
1ae6ccb5f1 | ||
|
|
0a6d9295df | ||
|
|
6598745f07 | ||
|
|
590a79ff8a | ||
|
|
2343feadd4 | ||
|
|
bb3ed784bc | ||
|
|
31950cb262 | ||
|
|
2932042a6d | ||
|
|
646e02b521 | ||
|
|
bf0edcbdea | ||
|
|
4bd5730e02 | ||
|
|
a3fb627350 | ||
|
|
6dc6926abe | ||
|
|
1e9730a779 |
@@ -1,5 +1,5 @@
|
||||
*
|
||||
!gitea
|
||||
!docker
|
||||
!bin
|
||||
!public
|
||||
!templates
|
||||
|
||||
39
.drone.yml
39
.drone.yml
@@ -8,9 +8,10 @@ pipeline:
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: cert sqlite pam miniwinsvc
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- apk -U add linux-pam-dev openssh-client
|
||||
- apk -U add openssh-client
|
||||
- make clean
|
||||
- make vet
|
||||
- make lint
|
||||
@@ -22,34 +23,46 @@ pipeline:
|
||||
test-mysql:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test-mysql
|
||||
- make test-mysql
|
||||
when:
|
||||
event: [ push ]
|
||||
|
||||
test-pgsql:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test-pgsql
|
||||
- make test-pgsql
|
||||
when:
|
||||
event: [ push ]
|
||||
|
||||
updater:
|
||||
image: karalabe/xgo-latest:latest
|
||||
pull: true
|
||||
environment:
|
||||
CGO_ENABLED: 1
|
||||
TAGS: sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make release
|
||||
when:
|
||||
event: [ push, tag ]
|
||||
branch: [ master, refs/tags/* ]
|
||||
|
||||
coverage:
|
||||
image: plugins/coverage
|
||||
server: https://coverage.gitea.io
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
updater:
|
||||
image: karalabe/xgo-latest:latest
|
||||
pull: true
|
||||
commands:
|
||||
- make publish
|
||||
when:
|
||||
event: [ push, tag ]
|
||||
branch: [ master, refs/tags/* ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
|
||||
@@ -1 +1 @@
|
||||
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9zcnYvYXBwCiAgcGF0aDogc3JjL2NvZGUuZ2l0ZWEuaW8vZ2l0ZWEKCnBpcGVsaW5lOgogIHRlc3Q6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogY2VydCBzcWxpdGUgcGFtIG1pbml3aW5zdmMKICAgIGNvbW1hbmRzOgogICAgICAtIGFwayAtVSBhZGQgbGludXgtcGFtLWRldiBvcGVuc3NoLWNsaWVudAogICAgICAtIG1ha2UgY2xlYW4KICAgICAgLSBtYWtlIHZldAogICAgICAtIG1ha2UgbGludAogICAgICAtIG1ha2UgdGVzdAogICAgICAtIG1ha2UgYnVpbGQKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2gsIHRhZywgcHVsbF9yZXF1ZXN0IF0KCiAgdGVzdC1teXNxbDoKICAgIGltYWdlOiB3ZWJoaXBwaWUvZ29sYW5nOmVkZ2UKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgIC0gbWFrZSB0ZXN0LW15c3FsCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KCiAgdGVzdC1wZ3NxbDoKICAgIGltYWdlOiB3ZWJoaXBwaWUvZ29sYW5nOmVkZ2UKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgIC0gbWFrZSB0ZXN0LXBnc3FsCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KCiAgY292ZXJhZ2U6CiAgICBpbWFnZTogcGx1Z2lucy9jb3ZlcmFnZQogICAgc2VydmVyOiBodHRwczovL2NvdmVyYWdlLmdpdGVhLmlvCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIHVwZGF0ZXI6CiAgICBpbWFnZToga2FyYWxhYmUveGdvLWxhdGVzdDpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIG1ha2UgcHVibGlzaAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCwgdGFnIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciwgcmVmcy90YWdzLyogXQoKICBkb2NrZXI6CiAgICBpbWFnZTogcGx1Z2lucy9kb2NrZXIKICAgIHJlcG86IGdpdGVhL2dpdGVhCiAgICB0YWdzOiBbICcke1RBR30nIF0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHRhZyBdCiAgICAgIGJyYW5jaDogWyByZWZzL3RhZ3MvKiBdCgogIGRvY2tlcjoKICAgIGltYWdlOiBwbHVnaW5zL2RvY2tlcgogICAgcmVwbzogZ2l0ZWEvZ2l0ZWEKICAgIHRhZ3M6IFsgJ2xhdGVzdCcgXQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCiAgICAgIGJyYW5jaDogWyBtYXN0ZXIgXQoKICByZWxlYXNlOgogICAgaW1hZ2U6IHBsdWdpbnMvczMKICAgIHBhdGhfc3R5bGU6IHRydWUKICAgIHN0cmlwX3ByZWZpeDogZGlzdC9yZWxlYXNlLwogICAgc291cmNlOiBkaXN0L3JlbGVhc2UvKgogICAgdGFyZ2V0OiAvZ2l0ZWEvbWFzdGVyCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8kJFRBRwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZ2l0aHViOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICAgIGZpbGVzOgogICAgICAtIGRpc3QvcmVsZWFzZS8qCiAgICB3aGVuOgogICAgICBldmVudDogWyB0YWcgXQogICAgICBicmFuY2g6IFsgcmVmcy90YWdzLyogXQoKICBnaXR0ZXI6CiAgICBpbWFnZTogcGx1Z2lucy9naXR0ZXIKCnNlcnZpY2VzOgogIG15c3FsOgogICAgaW1hZ2U6IG15c3FsOjUuNwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTVlTUUxfREFUQUJBU0U9dGVzdAogICAgICAtIE1ZU1FMX0FMTE9XX0VNUFRZX1BBU1NXT1JEPXllcwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHBnc3FsOgogICAgaW1hZ2U6IHBvc3RncmVzOjkuNQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUE9TVEdSRVNfREI9dGVzdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCg.fIX2wjyGG2j4vH7ZY2owmyND3XRjCTMgy3Vr3Q71eTE
|
||||
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9zcnYvYXBwCiAgcGF0aDogc3JjL2NvZGUuZ2l0ZWEuaW8vZ2l0ZWEKCnBpcGVsaW5lOgogIHRlc3Q6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIGFwayAtVSBhZGQgb3BlbnNzaC1jbGllbnQKICAgICAgLSBtYWtlIGNsZWFuCiAgICAgIC0gbWFrZSB2ZXQKICAgICAgLSBtYWtlIGxpbnQKICAgICAgLSBtYWtlIHRlc3QKICAgICAgLSBtYWtlIGJ1aWxkCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIHRlc3QtbXlzcWw6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIG1ha2UgdGVzdC1teXNxbAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHRlc3QtcGdzcWw6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQ0dPX0VOQUJMRUQ6IDEKICAgICAgVEFHUzogc3FsaXRlCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIG1ha2UgdGVzdC1wZ3NxbAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHVwZGF0ZXI6CiAgICBpbWFnZToga2FyYWxhYmUveGdvLWxhdGVzdDpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGVudmlyb25tZW50OgogICAgICBDR09fRU5BQkxFRDogMQogICAgICBUQUdTOiBzcWxpdGUKICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gbWFrZSByZWxlYXNlCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcgXQogICAgICBicmFuY2g6IFsgbWFzdGVyLCByZWZzL3RhZ3MvKiBdCgogIGNvdmVyYWdlOgogICAgaW1hZ2U6IHBsdWdpbnMvY292ZXJhZ2UKICAgIHNlcnZlcjogaHR0cHM6Ly9jb3ZlcmFnZS5naXRlYS5pbwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCwgdGFnLCBwdWxsX3JlcXVlc3QgXQoKICBkb2NrZXI6CiAgICBpbWFnZTogcGx1Z2lucy9kb2NrZXIKICAgIHJlcG86IGdpdGVhL2dpdGVhCiAgICB0YWdzOiBbICcke1RBR30nIF0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHRhZyBdCiAgICAgIGJyYW5jaDogWyByZWZzL3RhZ3MvKiBdCgogIGRvY2tlcjoKICAgIGltYWdlOiBwbHVnaW5zL2RvY2tlcgogICAgcmVwbzogZ2l0ZWEvZ2l0ZWEKICAgIHRhZ3M6IFsgJ2xhdGVzdCcgXQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCiAgICAgIGJyYW5jaDogWyBtYXN0ZXIgXQoKICByZWxlYXNlOgogICAgaW1hZ2U6IHBsdWdpbnMvczMKICAgIHBhdGhfc3R5bGU6IHRydWUKICAgIHN0cmlwX3ByZWZpeDogZGlzdC9yZWxlYXNlLwogICAgc291cmNlOiBkaXN0L3JlbGVhc2UvKgogICAgdGFyZ2V0OiAvZ2l0ZWEvbWFzdGVyCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8kJFRBRwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZ2l0aHViOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICAgIGZpbGVzOgogICAgICAtIGRpc3QvcmVsZWFzZS8qCiAgICB3aGVuOgogICAgICBldmVudDogWyB0YWcgXQogICAgICBicmFuY2g6IFsgcmVmcy90YWdzLyogXQoKICBnaXR0ZXI6CiAgICBpbWFnZTogcGx1Z2lucy9naXR0ZXIKCnNlcnZpY2VzOgogIG15c3FsOgogICAgaW1hZ2U6IG15c3FsOjUuNwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTVlTUUxfREFUQUJBU0U9dGVzdAogICAgICAtIE1ZU1FMX0FMTE9XX0VNUFRZX1BBU1NXT1JEPXllcwogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCgogIHBnc3FsOgogICAgaW1hZ2U6IHBvc3RncmVzOjkuNQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUE9TVEdSRVNfREI9dGVzdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCg.LjU9u_DQ4fD2CytUu9RwwSimdcS3-KzR6nO4ff4edNU
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,6 +28,7 @@ _testmain.go
|
||||
|
||||
coverage.out
|
||||
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
|
||||
*.db
|
||||
|
||||
@@ -24,17 +24,17 @@ This process gives everyone a chance to validate the design, helps prevent dupli
|
||||
|
||||
## Testing redux
|
||||
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. To make sure you are running the test suite exactly like we do you should install the CLI for [Drone CI](https://github.com/drone/drone) as we are using the server for continous testing, follow [these instructions](http://readme.drone.io/0.5/install/cli/). After that you can simply call `drone exec` within you working directory and it will try to run the test suite locally.
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. To make sure you are running the test suite exactly like we do you should install the CLI for [Drone CI](https://github.com/drone/drone), as we are using the server for continous testing, following [these instructions](http://readme.drone.io/0.5/install/cli/). After that you can simply call `drone exec` within your working directory and it will try to run the test suite locally.
|
||||
|
||||
## Code review
|
||||
|
||||
Changes to Gitea must be reviewed before they are accepted, no matter who makes the change even if an owner or a maintainer. We use GitHub's pull request workflow to do that and we also use [LGTM](http://lgtm.co) to ensure every PR is reviewed by at least 2 maintainers.
|
||||
Changes to Gitea must be reviewed before they are accepted, no matter who makes the change even if it is an owner or a maintainer. We use GitHub's pull request workflow to do that and we also use [LGTM](http://lgtm.co) to ensure every PR is reviewed by at least 2 maintainers.
|
||||
|
||||
Please try to make your pull request easy to review for us. Please read the "[How to get faster PR reviews](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md)" guide, it got useful tips for any project you may want to contribute. See some of the points:
|
||||
Please try to make your pull request easy to review for us. Please read the "[How to get faster PR reviews](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md)" guide, it has lots of useful tips for any project you may want to contribute. Some of the key points:
|
||||
|
||||
* Make small pull requests. The smaller, the faster to review and the more likely it will be merged soon.
|
||||
* Don't make changes unrelated to your PR. Maybe there are typos on some comments, maybe refactoring would welcome on a function... but if that is not related to you PR, please make *another* PR for that.
|
||||
* Split big pull requests in multiple. An incremental change will be faster to review than a huge PR.
|
||||
* Don't make changes unrelated to your PR. Maybe there are typos on some comments, maybe refactoring would be welcome on a function... but if that is not related to your PR, please make *another* PR for that.
|
||||
* Split big pull requests in multiple small ones. An incremental change will be faster to review than a huge PR.
|
||||
|
||||
## Sign your work
|
||||
|
||||
@@ -48,19 +48,19 @@ Please use your real name, we really dislike pseudonyms or anonymous contributio
|
||||
|
||||
## Maintainers
|
||||
|
||||
To make sure every PR have been checked, we got team maintainers. Any PR MUST be reviewed and by at least two maintainers before it can get merged. Maintainers should be a contributor of Gitea (or Gogs) and contributed at least 4 accepted PRs. A contributor should apply as a maintainer in [Gitter development channel](https://gitter.im/go-gitea/develop). The owners or the team maintainers could invite the contributor. A maintainer should spend some time on code reviews. If some maintainer have no time to do that, he should apply to leave the maintainers team and we will give him an honor to be as a member of advisor team. Of course, if an advisor have time to code view, welcome it back to maintainers team. If someone have no time to code review and forget to leave the maintainers team, the owners have the power to move him from maintainers team to advisors team.
|
||||
To make sure every PR is checked, we got team maintainers. Every PR **MUST** be reviewed by at least two maintainers (or owners) before it can get merged. A maintainer should be a contributor of Gitea (or Gogs) and contributed at least 4 accepted PRs. A contributor should apply as a maintainer in the [Gitter develop channel](https://gitter.im/go-gitea/develop). The owners or the team maintainers may invite the contributor. A maintainer should spend some time on code reviews. If a maintainer has no time to do that, they should apply to leave the maintainers team and we will give them the honor of being a member of the advisors team. Of course, if an advisor has time to code review, we will gladly welcome them back to maintainers team. If someone has no time to code review and forgets to leave the maintainers team, the owners have the power to move him from maintainers team to advisors team.
|
||||
|
||||
## Owners
|
||||
|
||||
Since Gitea is a pure community organization without any company support, to keep the development healthly we will elect the owners every year. Every time we will elect three owners. All the contributers could vote for three owners, one is the main owner, the other two are assistant owners. When the new owners have been elected, the old owners MUST move the power to the new owners. If some owner don't obey these rules, the other owners are allowed to revoke his owner status.
|
||||
Since Gitea is a pure community organization without any company support, to keep the development healthy we will elect the owners every year. Every time we will elect three owners. All the contributors may vote up to three people, one of which is the main owner, and the others are assistant owners. When the new owners have been elected, the old owners MUST move the power to the new ones. If an owner don't obey these rules, the others are allowed to revoke his owner status.
|
||||
|
||||
After the election, the new owners should say he agrees with these rules on the [CONTRIBUTING](CONTRIBUTING.md) on the [Gitter main channel](https://gitter.im/go-gitea/gitea). Below are the words to speak:
|
||||
After the election, the new owners should say they agree with these rules on the [CONTRIBUTING](CONTRIBUTING.md) on the [Gitter main channel](https://gitter.im/go-gitea/gitea). Below are the words to speak:
|
||||
|
||||
```
|
||||
I'm glad to be an owner of Gitea, I agree with [CONTRIBUTING](CONTRIBUTING.md). I will spend part of my time on Gitea and lead the development of Gitea.
|
||||
```
|
||||
|
||||
For a honor to the owners, this document will add the history owners below:
|
||||
To honor the past owners, here's the history of the owners and the time they served:
|
||||
|
||||
* 2016-11-04 ~ 2017-12-31
|
||||
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
@@ -69,9 +69,9 @@ For a honor to the owners, this document will add the history owners below:
|
||||
|
||||
## Versions
|
||||
|
||||
Gitea has one master as a tip branch and have version branches such as `v0.9`. `v0.9` is a release branch and we will tag `v0.9.0` for binary download. If `v0.9.0` got some bug, we will accept pull requests on the `v0.9` branch and publish a `v0.9.1` tag, afterwards we will port the bug fix also to the master branch.
|
||||
Gitea has the `master` branch as a tip branch and has version branches such as `v0.9`. `v0.9` is a release branch and we will tag `v0.9.0` for binary download. If `v0.9.0` has bugs, we will accept pull requests on the `v0.9` branch and publish a `v0.9.1` tag, after bringing the bug fix also to the master branch.
|
||||
|
||||
The `master` branch is a tip version, so if you wish a production usage, please download the latest release tag version. All the branches will be protected via github, all the PRs to all the branches should be review by two maintainers and pass the automatic tests.
|
||||
Since the `master` branch is a tip version, if you wish to use Gitea in production, please download the latest release tag version. All the branches will be protected via GitHub, all the PRs to every branch must be reviewed by two maintainers and must pass the automatic tests.
|
||||
|
||||
## Copyright
|
||||
|
||||
@@ -83,4 +83,4 @@ Code that you contribute should use the standard copyright header:
|
||||
// license that can be found in the LICENSE file.
|
||||
```
|
||||
|
||||
Files in the repository are copyright the year they are added and the year they are last changed. If the copyright author is changed, just copy the head below the old one.
|
||||
Files in the repository contain copyright from the year they are added to the year they are last changed. If the copyright author is changed, just paste the header below the old one.
|
||||
|
||||
@@ -41,4 +41,4 @@ COPY docker /
|
||||
|
||||
COPY public /app/gitea/public
|
||||
COPY templates /app/gitea/templates
|
||||
COPY bin/gitea /app/gitea/gitea
|
||||
COPY gitea /app/gitea/gitea
|
||||
|
||||
@@ -41,4 +41,4 @@ COPY docker /
|
||||
|
||||
COPY public /app/gitea/public
|
||||
COPY templates /app/gitea/templates
|
||||
COPY bin/gitea /app/gitea/gitea
|
||||
COPY gitea /app/gitea/gitea
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Alexey Makhov <amakhov@avito.ru> (@makhov)
|
||||
Andrey Nering <andrey.nering@gmail.com> (@andreynering)
|
||||
Bwko <bouwko@gmail.com> (@Bwko)
|
||||
Kees de Vries <bouwko@gmail.com> (@Bwko)
|
||||
Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
||||
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
||||
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
||||
|
||||
54
Makefile
54
Makefile
@@ -1,13 +1,10 @@
|
||||
DIST := dist
|
||||
BIN := bin
|
||||
|
||||
EXECUTABLE := gitea
|
||||
IMPORT := code.gitea.io/gitea
|
||||
|
||||
SHA := $(shell git rev-parse --short HEAD)
|
||||
DATE := $(shell date -u '+%Y-%m-%d %I:%M:%S %Z')
|
||||
|
||||
BINDATA := $(shell find conf | sed 's/ /\\ /g')
|
||||
STYLESHEETS := $(wildcard public/less/index.less public/less/_*.less)
|
||||
JAVASCRIPTS :=
|
||||
|
||||
@@ -35,7 +32,7 @@ all: build
|
||||
.PHONY: clean
|
||||
clean:
|
||||
go clean -i ./...
|
||||
rm -rf $(BIN) $(DIST)
|
||||
rm -rf $(EXECUTABLE) $(DIST)
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
@@ -86,58 +83,37 @@ install: $(wildcard *.go)
|
||||
go install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
||||
|
||||
.PHONY: build
|
||||
build: $(BIN)/$(EXECUTABLE)
|
||||
build: $(EXECUTABLE)
|
||||
|
||||
$(BIN)/$(EXECUTABLE): $(wildcard *.go)
|
||||
.PHONY: $(EXECUTABLE)
|
||||
$(EXECUTABLE): $(wildcard *.go)
|
||||
go build -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
.PHONY: release
|
||||
release: release-build release-copy release-check
|
||||
release: release-dirs release-build release-copy release-check
|
||||
|
||||
.PHONY: release-dirs
|
||||
release-dirs:
|
||||
mkdir -p $(DIST)/binaries $(DIST)/release
|
||||
|
||||
.PHONY: release-build
|
||||
release-build:
|
||||
@which xgo > /dev/null; if [ $$? -ne 0 ]; then \
|
||||
go get -u github.com/karalabe/xgo; \
|
||||
fi
|
||||
xgo -dest $(BIN) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets '$(TARGETS)' -out $(EXECUTABLE)-$(VERSION) $(IMPORT)
|
||||
xgo -dest $(DIST)/binaries -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets '$(TARGETS)' -out $(EXECUTABLE)-$(VERSION) $(IMPORT)
|
||||
ifeq ($(CI),drone)
|
||||
mv /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-copy
|
||||
release-copy:
|
||||
mkdir -p $(DIST)/release
|
||||
$(foreach file,$(wildcard $(BIN)/$(EXECUTABLE)-*),cp $(file) $(DIST)/release/$(notdir $(file));)
|
||||
$(foreach file,$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*),cp $(file) $(DIST)/release/$(notdir $(file));)
|
||||
|
||||
.PHONY: release-check
|
||||
release-check:
|
||||
cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
|
||||
|
||||
.PHONY: latest
|
||||
latest: release-build latest-copy latest-check
|
||||
|
||||
.PHONY: latest-copy
|
||||
latest-copy:
|
||||
mkdir -p $(DIST)/latest
|
||||
$(foreach file,$(wildcard $(BIN)/$(EXECUTABLE)-*),cp $(file) $(DIST)/latest/$(subst $(EXECUTABLE)-$(VERSION),$(EXECUTABLE)-latest,$(notdir $(file)));)
|
||||
|
||||
.PHONY: latest-check
|
||||
latest-check:
|
||||
cd $(DIST)/latest; $(foreach file,$(wildcard $(DIST)/latest/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
|
||||
|
||||
.PHONY: publish
|
||||
publish: release latest
|
||||
|
||||
.PHONY: bindata
|
||||
bindata: modules/bindata/bindata.go
|
||||
|
||||
.IGNORE: modules/bindata/bindata.go
|
||||
modules/bindata/bindata.go: $(BINDATA)
|
||||
@which go-bindata > /dev/null; if [ $$? -ne 0 ]; then \
|
||||
go get -u github.com/jteeuwen/go-bindata/...; \
|
||||
fi
|
||||
go-bindata -o=$@ -ignore="\\.go|README.md|TRANSLATORS" -pkg=bindata conf/...
|
||||
go fmt $@
|
||||
sed -i.bak 's/confLocaleLocale_/confLocaleLocale/' $@
|
||||
rm $@.bak
|
||||
|
||||
.PHONY: javascripts
|
||||
javascripts: public/js/index.js
|
||||
|
||||
@@ -153,4 +129,4 @@ public/css/index.css: $(STYLESHEETS)
|
||||
lessc $< $@
|
||||
|
||||
.PHONY: assets
|
||||
assets: bindata javascripts stylesheets
|
||||
assets: javascripts stylesheets
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// +build cert
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// 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.
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// +build !cert
|
||||
|
||||
// Copyright 2009 The Go 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.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdCert represents the available cert sub-command.
|
||||
var CmdCert = cli.Command{
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,
|
||||
Action: runCert,
|
||||
}
|
||||
|
||||
func runCert(*cli.Context) error {
|
||||
fmt.Println("Command cert not available, please use build tags 'cert' to rebuild.")
|
||||
os.Exit(1)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -79,7 +79,6 @@ func runDump(ctx *cli.Context) error {
|
||||
log.Printf("Packing dump files...")
|
||||
z, err := zip.Create(fileName)
|
||||
if err != nil {
|
||||
os.Remove(fileName)
|
||||
log.Fatalf("Fail to create %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
@@ -102,7 +101,7 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
// FIXME: SSH key file.
|
||||
if err = z.Close(); err != nil {
|
||||
os.Remove(fileName)
|
||||
_ = os.Remove(fileName)
|
||||
log.Fatalf("Fail to save %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
@@ -111,7 +110,10 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
log.Printf("Removing tmp work dir: %s", TmpWorkDir)
|
||||
os.RemoveAll(TmpWorkDir)
|
||||
|
||||
if err := os.RemoveAll(TmpWorkDir); err != nil {
|
||||
log.Fatalf("Fail to remove %s: %v", TmpWorkDir, err)
|
||||
}
|
||||
log.Printf("Finish dumping in file %s", fileName)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -51,7 +51,9 @@ func setup(logPath string) {
|
||||
|
||||
if setting.UseSQLite3 || setting.UseTiDB {
|
||||
workDir, _ := setting.WorkDir()
|
||||
os.Chdir(workDir)
|
||||
if err := os.Chdir(workDir); err != nil {
|
||||
log.GitLogger.Fatal(4, "Fail to change directory %s: %v", workDir, err)
|
||||
}
|
||||
}
|
||||
|
||||
models.SetEngine()
|
||||
@@ -256,7 +258,11 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
os.Setenv("uuid", uuid)
|
||||
|
||||
// Special handle for Windows.
|
||||
|
||||
@@ -49,7 +49,7 @@ func runUpdate(c *cli.Context) error {
|
||||
}
|
||||
|
||||
task := models.UpdateTask{
|
||||
UUID: os.Getenv("uuid"),
|
||||
UUID: os.Getenv("GITEA_UUID"),
|
||||
RefName: args[0],
|
||||
OldCommitID: args[1],
|
||||
NewCommitID: args[2],
|
||||
|
||||
32
cmd/web.go
32
cmd/web.go
@@ -18,9 +18,9 @@ import (
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/bindata"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/public"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/template"
|
||||
@@ -150,22 +150,29 @@ func newMacaron() *macaron.Macaron {
|
||||
models.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
|
||||
path.Join(setting.CustomPath, "templates/mail"), funcMap)
|
||||
|
||||
localeNames, err := bindata.AssetDir("conf/locale")
|
||||
localeNames, err := options.Dir("locale")
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to list locale files: %v", err)
|
||||
}
|
||||
|
||||
localFiles := make(map[string][]byte)
|
||||
|
||||
for _, name := range localeNames {
|
||||
localFiles[name] = bindata.MustAsset("conf/locale/" + name)
|
||||
localFiles[name], err = options.Locale(name)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(4, "Failed to load %s locale file. %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
m.Use(i18n.I18n(i18n.Options{
|
||||
SubURL: setting.AppSubURL,
|
||||
Files: localFiles,
|
||||
CustomDirectory: path.Join(setting.CustomPath, "conf/locale"),
|
||||
Langs: setting.Langs,
|
||||
Names: setting.Names,
|
||||
DefaultLang: "en-US",
|
||||
Redirect: true,
|
||||
SubURL: setting.AppSubURL,
|
||||
Files: localFiles,
|
||||
Langs: setting.Langs,
|
||||
Names: setting.Names,
|
||||
DefaultLang: "en-US",
|
||||
Redirect: true,
|
||||
}))
|
||||
m.Use(cache.Cacher(cache.Options{
|
||||
Adapter: setting.CacheAdapter,
|
||||
@@ -654,8 +661,9 @@ func runWeb(ctx *cli.Context) error {
|
||||
case setting.FCGI:
|
||||
err = fcgi.Serve(nil, m)
|
||||
case setting.UnixSocket:
|
||||
os.Remove(listenAddr)
|
||||
|
||||
if err := os.Remove(listenAddr); err != nil {
|
||||
log.Fatal(4, "Fail to remove unix socket directory %s: %v", listenAddr, err)
|
||||
}
|
||||
var listener *net.UnixListener
|
||||
listener, err = net.ListenUnix("unix", &net.UnixAddr{Name: listenAddr, Net: "unix"})
|
||||
if err != nil {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Execute following command in ROOT directory when anything is changed:
|
||||
|
||||
$ make bindata
|
||||
8
main.go
8
main.go
@@ -10,6 +10,8 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"code.gitea.io/gitea/cmd"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/urfave/cli"
|
||||
@@ -37,5 +39,9 @@ func main() {
|
||||
cmd.CmdAdmin,
|
||||
}
|
||||
app.Flags = append(app.Flags, []cli.Flag{}...)
|
||||
app.Run(os.Args)
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to run app with %s: %v", os.Args, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -584,6 +584,28 @@ func (err ErrPullRequestNotExist) Error() string {
|
||||
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBarcnh, err.BaseBranch)
|
||||
}
|
||||
|
||||
// ErrPullRequestAlreadyExists represents a "PullRequestAlreadyExists"-error
|
||||
type ErrPullRequestAlreadyExists struct {
|
||||
ID int64
|
||||
IssueID int64
|
||||
HeadRepoID int64
|
||||
BaseRepoID int64
|
||||
HeadBranch string
|
||||
BaseBranch string
|
||||
}
|
||||
|
||||
// IsErrPullRequestAlreadyExists checks if an error is a ErrPullRequestAlreadyExists.
|
||||
func IsErrPullRequestAlreadyExists(err error) bool {
|
||||
_, ok := err.(ErrPullRequestAlreadyExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Error does pretty-printing :D
|
||||
func (err ErrPullRequestAlreadyExists) Error() string {
|
||||
return fmt.Sprintf("pull request already exists for these targets [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
|
||||
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
|
||||
}
|
||||
|
||||
// _________ __
|
||||
// \_ ___ \ ____ _____ _____ ____ _____/ |_
|
||||
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
|
||||
|
||||
@@ -170,6 +170,22 @@ func (issue *Issue) HTMLURL() string {
|
||||
return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(), path, issue.Index)
|
||||
}
|
||||
|
||||
// DiffURL returns the absolute URL to this diff
|
||||
func (issue *Issue) DiffURL() string {
|
||||
if issue.IsPull {
|
||||
return fmt.Sprintf("%s/pulls/%d.diff", issue.Repo.HTMLURL(), issue.Index)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// PatchURL returns the absolute URL to this patch
|
||||
func (issue *Issue) PatchURL() string {
|
||||
if issue.IsPull {
|
||||
return fmt.Sprintf("%s/pulls/%d.patch", issue.Repo.HTMLURL(), issue.Index)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// State returns string representation of issue status.
|
||||
func (issue *Issue) State() api.StateType {
|
||||
if issue.IsClosed {
|
||||
|
||||
@@ -67,7 +67,7 @@ func (label *Label) APIFormat() *api.Label {
|
||||
return &api.Label{
|
||||
ID: label.ID,
|
||||
Name: label.Name,
|
||||
Color: label.Color,
|
||||
Color: strings.TrimLeft(label.Color, "#"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,27 @@ func NewLabels(labels ...*Label) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// getLabelInRepoByName returns a label by Name in given repository.
|
||||
// If pass repoID as 0, then ORM will ignore limitation of repository
|
||||
// and can return arbitrary label with any valid ID.
|
||||
func getLabelInRepoByName(e Engine, repoID int64, labelName string) (*Label, error) {
|
||||
if len(labelName) <= 0 {
|
||||
return nil, ErrLabelNotExist{0, repoID}
|
||||
}
|
||||
|
||||
l := &Label{
|
||||
Name: labelName,
|
||||
RepoID: repoID,
|
||||
}
|
||||
has, err := x.Get(l)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrLabelNotExist{0, l.RepoID}
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// getLabelInRepoByID returns a label by ID in given repository.
|
||||
// If pass repoID as 0, then ORM will ignore limitation of repository
|
||||
// and can return arbitrary label with any valid ID.
|
||||
@@ -128,6 +149,11 @@ func GetLabelByID(id int64) (*Label, error) {
|
||||
return getLabelInRepoByID(x, 0, id)
|
||||
}
|
||||
|
||||
// GetLabelInRepoByName returns a label by name in given repository.
|
||||
func GetLabelInRepoByName(repoID int64, labelName string) (*Label, error) {
|
||||
return getLabelInRepoByName(x, repoID, labelName)
|
||||
}
|
||||
|
||||
// GetLabelInRepoByID returns a label by ID in given repository.
|
||||
func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) {
|
||||
return getLabelInRepoByID(x, repoID, labelID)
|
||||
|
||||
@@ -192,7 +192,10 @@ func SetEngine() (err error) {
|
||||
// WARNING: for serv command, MUST remove the output to os.stdout,
|
||||
// so use log file to instead print to stdout.
|
||||
logPath := path.Join(setting.LogRootPath, "xorm.log")
|
||||
os.MkdirAll(path.Dir(logPath), os.ModePerm)
|
||||
|
||||
if err := os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", logPath, err)
|
||||
}
|
||||
|
||||
f, err := os.Create(logPath)
|
||||
if err != nil {
|
||||
|
||||
132
models/pull.go
132
models/pull.go
@@ -121,7 +121,54 @@ func (pr *PullRequest) LoadIssue() (err error) {
|
||||
// Required - Issue
|
||||
// Optional - Merger
|
||||
func (pr *PullRequest) APIFormat() *api.PullRequest {
|
||||
var (
|
||||
baseBranch *Branch
|
||||
headBranch *Branch
|
||||
baseCommit *git.Commit
|
||||
headCommit *git.Commit
|
||||
err error
|
||||
)
|
||||
apiIssue := pr.Issue.APIFormat()
|
||||
if pr.BaseRepo == nil {
|
||||
pr.BaseRepo, err = GetRepositoryByID(pr.BaseRepoID)
|
||||
if err != nil {
|
||||
log.Error(log.ERROR, "GetRepositoryById[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if pr.HeadRepo == nil {
|
||||
pr.HeadRepo, err = GetRepositoryByID(pr.HeadRepoID)
|
||||
if err != nil {
|
||||
log.Error(log.ERROR, "GetRepositoryById[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if baseBranch, err = pr.BaseRepo.GetBranch(pr.BaseBranch); err != nil {
|
||||
return nil
|
||||
}
|
||||
if baseCommit, err = baseBranch.GetCommit(); err != nil {
|
||||
return nil
|
||||
}
|
||||
if headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch); err != nil {
|
||||
return nil
|
||||
}
|
||||
if headCommit, err = headBranch.GetCommit(); err != nil {
|
||||
return nil
|
||||
}
|
||||
apiBaseBranchInfo := &api.PRBranchInfo{
|
||||
Name: pr.BaseBranch,
|
||||
Ref: pr.BaseBranch,
|
||||
Sha: baseCommit.ID.String(),
|
||||
RepoID: pr.BaseRepoID,
|
||||
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(nil),
|
||||
}
|
||||
apiPullRequest := &api.PullRequest{
|
||||
ID: pr.ID,
|
||||
Index: pr.Index,
|
||||
@@ -134,7 +181,12 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
||||
State: apiIssue.State,
|
||||
Comments: apiIssue.Comments,
|
||||
HTMLURL: pr.Issue.HTMLURL(),
|
||||
DiffURL: pr.Issue.DiffURL(),
|
||||
PatchURL: pr.Issue.PatchURL(),
|
||||
HasMerged: pr.HasMerged,
|
||||
Base: apiBaseBranchInfo,
|
||||
Head: apiHeadBranchInfo,
|
||||
MergeBase: pr.MergeBase,
|
||||
}
|
||||
|
||||
if pr.Status != PullRequestStatusChecking {
|
||||
@@ -218,7 +270,11 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
|
||||
// Clone base repo.
|
||||
tmpBasePath := path.Join(setting.AppDataPath, "tmp/repos", com.ToStr(time.Now().Nanosecond())+".git")
|
||||
os.MkdirAll(path.Dir(tmpBasePath), os.ModePerm)
|
||||
|
||||
if err := os.MkdirAll(path.Dir(tmpBasePath), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", tmpBasePath, err)
|
||||
}
|
||||
|
||||
defer os.RemoveAll(path.Dir(tmpBasePath))
|
||||
|
||||
var stderr string
|
||||
@@ -339,7 +395,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
return nil
|
||||
}
|
||||
|
||||
// patchConflicts is a list of conflit description from Git.
|
||||
// patchConflicts is a list of conflict description from Git.
|
||||
var patchConflicts = []string{
|
||||
"patch does not apply",
|
||||
"already exists in working directory",
|
||||
@@ -347,7 +403,7 @@ var patchConflicts = []string{
|
||||
"error:",
|
||||
}
|
||||
|
||||
// testPatch checks if patch can be merged to base repository without conflit.
|
||||
// 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 {
|
||||
@@ -384,7 +440,7 @@ func (pr *PullRequest) testPatch() (err error) {
|
||||
if err != nil {
|
||||
for i := range patchConflicts {
|
||||
if strings.Contains(stderr, patchConflicts[i]) {
|
||||
log.Trace("PullRequest[%d].testPatch (apply): has conflit", pr.ID)
|
||||
log.Trace("PullRequest[%d].testPatch (apply): has conflict", pr.ID)
|
||||
fmt.Println(stderr)
|
||||
pr.Status = PullRequestStatusConflict
|
||||
return nil
|
||||
@@ -468,6 +524,46 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
||||
return nil
|
||||
}
|
||||
|
||||
// PullRequestsOptions holds the options for PRs
|
||||
type PullRequestsOptions struct {
|
||||
Page int
|
||||
State string
|
||||
SortType string
|
||||
Labels []string
|
||||
MilestoneID int64
|
||||
}
|
||||
|
||||
func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) *xorm.Session {
|
||||
sess := x.Where("pull_request.base_repo_id=?", baseRepoID)
|
||||
|
||||
sess.Join("INNER", "issue", "pull_request.issue_id = issue.id")
|
||||
switch opts.State {
|
||||
case "closed", "open":
|
||||
sess.And("issue.is_closed=?", opts.State == "closed")
|
||||
}
|
||||
|
||||
return sess
|
||||
}
|
||||
|
||||
// PullRequests returns all pull requests for a base Repo by the given conditions
|
||||
func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, int64, error) {
|
||||
if opts.Page <= 0 {
|
||||
opts.Page = 1
|
||||
}
|
||||
|
||||
countSession := listPullRequestStatement(baseRepoID, opts)
|
||||
maxResults, err := countSession.Count(new(PullRequest))
|
||||
if err != nil {
|
||||
log.Error(4, "Count PRs", err)
|
||||
return nil, maxResults, err
|
||||
}
|
||||
|
||||
prs := make([]*PullRequest, 0, ItemsPerPage)
|
||||
findSession := listPullRequestStatement(baseRepoID, opts)
|
||||
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage)
|
||||
return prs, maxResults, findSession.Find(&prs)
|
||||
}
|
||||
|
||||
// GetUnmergedPullRequest returnss a pull request that is open and has not been merged
|
||||
// by given head/base and repo/branch.
|
||||
func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string) (*PullRequest, error) {
|
||||
@@ -508,6 +604,30 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
|
||||
Find(&prs)
|
||||
}
|
||||
|
||||
// GetPullRequestByIndex returns a pull request by the given index
|
||||
func GetPullRequestByIndex(repoID int64, index int64) (*PullRequest, error) {
|
||||
pr := &PullRequest{
|
||||
BaseRepoID: repoID,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
has, err := x.Get(pr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrPullRequestNotExist{0, repoID, index, 0, "", ""}
|
||||
}
|
||||
|
||||
if err = pr.LoadAttributes(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = pr.LoadIssue(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pr, nil
|
||||
}
|
||||
|
||||
func getPullRequestByID(e Engine, id int64) (*PullRequest, error) {
|
||||
pr := new(PullRequest)
|
||||
has, err := e.Id(id).Get(pr)
|
||||
@@ -622,7 +742,9 @@ func (pr *PullRequest) PushToBaseRepo() (err error) {
|
||||
headFile := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
|
||||
// Remove head in case there is a conflict.
|
||||
os.Remove(path.Join(pr.BaseRepo.RepoPath(), headFile))
|
||||
file := path.Join(pr.BaseRepo.RepoPath(), headFile)
|
||||
|
||||
_ = os.Remove(file)
|
||||
|
||||
if err = git.Push(headRepoPath, tmpRemoteName, fmt.Sprintf("%s:%s", pr.HeadBranch, headFile)); err != nil {
|
||||
return fmt.Errorf("Push: %v", err)
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/bindata"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markdown"
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/sync"
|
||||
@@ -80,11 +80,11 @@ func LoadRepoConfig() {
|
||||
types := []string{"gitignore", "license", "readme", "label"}
|
||||
typeFiles := make([][]string, 4)
|
||||
for i, t := range types {
|
||||
files, err := bindata.AssetDir("conf/" + t)
|
||||
files, err := options.Dir(t)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to get %s files: %v", t, err)
|
||||
}
|
||||
customPath := path.Join(setting.CustomPath, "conf", t)
|
||||
customPath := path.Join(setting.CustomPath, "options", t)
|
||||
if com.IsDir(customPath) {
|
||||
customFiles, err := com.StatDir(customPath)
|
||||
if err != nil {
|
||||
@@ -499,7 +499,7 @@ var (
|
||||
// DescriptionHTML does special handles to description and return HTML string.
|
||||
func (repo *Repository) DescriptionHTML() template.HTML {
|
||||
sanitize := func(s string) string {
|
||||
return fmt.Sprintf(`<a href="%[1]s" target="_blank">%[1]s</a>`, s)
|
||||
return fmt.Sprintf(`<a href="%[1]s" target="_blank" rel="noopener">%[1]s</a>`, s)
|
||||
}
|
||||
return template.HTML(descPattern.ReplaceAllStringFunc(markdown.Sanitizer.Sanitize(repo.Description), sanitize))
|
||||
}
|
||||
@@ -558,8 +558,12 @@ func (repo *Repository) SavePatch(index int64, patch []byte) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("PatchPath: %v", err)
|
||||
}
|
||||
dir := filepath.Dir(patchPath)
|
||||
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
os.MkdirAll(filepath.Dir(patchPath), os.ModePerm)
|
||||
if err = ioutil.WriteFile(patchPath, patch, 0644); err != nil {
|
||||
return fmt.Errorf("WriteFile: %v", err)
|
||||
}
|
||||
@@ -669,7 +673,10 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
|
||||
migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second
|
||||
|
||||
os.RemoveAll(repoPath)
|
||||
if err := os.RemoveAll(repoPath); err != nil {
|
||||
return repo, fmt.Errorf("Fail to remove %s: %v", repoPath, err)
|
||||
}
|
||||
|
||||
if err = git.Clone(opts.RemoteAddr, repoPath, git.CloneRepoOptions{
|
||||
Mirror: true,
|
||||
Quiet: true,
|
||||
@@ -680,7 +687,11 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
|
||||
wikiRemotePath := wikiRemoteURL(opts.RemoteAddr)
|
||||
if len(wikiRemotePath) > 0 {
|
||||
os.RemoveAll(wikiPath)
|
||||
|
||||
if err := os.RemoveAll(wikiPath); err != nil {
|
||||
return repo, fmt.Errorf("Fail to remove %s: %v", wikiPath, err)
|
||||
}
|
||||
|
||||
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{
|
||||
Mirror: true,
|
||||
Quiet: true,
|
||||
@@ -812,14 +823,25 @@ type CreateRepoOptions struct {
|
||||
}
|
||||
|
||||
func getRepoInitFile(tp, name string) ([]byte, error) {
|
||||
relPath := path.Join("conf", tp, strings.TrimLeft(name, "./"))
|
||||
cleanedName := strings.TrimLeft(name, "./")
|
||||
relPath := path.Join("options", tp, cleanedName)
|
||||
|
||||
// Use custom file when available.
|
||||
customPath := path.Join(setting.CustomPath, relPath)
|
||||
if com.IsFile(customPath) {
|
||||
return ioutil.ReadFile(customPath)
|
||||
}
|
||||
return bindata.Asset(relPath)
|
||||
|
||||
switch tp {
|
||||
case "readme":
|
||||
return options.Readme(cleanedName)
|
||||
case "gitignore":
|
||||
return options.Gitignore(cleanedName)
|
||||
case "license":
|
||||
return options.License(cleanedName)
|
||||
default:
|
||||
return []byte{}, fmt.Errorf("Invalid init file type")
|
||||
}
|
||||
}
|
||||
|
||||
func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRepoOptions) error {
|
||||
@@ -902,7 +924,11 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C
|
||||
|
||||
// Initialize repository according to user's choice.
|
||||
if opts.AutoInit {
|
||||
os.MkdirAll(tmpDir, os.ModePerm)
|
||||
|
||||
if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", tmpDir, err)
|
||||
}
|
||||
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
if err = prepareRepoCommit(repo, tmpDir, repoPath, opts); err != nil {
|
||||
@@ -1198,7 +1224,12 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
|
||||
}
|
||||
|
||||
// Rename remote repository to new path and delete local copy.
|
||||
os.MkdirAll(UserPath(newOwner.Name), os.ModePerm)
|
||||
dir := UserPath(newOwner.Name)
|
||||
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
|
||||
return fmt.Errorf("rename repository directory: %v", err)
|
||||
}
|
||||
|
||||
@@ -104,7 +104,11 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
|
||||
localPath := repo.LocalCopyPath()
|
||||
oldFilePath := path.Join(localPath, opts.OldTreeName)
|
||||
filePath := path.Join(localPath, opts.NewTreeName)
|
||||
os.MkdirAll(path.Dir(filePath), os.ModePerm)
|
||||
dir := path.Dir(filePath)
|
||||
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
// If it's meant to be a new file, make sure it doesn't exist.
|
||||
if opts.IsNewFile {
|
||||
@@ -185,7 +189,12 @@ func (repo *Repository) GetDiffPreview(branch, treePath, content string) (diff *
|
||||
|
||||
localPath := repo.LocalCopyPath()
|
||||
filePath := path.Join(localPath, treePath)
|
||||
os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
|
||||
dir := filepath.Dir(filePath)
|
||||
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return nil, fmt.Errorf("Fail to create dir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil {
|
||||
return nil, fmt.Errorf("WriteFile: %v", err)
|
||||
}
|
||||
@@ -475,7 +484,10 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
|
||||
|
||||
localPath := repo.LocalCopyPath()
|
||||
dirPath := path.Join(localPath, opts.TreePath)
|
||||
os.MkdirAll(dirPath, os.ModePerm)
|
||||
|
||||
if err := os.MkdirAll(dirPath, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", dirPath, err)
|
||||
}
|
||||
|
||||
// Copy uploaded files into repository.
|
||||
for _, upload := range uploads {
|
||||
|
||||
@@ -373,7 +373,12 @@ func addKey(e Engine, key *PublicKey) (err error) {
|
||||
// Calculate fingerprint.
|
||||
tmpPath := strings.Replace(path.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()),
|
||||
"id_rsa.pub"), "\\", "/", -1)
|
||||
os.MkdirAll(path.Dir(tmpPath), os.ModePerm)
|
||||
dir := path.Dir(tmpPath)
|
||||
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", dir, err)
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(tmpPath, []byte(key.Content), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -368,7 +369,7 @@ func (u *User) EncodePasswd() {
|
||||
func (u *User) ValidatePassword(passwd string) bool {
|
||||
newUser := &User{Passwd: passwd, Salt: u.Salt}
|
||||
newUser.EncodePasswd()
|
||||
return u.Passwd == newUser.Passwd
|
||||
return subtle.ConstantTimeCompare([]byte(u.Passwd), []byte(newUser.Passwd)) == 1
|
||||
}
|
||||
|
||||
// UploadAvatar saves custom avatar for user.
|
||||
@@ -392,7 +393,10 @@ func (u *User) UploadAvatar(data []byte) error {
|
||||
return fmt.Errorf("updateUser: %v", err)
|
||||
}
|
||||
|
||||
os.MkdirAll(setting.AvatarUploadPath, os.ModePerm)
|
||||
if err := os.MkdirAll(setting.AvatarUploadPath, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("Fail to create dir %s: %v", setting.AvatarUploadPath, err)
|
||||
}
|
||||
|
||||
fw, err := os.Create(u.CustomAvatarPath())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Create: %v", err)
|
||||
@@ -409,7 +413,10 @@ func (u *User) UploadAvatar(data []byte) error {
|
||||
// DeleteAvatar deletes the user's custom avatar.
|
||||
func (u *User) DeleteAvatar() error {
|
||||
log.Trace("DeleteAvatar[%d]: %s", u.ID, u.CustomAvatarPath())
|
||||
os.Remove(u.CustomAvatarPath())
|
||||
|
||||
if err := os.Remove(u.CustomAvatarPath()); err != nil {
|
||||
return fmt.Errorf("Fail to remove %s: %v", u.CustomAvatarPath(), err)
|
||||
}
|
||||
|
||||
u.UseCustomAvatar = false
|
||||
if err := UpdateUser(u); err != nil {
|
||||
@@ -866,9 +873,16 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
// FIXME: system notice
|
||||
// Note: There are something just cannot be roll back,
|
||||
// so just keep error logs of those operations.
|
||||
path := UserPath(u.Name)
|
||||
|
||||
os.RemoveAll(UserPath(u.Name))
|
||||
os.Remove(u.CustomAvatarPath())
|
||||
if err := os.RemoveAll(path); err != nil {
|
||||
return fmt.Errorf("Fail to RemoveAll %s: %v", path, err)
|
||||
}
|
||||
|
||||
avatarPath := u.CustomAvatarPath()
|
||||
if err := os.Remove(avatarPath); err != nil {
|
||||
return fmt.Errorf("Fail to remove %s: %v", avatarPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -112,7 +112,11 @@ func (repo *Repository) updateWikiPage(doer *User, oldTitle, title, content, mes
|
||||
return ErrWikiAlreadyExist{filename}
|
||||
}
|
||||
} else {
|
||||
os.Remove(path.Join(localPath, oldTitle+".md"))
|
||||
file := path.Join(localPath, oldTitle+".md")
|
||||
|
||||
if err := os.Remove(file); err != nil {
|
||||
return fmt.Errorf("Fail to remove %s: %v", file, err)
|
||||
}
|
||||
}
|
||||
|
||||
// SECURITY: if new file is a symlink to non-exist critical file,
|
||||
@@ -120,7 +124,8 @@ func (repo *Repository) updateWikiPage(doer *User, oldTitle, title, content, mes
|
||||
// as a new page operation.
|
||||
// So we want to make sure the symlink is removed before write anything.
|
||||
// The new file we created will be in normal text format.
|
||||
os.Remove(filename)
|
||||
|
||||
_ = os.Remove(filename)
|
||||
|
||||
if err = ioutil.WriteFile(filename, []byte(content), 0666); err != nil {
|
||||
return fmt.Errorf("WriteFile: %v", err)
|
||||
@@ -168,7 +173,10 @@ func (repo *Repository) DeleteWikiPage(doer *User, title string) (err error) {
|
||||
|
||||
title = ToWikiPageName(title)
|
||||
filename := path.Join(localPath, title+".md")
|
||||
os.Remove(filename)
|
||||
|
||||
if err := os.Remove(filename); err != nil {
|
||||
return fmt.Errorf("Fail to remove %s: %v", filename, err)
|
||||
}
|
||||
|
||||
message := "Delete page '" + title + "'"
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
|
||||
// Check access token.
|
||||
if IsAPIPath(ctx.Req.URL.Path) {
|
||||
tokenSHA := ctx.Query("token")
|
||||
if len(tokenSHA) <= 0 {
|
||||
tokenSHA = ctx.Query("access_token")
|
||||
}
|
||||
if len(tokenSHA) == 0 {
|
||||
// Well, check with header again.
|
||||
auHead := ctx.Req.Header.Get("Authorization")
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -103,3 +104,24 @@ func ExtractOwnerAndRepo() macaron.Handler {
|
||||
ctx.Data["Repository"] = repo
|
||||
}
|
||||
}
|
||||
|
||||
// ReferencesGitRepo injects the GitRepo into the Context
|
||||
func ReferencesGitRepo() macaron.Handler {
|
||||
return func(ctx *APIContext) {
|
||||
// Empty repository does not have reference information.
|
||||
if ctx.Repo.Repository.IsBare {
|
||||
return
|
||||
}
|
||||
|
||||
// For API calls.
|
||||
if ctx.Repo.GitRepo == nil {
|
||||
repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
|
||||
gitRepo, err := git.OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
ctx.Error(500, "RepoRef Invalid repo "+repoPath, err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.GitRepo = gitRepo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package context
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -186,8 +187,10 @@ func Contexter() macaron.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["CsrfToken"] = x.GetToken()
|
||||
ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + x.GetToken() + `">`)
|
||||
ctx.Resp.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)
|
||||
|
||||
ctx.Data["CsrfToken"] = html.EscapeString(x.GetToken())
|
||||
ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + ctx.Data["CsrfToken"].(string) + `">`)
|
||||
log.Debug("Session ID: %s", sess.ID())
|
||||
log.Debug("CSRF Token: %v", ctx.Data["CsrfToken"])
|
||||
|
||||
|
||||
@@ -219,7 +219,10 @@ func (w *FileLogWriter) deleteOldLog() {
|
||||
|
||||
if !info.IsDir() && info.ModTime().Unix() < (time.Now().Unix()-60*60*24*w.Maxdays) {
|
||||
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.Filename)) {
|
||||
os.Remove(path)
|
||||
|
||||
if err := os.Remove(path); err != nil {
|
||||
returnErr = fmt.Errorf("Fail to remove %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnErr
|
||||
|
||||
@@ -42,7 +42,12 @@ func NewLogger(bufLen int64, mode, config string) {
|
||||
// NewGitLogger create a logger for git
|
||||
// FIXME: use same log level as other loggers.
|
||||
func NewGitLogger(logPath string) {
|
||||
os.MkdirAll(path.Dir(logPath), os.ModePerm)
|
||||
path := path.Dir(logPath)
|
||||
|
||||
if err := os.MkdirAll(path, os.ModePerm); err != nil {
|
||||
Fatal(4, "Fail to create dir %s: %v", path, err)
|
||||
}
|
||||
|
||||
GitLogger = newLogger(0)
|
||||
GitLogger.SetLogger("file", fmt.Sprintf(`{"level":0,"filename":"%s","rotate":false}`, logPath))
|
||||
}
|
||||
|
||||
94
modules/options/dynamic.go
Normal file
94
modules/options/dynamic.go
Normal file
@@ -0,0 +1,94 @@
|
||||
// +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 options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
var (
|
||||
directories = make(directorySet)
|
||||
)
|
||||
|
||||
// Dir returns all files from static or custom directory.
|
||||
func Dir(name string) ([]string, error) {
|
||||
if directories.Filled(name) {
|
||||
return directories.Get(name), nil
|
||||
}
|
||||
|
||||
var (
|
||||
result []string
|
||||
)
|
||||
|
||||
customDir := path.Join(setting.CustomPath, "options", name)
|
||||
|
||||
if com.IsDir(customDir) {
|
||||
files, err := com.StatDir(customDir, true)
|
||||
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Failed to read custom directory. %v", err)
|
||||
}
|
||||
|
||||
result = append(result, files...)
|
||||
}
|
||||
|
||||
staticDir := path.Join(setting.StaticRootPath, "options", name)
|
||||
|
||||
if com.IsDir(staticDir) {
|
||||
files, err := com.StatDir(staticDir, true)
|
||||
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Failed to read static directory. %v", err)
|
||||
}
|
||||
|
||||
result = append(result, files...)
|
||||
}
|
||||
|
||||
return directories.AddAndGet(name, result), nil
|
||||
}
|
||||
|
||||
// Locale reads the content of a specific locale from static or custom path.
|
||||
func Locale(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("locale", name))
|
||||
}
|
||||
|
||||
// Readme reads the content of a specific readme from static or custom path.
|
||||
func Readme(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("readme", name))
|
||||
}
|
||||
|
||||
// Gitignore reads the content of a specific gitignore from static or custom path.
|
||||
func Gitignore(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("gitignore", name))
|
||||
}
|
||||
|
||||
// License reads the content of a specific license from static or custom path.
|
||||
func License(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("license", 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)
|
||||
|
||||
if com.IsFile(customPath) {
|
||||
return ioutil.ReadFile(customPath)
|
||||
}
|
||||
|
||||
staticPath := path.Join(setting.StaticRootPath, "options", name)
|
||||
|
||||
if com.IsFile(staticPath) {
|
||||
return ioutil.ReadFile(staticPath)
|
||||
}
|
||||
|
||||
return []byte{}, fmt.Errorf("Asset file does not exist: %s", name)
|
||||
}
|
||||
51
modules/options/options.go
Normal file
51
modules/options/options.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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 options
|
||||
|
||||
//go:generate go-bindata -tags "bindata" -ignore "TRANSLATORS" -pkg "options" -o "bindata.go" ../../options/...
|
||||
//go:generate go fmt bindata.go
|
||||
//go:generate sed -i.bak s/..\/..\/options\/// bindata.go
|
||||
//go:generate rm -f bindata.go.bak
|
||||
|
||||
type directorySet map[string][]string
|
||||
|
||||
func (s directorySet) Add(key string, value []string) {
|
||||
_, ok := s[key]
|
||||
|
||||
if !ok {
|
||||
s[key] = make([]string, 0, len(value))
|
||||
}
|
||||
|
||||
s[key] = append(s[key], value...)
|
||||
}
|
||||
|
||||
func (s directorySet) Get(key string) []string {
|
||||
_, ok := s[key]
|
||||
|
||||
if ok {
|
||||
result := []string{}
|
||||
seen := map[string]string{}
|
||||
|
||||
for _, val := range s[key] {
|
||||
if _, ok := seen[val]; !ok {
|
||||
result = append(result, val)
|
||||
seen[val] = val
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (s directorySet) AddAndGet(key string, value []string) []string {
|
||||
s.Add(key, value)
|
||||
return s.Get(key)
|
||||
}
|
||||
|
||||
func (s directorySet) Filled(key string) bool {
|
||||
return len(s[key]) > 0
|
||||
}
|
||||
84
modules/options/static.go
Normal file
84
modules/options/static.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// +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 options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
var (
|
||||
directories = make(directorySet)
|
||||
)
|
||||
|
||||
// Dir returns all files from bindata or custom directory.
|
||||
func Dir(name string) ([]string, error) {
|
||||
if directories.Filled(name) {
|
||||
return directories.Get(name), nil
|
||||
}
|
||||
|
||||
var (
|
||||
result []string
|
||||
)
|
||||
|
||||
customDir := path.Join(setting.CustomPath, "options", name)
|
||||
|
||||
if com.IsDir(customDir) {
|
||||
files, err := com.StatDir(customDir, true)
|
||||
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Failed to read custom directory. %v", err)
|
||||
}
|
||||
|
||||
result = append(result, files...)
|
||||
}
|
||||
|
||||
files, err := AssetDir(path.Join("..", "..", "options", name))
|
||||
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("Failed to read embedded directory. %v", err)
|
||||
}
|
||||
|
||||
result = append(result, files...)
|
||||
|
||||
return directories.AddAndGet(name, result), nil
|
||||
}
|
||||
|
||||
// Locale reads the content of a specific locale from bindata or custom path.
|
||||
func Locale(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("locale", name))
|
||||
}
|
||||
|
||||
// Readme reads the content of a specific readme from bindata or custom path.
|
||||
func Readme(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("readme", name))
|
||||
}
|
||||
|
||||
// Gitignore reads the content of a gitignore locale from bindata or custom path.
|
||||
func Gitignore(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("gitignore", name))
|
||||
}
|
||||
|
||||
// License reads the content of a specific license from bindata or custom path.
|
||||
func License(name string) ([]byte, error) {
|
||||
return fileFromDir(path.Join("license", 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)
|
||||
|
||||
if com.IsFile(customPath) {
|
||||
return ioutil.ReadFile(customPath)
|
||||
}
|
||||
|
||||
return Asset(name)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// +build miniwinsvc
|
||||
|
||||
// Copyright 2015 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.
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
_ "github.com/kardianos/minwinsvc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SupportMiniWinService = true
|
||||
}
|
||||
@@ -17,17 +17,16 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/user"
|
||||
"github.com/Unknwon/com"
|
||||
_ "github.com/go-macaron/cache/memcache" // memcache plugin for cache
|
||||
_ "github.com/go-macaron/cache/redis"
|
||||
"github.com/go-macaron/session"
|
||||
_ "github.com/go-macaron/session/redis" // redis plugin for store session
|
||||
_ "github.com/kardianos/minwinsvc" // import minwinsvc for windows services
|
||||
"gopkg.in/ini.v1"
|
||||
"strk.kbt.io/projects/go/libravatar"
|
||||
|
||||
"code.gitea.io/gitea/modules/bindata"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/user"
|
||||
)
|
||||
|
||||
// Scheme describes protocol types
|
||||
@@ -259,7 +258,6 @@ var (
|
||||
ShowFooterBranding bool
|
||||
ShowFooterVersion bool
|
||||
ShowFooterTemplateLoadTime bool
|
||||
SupportMiniWinService bool
|
||||
|
||||
// Global setting objects
|
||||
Cfg *ini.File
|
||||
@@ -352,10 +350,7 @@ func NewContext() {
|
||||
log.Fatal(4, "Fail to get work directory: %v", err)
|
||||
}
|
||||
|
||||
Cfg, err = ini.Load(bindata.MustAsset("conf/app.ini"))
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to parse 'conf/app.ini': %v", err)
|
||||
}
|
||||
Cfg = ini.Empty()
|
||||
|
||||
CustomPath = os.Getenv("GITEA_CUSTOM")
|
||||
if len(CustomPath) == 0 {
|
||||
@@ -393,7 +388,7 @@ please consider changing to GITEA_CUSTOM`)
|
||||
forcePathSeparator(LogRootPath)
|
||||
|
||||
sec := Cfg.Section("server")
|
||||
AppName = Cfg.Section("").Key("APP_NAME").MustString("Gogs: Go Git Service")
|
||||
AppName = Cfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea")
|
||||
AppURL = sec.Key("ROOT_URL").MustString("http://localhost:3000/")
|
||||
if AppURL[len(AppURL)-1] != '/' {
|
||||
AppURL += "/"
|
||||
|
||||
@@ -162,7 +162,12 @@ func Listen(port int) {
|
||||
|
||||
keyPath := filepath.Join(setting.AppDataPath, "ssh/gogs.rsa")
|
||||
if !com.IsExist(keyPath) {
|
||||
os.MkdirAll(filepath.Dir(keyPath), os.ModePerm)
|
||||
filePath := filepath.Dir(keyPath)
|
||||
|
||||
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
|
||||
log.Error(4, "Fail to create dir %s: %v", filePath, err)
|
||||
}
|
||||
|
||||
_, stderr, err := com.ExecCmd("ssh-keygen", "-f", keyPath, "-t", "rsa", "-N", "")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Fail to generate private key: %v - %s", err, stderr))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user