mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-05 18:32:41 +09:00
Compare commits
41 Commits
v1.2.0-rc1
...
v1.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d81cf34e37 | ||
|
|
9902317679 | ||
|
|
33e164168f | ||
|
|
f40ba68d57 | ||
|
|
cb0c8b8ae4 | ||
|
|
eba5945d2f | ||
|
|
4c67925531 | ||
|
|
3c60121ca7 | ||
|
|
46bb1cf026 | ||
|
|
13013e90f3 | ||
|
|
785ba171f4 | ||
|
|
fb80265b52 | ||
|
|
6fae585d28 | ||
|
|
670562a9c5 | ||
|
|
ed07d8a308 | ||
|
|
74399f333f | ||
|
|
d1cec5ecfa | ||
|
|
73ad7d2ef3 | ||
|
|
5b36379172 | ||
|
|
e38e502e20 | ||
|
|
3cc5b11b0d | ||
|
|
4c9bf91a2c | ||
|
|
03ff7687e0 | ||
|
|
f646154ead | ||
|
|
a6d2f47a2b | ||
|
|
1837194882 | ||
|
|
9ca26432f6 | ||
|
|
67595c0d0b | ||
|
|
6d03cf831e | ||
|
|
e232c49b10 | ||
|
|
25e71ad41e | ||
|
|
f014e42a06 | ||
|
|
d14a724b53 | ||
|
|
91788e0200 | ||
|
|
fc0c6f48c7 | ||
|
|
002fa73460 | ||
|
|
2fdc649202 | ||
|
|
0c910afe11 | ||
|
|
1cbe502cc2 | ||
|
|
f916aa0fe3 | ||
|
|
04728b5b91 |
91
.drone.yml
91
.drone.yml
@@ -2,12 +2,13 @@ workspace:
|
|||||||
base: /srv/app
|
base: /srv/app
|
||||||
path: src/code.gitea.io/gitea
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
pipeline:
|
clone:
|
||||||
clone:
|
git:
|
||||||
image: plugins/git
|
image: plugins/git:1
|
||||||
depth: 50
|
depth: 50
|
||||||
tags: true
|
tags: true
|
||||||
|
|
||||||
|
pipeline:
|
||||||
build:
|
build:
|
||||||
image: webhippie/golang:edge
|
image: webhippie/golang:edge
|
||||||
pull: true
|
pull: true
|
||||||
@@ -15,7 +16,6 @@ pipeline:
|
|||||||
TAGS: bindata sqlite
|
TAGS: bindata sqlite
|
||||||
GOPATH: /srv/app
|
GOPATH: /srv/app
|
||||||
commands:
|
commands:
|
||||||
- apk -U add openssh-client
|
|
||||||
- make clean
|
- make clean
|
||||||
- make generate
|
- make generate
|
||||||
- make vet
|
- make vet
|
||||||
@@ -34,35 +34,21 @@ pipeline:
|
|||||||
TAGS: bindata sqlite
|
TAGS: bindata sqlite
|
||||||
GOPATH: /srv/app
|
GOPATH: /srv/app
|
||||||
commands:
|
commands:
|
||||||
- apk -U add openssh-client
|
|
||||||
- make test
|
- make test
|
||||||
when:
|
when:
|
||||||
event: [ tag, pull_request ]
|
event: [ tag, pull_request ]
|
||||||
|
|
||||||
test-coverage:
|
# Commented until db locking have been resolved!
|
||||||
image: webhippie/golang:edge
|
# test-sqlite:
|
||||||
pull: true
|
# image: webhippie/golang:edge
|
||||||
environment:
|
# pull: true
|
||||||
TAGS: bindata sqlite
|
# environment:
|
||||||
GOPATH: /srv/app
|
# TAGS: bindata
|
||||||
commands:
|
# GOPATH: /srv/app
|
||||||
- apk -U add openssh-client
|
# commands:
|
||||||
- go get github.com/wadey/gocovmerge
|
# - make test-sqlite
|
||||||
- make test-coverage
|
# when:
|
||||||
when:
|
# event: [ push, tag, pull_request ]
|
||||||
event: [ push ]
|
|
||||||
branch: master
|
|
||||||
|
|
||||||
test-sqlite:
|
|
||||||
image: webhippie/golang:edge
|
|
||||||
pull: true
|
|
||||||
environment:
|
|
||||||
TAGS: bindata
|
|
||||||
GOPATH: /srv/app
|
|
||||||
commands:
|
|
||||||
- echo "Needs to be fixed" # make test-sqlite
|
|
||||||
when:
|
|
||||||
event: [ push, tag, pull_request ]
|
|
||||||
|
|
||||||
test-mysql:
|
test-mysql:
|
||||||
image: webhippie/golang:edge
|
image: webhippie/golang:edge
|
||||||
@@ -97,25 +83,19 @@ pipeline:
|
|||||||
when:
|
when:
|
||||||
event: [ push, tag ]
|
event: [ push, tag ]
|
||||||
|
|
||||||
# coverage:
|
|
||||||
# image: plugins/coverage
|
|
||||||
# server: https://coverage.gitea.io
|
|
||||||
# when:
|
|
||||||
# event: [ push ]
|
|
||||||
# branch: master
|
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
image: plugins/docker
|
image: plugins/docker:17.05
|
||||||
pull: true
|
pull: true
|
||||||
|
secrets: [ docker_username, docker_password ]
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
tags: [ '${DRONE_TAG##v}' ]
|
tags: [ '${DRONE_TAG##v}' ]
|
||||||
when:
|
when:
|
||||||
event: [ tag ]
|
event: [ tag ]
|
||||||
branch: [ refs/tags/* ]
|
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
image: plugins/docker
|
image: plugins/docker:17.05
|
||||||
pull: true
|
pull: true
|
||||||
|
secrets: [ docker_username, docker_password ]
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
tags: [ '${DRONE_BRANCH##release/v}' ]
|
tags: [ '${DRONE_BRANCH##release/v}' ]
|
||||||
when:
|
when:
|
||||||
@@ -123,8 +103,9 @@ pipeline:
|
|||||||
branch: [ release/* ]
|
branch: [ release/* ]
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
image: plugins/docker
|
image: plugins/docker:17.05
|
||||||
pull: true
|
pull: true
|
||||||
|
secrets: [ docker_username, docker_password ]
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
tags: [ 'latest' ]
|
tags: [ 'latest' ]
|
||||||
when:
|
when:
|
||||||
@@ -132,17 +113,24 @@ pipeline:
|
|||||||
branch: [ master ]
|
branch: [ master ]
|
||||||
|
|
||||||
release:
|
release:
|
||||||
image: plugins/s3
|
image: plugins/s3:1
|
||||||
|
pull: true
|
||||||
|
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||||
|
bucket: releases
|
||||||
|
endpoint: https://storage.gitea.io
|
||||||
path_style: true
|
path_style: true
|
||||||
strip_prefix: dist/release/
|
strip_prefix: dist/release/
|
||||||
source: dist/release/*
|
source: dist/release/*
|
||||||
target: /gitea/${DRONE_TAG##v}
|
target: /gitea/${DRONE_TAG##v}
|
||||||
when:
|
when:
|
||||||
event: [ tag ]
|
event: [ tag ]
|
||||||
branch: [ refs/tags/* ]
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
image: plugins/s3
|
image: plugins/s3:1
|
||||||
|
pull: true
|
||||||
|
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||||
|
bucket: releases
|
||||||
|
endpoint: https://storage.gitea.io
|
||||||
path_style: true
|
path_style: true
|
||||||
strip_prefix: dist/release/
|
strip_prefix: dist/release/
|
||||||
source: dist/release/*
|
source: dist/release/*
|
||||||
@@ -152,7 +140,11 @@ pipeline:
|
|||||||
branch: [ release/* ]
|
branch: [ release/* ]
|
||||||
|
|
||||||
release:
|
release:
|
||||||
image: plugins/s3
|
image: plugins/s3:1
|
||||||
|
pull: true
|
||||||
|
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
||||||
|
bucket: releases
|
||||||
|
endpoint: https://storage.gitea.io
|
||||||
path_style: true
|
path_style: true
|
||||||
strip_prefix: dist/release/
|
strip_prefix: dist/release/
|
||||||
source: dist/release/*
|
source: dist/release/*
|
||||||
@@ -162,17 +154,18 @@ pipeline:
|
|||||||
branch: [ master ]
|
branch: [ master ]
|
||||||
|
|
||||||
github:
|
github:
|
||||||
image: plugins/github-release
|
image: plugins/github-release:1
|
||||||
|
pull: true
|
||||||
|
secrets: [ github_token ]
|
||||||
files:
|
files:
|
||||||
- dist/release/*
|
- dist/release/*
|
||||||
when:
|
when:
|
||||||
event: [ tag ]
|
event: [ tag ]
|
||||||
branch: [ refs/tags/* ]
|
|
||||||
|
|
||||||
discord:
|
discord:
|
||||||
image: appleboy/drone-discord:0.0.4
|
image: appleboy/drone-discord:1.0.0
|
||||||
webhook_id: ${WEBHOOK_ID}
|
pull: true
|
||||||
webhook_token: ${WEBHOOK_TOKEN}
|
secrets: [ discord_webhook_id, discord_webhook_token ]
|
||||||
when:
|
when:
|
||||||
event: [ push, tag, pull_request ]
|
event: [ push, tag, pull_request ]
|
||||||
status: [ changed, failure ]
|
status: [ changed, failure ]
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
336
CHANGELOG.md
336
CHANGELOG.md
@@ -1,38 +1,111 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## [1.2.2](https://github.com/go-gitea/gitea/releases/tag/v1.2.2) - 2017-10-26
|
||||||
|
* BUGFIXES
|
||||||
|
* Add checks for commits with missing author and time (#2771) (#2785)
|
||||||
|
* Fix sending mail with a non-latin display name (#2559) (#2783)
|
||||||
|
* Sync MaxGitDiffLineCharacters with conf/app.ini (#2779) (#2780)
|
||||||
|
* Update vendor git (#2765) (#2772)
|
||||||
|
* Fix emojify image URL (#2769) (#2773)
|
||||||
|
|
||||||
## [go-gitea/gitea](https://github.com/1.2.0/releases/tag/v1.2.0-rc1) - 2017-08-25
|
## [1.2.1](https://github.com/go-gitea/gitea/releases/tag/v1.2.1) - 2017-10-16
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix PR, milestone and label functionality if issue unit is disabled (#2710) (#2714)
|
||||||
|
* Fix plain readme didn't render correctly on repo home page (#2705) (#2712)
|
||||||
|
* Fix so that user can still fork his own repository to his organizations (#2699) (#2707)
|
||||||
|
* Fix .netrc authentication (#2700) (#2708)
|
||||||
|
* Fix slice out of bounds error in mailer (#2479) (#2696)
|
||||||
|
|
||||||
|
## [1.2.0](https://github.com/go-gitea/gitea/releases/tag/v1.2.0) - 2017-10-10
|
||||||
|
* SECURITY
|
||||||
|
* Sanitation fix from Gogs (#1461)
|
||||||
* BREAKING
|
* BREAKING
|
||||||
* Rename /forget_password url to /forgot_password (#1219)
|
* Rename /forget_password url to /forgot_password (#1219)
|
||||||
* SSH keys management URL changed from `/user/settings/ssh` to `/user/settings/keys` (#1293)
|
|
||||||
* FEATURE
|
* FEATURE
|
||||||
* API: support '/orgs/:org/repos' (#2047)
|
* Logo: Add task to generate images from SVG and change to new logo (#2194)
|
||||||
* Add Gitea Webhook (#1755)
|
|
||||||
* Display all organization from user settings (#1739)
|
|
||||||
* Show commit status icon in commits table (#1688)
|
|
||||||
* Adding #issuecomment to the URL in E-Mail notifications (#1674)
|
|
||||||
* feat: add download count field and unit testing for attachment. (#1512)
|
|
||||||
* Add repo mirror sync API endpoint (#1508)
|
|
||||||
* Add markup package to prepare for org markup format (#1493)
|
|
||||||
* Repo size in admin panel (#1482)
|
|
||||||
* LDAP user synchronization (#1478)
|
|
||||||
* Support for custom html meta (#1423)
|
|
||||||
* [Notifications Step 6] Per issue/PR watch/unwatch (#1410)
|
|
||||||
* Allow ENABLE_OPENID_SIGNUP to depend on DISABLE_REGISTRATION (#1369)
|
|
||||||
* Fix FCGI (over TCP) support (#1368)
|
|
||||||
* Status-API (#1332)
|
* Status-API (#1332)
|
||||||
* Show user OpenID URIs in their profile (#1314)
|
* Show commit status icon in commits table (#1688)
|
||||||
* Add change-password admin command (#1304)
|
|
||||||
* feat: Only use issue and wiki on repo. (#1297)
|
|
||||||
* Rework SSH key management UI to add GPG (#1293)
|
|
||||||
* Allow push to init a wiki repo (#1279)
|
|
||||||
* GPG commit validation (#1150)
|
|
||||||
* Dockerfile for aarch64 (#1128) (#1130)
|
|
||||||
* Additional OAuth2 providers (#1010)
|
* Additional OAuth2 providers (#1010)
|
||||||
* Add units to team (#947)
|
* GPG commit validation (#1150)
|
||||||
* Batch updates for issues (#926)
|
* Rework SSH key management UI to add GPG (#1293)
|
||||||
* Implement GPG api (#710)
|
* Implement GPG api (#710)
|
||||||
* Login via OpenID-2.0 (#618)
|
* Login via OpenID-2.0 (#618)
|
||||||
|
* Add units to team (#947)
|
||||||
|
* Batch updates for issues (#926)
|
||||||
|
* Add Gitea Webhook (#1755)
|
||||||
|
* API: support '/orgs/:org/repos' (#2047)
|
||||||
|
* Display all organization from user settings (#1739)
|
||||||
|
* LDAP user synchronization (#1478)
|
||||||
|
* Adding #issuecomment to the URL in E-Mail notifications (#1674)
|
||||||
|
* Add download count field and unit testing for attachment. (#1512)
|
||||||
|
* Add repo mirror sync API endpoint (#1508)
|
||||||
|
* Add markup package to prepare for org markup format (#1493)
|
||||||
|
* Support for custom html meta (#1423)
|
||||||
|
* Per issue/PR watch/unwatch (#1410)
|
||||||
|
* Allow ENABLE_OPENID_SIGNUP to depend on DISABLE_REGISTRATION (#1369)
|
||||||
|
* Repo size in admin panel (#1482)
|
||||||
|
* Show user OpenID URIs in their profile (#1314)
|
||||||
|
* Add change-password admin command (#1304)
|
||||||
|
* Only use issue and wiki on repo. (#1297)
|
||||||
|
* Allow push to init a wiki repo (#1279)
|
||||||
|
* ENHANCEMENT
|
||||||
|
* Make time diff translatable (#2057)
|
||||||
|
* Smaller watch, star, and fork buttons (#2052)
|
||||||
|
* Display config file path on admin panel (#2030)
|
||||||
|
* Only show SSH clone URL if signed in (#2169) (#2170)
|
||||||
|
* Only show "No Description" to repo admins (#2167)
|
||||||
|
* Always return valid go-get meta, even if unauthorized (#2010)
|
||||||
|
* Enable assignee e-mail notification (#2003)
|
||||||
|
* Let not-logged-in users view releases (#1999)
|
||||||
|
* No highlighting for .txt files (#1922)
|
||||||
|
* Make side nav on dashboard stackable (#1778)
|
||||||
|
* Setting to disable authorized_keys backup (#1856)
|
||||||
|
* Hide the create organization button (in dashboard/organization section) (#1705)
|
||||||
|
* LFS: Return 404 for unimplemented endpoints (#1330)
|
||||||
|
* Show a link to password reset from user settings requiring a password (#862)
|
||||||
|
* Reserve the "explore" user/org name (#1222)
|
||||||
|
* Send notifications to partecipants in issue comments (#1217)
|
||||||
|
* Improve style of user OpenID setting page (#1324)
|
||||||
|
* Use font-awesome OpenID icon more (#1320)
|
||||||
|
* Use readonly input form to show the validated OpenID URI (#1308)
|
||||||
|
* Add captcha support to OpenID based signup (#1307)
|
||||||
|
* Minor improvements on commit graph UI (#1380)
|
||||||
|
* Mirror sync interval specified as duration string (#1407)
|
||||||
|
* Make issue in commit graph "clickable" (#1392)
|
||||||
|
* Use whole button (commit graph) as link (#1390)
|
||||||
|
* Autofocus on 2fa passcode fields (#1460)
|
||||||
|
* Sort on repo size in admin panel (#1654)
|
||||||
|
* Improve dashboard repo search (#1652)
|
||||||
|
* Use a better default MAX_GIT_DIFF_LINE_CHARACTERS (#1845)
|
||||||
|
* Adds Parent property to the repo API (#1687)
|
||||||
|
* Add configuration option for default permission to create Organizations (#1686)
|
||||||
|
* Remove sha1 hash display in repository table (#1678)
|
||||||
|
* Download files to their original filename (#1676)
|
||||||
|
* Exposes in API the Repo entity's Size and IsBare property (#1668)
|
||||||
|
* Change two factor code entry box from text to number (#1733)
|
||||||
|
* Directly show error if user hit repository limit (#1767)
|
||||||
|
* Generate small and large logos at 4x resolution (#2233)
|
||||||
|
* Tags listed in releases tab (#2389) (#2424)
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
|
* Fix adding branch as protected to not allow pushing to it (#2556)
|
||||||
|
* Orgs: fix org page title when full name is not defined (#1495)
|
||||||
|
* Fix double borders on edit page (#1152) (#1153)
|
||||||
|
* Search bar fixes for #1187 and #1205 (#1207)
|
||||||
|
* Fix upgrade failed after ever rollback (#1194)
|
||||||
|
* Fix FCGI (over TCP) support (#1368)
|
||||||
|
* Backport of migration fixes (#2604) (#2677)
|
||||||
|
* fix panic on gogs webhook creation (#2675) (#2676)
|
||||||
|
* Backport: Fixes 500 error on dashboard when using MSSQL (#2504) (#2662)
|
||||||
|
* Fix go get response if only app URL is custom in configuration (#2634) (#2640)
|
||||||
|
* Fix deletion of unprotected branches (#2630)
|
||||||
|
* Backport of 2611 / Fix doubled issue tab introduced in migration v16 (#2622)
|
||||||
|
* v38 migration used an outdated version of RepoUnit model (#2602)
|
||||||
|
* fix go get subpackage bug (#2584) (#2589)
|
||||||
|
* Backport: Sync releases table with tags on push and for mirrors (#2459) (#2554)
|
||||||
|
* Backport: Restricting access to fork functioanlity to users with Code access (#2542)
|
||||||
|
* Fix migration from pre-v15 to 1.2.0 (#2460) (#2465)
|
||||||
|
* Fix migration from pre-v15 to 1.2.0 (#2460)
|
||||||
|
* fix duplicated feed (#2370) (#2413)
|
||||||
|
* Fix releases to be counted from database not tags (#2389)
|
||||||
* Fix missing collabrative repos (#2367) (#2382)
|
* Fix missing collabrative repos (#2367) (#2382)
|
||||||
* Add more test for login links and fix a bug on action retrieve (#2361)
|
* Add more test for login links and fix a bug on action retrieve (#2361)
|
||||||
* Fix SQL condition bug in GetFeeds(..) (#2360)
|
* Fix SQL condition bug in GetFeeds(..) (#2360)
|
||||||
@@ -224,131 +297,8 @@
|
|||||||
* Bug fixed for delete repo failed (#1193)
|
* Bug fixed for delete repo failed (#1193)
|
||||||
* Fix migration failed when authorized_keys is not exist (#1180)
|
* Fix migration failed when authorized_keys is not exist (#1180)
|
||||||
* Fix ini format incomiptable with crowdin (#1177)
|
* Fix ini format incomiptable with crowdin (#1177)
|
||||||
* ENHANCEMENT
|
|
||||||
* Move 3rd party js/css into `public/vendor` and document sources (#2383)
|
|
||||||
* Prevent conflicting TOTP accounts by adding AppURL to issuer parameter (#2335)
|
|
||||||
* Fix variable name typo (#2327)
|
|
||||||
* Make use of Vue more universal (#2318)
|
|
||||||
* Remove (almost) server side data rendering from repo-search component (#2317)
|
|
||||||
* Add OpenID configuration in install page (#2276)
|
|
||||||
* More tweaks to repo top panel (#2267)
|
|
||||||
* File path tweaks in UI (#2264)
|
|
||||||
* Make SHOW_USER_EMAIL also apply to profiles (#2258)
|
|
||||||
* EnableUnit() -> UnitEnabled() (#2242)
|
|
||||||
* Prevent selection of diff line numbers (#2240)
|
|
||||||
* Generate small and large logos at 4x resolution (#2233)
|
|
||||||
* remove unused variable on makefile (#2225)
|
|
||||||
* No error log entries for repo 404 (#2200)
|
|
||||||
* Add task to generate images from SVG and change to new logo (#2194)
|
|
||||||
* Refactor vue delimeters to use es6 template delimeters (#2171)
|
|
||||||
* Only show SSH clone URL if signed in (#2169) (#2170)
|
|
||||||
* Only show "No Description" to repo admins (#2167)
|
|
||||||
* fix: replace tmp with TMPDIR. (#2152)
|
|
||||||
* Remove unused files (#2124)
|
|
||||||
* Improve org error handling (#2117)
|
|
||||||
* Absolute path for setting.CustomConf (#2085)
|
|
||||||
* Integration tests for issues API (#2059)
|
|
||||||
* Make time diff translatable (#2057)
|
|
||||||
* Smaller watch, star, and fork buttons (#2052)
|
|
||||||
* remove deprecated code for Gogs compitable (#2041)
|
|
||||||
* Display config file path on admin panel (#2030)
|
|
||||||
* Refactor session close as xorm already does everything needed internally (#2020)
|
|
||||||
* Always return valid go-get meta, even if unauthorized (#2010)
|
|
||||||
* Enable assignee e-mail notification (#2003)
|
|
||||||
* Let not-logged-in users view releases (#1999)
|
|
||||||
* SQLite has a query timeout. Hopefully fixes most 'database locked' errors (#1961)
|
|
||||||
* Use monospace font in githook editor (#1958)
|
|
||||||
* Fix import order (#1951)
|
|
||||||
* Gracefully handle bare repositories on API operations. (#1932)
|
|
||||||
* Fix errors caused by force push (#1927)
|
|
||||||
* Display URLs in integration test logs (#1924)
|
|
||||||
* No highlighting for .txt files (#1922)
|
|
||||||
* Set TMPDIR enviroment variable for dump command (#1915)
|
|
||||||
* Cache ctx.User in retrieveFeeds (#1902)
|
|
||||||
* Make `LocalCopyPath` a setting instead of a hard-coded path (#1881)
|
|
||||||
* feat: add check misspelling (#1877)
|
|
||||||
* Fix misspelled variables (#1874)
|
|
||||||
* gofmt (#1868)
|
|
||||||
* Rename misnamed migration (#1867)
|
|
||||||
* Support CRLF when splitting code lines for display (#1862)
|
|
||||||
* feat: add convert less css file step. (#1861)
|
|
||||||
* Prevent accidential selection of line numbers in code view (#1860)
|
|
||||||
* Setting to disable authorized_keys backup (#1856)
|
|
||||||
* Delete Public SSH Key tmp file after calculating fingerprint (#1855)
|
|
||||||
* Remove annoying difference in button heights. (#1853)
|
|
||||||
* Use a better default MAX_GIT_DIFF_LINE_CHARACTERS (#1845)
|
|
||||||
* fix: only run test coverage on master branch. (#1838)
|
|
||||||
* fix: error from mktemp command in MacOS. (#1837)
|
|
||||||
* use writeTmpKeyFile in calcFingerprint (#1828)
|
|
||||||
* ROOT_URL setting use the default as shown in conf/app.ini (#1823)
|
|
||||||
* Make side nav on dashboard stackable (#1778)
|
|
||||||
* Directly show error if user hit repository limit (#1767)
|
|
||||||
* Rename RepoCreationNum -> MaxCreationLimit (#1766)
|
|
||||||
* Add button to admin ui (#1738)
|
|
||||||
* Change two factor code entry box from text to number (#1733)
|
|
||||||
* gofmt (#1710)
|
|
||||||
* Hide the create organization button (in dashboard/organization section) (#1705)
|
|
||||||
* Correct spelling mistakes (#1703)
|
|
||||||
* Adds Parent property to the repo API (#1687)
|
|
||||||
* Add configuration option for default permission to create Organizations (#1686)
|
|
||||||
* Remove sha1 hash display in repository table (#1678)
|
|
||||||
* Download files to their original filename (#1676)
|
|
||||||
* Exposes in API the Repo entity's Size and IsBare property
|
|
||||||
(#1668)
|
|
||||||
* gofmt (#1662)
|
|
||||||
* Sort on repo size in admin panel (#1654)
|
|
||||||
* Improve dashboard repo search (#1652)
|
|
||||||
* Update xorm to latest version (#1651)
|
|
||||||
* Make openid support default false for compitable with v1.1 (#1650)
|
|
||||||
* Send mails as HTML as default. Setting for send as plain text. (#1648)
|
|
||||||
* fix potential lock when sqlite (#1647)
|
|
||||||
* Optimize png images via Google zopflipng [ci skip] (#1639)
|
|
||||||
* Upgrade alpine to v3.5 in Dockerfile (#1633)
|
|
||||||
* remove unused vendor packages (#1620)
|
|
||||||
* markup: microoptimise for many short filenames in directory (#1534)
|
|
||||||
* support health check via / and fix #969 (#1520)
|
|
||||||
* Remove env user salt since no need to use (#1515)
|
|
||||||
* Drop db operations from hook commands (#1514)
|
|
||||||
* Better URL validation (#1507)
|
|
||||||
* Orgs: fix org page title when full name is not defined (#1495)
|
|
||||||
* Migrate WatchInfo struct to api (#1492)
|
|
||||||
* refactor: show command help message. (#1486)
|
|
||||||
* refactor update ssh key use time (#1466)
|
|
||||||
* Autofocus on 2fa passcode fields (#1460)
|
|
||||||
* Set VERSION from git once, in a variable (#1447)
|
|
||||||
* Remove unused mutex field (#1440)
|
|
||||||
* Mirror sync interval specified as duration string (#1407)
|
|
||||||
* Make issue in commit graph "clickable" (#1392)
|
|
||||||
* Use whole button (commit graph) as link (#1390)
|
|
||||||
* Simplify settings pages with item list (#1389)
|
|
||||||
* Minor improvements on commit graph UI (#1380)
|
|
||||||
* Clean-up PostgreSQL Tests (#1361)
|
|
||||||
* refactor: remove workaround after the golang 1.7 release. (#1349)
|
|
||||||
* Delete the useless code (#1335)
|
|
||||||
* Run "make fmt" with go-1.6 (#1333)
|
|
||||||
* LFS: Return 404 for unimplemented endpoints (#1330)
|
|
||||||
* Improve style of user OpenID setting page (#1324)
|
|
||||||
* Use font-awesome OpenID icon more (#1320)
|
|
||||||
* Use readonly input form to show the validated OpenID URI (#1308)
|
|
||||||
* Add captcha support to OpenID based signup (#1307)
|
|
||||||
* Refactor admin/auth/new.tmpl (#1277)
|
|
||||||
* Refactor repo/issue/view_content.tmpl (#1276)
|
|
||||||
* Cleaner ui for admin, repo settings, and user settings page (#1269) (#1270)
|
|
||||||
* Cleaner UI for explore page (#1253) (#1255)
|
|
||||||
* Synced licenses with github repo (#1246)
|
|
||||||
* Synced gitignores with github repo (#1245)
|
|
||||||
* Reserve the "explore" user/org name (#1222)
|
|
||||||
* Send notifications to partecipants in issue comments (#1217)
|
|
||||||
* Simplify RepositoryList.loadAttributes() (#1211)
|
|
||||||
* Move user_follow to separate file (#1210)
|
|
||||||
* Search bar fixes for #1187 and #1205 (#1207)
|
|
||||||
* Fix upgrade failed after ever rollback (#1194)
|
|
||||||
* Fix double borders on edit page (#1152) (#1153)
|
|
||||||
* Reduce conditionals in signin/signup inner forms (#1138)
|
|
||||||
* Show a link to password reset from user settings requiring a password (#862)
|
|
||||||
* SECURITY
|
|
||||||
* Sanitation fix from Gogs (#1461)
|
|
||||||
* TESTING
|
* TESTING
|
||||||
|
* Integration tests for issues API (#2059)
|
||||||
* Add integration tests for signin (#2363)
|
* Add integration tests for signin (#2363)
|
||||||
* Add INTERNAL_TOKEN to integration .ini file (#2346)
|
* Add INTERNAL_TOKEN to integration .ini file (#2346)
|
||||||
* Add public links check (#2323)
|
* Add public links check (#2323)
|
||||||
@@ -389,6 +339,14 @@
|
|||||||
* Fix bad grammar and wordiness (#1741)
|
* Fix bad grammar and wordiness (#1741)
|
||||||
* Make strings translatable (#1188) (#1198)
|
* Make strings translatable (#1188) (#1198)
|
||||||
* BUILD
|
* BUILD
|
||||||
|
* Dockerfile for aarch64 (#1128) (#1130)
|
||||||
|
* backport from v1.2 branch: add secrets for github release (#2588) (#2598)
|
||||||
|
* Add secrets for github release to fix drone failed (#2588)
|
||||||
|
* Backport changes for latest drone (#2586)
|
||||||
|
* Removing .drone.yml.sig (#2579)
|
||||||
|
* Fix drone for tags (#2573) (#2576)
|
||||||
|
* Backport: Remove go version check for make fmt (#2558) (#2561)
|
||||||
|
* Backport: Fix lint, fmt and integration testing errors (#2553)
|
||||||
* update latest xorm version to vendor (#2353)
|
* update latest xorm version to vendor (#2353)
|
||||||
* Remove integration test executables on `make clean` (#2340)
|
* Remove integration test executables on `make clean` (#2340)
|
||||||
* refactor(Makefile): allow overriding default go program (#2310)
|
* refactor(Makefile): allow overriding default go program (#2310)
|
||||||
@@ -396,7 +354,6 @@
|
|||||||
* Use /dev/urandom to create random password (#2298)
|
* Use /dev/urandom to create random password (#2298)
|
||||||
* update drone sig file. (#2262)
|
* update drone sig file. (#2262)
|
||||||
* go get github.com/wadey/gocovmerge when needed (#2235)
|
* go get github.com/wadey/gocovmerge when needed (#2235)
|
||||||
* Update code.gitea.io/git dependency (#2149)
|
|
||||||
* fix typo (#2145)
|
* fix typo (#2145)
|
||||||
* Revert "Reduce number of layer" (#2086)
|
* Revert "Reduce number of layer" (#2086)
|
||||||
* Reduce number of layer (#2078)
|
* Reduce number of layer (#2078)
|
||||||
@@ -423,15 +380,14 @@
|
|||||||
* Add GOFLAGS and EXTRA_GOFLAGS (#1438)
|
* Add GOFLAGS and EXTRA_GOFLAGS (#1438)
|
||||||
* Include formatting check to the `make test` (and thus also `check`) rule (#1366)
|
* Include formatting check to the `make test` (and thus also `check`) rule (#1366)
|
||||||
* DOCS
|
* DOCS
|
||||||
|
* fix wrong changelog title (#2395)
|
||||||
* fix webhook link (#2289)
|
* fix webhook link (#2289)
|
||||||
* Improve swagger doc (#2274)
|
* Improve swagger doc (#2274)
|
||||||
* Add changelog of release v1.1.3 (#2252)
|
|
||||||
* Add link to forum in issue template (#2070)
|
* Add link to forum in issue template (#2070)
|
||||||
* add missing lfs config on example file (#2039)
|
* add missing lfs config on example file (#2039)
|
||||||
* Add discourse link (#2027)
|
* Add discourse link (#2027)
|
||||||
* Fix wording (#2024)
|
* Fix wording (#2024)
|
||||||
* Fix typo (#1974)
|
* Fix typo (#1974)
|
||||||
* [ci skip] add 1.1.2 change log. (#1945)
|
|
||||||
* Swagger docs for list/create forks (#1941)
|
* Swagger docs for list/create forks (#1941)
|
||||||
* Update links to Discord server (#1940)
|
* Update links to Discord server (#1940)
|
||||||
* [ci skip] update discord badge. (#1930)
|
* [ci skip] update discord badge. (#1930)
|
||||||
@@ -463,7 +419,81 @@
|
|||||||
* Use sqlite3 database as default for Docker image (#2182)
|
* Use sqlite3 database as default for Docker image (#2182)
|
||||||
* update drone discord plugin to 0.0.4 version (#1992)
|
* update drone discord plugin to 0.0.4 version (#1992)
|
||||||
* fix typo (#1990)
|
* fix typo (#1990)
|
||||||
* Applying to become maintainer (#1671)
|
* Move 3rd party js/css into `public/vendor` and document sources (#2383)
|
||||||
|
* Prevent conflicting TOTP accounts by adding AppURL to issuer parameter (#2335)
|
||||||
|
* Fix variable name typo (#2327)
|
||||||
|
* Make use of Vue more universal (#2318)
|
||||||
|
* Remove (almost) server side data rendering from repo-search component (#2317)
|
||||||
|
* Add OpenID configuration in install page (#2276)
|
||||||
|
* More tweaks to repo top panel (#2267)
|
||||||
|
* File path tweaks in UI (#2264)
|
||||||
|
* Make SHOW_USER_EMAIL also apply to profiles (#2258)
|
||||||
|
* EnableUnit() -> UnitEnabled() (#2242)
|
||||||
|
* Prevent selection of diff line numbers (#2240)
|
||||||
|
* Remove unused variable on makefile (#2225)
|
||||||
|
* No error log entries for repo 404 (#2200)
|
||||||
|
* Refactor vue delimeters to use es6 template delimeters (#2171)
|
||||||
|
* Replace tmp with TMPDIR. (#2152)
|
||||||
|
* Remove unused files (#2124)
|
||||||
|
* Improve org error handling (#2117)
|
||||||
|
* Absolute path for setting.CustomConf (#2085)
|
||||||
|
* remove deprecated code for Gogs compitable (#2041)
|
||||||
|
* Refactor session close as xorm already does everything needed internally (#2020)
|
||||||
|
* SQLite has a query timeout. Hopefully fixes most 'database locked' errors (#1961)
|
||||||
|
* Use monospace font in githook editor (#1958)
|
||||||
|
* Fix import order (#1951)
|
||||||
|
* Gracefully handle bare repositories on API operations. (#1932)
|
||||||
|
* Fix errors caused by force push (#1927)
|
||||||
|
* Display URLs in integration test logs (#1924)
|
||||||
|
* Set TMPDIR enviroment variable for dump command (#1915)
|
||||||
|
* Cache ctx.User in retrieveFeeds (#1902)
|
||||||
|
* Make `LocalCopyPath` a setting instead of a hard-coded path (#1881)
|
||||||
|
* Add check misspelling (#1877)
|
||||||
|
* Fix misspelled variables (#1874)
|
||||||
|
* Gofmt (#1868, #1710, #1662)
|
||||||
|
* Rename misnamed migration (#1867)
|
||||||
|
* Support CRLF when splitting code lines for display (#1862)
|
||||||
|
* Add convert less css file step. (#1861)
|
||||||
|
* Prevent accidential selection of line numbers in code view (#1860)
|
||||||
|
* Delete Public SSH Key tmp file after calculating fingerprint (#1855)
|
||||||
|
* Remove annoying difference in button heights. (#1853)
|
||||||
|
* Only run test coverage on master branch. (#1838)
|
||||||
|
* Error from mktemp command in MacOS. (#1837)
|
||||||
|
* Use writeTmpKeyFile in calcFingerprint (#1828)
|
||||||
|
* ROOT_URL setting use the default as shown in conf/app.ini (#1823)
|
||||||
|
* Rename RepoCreationNum -> MaxCreationLimit (#1766)
|
||||||
|
* Add button to admin ui (#1738)
|
||||||
|
* Correct spelling mistakes (#1703)
|
||||||
|
* Make openid support default false for compitable with v1.1 (#1650)
|
||||||
|
* Send mails as HTML as default. Setting for send as plain text. (#1648)
|
||||||
|
* fix potential lock when sqlite (#1647)
|
||||||
|
* Optimize png images via Google zopflipng [ci skip] (#1639)
|
||||||
|
* Upgrade alpine to v3.5 in Dockerfile (#1633)
|
||||||
|
* remove unused vendor packages (#1620)
|
||||||
|
* markup: microoptimise for many short filenames in directory (#1534)
|
||||||
|
* support health check via / and fix #969 (#1520)
|
||||||
|
* Remove env user salt since no need to use (#1515)
|
||||||
|
* Drop db operations from hook commands (#1514)
|
||||||
|
* Better URL validation (#1507)
|
||||||
|
* Migrate WatchInfo struct to api (#1492)
|
||||||
|
* refactor: show command help message. (#1486)
|
||||||
|
* refactor update ssh key use time (#1466)
|
||||||
|
* Set VERSION from git once, in a variable (#1447)
|
||||||
|
* Remove unused mutex field (#1440)
|
||||||
|
* Simplify settings pages with item list (#1389)
|
||||||
|
* Clean-up PostgreSQL Tests (#1361)
|
||||||
|
* refactor: remove workaround after the golang 1.7 release. (#1349)
|
||||||
|
* Delete the useless code (#1335)
|
||||||
|
* Run "make fmt" with go-1.6 (#1333)
|
||||||
|
* Refactor admin/auth/new.tmpl (#1277)
|
||||||
|
* Refactor repo/issue/view_content.tmpl (#1276)
|
||||||
|
* Cleaner ui for admin, repo settings, and user settings page (#1269) (#1270)
|
||||||
|
* Cleaner UI for explore page (#1253) (#1255)
|
||||||
|
* Synced licenses with github repo (#1246)
|
||||||
|
* Synced gitignores with github repo (#1245)
|
||||||
|
* Simplify RepositoryList.loadAttributes() (#1211)
|
||||||
|
* Move user_follow to separate file (#1210)
|
||||||
|
* Reduce conditionals in signin/signup inner forms (#1138)
|
||||||
|
|
||||||
## [1.1.3](https://github.com/go-gitea/gitea/releases/tag/v1.1.3) - 2017-08-03
|
## [1.1.3](https://github.com/go-gitea/gitea/releases/tag/v1.1.3) - 2017-08-03
|
||||||
|
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -56,11 +56,8 @@ clean:
|
|||||||
$(GO) clean -i ./...
|
$(GO) clean -i ./...
|
||||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) integrations*.test
|
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) integrations*.test
|
||||||
|
|
||||||
required-gofmt-version:
|
|
||||||
@$(GO) version | grep -q '\(1.7\|1.8\)' || { echo "We require go version 1.7 or 1.8 to format code" >&2 && exit 1; }
|
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt: required-gofmt-version
|
fmt:
|
||||||
$(GOFMT) -w $(GOFILES)
|
$(GOFMT) -w $(GOFILES)
|
||||||
|
|
||||||
.PHONY: vet
|
.PHONY: vet
|
||||||
@@ -112,7 +109,7 @@ misspell:
|
|||||||
misspell -w -i unknwon $(GOFILES)
|
misspell -w -i unknwon $(GOFILES)
|
||||||
|
|
||||||
.PHONY: fmt-check
|
.PHONY: fmt-check
|
||||||
fmt-check: required-gofmt-version
|
fmt-check:
|
||||||
# get all go files and run go fmt on them
|
# get all go files and run go fmt on them
|
||||||
@diff=$$($(GOFMT) -d $(GOFILES)); \
|
@diff=$$($(GOFMT) -d $(GOFILES)); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
|
|||||||
16
cmd/hook.go
16
cmd/hook.go
@@ -126,15 +126,13 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if protectBranch != nil {
|
if protectBranch != nil && protectBranch.IsProtected() {
|
||||||
if !protectBranch.CanPush {
|
// check and deletion
|
||||||
// check and deletion
|
if newCommitID == git.EmptySHA {
|
||||||
if newCommitID == git.EmptySHA {
|
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
} else if !protectBranch.CanPush {
|
||||||
} else {
|
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
//fail(fmt.Sprintf("branch %s is protected from force push", branchName), "")
|
||||||
//fail(fmt.Sprintf("branch %s is protected from force push", branchName), "")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func TestCreateFileOnProtectedBranch(t *testing.T) {
|
|||||||
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches?action=protected_branch", map[string]string{
|
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches?action=protected_branch", map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"branchName": "master",
|
"branchName": "master",
|
||||||
"canPush": "true",
|
"canPush": "false",
|
||||||
})
|
})
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
// Check if master branch has been locked successfully
|
// Check if master branch has been locked successfully
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertProtectedBranch(t *testing.T, repoID int64, branchName string, isErr, canPush bool) {
|
func assertProtectedBranch(t *testing.T, repoID int64, branchName string, isErr, isProtected bool) {
|
||||||
reqURL := fmt.Sprintf("/api/internal/branch/%d/%s", repoID, url.QueryEscape(branchName))
|
reqURL := fmt.Sprintf("/api/internal/branch/%d/%s", repoID, url.QueryEscape(branchName))
|
||||||
req := NewRequest(t, "GET", reqURL)
|
req := NewRequest(t, "GET", reqURL)
|
||||||
t.Log(reqURL)
|
t.Log(reqURL)
|
||||||
@@ -31,14 +31,14 @@ func assertProtectedBranch(t *testing.T, repoID int64, branchName string, isErr,
|
|||||||
var branch models.ProtectedBranch
|
var branch models.ProtectedBranch
|
||||||
t.Log(string(resp.Body))
|
t.Log(string(resp.Body))
|
||||||
assert.NoError(t, json.Unmarshal(resp.Body, &branch))
|
assert.NoError(t, json.Unmarshal(resp.Body, &branch))
|
||||||
assert.Equal(t, canPush, branch.CanPush)
|
assert.Equal(t, isProtected, branch.IsProtected())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInternal_GetProtectedBranch(t *testing.T) {
|
func TestInternal_GetProtectedBranch(t *testing.T) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
|
|
||||||
assertProtectedBranch(t, 1, "master", false, true)
|
assertProtectedBranch(t, 1, "master", false, false)
|
||||||
assertProtectedBranch(t, 1, "dev", false, true)
|
assertProtectedBranch(t, 1, "dev", false, false)
|
||||||
assertProtectedBranch(t, 1, "lunny/dev", false, true)
|
assertProtectedBranch(t, 1, "lunny/dev", false, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ RUN_MODE = prod
|
|||||||
|
|
||||||
[database]
|
[database]
|
||||||
DB_TYPE = mysql
|
DB_TYPE = mysql
|
||||||
HOST = 127.0.0.1:3306
|
HOST = mysql:3306
|
||||||
NAME = testgitea
|
NAME = testgitea
|
||||||
USER = root
|
USER = root
|
||||||
PASSWD =
|
PASSWD =
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ RUN_MODE = prod
|
|||||||
|
|
||||||
[database]
|
[database]
|
||||||
DB_TYPE = postgres
|
DB_TYPE = postgres
|
||||||
HOST = 127.0.0.1:5432
|
HOST = pgsql:5432
|
||||||
NAME = testgitea
|
NAME = testgitea
|
||||||
USER = postgres
|
USER = postgres
|
||||||
PASSWD = postgres
|
PASSWD = postgres
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func testPullCreate(t *testing.T, session *TestSession, user, repo, branch strin
|
|||||||
func TestPullCreate(t *testing.T) {
|
func TestPullCreate(t *testing.T) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session)
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md")
|
||||||
testPullCreate(t, session, "user1", "repo1", "master")
|
testPullCreate(t, session, "user1", "repo1", "master")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str
|
|||||||
func TestPullMerge(t *testing.T) {
|
func TestPullMerge(t *testing.T) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session)
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md")
|
||||||
|
|
||||||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||||
@@ -61,7 +61,7 @@ func TestPullMerge(t *testing.T) {
|
|||||||
func TestPullCleanUpAfterMerge(t *testing.T) {
|
func TestPullCleanUpAfterMerge(t *testing.T) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session)
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md")
|
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md")
|
||||||
|
|
||||||
resp := testPullCreate(t, session, "user1", "repo1", "feature/test")
|
resp := testPullCreate(t, session, "user1", "repo1", "feature/test")
|
||||||
|
|||||||
@@ -5,19 +5,24 @@
|
|||||||
package integrations
|
package integrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testRepoFork(t *testing.T, session *TestSession) *TestResponse {
|
func testRepoFork(t *testing.T, session *TestSession, ownerName, repoName, forkOwnerName, forkRepoName string) *TestResponse {
|
||||||
|
forkOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: forkOwnerName}).(*models.User)
|
||||||
|
|
||||||
// Step0: check the existence of the to-fork repo
|
// Step0: check the existence of the to-fork repo
|
||||||
req := NewRequest(t, "GET", "/user1/repo1")
|
req := NewRequestf(t, "GET", "/%s/%s", forkOwnerName, forkRepoName)
|
||||||
resp := session.MakeRequest(t, req, http.StatusNotFound)
|
resp := session.MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
||||||
// Step1: go to the main page of repo
|
// Step1: go to the main page of repo
|
||||||
req = NewRequest(t, "GET", "/user2/repo1")
|
req = NewRequestf(t, "GET", "/%s/%s", ownerName, repoName)
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
// Step2: click the fork button
|
// Step2: click the fork button
|
||||||
@@ -31,15 +36,17 @@ func testRepoFork(t *testing.T, session *TestSession) *TestResponse {
|
|||||||
htmlDoc = NewHTMLParser(t, resp.Body)
|
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||||
link, exists = htmlDoc.doc.Find("form.ui.form[action^=\"/repo/fork/\"]").Attr("action")
|
link, exists = htmlDoc.doc.Find("form.ui.form[action^=\"/repo/fork/\"]").Attr("action")
|
||||||
assert.True(t, exists, "The template has changed")
|
assert.True(t, exists, "The template has changed")
|
||||||
|
_, exists = htmlDoc.doc.Find(fmt.Sprintf(".owner.dropdown .item[data-value=\"%d\"]", forkOwner.ID)).Attr("data-value")
|
||||||
|
assert.True(t, exists, fmt.Sprintf("Fork owner '%s' is not present in select box", forkOwnerName))
|
||||||
req = NewRequestWithValues(t, "POST", link, map[string]string{
|
req = NewRequestWithValues(t, "POST", link, map[string]string{
|
||||||
"_csrf": htmlDoc.GetCSRF(),
|
"_csrf": htmlDoc.GetCSRF(),
|
||||||
"uid": "1",
|
"uid": fmt.Sprintf("%d", forkOwner.ID),
|
||||||
"repo_name": "repo1",
|
"repo_name": forkRepoName,
|
||||||
})
|
})
|
||||||
resp = session.MakeRequest(t, req, http.StatusFound)
|
resp = session.MakeRequest(t, req, http.StatusFound)
|
||||||
|
|
||||||
// Step4: check the existence of the forked repo
|
// Step4: check the existence of the forked repo
|
||||||
req = NewRequest(t, "GET", "/user1/repo1")
|
req = NewRequestf(t, "GET", "/%s/%s", forkOwnerName, forkRepoName)
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
@@ -48,5 +55,19 @@ func testRepoFork(t *testing.T, session *TestSession) *TestResponse {
|
|||||||
func TestRepoFork(t *testing.T) {
|
func TestRepoFork(t *testing.T) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session)
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepoForkToOrg(t *testing.T) {
|
||||||
|
prepareTestEnv(t)
|
||||||
|
session := loginUser(t, "user2")
|
||||||
|
testRepoFork(t, session, "user2", "repo1", "user3", "repo1")
|
||||||
|
|
||||||
|
// Check that no more forking is allowed as user2 owns repository
|
||||||
|
// and user3 organization that owner user2 is also now has forked this repository
|
||||||
|
req := NewRequest(t, "GET", "/user2/repo1")
|
||||||
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
_, exists := htmlDoc.doc.Find("a.ui.button[href^=\"/repo/fork/\"]").Attr("href")
|
||||||
|
assert.False(t, exists, "Forking should not be allowed anymore")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,6 @@ RUN_MODE = prod
|
|||||||
|
|
||||||
[database]
|
[database]
|
||||||
DB_TYPE = sqlite3
|
DB_TYPE = sqlite3
|
||||||
HOST = 127.0.0.1:3306
|
|
||||||
NAME = testgitea
|
|
||||||
USER = gitea
|
|
||||||
PASSWD =
|
|
||||||
SSL_MODE = disable
|
|
||||||
PATH = :memory:
|
PATH = :memory:
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Version holds the current Gitea version
|
// Version holds the current Gitea version
|
||||||
var Version = "1.1.0+dev"
|
var Version = "1.2.0-dev"
|
||||||
|
|
||||||
// Tags holds the build tags used
|
// Tags holds the build tags used
|
||||||
var Tags = ""
|
var Tags = ""
|
||||||
|
|||||||
@@ -713,7 +713,6 @@ type GetFeedsOptions struct {
|
|||||||
IncludePrivate bool // include private actions
|
IncludePrivate bool // include private actions
|
||||||
OnlyPerformedBy bool // only actions performed by requested user
|
OnlyPerformedBy bool // only actions performed by requested user
|
||||||
IncludeDeleted bool // include deleted actions
|
IncludeDeleted bool // include deleted actions
|
||||||
Collaborate bool // Include collaborative repositories
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFeeds returns actions according to the provided options
|
// GetFeeds returns actions according to the provided options
|
||||||
@@ -733,13 +732,7 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
|
|||||||
cond = cond.And(builder.In("repo_id", repoIDs))
|
cond = cond.And(builder.In("repo_id", repoIDs))
|
||||||
}
|
}
|
||||||
|
|
||||||
var userIDCond builder.Cond = builder.Eq{"user_id": opts.RequestedUser.ID}
|
cond = cond.And(builder.Eq{"user_id": opts.RequestedUser.ID})
|
||||||
if opts.Collaborate {
|
|
||||||
userIDCond = userIDCond.Or(builder.Expr(
|
|
||||||
"repo_id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)",
|
|
||||||
opts.RequestedUser.ID))
|
|
||||||
}
|
|
||||||
cond = cond.And(userIDCond)
|
|
||||||
|
|
||||||
if opts.OnlyPerformedBy {
|
if opts.OnlyPerformedBy {
|
||||||
cond = cond.And(builder.Eq{"act_user_id": opts.RequestedUser.ID})
|
cond = cond.And(builder.Eq{"act_user_id": opts.RequestedUser.ID})
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ const (
|
|||||||
|
|
||||||
// ProtectedBranch struct
|
// ProtectedBranch struct
|
||||||
type ProtectedBranch struct {
|
type ProtectedBranch struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||||
BranchName string `xorm:"UNIQUE(s)"`
|
BranchName string `xorm:"UNIQUE(s)"`
|
||||||
CanPush bool
|
CanPush bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
Created time.Time `xorm:"-"`
|
Created time.Time `xorm:"-"`
|
||||||
CreatedUnix int64
|
CreatedUnix int64
|
||||||
Updated time.Time `xorm:"-"`
|
Updated time.Time `xorm:"-"`
|
||||||
@@ -38,6 +38,11 @@ func (protectBranch *ProtectedBranch) BeforeUpdate() {
|
|||||||
protectBranch.UpdatedUnix = time.Now().Unix()
|
protectBranch.UpdatedUnix = time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsProtected returns if the branch is protected
|
||||||
|
func (protectBranch *ProtectedBranch) IsProtected() bool {
|
||||||
|
return protectBranch.ID > 0
|
||||||
|
}
|
||||||
|
|
||||||
// GetProtectedBranchByRepoID getting protected branch by repo ID
|
// GetProtectedBranchByRepoID getting protected branch by repo ID
|
||||||
func GetProtectedBranchByRepoID(RepoID int64) ([]*ProtectedBranch, error) {
|
func GetProtectedBranchByRepoID(RepoID int64) ([]*ProtectedBranch, error) {
|
||||||
protectedBranches := make([]*ProtectedBranch, 0)
|
protectedBranches := make([]*ProtectedBranch, 0)
|
||||||
|
|||||||
@@ -276,11 +276,7 @@ func DeleteGPGKey(doer *User, id int64) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
return sess.Commit()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitVerification represents a commit validation of signature
|
// CommitVerification represents a commit validation of signature
|
||||||
|
|||||||
@@ -572,11 +572,7 @@ func (issue *Issue) ReadBy(userID int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setNotificationStatusReadIfUnread(x, userID, issue.ID); err != nil {
|
return setNotificationStatusReadIfUnread(x, userID, issue.ID)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateIssueCols(e Engine, issue *Issue, cols ...string) error {
|
func updateIssueCols(e Engine, issue *Issue, cols ...string) error {
|
||||||
|
|||||||
@@ -509,10 +509,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok, _ := c.Extension("AUTH"); ok {
|
if ok, _ := c.Extension("AUTH"); ok {
|
||||||
if err = c.Auth(a); err != nil {
|
return c.Auth(a)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return ErrUnsupportedLoginType
|
return ErrUnsupportedLoginType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ func composeIssueCommentMessage(issue *Issue, doer *User, comment *Comment, tplN
|
|||||||
log.Error(3, "Template: %v", err)
|
log.Error(3, "Template: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content.String())
|
msg := mailer.NewMessageFrom(tos, doer.DisplayName(), setting.MailService.FromEmail, subject, content.String())
|
||||||
msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info)
|
msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info)
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ var migrations = []Migration{
|
|||||||
NewMigration("unescape user full names", unescapeUserFullNames),
|
NewMigration("unescape user full names", unescapeUserFullNames),
|
||||||
// v38 -> v39
|
// v38 -> v39
|
||||||
NewMigration("remove commits and settings unit types", removeCommitsUnitType),
|
NewMigration("remove commits and settings unit types", removeCommitsUnitType),
|
||||||
|
// v43 -> v44
|
||||||
|
NewMigration("fix protected branch can push value to false", fixProtectedBranchCanPushValue),
|
||||||
|
// v42 -> v43
|
||||||
|
NewMigration("add tags to releases and sync existing repositories", releaseAddColumnIsTagAndSyncTags),
|
||||||
|
// v44 -> v45
|
||||||
|
NewMigration("remove duplicate unit types", removeDuplicateUnitTypes),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate database to current version
|
// Migrate database to current version
|
||||||
|
|||||||
@@ -10,20 +10,15 @@ import (
|
|||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserV15 describes the added field for User
|
|
||||||
type UserV15 struct {
|
|
||||||
AllowCreateOrganization bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName will be invoked by XORM to customrize the table name
|
|
||||||
func (*UserV15) TableName() string {
|
|
||||||
return "user"
|
|
||||||
}
|
|
||||||
|
|
||||||
func createAllowCreateOrganizationColumn(x *xorm.Engine) error {
|
func createAllowCreateOrganizationColumn(x *xorm.Engine) error {
|
||||||
if err := x.Sync2(new(UserV15)); err != nil {
|
type User struct {
|
||||||
|
KeepEmailPrivate bool
|
||||||
|
AllowCreateOrganization bool
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := x.Sync2(new(User)); err != nil {
|
||||||
return fmt.Errorf("Sync2: %v", err)
|
return fmt.Errorf("Sync2: %v", err)
|
||||||
} else if _, err = x.Where("type=0").Cols("allow_create_organization").Update(&UserV15{AllowCreateOrganization: true}); err != nil {
|
} else if _, err = x.Where("`type` = 0").Cols("allow_create_organization").Update(&User{AllowCreateOrganization: true}); err != nil {
|
||||||
return fmt.Errorf("set allow_create_organization: %v", err)
|
return fmt.Errorf("set allow_create_organization: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -13,17 +13,6 @@ import (
|
|||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RepoUnit describes all units of a repository
|
|
||||||
type RepoUnit struct {
|
|
||||||
ID int64
|
|
||||||
RepoID int64 `xorm:"INDEX(s)"`
|
|
||||||
Type int `xorm:"INDEX(s)"`
|
|
||||||
Index int
|
|
||||||
Config map[string]string `xorm:"JSON"`
|
|
||||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
|
||||||
Created time.Time `xorm:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumerate all the unit types
|
// Enumerate all the unit types
|
||||||
const (
|
const (
|
||||||
V16UnitTypeCode = iota + 1 // 1 code
|
V16UnitTypeCode = iota + 1 // 1 code
|
||||||
@@ -37,14 +26,25 @@ const (
|
|||||||
V16UnitTypeExternalTracker // 9 ExternalTracker
|
V16UnitTypeExternalTracker // 9 ExternalTracker
|
||||||
)
|
)
|
||||||
|
|
||||||
// Repo describes a repository
|
|
||||||
type Repo struct {
|
|
||||||
ID int64
|
|
||||||
EnableWiki, EnableExternalWiki, EnableIssues, EnableExternalTracker, EnablePulls bool
|
|
||||||
ExternalWikiURL, ExternalTrackerURL, ExternalTrackerFormat, ExternalTrackerStyle string
|
|
||||||
}
|
|
||||||
|
|
||||||
func addUnitsToTables(x *xorm.Engine) error {
|
func addUnitsToTables(x *xorm.Engine) error {
|
||||||
|
// RepoUnit describes all units of a repository
|
||||||
|
type RepoUnit struct {
|
||||||
|
ID int64
|
||||||
|
RepoID int64 `xorm:"INDEX(s)"`
|
||||||
|
Type int `xorm:"INDEX(s)"`
|
||||||
|
Index int
|
||||||
|
Config map[string]interface{} `xorm:"JSON"`
|
||||||
|
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||||
|
Created time.Time `xorm:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repo describes a repository
|
||||||
|
type Repo struct {
|
||||||
|
ID int64
|
||||||
|
EnableWiki, EnableExternalWiki, EnableIssues, EnableExternalTracker, EnablePulls bool
|
||||||
|
ExternalWikiURL, ExternalTrackerURL, ExternalTrackerFormat, ExternalTrackerStyle string
|
||||||
|
}
|
||||||
|
|
||||||
var repos []Repo
|
var repos []Repo
|
||||||
err := x.Table("repository").Select("*").Find(&repos)
|
err := x.Table("repository").Select("*").Find(&repos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -95,7 +95,7 @@ func addUnitsToTables(x *xorm.Engine) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = make(map[string]string)
|
var config = make(map[string]interface{})
|
||||||
switch i {
|
switch i {
|
||||||
case V16UnitTypeExternalTracker:
|
case V16UnitTypeExternalTracker:
|
||||||
config["ExternalTrackerURL"] = repo.ExternalTrackerURL
|
config["ExternalTrackerURL"] = repo.ExternalTrackerURL
|
||||||
@@ -119,9 +119,5 @@ func addUnitsToTables(x *xorm.Engine) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sess.Commit(); err != nil {
|
return sess.Commit()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,5 @@ func useNewPublickeyFormat(x *xorm.Engine) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.Close()
|
f.Close()
|
||||||
if err = os.Rename(tmpPath, fpath); err != nil {
|
return os.Rename(tmpPath, fpath)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,19 @@ package migrations
|
|||||||
import (
|
import (
|
||||||
"html"
|
"html"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func unescapeUserFullNames(x *xorm.Engine) (err error) {
|
func unescapeUserFullNames(x *xorm.Engine) (err error) {
|
||||||
|
type User struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
FullName string
|
||||||
|
}
|
||||||
|
|
||||||
const batchSize = 100
|
const batchSize = 100
|
||||||
for start := 0; ; start += batchSize {
|
for start := 0; ; start += batchSize {
|
||||||
users := make([]*models.User, 0, batchSize)
|
users := make([]*User, 0, batchSize)
|
||||||
if err := x.Limit(start, batchSize).Find(users); err != nil {
|
if err := x.Limit(batchSize, start).Find(&users); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
@@ -24,7 +27,7 @@ func unescapeUserFullNames(x *xorm.Engine) (err error) {
|
|||||||
}
|
}
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
user.FullName = html.UnescapeString(user.FullName)
|
user.FullName = html.UnescapeString(user.FullName)
|
||||||
if _, err := x.Cols("full_name").Update(user); err != nil {
|
if _, err := x.ID(user.ID).Cols("full_name").Update(user); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,26 @@
|
|||||||
package migrations
|
package migrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
|
||||||
|
"github.com/go-xorm/core"
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func removeCommitsUnitType(x *xorm.Engine) (err error) {
|
func removeCommitsUnitType(x *xorm.Engine) (err error) {
|
||||||
|
// RepoUnit describes all units of a repository
|
||||||
|
type RepoUnit struct {
|
||||||
|
ID int64
|
||||||
|
RepoID int64 `xorm:"INDEX(s)"`
|
||||||
|
Type int `xorm:"INDEX(s)"`
|
||||||
|
Index int
|
||||||
|
Config core.Conversion `xorm:"TEXT"`
|
||||||
|
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||||
|
Created time.Time `xorm:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
// Update team unit types
|
// Update team unit types
|
||||||
const batchSize = 100
|
const batchSize = 100
|
||||||
for start := 0; ; start += batchSize {
|
for start := 0; ; start += batchSize {
|
||||||
@@ -33,7 +47,7 @@ func removeCommitsUnitType(x *xorm.Engine) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
team.UnitTypes = ut
|
team.UnitTypes = ut
|
||||||
if _, err := x.Id(team.ID).Cols("unit_types").Update(team); err != nil {
|
if _, err := x.ID(team.ID).Cols("unit_types").Update(team); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
57
models/migrations/v42.go
Normal file
57
models/migrations/v42.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2017 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 migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReleaseV39 describes the added field for Release
|
||||||
|
type ReleaseV39 struct {
|
||||||
|
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName will be invoked by XORM to customrize the table name
|
||||||
|
func (*ReleaseV39) TableName() string {
|
||||||
|
return "release"
|
||||||
|
}
|
||||||
|
|
||||||
|
func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
|
||||||
|
if err := x.Sync2(new(ReleaseV39)); err != nil {
|
||||||
|
return fmt.Errorf("Sync2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the sake of SQLite3, we can't use x.Iterate here.
|
||||||
|
offset := 0
|
||||||
|
pageSize := 20
|
||||||
|
for {
|
||||||
|
repos := make([]*models.Repository, 0, pageSize)
|
||||||
|
if err := x.Table("repository").Asc("id").Limit(pageSize, offset).Find(&repos); err != nil {
|
||||||
|
return fmt.Errorf("select repos [offset: %d]: %v", offset, err)
|
||||||
|
}
|
||||||
|
for _, repo := range repos {
|
||||||
|
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("OpenRepository: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||||
|
log.Warn("SyncReleasesWithTags: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(repos) < pageSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
offset += pageSize
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
18
models/migrations/v43.go
Normal file
18
models/migrations/v43.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2017 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 migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fixProtectedBranchCanPushValue(x *xorm.Engine) error {
|
||||||
|
_, err := x.Cols("can_push").Update(&models.ProtectedBranch{
|
||||||
|
CanPush: false,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
69
models/migrations/v44.go
Normal file
69
models/migrations/v44.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2017 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 migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func removeDuplicateUnitTypes(x *xorm.Engine) error {
|
||||||
|
// RepoUnit describes all units of a repository
|
||||||
|
type RepoUnit struct {
|
||||||
|
RepoID int64
|
||||||
|
Type int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate all the unit types
|
||||||
|
const (
|
||||||
|
UnitTypeCode = iota + 1 // 1 code
|
||||||
|
UnitTypeIssues // 2 issues
|
||||||
|
UnitTypePullRequests // 3 PRs
|
||||||
|
UnitTypeReleases // 4 Releases
|
||||||
|
UnitTypeWiki // 5 Wiki
|
||||||
|
UnitTypeExternalWiki // 6 ExternalWiki
|
||||||
|
UnitTypeExternalTracker // 7 ExternalTracker
|
||||||
|
)
|
||||||
|
|
||||||
|
var externalIssueRepoUnits []RepoUnit
|
||||||
|
err := x.Where("type = ?", UnitTypeExternalTracker).Find(&externalIssueRepoUnits)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Query repositories: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var externalWikiRepoUnits []RepoUnit
|
||||||
|
err = x.Where("type = ?", UnitTypeExternalWiki).Find(&externalWikiRepoUnits)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Query repositories: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := x.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
|
||||||
|
if err := sess.Begin(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, repoUnit := range externalIssueRepoUnits {
|
||||||
|
if _, err = sess.Delete(&RepoUnit{
|
||||||
|
RepoID: repoUnit.RepoID,
|
||||||
|
Type: UnitTypeIssues,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("Delete repo unit: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, repoUnit := range externalWikiRepoUnits {
|
||||||
|
if _, err = sess.Delete(&RepoUnit{
|
||||||
|
RepoID: repoUnit.RepoID,
|
||||||
|
Type: UnitTypeWiki,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("Delete repo unit: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sess.Commit()
|
||||||
|
}
|
||||||
@@ -235,11 +235,7 @@ func DeleteOrganization(org *User) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
return sess.Commit()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteOrg(e *xorm.Session, u *User) error {
|
func deleteOrg(e *xorm.Session, u *User) error {
|
||||||
@@ -675,7 +671,7 @@ func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
|||||||
Table("repository").
|
Table("repository").
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
||||||
Where(env.cond()).
|
Where(env.cond()).
|
||||||
GroupBy("`repository`.id").
|
GroupBy("`repository`.id, `repository`.updated_unix").
|
||||||
OrderBy("updated_unix DESC").
|
OrderBy("updated_unix DESC").
|
||||||
Cols("`repository`.id").
|
Cols("`repository`.id").
|
||||||
Find(&repoIDs)
|
Find(&repoIDs)
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ type Release struct {
|
|||||||
NumCommitsBehind int64 `xorm:"-"`
|
NumCommitsBehind int64 `xorm:"-"`
|
||||||
Note string `xorm:"TEXT"`
|
Note string `xorm:"TEXT"`
|
||||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
IsPrerelease bool
|
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
|
||||||
Attachments []*Attachment `xorm:"-"`
|
Attachments []*Attachment `xorm:"-"`
|
||||||
|
|
||||||
@@ -139,17 +140,18 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
rel.LowerTagName = strings.ToLower(rel.TagName)
|
||||||
commit, err := gitRepo.GetTagCommit(rel.TagName)
|
}
|
||||||
if err != nil {
|
commit, err := gitRepo.GetTagCommit(rel.TagName)
|
||||||
return fmt.Errorf("GetTagCommit: %v", err)
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("GetTagCommit: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
rel.Sha1 = commit.ID.String()
|
rel.Sha1 = commit.ID.String()
|
||||||
rel.NumCommits, err = commit.CommitsCount()
|
rel.CreatedUnix = commit.Author.When.Unix()
|
||||||
if err != nil {
|
rel.NumCommits, err = commit.CommitsCount()
|
||||||
return fmt.Errorf("CommitsCount: %v", err)
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("CommitsCount: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -236,6 +238,7 @@ func GetReleaseByID(id int64) (*Release, error) {
|
|||||||
// FindReleasesOptions describes the conditions to Find releases
|
// FindReleasesOptions describes the conditions to Find releases
|
||||||
type FindReleasesOptions struct {
|
type FindReleasesOptions struct {
|
||||||
IncludeDrafts bool
|
IncludeDrafts bool
|
||||||
|
IncludeTags bool
|
||||||
TagNames []string
|
TagNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +249,9 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond {
|
|||||||
if !opts.IncludeDrafts {
|
if !opts.IncludeDrafts {
|
||||||
cond = cond.And(builder.Eq{"is_draft": false})
|
cond = cond.And(builder.Eq{"is_draft": false})
|
||||||
}
|
}
|
||||||
|
if !opts.IncludeTags {
|
||||||
|
cond = cond.And(builder.Eq{"is_tag": false})
|
||||||
|
}
|
||||||
if len(opts.TagNames) > 0 {
|
if len(opts.TagNames) > 0 {
|
||||||
cond = cond.And(builder.In("tag_name", opts.TagNames))
|
cond = cond.And(builder.In("tag_name", opts.TagNames))
|
||||||
}
|
}
|
||||||
@@ -361,6 +367,8 @@ func UpdateRelease(gitRepo *git.Repository, rel *Release, attachmentUUIDs []stri
|
|||||||
if err = createTag(gitRepo, rel); err != nil {
|
if err = createTag(gitRepo, rel); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rel.LowerTagName = strings.ToLower(rel.TagName)
|
||||||
|
|
||||||
_, err = x.Id(rel.ID).AllCols().Update(rel)
|
_, err = x.Id(rel.ID).AllCols().Update(rel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -397,11 +405,64 @@ func DeleteReleaseByID(id int64, u *User, delTag bool) error {
|
|||||||
if err != nil && !strings.Contains(stderr, "not found") {
|
if err != nil && !strings.Contains(stderr, "not found") {
|
||||||
return fmt.Errorf("git tag -d: %v - %s", err, stderr)
|
return fmt.Errorf("git tag -d: %v - %s", err, stderr)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
|
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
|
||||||
return fmt.Errorf("Delete: %v", err)
|
return fmt.Errorf("Delete: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rel.IsTag = true
|
||||||
|
rel.IsDraft = false
|
||||||
|
rel.IsPrerelease = false
|
||||||
|
rel.Title = ""
|
||||||
|
rel.Note = ""
|
||||||
|
|
||||||
|
if _, err = x.Id(rel.ID).AllCols().Update(rel); err != nil {
|
||||||
|
return fmt.Errorf("Update: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncReleasesWithTags synchronizes release table with repository tags
|
||||||
|
func SyncReleasesWithTags(repo *Repository, gitRepo *git.Repository) error {
|
||||||
|
existingRelTags := make(map[string]struct{})
|
||||||
|
opts := FindReleasesOptions{IncludeDrafts: true, IncludeTags: true}
|
||||||
|
for page := 1; ; page++ {
|
||||||
|
rels, err := GetReleasesByRepoID(repo.ID, opts, page, 100)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetReleasesByRepoID: %v", err)
|
||||||
|
}
|
||||||
|
if len(rels) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for _, rel := range rels {
|
||||||
|
if rel.IsDraft {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
commitID, err := gitRepo.GetTagCommitID(rel.TagName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetTagCommitID: %v", err)
|
||||||
|
}
|
||||||
|
if !gitRepo.IsTagExist(rel.TagName) || commitID != rel.Sha1 {
|
||||||
|
if err := pushUpdateDeleteTag(repo, gitRepo, rel.TagName); err != nil {
|
||||||
|
return fmt.Errorf("pushUpdateDeleteTag: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
existingRelTags[strings.ToLower(rel.TagName)] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tags, err := gitRepo.GetTags()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetTags: %v", err)
|
||||||
|
}
|
||||||
|
for _, tagName := range tags {
|
||||||
|
if _, ok := existingRelTags[strings.ToLower(tagName)]; !ok {
|
||||||
|
if err := pushUpdateAddTag(repo, gitRepo, tagName); err != nil {
|
||||||
|
return fmt.Errorf("pushUpdateAddTag: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ type Repository struct {
|
|||||||
NumMilestones int `xorm:"NOT NULL DEFAULT 0"`
|
NumMilestones int `xorm:"NOT NULL DEFAULT 0"`
|
||||||
NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"`
|
NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"`
|
||||||
NumOpenMilestones int `xorm:"-"`
|
NumOpenMilestones int `xorm:"-"`
|
||||||
NumTags int `xorm:"-"`
|
NumReleases int `xorm:"-"`
|
||||||
|
|
||||||
IsPrivate bool `xorm:"INDEX"`
|
IsPrivate bool `xorm:"INDEX"`
|
||||||
IsBare bool `xorm:"INDEX"`
|
IsBare bool `xorm:"INDEX"`
|
||||||
@@ -409,6 +409,21 @@ func (repo *Repository) UnitEnabled(tp UnitType) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AnyUnitEnabled if this repository has the any of the given units enabled
|
||||||
|
func (repo *Repository) AnyUnitEnabled(tps ...UnitType) bool {
|
||||||
|
if err := repo.getUnits(x); err != nil {
|
||||||
|
log.Warn("Error loading repository (ID: %d) units: %s", repo.ID, err.Error())
|
||||||
|
}
|
||||||
|
for _, unit := range repo.Units {
|
||||||
|
for _, tp := range tps {
|
||||||
|
if unit.Type == tp {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrUnitNotExist organization does not exist
|
// ErrUnitNotExist organization does not exist
|
||||||
ErrUnitNotExist = errors.New("Unit does not exist")
|
ErrUnitNotExist = errors.New("Unit does not exist")
|
||||||
@@ -648,7 +663,26 @@ func (repo *Repository) UpdateSize() error {
|
|||||||
|
|
||||||
// CanBeForked returns true if repository meets the requirements of being forked.
|
// CanBeForked returns true if repository meets the requirements of being forked.
|
||||||
func (repo *Repository) CanBeForked() bool {
|
func (repo *Repository) CanBeForked() bool {
|
||||||
return !repo.IsBare
|
return !repo.IsBare && repo.UnitEnabled(UnitTypeCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanUserFork returns true if specified user can fork repository.
|
||||||
|
func (repo *Repository) CanUserFork(user *User) (bool, error) {
|
||||||
|
if user == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if repo.OwnerID != user.ID && !user.HasForkedRepo(repo.ID) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if err := user.GetOwnedOrganizations(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
for _, org := range user.OwnedOrgs {
|
||||||
|
if repo.OwnerID != org.ID && !org.HasForkedRepo(repo.ID) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanEnablePulls returns true if repository meets the requirements of accepting pulls.
|
// CanEnablePulls returns true if repository meets the requirements of accepting pulls.
|
||||||
@@ -912,6 +946,10 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
|||||||
if headBranch != nil {
|
if headBranch != nil {
|
||||||
repo.DefaultBranch = headBranch.Name
|
repo.DefaultBranch = headBranch.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||||
|
log.Error(4, "Failed to synchronize tags to releases for repository: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = repo.UpdateSize(); err != nil {
|
if err = repo.UpdateSize(); err != nil {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
|
"code.gitea.io/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/process"
|
"code.gitea.io/gitea/modules/process"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@@ -148,6 +149,15 @@ func (m *Mirror) runSync() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gitRepo, err := git.OpenRepository(repoPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(4, "OpenRepository: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err = SyncReleasesWithTags(m.Repo, gitRepo); err != nil {
|
||||||
|
log.Error(4, "Failed to synchronize tags to releases for repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := m.Repo.UpdateSize(); err != nil {
|
if err := m.Repo.UpdateSize(); err != nil {
|
||||||
log.Error(4, "Failed to update size for mirror repository: %v", err)
|
log.Error(4, "Failed to update size for mirror repository: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -609,11 +609,7 @@ func RewriteAllPublicKeys() error {
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = os.Rename(tmpPath, fPath); err != nil {
|
return os.Rename(tmpPath, fPath)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ________ .__ ____ __.
|
// ________ .__ ____ __.
|
||||||
|
|||||||
123
models/update.go
123
models/update.go
@@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/git"
|
"code.gitea.io/git"
|
||||||
|
|
||||||
@@ -81,6 +82,108 @@ func PushUpdate(branch string, opt PushUpdateOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pushUpdateDeleteTag(repo *Repository, gitRepo *git.Repository, tagName string) error {
|
||||||
|
rel, err := GetRelease(repo.ID, tagName)
|
||||||
|
if err != nil {
|
||||||
|
if IsErrReleaseNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("GetRelease: %v", err)
|
||||||
|
}
|
||||||
|
if rel.IsTag {
|
||||||
|
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
|
||||||
|
return fmt.Errorf("Delete: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rel.IsDraft = true
|
||||||
|
rel.NumCommits = 0
|
||||||
|
rel.Sha1 = ""
|
||||||
|
if _, err = x.Id(rel.ID).AllCols().Update(rel); err != nil {
|
||||||
|
return fmt.Errorf("Update: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string) error {
|
||||||
|
rel, err := GetRelease(repo.ID, tagName)
|
||||||
|
if err != nil && !IsErrReleaseNotExist(err) {
|
||||||
|
return fmt.Errorf("GetRelease: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tag, err := gitRepo.GetTag(tagName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetTag: %v", err)
|
||||||
|
}
|
||||||
|
commit, err := tag.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Commit: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sig := tag.Tagger
|
||||||
|
if sig == nil {
|
||||||
|
sig = commit.Author
|
||||||
|
}
|
||||||
|
if sig == nil {
|
||||||
|
sig = commit.Committer
|
||||||
|
}
|
||||||
|
|
||||||
|
var author *User
|
||||||
|
var createdAt = time.Unix(1, 0)
|
||||||
|
|
||||||
|
if sig != nil {
|
||||||
|
author, err = GetUserByEmail(sig.Email)
|
||||||
|
if err != nil && !IsErrUserNotExist(err) {
|
||||||
|
return fmt.Errorf("GetUserByEmail: %v", err)
|
||||||
|
}
|
||||||
|
createdAt = sig.When
|
||||||
|
}
|
||||||
|
|
||||||
|
commitsCount, err := commit.CommitsCount()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CommitsCount: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rel == nil {
|
||||||
|
rel = &Release{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Title: "",
|
||||||
|
TagName: tagName,
|
||||||
|
LowerTagName: strings.ToLower(tagName),
|
||||||
|
Target: "",
|
||||||
|
Sha1: commit.ID.String(),
|
||||||
|
NumCommits: commitsCount,
|
||||||
|
Note: "",
|
||||||
|
IsDraft: false,
|
||||||
|
IsPrerelease: false,
|
||||||
|
IsTag: true,
|
||||||
|
Created: createdAt,
|
||||||
|
CreatedUnix: createdAt.Unix(),
|
||||||
|
}
|
||||||
|
if author != nil {
|
||||||
|
rel.PublisherID = author.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = x.InsertOne(rel); err != nil {
|
||||||
|
return fmt.Errorf("InsertOne: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rel.Sha1 = commit.ID.String()
|
||||||
|
rel.Created = createdAt
|
||||||
|
rel.CreatedUnix = createdAt.Unix()
|
||||||
|
rel.NumCommits = commitsCount
|
||||||
|
rel.IsDraft = false
|
||||||
|
if rel.IsTag && author != nil {
|
||||||
|
rel.PublisherID = author.ID
|
||||||
|
}
|
||||||
|
if _, err = x.Id(rel.ID).AllCols().Update(rel); err != nil {
|
||||||
|
return fmt.Errorf("Update: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
|
func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
|
||||||
isNewRef := opts.OldCommitID == git.EmptySHA
|
isNewRef := opts.OldCommitID == git.EmptySHA
|
||||||
isDelRef := opts.NewCommitID == git.EmptySHA
|
isDelRef := opts.NewCommitID == git.EmptySHA
|
||||||
@@ -106,23 +209,31 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
|
|||||||
return nil, fmt.Errorf("GetRepositoryByName: %v", err)
|
return nil, fmt.Errorf("GetRepositoryByName: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isDelRef {
|
|
||||||
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s",
|
|
||||||
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
|
|
||||||
return repo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(repoPath)
|
gitRepo, err := git.OpenRepository(repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("OpenRepository: %v", err)
|
return nil, fmt.Errorf("OpenRepository: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isDelRef {
|
||||||
|
// Tag has been deleted
|
||||||
|
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||||
|
err = pushUpdateDeleteTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s",
|
||||||
|
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
|
|
||||||
if err = repo.UpdateSize(); err != nil {
|
if err = repo.UpdateSize(); err != nil {
|
||||||
log.Error(4, "Failed to update size for repository: %v", err)
|
log.Error(4, "Failed to update size for repository: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push tags.
|
// Push tags.
|
||||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||||
|
pushUpdateAddTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
|
||||||
if err := CommitRepoAction(CommitRepoActionOptions{
|
if err := CommitRepoAction(CommitRepoActionOptions{
|
||||||
PusherName: opts.PusherName,
|
PusherName: opts.PusherName,
|
||||||
RepoOwnerID: owner.ID,
|
RepoOwnerID: owner.ID,
|
||||||
|
|||||||
@@ -1205,6 +1205,9 @@ type UserCommit struct {
|
|||||||
|
|
||||||
// ValidateCommitWithEmail check if author's e-mail of commit is corresponding to a user.
|
// ValidateCommitWithEmail check if author's e-mail of commit is corresponding to a user.
|
||||||
func ValidateCommitWithEmail(c *git.Commit) *User {
|
func ValidateCommitWithEmail(c *git.Commit) *User {
|
||||||
|
if c.Author == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
u, err := GetUserByEmail(c.Author.Email)
|
u, err := GetUserByEmail(c.Author.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -1223,11 +1226,15 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
|
|||||||
for e != nil {
|
for e != nil {
|
||||||
c := e.Value.(*git.Commit)
|
c := e.Value.(*git.Commit)
|
||||||
|
|
||||||
if v, ok := emails[c.Author.Email]; !ok {
|
if c.Author != nil {
|
||||||
u, _ = GetUserByEmail(c.Author.Email)
|
if v, ok := emails[c.Author.Email]; !ok {
|
||||||
emails[c.Author.Email] = u
|
u, _ = GetUserByEmail(c.Author.Email)
|
||||||
|
emails[c.Author.Email] = u
|
||||||
|
} else {
|
||||||
|
u = v
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
u = v
|
u = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
newCommits.PushBack(UserCommit{
|
newCommits.PushBack(UserCommit{
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ func Contexter() macaron.Handler {
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`, map[string]string{
|
`, map[string]string{
|
||||||
"GoGetImport": path.Join(setting.Domain, setting.AppSubURL, ctx.Link),
|
"GoGetImport": ComposeGoGetImport(ownerName, strings.TrimSuffix(repoName, ".git")),
|
||||||
"CloneLink": models.ComposeHTTPSCloneURL(ownerName, repoName),
|
"CloneLink": models.ComposeHTTPSCloneURL(ownerName, repoName),
|
||||||
"GoDocDirectory": prefix + "{/dir}",
|
"GoDocDirectory": prefix + "{/dir}",
|
||||||
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
||||||
|
|||||||
@@ -124,21 +124,23 @@ func RetrieveBaseRepo(ctx *Context, repo *models.Repository) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// composeGoGetImport returns go-get-import meta content.
|
// ComposeGoGetImport returns go-get-import meta content.
|
||||||
func composeGoGetImport(owner, repo string) string {
|
func ComposeGoGetImport(owner, repo string) string {
|
||||||
return path.Join(setting.Domain, setting.AppSubURL, owner, repo)
|
return path.Join(setting.Domain, setting.AppSubURL, owner, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// earlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
// EarlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
||||||
// if user does not have actual access to the requested repository,
|
// if user does not have actual access to the requested repository,
|
||||||
// or the owner or repository does not exist at all.
|
// or the owner or repository does not exist at all.
|
||||||
// This is particular a workaround for "go get" command which does not respect
|
// This is particular a workaround for "go get" command which does not respect
|
||||||
// .netrc file.
|
// .netrc file.
|
||||||
func earlyResponseForGoGetMeta(ctx *Context) {
|
func EarlyResponseForGoGetMeta(ctx *Context) {
|
||||||
|
username := ctx.Params(":username")
|
||||||
|
reponame := ctx.Params(":reponame")
|
||||||
ctx.PlainText(200, []byte(com.Expand(`<meta name="go-import" content="{GoGetImport} git {CloneLink}">`,
|
ctx.PlainText(200, []byte(com.Expand(`<meta name="go-import" content="{GoGetImport} git {CloneLink}">`,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"GoGetImport": composeGoGetImport(ctx.Params(":username"), strings.TrimSuffix(ctx.Params(":reponame"), ".git")),
|
"GoGetImport": ComposeGoGetImport(username, strings.TrimSuffix(reponame, ".git")),
|
||||||
"CloneLink": models.ComposeHTTPSCloneURL(ctx.Params(":username"), ctx.Params(":reponame")),
|
"CloneLink": models.ComposeHTTPSCloneURL(username, reponame),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,6 +164,75 @@ func RedirectToRepo(ctx *Context, redirectRepoID int64) {
|
|||||||
ctx.Redirect(redirectPath)
|
ctx.Redirect(redirectPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepoIDAssignment returns an macaron handler which assigns the repo to the context.
|
||||||
|
func RepoIDAssignment() macaron.Handler {
|
||||||
|
return func(ctx *Context) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
repoID := ctx.ParamsInt64(":repoid")
|
||||||
|
|
||||||
|
// Get repository.
|
||||||
|
repo, err := models.GetRepositoryByID(repoID)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrRepoNotExist(err) {
|
||||||
|
ctx.Handle(404, "GetRepositoryByID", nil)
|
||||||
|
} else {
|
||||||
|
ctx.Handle(500, "GetRepositoryByID", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = repo.GetOwner(); err != nil {
|
||||||
|
ctx.Handle(500, "GetOwner", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Admin has super access.
|
||||||
|
if ctx.IsSigned && ctx.User.IsAdmin {
|
||||||
|
ctx.Repo.AccessMode = models.AccessModeOwner
|
||||||
|
} else {
|
||||||
|
var userID int64
|
||||||
|
if ctx.User != nil {
|
||||||
|
userID = ctx.User.ID
|
||||||
|
}
|
||||||
|
mode, err := models.AccessLevel(userID, repo)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "AccessLevel", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Repo.AccessMode = mode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check access.
|
||||||
|
if ctx.Repo.AccessMode == models.AccessModeNone {
|
||||||
|
if ctx.Query("go-get") == "1" {
|
||||||
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Handle(404, "no access right", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["HasAccess"] = true
|
||||||
|
|
||||||
|
if repo.IsMirror {
|
||||||
|
ctx.Repo.Mirror, err = models.GetMirrorByRepoID(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "GetMirror", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["MirrorEnablePrune"] = ctx.Repo.Mirror.EnablePrune
|
||||||
|
ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
|
||||||
|
ctx.Data["Mirror"] = ctx.Repo.Mirror
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Repo.Repository = repo
|
||||||
|
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
|
||||||
|
ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RepoAssignment returns a macaron to handle repository assignment
|
// RepoAssignment returns a macaron to handle repository assignment
|
||||||
func RepoAssignment() macaron.Handler {
|
func RepoAssignment() macaron.Handler {
|
||||||
return func(ctx *Context) {
|
return func(ctx *Context) {
|
||||||
@@ -181,7 +252,7 @@ func RepoAssignment() macaron.Handler {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
if ctx.Query("go-get") == "1" {
|
if ctx.Query("go-get") == "1" {
|
||||||
earlyResponseForGoGetMeta(ctx)
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Handle(404, "GetUserByName", nil)
|
ctx.Handle(404, "GetUserByName", nil)
|
||||||
@@ -203,7 +274,7 @@ func RepoAssignment() macaron.Handler {
|
|||||||
RedirectToRepo(ctx, redirectRepoID)
|
RedirectToRepo(ctx, redirectRepoID)
|
||||||
} else if models.IsErrRepoRedirectNotExist(err) {
|
} else if models.IsErrRepoRedirectNotExist(err) {
|
||||||
if ctx.Query("go-get") == "1" {
|
if ctx.Query("go-get") == "1" {
|
||||||
earlyResponseForGoGetMeta(ctx)
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Handle(404, "GetRepositoryByName", nil)
|
ctx.Handle(404, "GetRepositoryByName", nil)
|
||||||
@@ -236,7 +307,7 @@ func RepoAssignment() macaron.Handler {
|
|||||||
// Check access.
|
// Check access.
|
||||||
if ctx.Repo.AccessMode == models.AccessModeNone {
|
if ctx.Repo.AccessMode == models.AccessModeNone {
|
||||||
if ctx.Query("go-get") == "1" {
|
if ctx.Query("go-get") == "1" {
|
||||||
earlyResponseForGoGetMeta(ctx)
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Handle(404, "no access right", err)
|
ctx.Handle(404, "no access right", err)
|
||||||
@@ -275,7 +346,16 @@ func RepoAssignment() macaron.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Tags"] = tags
|
ctx.Data["Tags"] = tags
|
||||||
ctx.Repo.Repository.NumTags = len(tags)
|
|
||||||
|
count, err := models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{
|
||||||
|
IncludeDrafts: false,
|
||||||
|
IncludeTags: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "GetReleaseCountByRepoID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Repo.Repository.NumReleases = int(count)
|
||||||
|
|
||||||
ctx.Data["Title"] = owner.Name + "/" + repo.Name
|
ctx.Data["Title"] = owner.Name + "/" + repo.Name
|
||||||
ctx.Data["Repository"] = repo
|
ctx.Data["Repository"] = repo
|
||||||
@@ -284,6 +364,11 @@ func RepoAssignment() macaron.Handler {
|
|||||||
ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin()
|
ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin()
|
||||||
ctx.Data["IsRepositoryWriter"] = ctx.Repo.IsWriter()
|
ctx.Data["IsRepositoryWriter"] = ctx.Repo.IsWriter()
|
||||||
|
|
||||||
|
if ctx.Data["CanSignedUserFork"], err = ctx.Repo.Repository.CanUserFork(ctx.User); err != nil {
|
||||||
|
ctx.Handle(500, "CanUserFork", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["DisableSSH"] = setting.SSH.Disabled
|
ctx.Data["DisableSSH"] = setting.SSH.Disabled
|
||||||
ctx.Data["ExposeAnonSSH"] = setting.SSH.ExposeAnonymous
|
ctx.Data["ExposeAnonSSH"] = setting.SSH.ExposeAnonymous
|
||||||
ctx.Data["DisableHTTP"] = setting.Repository.DisableHTTPGit
|
ctx.Data["DisableHTTP"] = setting.Repository.DisableHTTPGit
|
||||||
@@ -355,7 +440,7 @@ func RepoAssignment() macaron.Handler {
|
|||||||
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
|
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
|
||||||
|
|
||||||
if ctx.Query("go-get") == "1" {
|
if ctx.Query("go-get") == "1" {
|
||||||
ctx.Data["GoGetImport"] = composeGoGetImport(owner.Name, repo.Name)
|
ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name)
|
||||||
prefix := setting.AppURL + path.Join(owner.Name, repo.Name, "src", ctx.Repo.BranchName)
|
prefix := setting.AppURL + path.Join(owner.Name, repo.Name, "src", ctx.Repo.BranchName)
|
||||||
ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
|
ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
|
||||||
ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
|
ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
|
||||||
@@ -529,6 +614,15 @@ func CheckUnit(unitType models.UnitType) macaron.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckAnyUnit will check whether any of the unit types are enabled
|
||||||
|
func CheckAnyUnit(unitTypes ...models.UnitType) macaron.Handler {
|
||||||
|
return func(ctx *Context) {
|
||||||
|
if !ctx.Repo.Repository.AnyUnitEnabled(unitTypes...) {
|
||||||
|
ctx.Handle(404, "CheckAnyUnit", fmt.Errorf("%s: %v", ctx.Tr("units.error.unit_not_allowed"), unitTypes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GitHookService checks if repository Git hooks service has been enabled.
|
// GitHookService checks if repository Git hooks service has been enabled.
|
||||||
func GitHookService() macaron.Handler {
|
func GitHookService() macaron.Handler {
|
||||||
return func(ctx *Context) {
|
return func(ctx *Context) {
|
||||||
|
|||||||
@@ -70,10 +70,7 @@ func (s *ContentStore) Put(meta *models.LFSMetaObject, r io.Reader) error {
|
|||||||
return errHashMismatch
|
return errHashMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Rename(tmpPath, path); err != nil {
|
return os.Rename(tmpPath, path)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exists returns true if the object exists in the content store.
|
// Exists returns true if the object exists in the content store.
|
||||||
|
|||||||
@@ -110,10 +110,7 @@ func (w *FileLogWriter) StartLogger() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.mw.SetFd(fd)
|
w.mw.SetFd(fd)
|
||||||
if err = w.initFd(); err != nil {
|
return w.initFd()
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *FileLogWriter) docheck(size int) {
|
func (w *FileLogWriter) docheck(size int) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
@@ -30,18 +31,18 @@ type Message struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMessageFrom creates new mail message object with custom From header.
|
// NewMessageFrom creates new mail message object with custom From header.
|
||||||
func NewMessageFrom(to []string, from, subject, body string) *Message {
|
func NewMessageFrom(to []string, fromDisplayName, fromAddress, subject, body string) *Message {
|
||||||
log.Trace("NewMessageFrom (body):\n%s", body)
|
log.Trace("NewMessageFrom (body):\n%s", body)
|
||||||
|
|
||||||
msg := gomail.NewMessage()
|
msg := gomail.NewMessage()
|
||||||
msg.SetHeader("From", from)
|
msg.SetAddressHeader("From", fromAddress, fromDisplayName)
|
||||||
msg.SetHeader("To", to...)
|
msg.SetHeader("To", to...)
|
||||||
msg.SetHeader("Subject", subject)
|
msg.SetHeader("Subject", subject)
|
||||||
msg.SetDateHeader("Date", time.Now())
|
msg.SetDateHeader("Date", time.Now())
|
||||||
|
|
||||||
plainBody, err := html2text.FromString(body)
|
plainBody, err := html2text.FromString(body)
|
||||||
if err != nil || setting.MailService.SendAsPlainText {
|
if err != nil || setting.MailService.SendAsPlainText {
|
||||||
if strings.Contains(body[:100], "<html>") {
|
if strings.Contains(base.TruncateString(body, 100), "<html>") {
|
||||||
log.Warn("Mail contains HTML but configured to send as plain text.")
|
log.Warn("Mail contains HTML but configured to send as plain text.")
|
||||||
}
|
}
|
||||||
msg.SetBody("text/plain", plainBody)
|
msg.SetBody("text/plain", plainBody)
|
||||||
@@ -57,7 +58,7 @@ func NewMessageFrom(to []string, from, subject, body string) *Message {
|
|||||||
|
|
||||||
// NewMessage creates new mail message object with default From header.
|
// NewMessage creates new mail message object with default From header.
|
||||||
func NewMessage(to []string, subject, body string) *Message {
|
func NewMessage(to []string, subject, body string) *Message {
|
||||||
return NewMessageFrom(to, setting.MailService.From, subject, body)
|
return NewMessageFrom(to, setting.MailService.FromName, setting.MailService.FromEmail, subject, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
type loginAuth struct {
|
type loginAuth struct {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@@ -431,7 +432,7 @@ var (
|
|||||||
}{
|
}{
|
||||||
DisableDiffHighlight: false,
|
DisableDiffHighlight: false,
|
||||||
MaxGitDiffLines: 1000,
|
MaxGitDiffLines: 1000,
|
||||||
MaxGitDiffLineCharacters: 500,
|
MaxGitDiffLineCharacters: 5000,
|
||||||
MaxGitDiffFiles: 100,
|
MaxGitDiffFiles: 100,
|
||||||
GCArgs: []string{},
|
GCArgs: []string{},
|
||||||
Timeout: struct {
|
Timeout: struct {
|
||||||
@@ -657,6 +658,12 @@ func NewContext() {
|
|||||||
// This value is empty if site does not have sub-url.
|
// This value is empty if site does not have sub-url.
|
||||||
AppSubURL = strings.TrimSuffix(url.Path, "/")
|
AppSubURL = strings.TrimSuffix(url.Path, "/")
|
||||||
AppSubURLDepth = strings.Count(AppSubURL, "/")
|
AppSubURLDepth = strings.Count(AppSubURL, "/")
|
||||||
|
// Check if Domain differs from AppURL domain than update it to AppURL's domain
|
||||||
|
// TODO: Can be replaced with url.Hostname() when minimal GoLang version is 1.8
|
||||||
|
urlHostname := strings.SplitN(url.Host, ":", 2)[0]
|
||||||
|
if urlHostname != Domain && net.ParseIP(urlHostname) == nil {
|
||||||
|
Domain = urlHostname
|
||||||
|
}
|
||||||
|
|
||||||
var defaultLocalURL string
|
var defaultLocalURL string
|
||||||
switch Protocol {
|
switch Protocol {
|
||||||
@@ -1274,6 +1281,7 @@ type Mailer struct {
|
|||||||
QueueLength int
|
QueueLength int
|
||||||
Name string
|
Name string
|
||||||
From string
|
From string
|
||||||
|
FromName string
|
||||||
FromEmail string
|
FromEmail string
|
||||||
SendAsPlainText bool
|
SendAsPlainText bool
|
||||||
|
|
||||||
@@ -1332,6 +1340,7 @@ func newMailService() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(4, "Invalid mailer.FROM (%s): %v", MailService.From, err)
|
log.Fatal(4, "Invalid mailer.FROM (%s): %v", MailService.From, err)
|
||||||
}
|
}
|
||||||
|
MailService.FromName = parsed.Name
|
||||||
MailService.FromEmail = parsed.Address
|
MailService.FromEmail = parsed.Address
|
||||||
|
|
||||||
log.Info("Mail Service Enabled")
|
log.Info("Mail Service Enabled")
|
||||||
|
|||||||
@@ -625,7 +625,7 @@ function initProtectedBranch() {
|
|||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
$.post($this.data('url'), {
|
$.post($this.data('url'), {
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"canPush": true,
|
"canPush": false,
|
||||||
"branchName": $this.val(),
|
"branchName": $this.val(),
|
||||||
},
|
},
|
||||||
function (data) {
|
function (data) {
|
||||||
@@ -642,7 +642,7 @@ function initProtectedBranch() {
|
|||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
$.post($this.data('url'), {
|
$.post($this.data('url'), {
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"canPush": false,
|
"canPush": true,
|
||||||
"branchName": $this.data('val'),
|
"branchName": $this.data('val'),
|
||||||
},
|
},
|
||||||
function (data) {
|
function (data) {
|
||||||
@@ -1456,7 +1456,7 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
// Emojify
|
// Emojify
|
||||||
emojify.setConfig({
|
emojify.setConfig({
|
||||||
img_dir: suburl + '/plugins/emojify/images',
|
img_dir: suburl + '/vendor/plugins/emojify/images',
|
||||||
ignore_emoticons: true
|
ignore_emoticons: true
|
||||||
});
|
});
|
||||||
var hasEmoji = document.getElementsByClassName('has-emoji');
|
var hasEmoji = document.getElementsByClassName('has-emoji');
|
||||||
|
|||||||
2
public/vendor/plugins/autolink/autolink.js
vendored
2
public/vendor/plugins/autolink/autolink.js
vendored
@@ -26,7 +26,7 @@
|
|||||||
re.lastIndex = 0;
|
re.lastIndex = 0;
|
||||||
var results = re.exec(node.textContent);
|
var results = re.exec(node.textContent);
|
||||||
if(results !== null) {
|
if(results !== null) {
|
||||||
if($(node).parents().filter('pre>code').length === 0) {
|
if($(node).parents().filter('code').length === 0) {
|
||||||
$(node).replaceWith(
|
$(node).replaceWith(
|
||||||
$('<span />').html(
|
$('<span />').html(
|
||||||
node.nodeValue.replace(re, '<a href="$1">$1</a>')
|
node.nodeValue.replace(re, '<a href="$1">$1</a>')
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
api "code.gitea.io/sdk/gitea"
|
api "code.gitea.io/sdk/gitea"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
@@ -36,6 +34,7 @@ func GetRelease(ctx *context.APIContext) {
|
|||||||
func ListReleases(ctx *context.APIContext) {
|
func ListReleases(ctx *context.APIContext) {
|
||||||
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{
|
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{
|
||||||
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite,
|
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite,
|
||||||
|
IncludeTags: false,
|
||||||
}, 1, 2147483647)
|
}, 1, 2147483647)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, "GetReleasesByRepoID", err)
|
ctx.Error(500, "GetReleasesByRepoID", err)
|
||||||
@@ -62,43 +61,49 @@ func CreateRelease(ctx *context.APIContext, form api.CreateReleaseOption) {
|
|||||||
ctx.Status(404)
|
ctx.Status(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag, err := ctx.Repo.GitRepo.GetTag(form.TagName)
|
rel, err := models.GetRelease(ctx.Repo.Repository.ID, form.TagName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, "GetTag", err)
|
if !models.IsErrReleaseNotExist(err) {
|
||||||
return
|
ctx.Handle(500, "GetRelease", err)
|
||||||
}
|
return
|
||||||
commit, err := tag.Commit()
|
}
|
||||||
if err != nil {
|
rel = &models.Release{
|
||||||
ctx.Error(500, "Commit", err)
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
return
|
PublisherID: ctx.User.ID,
|
||||||
}
|
Publisher: ctx.User,
|
||||||
commitsCount, err := commit.CommitsCount()
|
TagName: form.TagName,
|
||||||
if err != nil {
|
Target: form.Target,
|
||||||
ctx.Error(500, "CommitsCount", err)
|
Title: form.Title,
|
||||||
return
|
Note: form.Note,
|
||||||
}
|
IsDraft: form.IsDraft,
|
||||||
rel := &models.Release{
|
IsPrerelease: form.IsPrerelease,
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
IsTag: false,
|
||||||
PublisherID: ctx.User.ID,
|
}
|
||||||
Publisher: ctx.User,
|
if err := models.CreateRelease(ctx.Repo.GitRepo, rel, nil); err != nil {
|
||||||
TagName: form.TagName,
|
if models.IsErrReleaseAlreadyExist(err) {
|
||||||
LowerTagName: strings.ToLower(form.TagName),
|
ctx.Status(409)
|
||||||
Target: form.Target,
|
} else {
|
||||||
Title: form.Title,
|
ctx.Error(500, "CreateRelease", err)
|
||||||
Sha1: commit.ID.String(),
|
}
|
||||||
NumCommits: commitsCount,
|
return
|
||||||
Note: form.Note,
|
}
|
||||||
IsDraft: form.IsDraft,
|
} else {
|
||||||
IsPrerelease: form.IsPrerelease,
|
if !rel.IsTag {
|
||||||
CreatedUnix: commit.Author.When.Unix(),
|
ctx.Status(409)
|
||||||
}
|
return
|
||||||
if err := models.CreateRelease(ctx.Repo.GitRepo, rel, nil); err != nil {
|
}
|
||||||
if models.IsErrReleaseAlreadyExist(err) {
|
|
||||||
ctx.Status(409)
|
rel.Title = form.Title
|
||||||
} else {
|
rel.Note = form.Note
|
||||||
ctx.Error(500, "CreateRelease", err)
|
rel.IsDraft = form.IsDraft
|
||||||
|
rel.IsPrerelease = form.IsPrerelease
|
||||||
|
rel.PublisherID = ctx.User.ID
|
||||||
|
rel.IsTag = false
|
||||||
|
|
||||||
|
if err = models.UpdateRelease(ctx.Repo.GitRepo, rel, nil); err != nil {
|
||||||
|
ctx.Handle(500, "UpdateRelease", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ctx.JSON(201, rel.APIFormat())
|
ctx.JSON(201, rel.APIFormat())
|
||||||
}
|
}
|
||||||
@@ -111,11 +116,12 @@ func EditRelease(ctx *context.APIContext, form api.EditReleaseOption) {
|
|||||||
}
|
}
|
||||||
id := ctx.ParamsInt64(":id")
|
id := ctx.ParamsInt64(":id")
|
||||||
rel, err := models.GetReleaseByID(id)
|
rel, err := models.GetReleaseByID(id)
|
||||||
if err != nil {
|
if err != nil && !models.IsErrReleaseNotExist(err) {
|
||||||
ctx.Error(500, "GetReleaseByID", err)
|
ctx.Error(500, "GetReleaseByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if rel.RepoID != ctx.Repo.Repository.ID {
|
if err != nil && models.IsErrReleaseNotExist(err) ||
|
||||||
|
rel.IsTag || rel.RepoID != ctx.Repo.Repository.ID {
|
||||||
ctx.Status(404)
|
ctx.Status(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -162,12 +168,13 @@ func DeleteRelease(ctx *context.APIContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
id := ctx.ParamsInt64(":id")
|
id := ctx.ParamsInt64(":id")
|
||||||
release, err := models.GetReleaseByID(id)
|
rel, err := models.GetReleaseByID(id)
|
||||||
if err != nil {
|
if err != nil && !models.IsErrReleaseNotExist(err) {
|
||||||
ctx.Error(500, "GetReleaseByID", err)
|
ctx.Error(500, "GetReleaseByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if release.RepoID != ctx.Repo.Repository.ID {
|
if err != nil && models.IsErrReleaseNotExist(err) ||
|
||||||
|
rel.IsTag || rel.RepoID != ctx.Repo.Repository.ID {
|
||||||
ctx.Status(404)
|
ctx.Status(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ package user
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Unknwon/com"
|
|
||||||
|
|
||||||
api "code.gitea.io/sdk/gitea"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
"code.gitea.io/gitea/modules/markdown"
|
||||||
|
api "code.gitea.io/sdk/gitea"
|
||||||
|
|
||||||
|
"github.com/Unknwon/com"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Search search users
|
// Search search users
|
||||||
@@ -50,7 +50,7 @@ func Search(ctx *context.APIContext) {
|
|||||||
ID: users[i].ID,
|
ID: users[i].ID,
|
||||||
UserName: users[i].Name,
|
UserName: users[i].Name,
|
||||||
AvatarURL: users[i].AvatarLink(),
|
AvatarURL: users[i].AvatarLink(),
|
||||||
FullName: users[i].FullName,
|
FullName: markdown.Sanitize(users[i].FullName),
|
||||||
}
|
}
|
||||||
if ctx.IsSigned {
|
if ctx.IsSigned {
|
||||||
results[i].Email = users[i].Email
|
results[i].Email = users[i].Email
|
||||||
|
|||||||
@@ -20,11 +20,6 @@ func GetProtectedBranchBy(ctx *macaron.Context) {
|
|||||||
"err": err.Error(),
|
"err": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
} else if protectBranch != nil {
|
|
||||||
ctx.JSON(200, protectBranch)
|
|
||||||
} else {
|
|
||||||
ctx.JSON(200, &models.ProtectedBranch{
|
|
||||||
CanPush: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
ctx.JSON(200, protectBranch)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,35 +22,15 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/Unknwon/com"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func composeGoGetImport(owner, repo, sub string) string {
|
|
||||||
return path.Join(setting.Domain, setting.AppSubURL, owner, repo, sub)
|
|
||||||
}
|
|
||||||
|
|
||||||
// earlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
|
||||||
// if user does not have actual access to the requested repository,
|
|
||||||
// or the owner or repository does not exist at all.
|
|
||||||
// This is particular a workaround for "go get" command which does not respect
|
|
||||||
// .netrc file.
|
|
||||||
func earlyResponseForGoGetMeta(ctx *context.Context, username, reponame, subpath string) {
|
|
||||||
ctx.PlainText(200, []byte(com.Expand(`<meta name="go-import" content="{GoGetImport} git {CloneLink}">`,
|
|
||||||
map[string]string{
|
|
||||||
"GoGetImport": composeGoGetImport(username, reponame, subpath),
|
|
||||||
"CloneLink": models.ComposeHTTPSCloneURL(username, reponame),
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP implmentation git smart HTTP protocol
|
// HTTP implmentation git smart HTTP protocol
|
||||||
func HTTP(ctx *context.Context) {
|
func HTTP(ctx *context.Context) {
|
||||||
username := ctx.Params(":username")
|
username := ctx.Params(":username")
|
||||||
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
|
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
|
||||||
subpath := ctx.Params("*")
|
|
||||||
|
|
||||||
if ctx.Query("go-get") == "1" {
|
if ctx.Query("go-get") == "1" {
|
||||||
earlyResponseForGoGetMeta(ctx, username, reponame, subpath)
|
context.EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,19 +139,28 @@ func HTTP(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if authUser == nil {
|
if authUser == nil {
|
||||||
authUser, err = models.GetUserByName(authUsername)
|
isUsernameToken := len(authPasswd) == 0 || authPasswd == "x-oauth-basic"
|
||||||
|
|
||||||
if err != nil {
|
// Assume username is token
|
||||||
if models.IsErrUserNotExist(err) {
|
authToken := authUsername
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
|
||||||
} else {
|
if !isUsernameToken {
|
||||||
ctx.Handle(http.StatusInternalServerError, "GetUserByName", err)
|
// Assume password is token
|
||||||
|
authToken = authPasswd
|
||||||
|
|
||||||
|
authUser, err = models.GetUserByName(authUsername)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
|
} else {
|
||||||
|
ctx.Handle(http.StatusInternalServerError, "GetUserByName", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume password is a token.
|
// Assume password is a token.
|
||||||
token, err := models.GetAccessTokenBySHA(authPasswd)
|
token, err := models.GetAccessTokenBySHA(authToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
@@ -181,7 +170,13 @@ func HTTP(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if authUser.ID != token.UID {
|
if isUsernameToken {
|
||||||
|
authUser, err = models.GetUserByID(token.UID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(http.StatusInternalServerError, "GetUserByID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if authUser.ID != token.UID {
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
ctx.HandleText(http.StatusUnauthorized, "invalid credentials")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -190,7 +185,6 @@ func HTTP(ctx *context.Context) {
|
|||||||
if err = models.UpdateAccessToken(token); err != nil {
|
if err = models.UpdateAccessToken(token); err != nil {
|
||||||
ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
|
ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_, err = models.GetTwoFactorByUID(authUser.ID)
|
_, err = models.GetTwoFactorByUID(authUser.ID)
|
||||||
|
|
||||||
|
|||||||
@@ -676,11 +676,16 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
func getActionIssue(ctx *context.Context) *models.Issue {
|
func getActionIssue(ctx *context.Context) *models.Issue {
|
||||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrIssueNotExist(err) {
|
ctx.NotFoundOrServerError("GetIssueByIndex", models.IsErrIssueNotExist, err)
|
||||||
ctx.Error(404, "GetIssueByIndex")
|
return nil
|
||||||
} else {
|
}
|
||||||
ctx.Handle(500, "GetIssueByIndex", err)
|
if issue.IsPull && !ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests) ||
|
||||||
}
|
!issue.IsPull && !ctx.Repo.Repository.UnitEnabled(models.UnitTypeIssues) {
|
||||||
|
ctx.Handle(404, "IssueOrPullRequestUnitNotAllowed", nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err = issue.LoadAttributes(); err != nil {
|
||||||
|
ctx.Handle(500, "LoadAttributes", nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return issue
|
return issue
|
||||||
@@ -705,6 +710,19 @@ func getActionIssues(ctx *context.Context) []*models.Issue {
|
|||||||
ctx.Handle(500, "GetIssuesByIDs", err)
|
ctx.Handle(500, "GetIssuesByIDs", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// Check access rights for all issues
|
||||||
|
issueUnitEnabled := ctx.Repo.Repository.UnitEnabled(models.UnitTypeIssues)
|
||||||
|
prUnitEnabled := ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests)
|
||||||
|
for _, issue := range issues {
|
||||||
|
if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled {
|
||||||
|
ctx.Handle(404, "IssueOrPullRequestUnitNotAllowed", nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err = issue.LoadAttributes(); err != nil {
|
||||||
|
ctx.Handle(500, "LoadAttributes", nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
return issues
|
return issues
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,9 +858,8 @@ func UpdateIssueStatus(ctx *context.Context) {
|
|||||||
|
|
||||||
// NewComment create a comment for issue
|
// NewComment create a comment for issue
|
||||||
func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
issue := getActionIssue(ctx)
|
||||||
if err != nil {
|
if ctx.Written() {
|
||||||
ctx.NotFoundOrServerError("GetIssueByIndex", models.IsErrIssueNotExist, err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,7 +886,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
|||||||
|
|
||||||
if form.Status == "reopen" && issue.IsPull {
|
if form.Status == "reopen" && issue.IsPull {
|
||||||
pull := issue.PullRequest
|
pull := issue.PullRequest
|
||||||
pr, err = models.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch)
|
pr, err := models.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !models.IsErrPullRequestNotExist(err) {
|
if !models.IsErrPullRequestNotExist(err) {
|
||||||
ctx.Handle(500, "GetUnmergedPullRequest", err)
|
ctx.Handle(500, "GetUnmergedPullRequest", err)
|
||||||
@@ -891,7 +908,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
|||||||
if pr != nil {
|
if pr != nil {
|
||||||
ctx.Flash.Info(ctx.Tr("repo.pulls.open_unmerged_pull_exists", pr.Index))
|
ctx.Flash.Info(ctx.Tr("repo.pulls.open_unmerged_pull_exists", pr.Index))
|
||||||
} else {
|
} else {
|
||||||
if err = issue.ChangeStatus(ctx.User, ctx.Repo.Repository, form.Status == "close"); err != nil {
|
if err := issue.ChangeStatus(ctx.User, ctx.Repo.Repository, form.Status == "close"); err != nil {
|
||||||
log.Error(4, "ChangeStatus: %v", err)
|
log.Error(4, "ChangeStatus: %v", err)
|
||||||
} else {
|
} else {
|
||||||
log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
|
log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
|
||||||
@@ -918,7 +935,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err = models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments)
|
comment, err := models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(500, "CreateIssueComment", err)
|
ctx.Handle(500, "CreateIssueComment", err)
|
||||||
return
|
return
|
||||||
@@ -988,10 +1005,6 @@ func DeleteComment(ctx *context.Context) {
|
|||||||
|
|
||||||
// Milestones render milestones page
|
// Milestones render milestones page
|
||||||
func Milestones(ctx *context.Context) {
|
func Milestones(ctx *context.Context) {
|
||||||
MustEnableIssues(ctx)
|
|
||||||
if ctx.Written() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.milestones")
|
ctx.Data["Title"] = ctx.Tr("repo.milestones")
|
||||||
ctx.Data["PageIsIssueList"] = true
|
ctx.Data["PageIsIssueList"] = true
|
||||||
ctx.Data["PageIsMilestones"] = true
|
ctx.Data["PageIsMilestones"] = true
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ const (
|
|||||||
|
|
||||||
// Labels render issue's labels page
|
// Labels render issue's labels page
|
||||||
func Labels(ctx *context.Context) {
|
func Labels(ctx *context.Context) {
|
||||||
MustEnableIssues(ctx)
|
|
||||||
if ctx.Written() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.labels")
|
ctx.Data["Title"] = ctx.Tr("repo.labels")
|
||||||
ctx.Data["PageIsIssueList"] = true
|
ctx.Data["PageIsIssueList"] = true
|
||||||
ctx.Data["PageIsLabels"] = true
|
ctx.Data["PageIsLabels"] = true
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ func IssueWatch(c *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
issueIndex := c.ParamsInt64("index")
|
issue := getActionIssue(c)
|
||||||
issue, err := models.GetIssueByIndex(c.Repo.Repository.ID, issueIndex)
|
if c.Written() {
|
||||||
if err != nil {
|
|
||||||
c.Handle(http.StatusInternalServerError, "GetIssueByIndex", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +31,6 @@ func IssueWatch(c *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/issues/%d", c.Repo.RepoLink, issueIndex)
|
url := fmt.Sprintf("%s/issues/%d", c.Repo.RepoLink, issue.Index)
|
||||||
c.Redirect(url, http.StatusSeeOther)
|
c.Redirect(url, http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ func getForkRepository(ctx *context.Context) *models.Repository {
|
|||||||
ctx.Data["repo_name"] = forkRepo.Name
|
ctx.Data["repo_name"] = forkRepo.Name
|
||||||
ctx.Data["description"] = forkRepo.Description
|
ctx.Data["description"] = forkRepo.Description
|
||||||
ctx.Data["IsPrivate"] = forkRepo.IsPrivate
|
ctx.Data["IsPrivate"] = forkRepo.IsPrivate
|
||||||
|
canForkToUser := forkRepo.OwnerID != ctx.User.ID && !ctx.User.HasForkedRepo(forkRepo.ID)
|
||||||
|
ctx.Data["CanForkToUser"] = canForkToUser
|
||||||
|
|
||||||
if err = forkRepo.GetOwner(); err != nil {
|
if err = forkRepo.GetOwner(); err != nil {
|
||||||
ctx.Handle(500, "GetOwner", err)
|
ctx.Handle(500, "GetOwner", err)
|
||||||
@@ -69,11 +71,23 @@ func getForkRepository(ctx *context.Context) *models.Repository {
|
|||||||
ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name
|
ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name
|
||||||
ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID
|
ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID
|
||||||
|
|
||||||
if err := ctx.User.GetOrganizations(true); err != nil {
|
if err := ctx.User.GetOwnedOrganizations(); err != nil {
|
||||||
ctx.Handle(500, "GetOrganizations", err)
|
ctx.Handle(500, "GetOwnedOrganizations", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Data["Orgs"] = ctx.User.Orgs
|
var orgs []*models.User
|
||||||
|
for _, org := range ctx.User.OwnedOrgs {
|
||||||
|
if forkRepo.OwnerID != org.ID && !org.HasForkedRepo(forkRepo.ID) {
|
||||||
|
orgs = append(orgs, org)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Data["Orgs"] = orgs
|
||||||
|
|
||||||
|
if canForkToUser {
|
||||||
|
ctx.Data["ContextUser"] = ctx.User
|
||||||
|
} else if len(orgs) > 0 {
|
||||||
|
ctx.Data["ContextUser"] = orgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
return forkRepo
|
return forkRepo
|
||||||
}
|
}
|
||||||
@@ -87,7 +101,6 @@ func Fork(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["ContextUser"] = ctx.User
|
|
||||||
ctx.HTML(200, tplFork)
|
ctx.HTML(200, tplFork)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,15 +108,16 @@ func Fork(ctx *context.Context) {
|
|||||||
func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
|
func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||||
ctx.Data["Title"] = ctx.Tr("new_fork")
|
ctx.Data["Title"] = ctx.Tr("new_fork")
|
||||||
|
|
||||||
|
ctxUser := checkContextUser(ctx, form.UID)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
forkRepo := getForkRepository(ctx)
|
forkRepo := getForkRepository(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxUser := checkContextUser(ctx, form.UID)
|
|
||||||
if ctx.Written() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["ContextUser"] = ctxUser
|
ctx.Data["ContextUser"] = ctxUser
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ func Releases(ctx *context.Context) {
|
|||||||
|
|
||||||
opts := models.FindReleasesOptions{
|
opts := models.FindReleasesOptions{
|
||||||
IncludeDrafts: ctx.Repo.IsWriter(),
|
IncludeDrafts: ctx.Repo.IsWriter(),
|
||||||
|
IncludeTags: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts, page, limit)
|
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts, page, limit)
|
||||||
@@ -145,57 +146,61 @@ func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagCreatedUnix int64
|
|
||||||
tag, err := ctx.Repo.GitRepo.GetTag(form.TagName)
|
|
||||||
if err == nil {
|
|
||||||
commit, err := tag.Commit()
|
|
||||||
if err == nil {
|
|
||||||
tagCreatedUnix = commit.Author.When.Unix()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commit, err := ctx.Repo.GitRepo.GetBranchCommit(form.Target)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Handle(500, "GetBranchCommit", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
commitsCount, err := commit.CommitsCount()
|
|
||||||
if err != nil {
|
|
||||||
ctx.Handle(500, "CommitsCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rel := &models.Release{
|
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
|
||||||
PublisherID: ctx.User.ID,
|
|
||||||
Title: form.Title,
|
|
||||||
TagName: form.TagName,
|
|
||||||
Target: form.Target,
|
|
||||||
Sha1: commit.ID.String(),
|
|
||||||
NumCommits: commitsCount,
|
|
||||||
Note: form.Content,
|
|
||||||
IsDraft: len(form.Draft) > 0,
|
|
||||||
IsPrerelease: form.Prerelease,
|
|
||||||
CreatedUnix: tagCreatedUnix,
|
|
||||||
}
|
|
||||||
|
|
||||||
var attachmentUUIDs []string
|
var attachmentUUIDs []string
|
||||||
if setting.AttachmentEnabled {
|
if setting.AttachmentEnabled {
|
||||||
attachmentUUIDs = form.Files
|
attachmentUUIDs = form.Files
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = models.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs); err != nil {
|
rel, err := models.GetRelease(ctx.Repo.Repository.ID, form.TagName)
|
||||||
ctx.Data["Err_TagName"] = true
|
if err != nil {
|
||||||
switch {
|
if !models.IsErrReleaseNotExist(err) {
|
||||||
case models.IsErrReleaseAlreadyExist(err):
|
ctx.Handle(500, "GetRelease", err)
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
|
return
|
||||||
case models.IsErrInvalidTagName(err):
|
}
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form)
|
|
||||||
default:
|
rel := &models.Release{
|
||||||
ctx.Handle(500, "CreateRelease", err)
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
|
PublisherID: ctx.User.ID,
|
||||||
|
Title: form.Title,
|
||||||
|
TagName: form.TagName,
|
||||||
|
Target: form.Target,
|
||||||
|
Note: form.Content,
|
||||||
|
IsDraft: len(form.Draft) > 0,
|
||||||
|
IsPrerelease: form.Prerelease,
|
||||||
|
IsTag: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = models.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs); err != nil {
|
||||||
|
ctx.Data["Err_TagName"] = true
|
||||||
|
switch {
|
||||||
|
case models.IsErrReleaseAlreadyExist(err):
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
|
||||||
|
case models.IsErrInvalidTagName(err):
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form)
|
||||||
|
default:
|
||||||
|
ctx.Handle(500, "CreateRelease", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !rel.IsTag {
|
||||||
|
ctx.Data["Err_TagName"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rel.Title = form.Title
|
||||||
|
rel.Note = form.Content
|
||||||
|
rel.IsDraft = len(form.Draft) > 0
|
||||||
|
rel.IsPrerelease = form.Prerelease
|
||||||
|
rel.PublisherID = ctx.User.ID
|
||||||
|
rel.IsTag = false
|
||||||
|
|
||||||
|
if err = models.UpdateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs); err != nil {
|
||||||
|
ctx.Data["Err_TagName"] = true
|
||||||
|
ctx.Handle(500, "UpdateRelease", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
log.Trace("Release created: %s/%s:%s", ctx.User.LowerName, ctx.Repo.Repository.Name, form.TagName)
|
log.Trace("Release created: %s/%s:%s", ctx.User.LowerName, ctx.Repo.Repository.Name, form.TagName)
|
||||||
|
|
||||||
@@ -246,6 +251,10 @@ func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if rel.IsTag {
|
||||||
|
ctx.Handle(404, "GetRelease", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Data["tag_name"] = rel.TagName
|
ctx.Data["tag_name"] = rel.TagName
|
||||||
ctx.Data["tag_target"] = rel.Target
|
ctx.Data["tag_target"] = rel.Target
|
||||||
ctx.Data["title"] = rel.Title
|
ctx.Data["title"] = rel.Title
|
||||||
@@ -275,8 +284,7 @@ func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) {
|
|||||||
|
|
||||||
// DeleteRelease delete a release
|
// DeleteRelease delete a release
|
||||||
func DeleteRelease(ctx *context.Context) {
|
func DeleteRelease(ctx *context.Context) {
|
||||||
delTag := ctx.QueryBool("delTag")
|
if err := models.DeleteReleaseByID(ctx.QueryInt64("id"), ctx.User, true); err != nil {
|
||||||
if err := models.DeleteReleaseByID(ctx.QueryInt64("id"), ctx.User, delTag); err != nil {
|
|
||||||
ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
|
ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Success(ctx.Tr("repo.release.deletion_success"))
|
ctx.Flash.Success(ctx.Tr("repo.release.deletion_success"))
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ func ProtectedBranchPost(ctx *context.Context) {
|
|||||||
|
|
||||||
canPush := ctx.QueryBool("canPush")
|
canPush := ctx.QueryBool("canPush")
|
||||||
|
|
||||||
if canPush {
|
if !canPush {
|
||||||
if err := ctx.Repo.Repository.AddProtectedBranch(branchName, canPush); err != nil {
|
if err := ctx.Repo.Repository.AddProtectedBranch(branchName, canPush); err != nil {
|
||||||
ctx.Flash.Error(ctx.Tr("repo.settings.add_protected_branch_failed", branchName))
|
ctx.Flash.Error(ctx.Tr("repo.settings.add_protected_branch_failed", branchName))
|
||||||
ctx.JSON(200, map[string]string{
|
ctx.JSON(200, map[string]string{
|
||||||
|
|||||||
@@ -93,16 +93,12 @@ func renderDirectory(ctx *context.Context, treeLink string) {
|
|||||||
if isTextFile {
|
if isTextFile {
|
||||||
d, _ := ioutil.ReadAll(dataRc)
|
d, _ := ioutil.ReadAll(dataRc)
|
||||||
buf = append(buf, d...)
|
buf = append(buf, d...)
|
||||||
newbuf := markup.Render(readmeFile.Name(), buf, treeLink, ctx.Repo.Repository.ComposeMetas())
|
ctx.Data["IsRenderedHTML"] = true
|
||||||
if newbuf != nil {
|
if markup.Type(readmeFile.Name()) != "" {
|
||||||
ctx.Data["IsMarkdown"] = true
|
ctx.Data["FileContent"] = string(markup.Render(readmeFile.Name(), buf, treeLink, ctx.Repo.Repository.ComposeMetas()))
|
||||||
} else {
|
} else {
|
||||||
// FIXME This is the only way to show non-markdown files
|
ctx.Data["FileContent"] = string(bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1))
|
||||||
// instead of a broken "View Raw" link
|
|
||||||
ctx.Data["IsMarkdown"] = true
|
|
||||||
newbuf = bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1)
|
|
||||||
}
|
}
|
||||||
ctx.Data["FileContent"] = string(newbuf)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,15 +184,14 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
|||||||
d, _ := ioutil.ReadAll(dataRc)
|
d, _ := ioutil.ReadAll(dataRc)
|
||||||
buf = append(buf, d...)
|
buf = append(buf, d...)
|
||||||
|
|
||||||
tp := markup.Type(blob.Name())
|
readmeExist := markup.IsReadmeFile(blob.Name())
|
||||||
isSupportedMarkup := tp != ""
|
|
||||||
// FIXME: currently set IsMarkdown for compatible
|
|
||||||
ctx.Data["IsMarkdown"] = isSupportedMarkup
|
|
||||||
|
|
||||||
readmeExist := isSupportedMarkup || markup.IsReadmeFile(blob.Name())
|
|
||||||
ctx.Data["ReadmeExist"] = readmeExist
|
ctx.Data["ReadmeExist"] = readmeExist
|
||||||
if readmeExist && isSupportedMarkup {
|
if markup.Type(blob.Name()) != "" {
|
||||||
|
ctx.Data["IsRenderedHTML"] = true
|
||||||
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
|
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
|
||||||
|
} else if readmeExist {
|
||||||
|
ctx.Data["IsRenderedHTML"] = true
|
||||||
|
ctx.Data["FileContent"] = string(bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1))
|
||||||
} else {
|
} else {
|
||||||
// Building code view blocks with line number on server side.
|
// Building code view blocks with line number on server side.
|
||||||
var fileContent string
|
var fileContent string
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GogsHooksNewPost response for creating webhook
|
// GogsHooksNewPost response for creating webhook
|
||||||
func GogsHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
func GogsHooksNewPost(ctx *context.Context, form auth.NewGogshookForm) {
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
|
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
|
||||||
ctx.Data["PageIsSettingsHooks"] = true
|
ctx.Data["PageIsSettingsHooks"] = true
|
||||||
ctx.Data["PageIsSettingsHooksNew"] = true
|
ctx.Data["PageIsSettingsHooksNew"] = true
|
||||||
@@ -361,7 +361,7 @@ func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GogsHooksEditPost response for editing gogs hook
|
// GogsHooksEditPost response for editing gogs hook
|
||||||
func GogsHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) {
|
func GogsHooksEditPost(ctx *context.Context, form auth.NewGogshookForm) {
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
|
ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
|
||||||
ctx.Data["PageIsSettingsHooks"] = true
|
ctx.Data["PageIsSettingsHooks"] = true
|
||||||
ctx.Data["PageIsSettingsHooksEdit"] = true
|
ctx.Data["PageIsSettingsHooksEdit"] = true
|
||||||
|
|||||||
@@ -416,8 +416,10 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
||||||
m.Get("/migrate", repo.Migrate)
|
m.Get("/migrate", repo.Migrate)
|
||||||
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
||||||
m.Combo("/fork/:repoid").Get(repo.Fork).
|
m.Group("/fork", func() {
|
||||||
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
|
m.Combo("/:repoid").Get(repo.Fork).
|
||||||
|
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
|
||||||
|
}, context.RepoIDAssignment(), context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeCode))
|
||||||
}, reqSignIn)
|
}, reqSignIn)
|
||||||
|
|
||||||
m.Group("/:username/:reponame", func() {
|
m.Group("/:username/:reponame", func() {
|
||||||
@@ -469,12 +471,13 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
|
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
|
||||||
|
|
||||||
m.Group("/:username/:reponame", func() {
|
m.Group("/:username/:reponame", func() {
|
||||||
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
|
|
||||||
// So they can apply their own enable/disable logic on routers.
|
|
||||||
m.Group("/issues", func() {
|
m.Group("/issues", func() {
|
||||||
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
|
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
|
||||||
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
|
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
|
||||||
|
}, context.CheckUnit(models.UnitTypeIssues))
|
||||||
|
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
|
||||||
|
// So they can apply their own enable/disable logic on routers.
|
||||||
|
m.Group("/issues", func() {
|
||||||
m.Group("/:index", func() {
|
m.Group("/:index", func() {
|
||||||
m.Post("/title", repo.UpdateIssueTitle)
|
m.Post("/title", repo.UpdateIssueTitle)
|
||||||
m.Post("/content", repo.UpdateIssueContent)
|
m.Post("/content", repo.UpdateIssueContent)
|
||||||
@@ -482,21 +485,21 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
|
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Post("/labels", repo.UpdateIssueLabel, reqRepoWriter)
|
m.Post("/labels", reqRepoWriter, repo.UpdateIssueLabel)
|
||||||
m.Post("/milestone", repo.UpdateIssueMilestone, reqRepoWriter)
|
m.Post("/milestone", reqRepoWriter, repo.UpdateIssueMilestone)
|
||||||
m.Post("/assignee", repo.UpdateIssueAssignee, reqRepoWriter)
|
m.Post("/assignee", reqRepoWriter, repo.UpdateIssueAssignee)
|
||||||
m.Post("/status", repo.UpdateIssueStatus, reqRepoWriter)
|
m.Post("/status", reqRepoWriter, repo.UpdateIssueStatus)
|
||||||
}, context.CheckUnit(models.UnitTypeIssues))
|
})
|
||||||
m.Group("/comments/:id", func() {
|
m.Group("/comments/:id", func() {
|
||||||
m.Post("", repo.UpdateCommentContent)
|
m.Post("", repo.UpdateCommentContent)
|
||||||
m.Post("/delete", repo.DeleteComment)
|
m.Post("/delete", repo.DeleteComment)
|
||||||
}, context.CheckUnit(models.UnitTypeIssues))
|
}, context.CheckAnyUnit(models.UnitTypeIssues, models.UnitTypePullRequests))
|
||||||
m.Group("/labels", func() {
|
m.Group("/labels", func() {
|
||||||
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||||
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||||
m.Post("/delete", repo.DeleteLabel)
|
m.Post("/delete", repo.DeleteLabel)
|
||||||
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels)
|
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels)
|
||||||
}, reqRepoWriter, context.RepoRef(), context.CheckUnit(models.UnitTypeIssues))
|
}, reqRepoWriter, context.RepoRef(), context.CheckAnyUnit(models.UnitTypeIssues, models.UnitTypePullRequests))
|
||||||
m.Group("/milestones", func() {
|
m.Group("/milestones", func() {
|
||||||
m.Combo("/new").Get(repo.NewMilestone).
|
m.Combo("/new").Get(repo.NewMilestone).
|
||||||
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
||||||
@@ -504,7 +507,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
|
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
|
||||||
m.Get("/:id/:action", repo.ChangeMilestonStatus)
|
m.Get("/:id/:action", repo.ChangeMilestonStatus)
|
||||||
m.Post("/delete", repo.DeleteMilestone)
|
m.Post("/delete", repo.DeleteMilestone)
|
||||||
}, reqRepoWriter, context.RepoRef(), context.CheckUnit(models.UnitTypeIssues))
|
}, reqRepoWriter, context.RepoRef(), context.CheckAnyUnit(models.UnitTypeIssues, models.UnitTypePullRequests))
|
||||||
|
|
||||||
m.Combo("/compare/*", repo.MustAllowPulls, repo.SetEditorconfigIfExists).
|
m.Combo("/compare/*", repo.MustAllowPulls, repo.SetEditorconfigIfExists).
|
||||||
Get(repo.CompareAndPullRequest).
|
Get(repo.CompareAndPullRequest).
|
||||||
@@ -571,8 +574,8 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Group("", func() {
|
m.Group("", func() {
|
||||||
m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues)
|
m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues)
|
||||||
m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue)
|
m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue)
|
||||||
m.Get("/labels/", repo.RetrieveLabels, repo.Labels)
|
m.Get("/labels/", context.CheckAnyUnit(models.UnitTypeIssues, models.UnitTypePullRequests), repo.RetrieveLabels, repo.Labels)
|
||||||
m.Get("/milestones", repo.Milestones)
|
m.Get("/milestones", context.CheckAnyUnit(models.UnitTypeIssues, models.UnitTypePullRequests), repo.Milestones)
|
||||||
}, context.RepoRef())
|
}, context.RepoRef())
|
||||||
|
|
||||||
m.Group("/wiki", func() {
|
m.Group("/wiki", func() {
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ func Dashboard(ctx *context.Context) {
|
|||||||
retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
|
retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
OnlyPerformedBy: false,
|
OnlyPerformedBy: false,
|
||||||
Collaborate: true,
|
|
||||||
IncludeDeleted: false,
|
IncludeDeleted: false,
|
||||||
})
|
})
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ func Profile(ctx *context.Context) {
|
|||||||
retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
|
retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
|
||||||
IncludePrivate: showPrivate,
|
IncludePrivate: showPrivate,
|
||||||
OnlyPerformedBy: true,
|
OnlyPerformedBy: true,
|
||||||
Collaborate: true,
|
|
||||||
IncludeDeleted: false,
|
IncludeDeleted: false,
|
||||||
})
|
})
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct" {{if eq .commit_choice "direct"}}checked{{end}}>
|
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct" {{if eq .commit_choice "direct"}}checked{{end}}>
|
||||||
<label>
|
<label>
|
||||||
<i class="octicon octicon-git-commit" height="16" width="14"></i>
|
<i class="octicon octicon-git-commit" height="16" width="14"></i>
|
||||||
{{.i18n.Tr "repo.editor.commit_directly_to_this_branch" .BranchName | Safe}}
|
{{$branchName := .BranchName | Str2html}}
|
||||||
|
{{.i18n.Tr "repo.editor.commit_directly_to_this_branch" $branchName | Safe}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{if .CanBeForked}}
|
{{if .CanBeForked}}
|
||||||
<div class="ui compact labeled button" tabindex="0">
|
<div class="ui compact labeled button" tabindex="0">
|
||||||
<a class="ui compact button {{if eq .OwnerID $.SignedUserID}}poping up{{end}}" {{if not (eq .OwnerID $.SignedUserID)}}href="{{AppSubUrl}}/repo/fork/{{.ID}}"{{else}} data-content="{{$.i18n.Tr "repo.fork_from_self"}}" data-position="top center" data-variation="tiny"{{end}}>
|
<a class="ui compact button {{if not $.CanSignedUserFork}}poping up{{end}}" {{if $.CanSignedUserFork}}href="{{AppSubUrl}}/repo/fork/{{.ID}}"{{else}} data-content="{{$.i18n.Tr "repo.fork_from_self"}}" data-position="top center" data-variation="tiny"{{end}}>
|
||||||
<i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
|
<i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="ui basic label" href="{{.Link}}/forks">
|
<a class="ui basic label" href="{{.Link}}/forks">
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
{{if and (.Repository.UnitEnabled $.UnitTypeReleases) (not .IsBareRepo) }}
|
{{if and (.Repository.UnitEnabled $.UnitTypeReleases) (not .IsBareRepo) }}
|
||||||
<a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases">
|
<a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases">
|
||||||
<i class="octicon octicon-tag"></i> {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .Repository.NumTags}}gray{{else}}blue{{end}} small label">{{.Repository.NumTags}}</span>
|
<i class="octicon octicon-tag"></i> {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .Repository.NumReleases}}gray{{else}}blue{{end}} small label">{{.Repository.NumReleases}}</span>
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|||||||
@@ -103,8 +103,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="issue-actions">
|
<div class="issue-actions">
|
||||||
<div class="ui basic status buttons">
|
<div class="ui basic status buttons">
|
||||||
<div class="ui green active basic button issue-action" data-action="open" data-url="{{$.Link}}/status">{{.i18n.Tr "repo.issues.action_open"}}</div>
|
<div class="ui green active basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status">{{.i18n.Tr "repo.issues.action_open"}}</div>
|
||||||
<div class="ui red active basic button issue-action" data-action="close" data-url="{{$.Link}}/status">{{.i18n.Tr "repo.issues.action_close"}}</div>
|
<div class="ui red active basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status">{{.i18n.Tr "repo.issues.action_close"}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui secondary filter menu floated right">
|
<div class="ui secondary filter menu floated right">
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{{range .Labels}}
|
{{range .Labels}}
|
||||||
<div class="item issue-action" data-action="toggle" data-element-id="{{.ID}}" data-url="{{$.Link}}/labels">
|
<div class="item issue-action" data-action="toggle" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/labels">
|
||||||
<span class="octicon {{if eq $.SelectLabels .ID}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name | Sanitize}}
|
<span class="octicon {{if eq $.SelectLabels .ID}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name | Sanitize}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
{{.i18n.Tr "repo.issues.action_milestone_no_select"}}
|
{{.i18n.Tr "repo.issues.action_milestone_no_select"}}
|
||||||
</div>
|
</div>
|
||||||
{{range .Milestones}}
|
{{range .Milestones}}
|
||||||
<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.Link}}/milestone">
|
<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/milestone">
|
||||||
{{.Name | Sanitize}}
|
{{.Name | Sanitize}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
{{.i18n.Tr "repo.issues.action_assignee_no_select"}}
|
{{.i18n.Tr "repo.issues.action_assignee_no_select"}}
|
||||||
</div>
|
</div>
|
||||||
{{range .Assignees}}
|
{{range .Assignees}}
|
||||||
<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.Link}}/assignee">
|
<div class="item issue-action" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/assignee">
|
||||||
<img src="{{.RelAvatarLink}}"> {{.Name}}
|
<img src="{{.RelAvatarLink}}"> {{.Name}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
{{if .Issue.PullRequest.HasMerged}}
|
{{if .Issue.PullRequest.HasMerged}}
|
||||||
{{ $mergedStr:= TimeSince .Issue.PullRequest.Merged $.Lang }}
|
{{ $mergedStr:= TimeSince .Issue.PullRequest.Merged $.Lang }}
|
||||||
<a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.Name}}</a>
|
<a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.Name}}</a>
|
||||||
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Safe}}</span>
|
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Str2html}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a>
|
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a>
|
||||||
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
|
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
|
||||||
|
|||||||
@@ -19,17 +19,17 @@
|
|||||||
</span>
|
</span>
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div class="item" data-value="{{.SignedUser.ID}}">
|
{{if .CanForkToUser}}
|
||||||
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}">
|
<div class="item" data-value="{{.SignedUser.ID}}">
|
||||||
{{.SignedUser.ShortName 20}}
|
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}">
|
||||||
</div>
|
{{.SignedUser.ShortName 20}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
{{range .Orgs}}
|
{{range .Orgs}}
|
||||||
{{if and (.IsOwnedBy $.SignedUser.ID) (ne .ID $.ForkFromOwnerID)}}
|
<div class="item" data-value="{{.ID}}">
|
||||||
<div class="item" data-value="{{.ID}}">
|
<img class="ui mini image" src="{{.RelAvatarLink}}">
|
||||||
<img class="ui mini image" src="{{.RelAvatarLink}}">
|
{{.ShortName 20}}
|
||||||
{{.ShortName 20}}
|
</div>
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
{{range .Releases}}
|
{{range .Releases}}
|
||||||
<li class="ui grid">
|
<li class="ui grid">
|
||||||
<div class="ui four wide column meta">
|
<div class="ui four wide column meta">
|
||||||
{{if .PublisherID}}
|
{{if .IsTag}}
|
||||||
|
{{if .Created}}<span class="time">{{TimeSince .Created $.Lang}}</span>{{end}}
|
||||||
|
{{else}}
|
||||||
{{if .IsDraft}}
|
{{if .IsDraft}}
|
||||||
<span class="ui yellow label">{{$.i18n.Tr "repo.release.draft"}}</span>
|
<span class="ui yellow label">{{$.i18n.Tr "repo.release.draft"}}</span>
|
||||||
{{else if .IsPrerelease}}
|
{{else if .IsPrerelease}}
|
||||||
@@ -28,13 +30,22 @@
|
|||||||
<span class="tag text blue">
|
<span class="tag text blue">
|
||||||
<a href="{{$.RepoLink}}/src/{{.TagName}}" rel="nofollow"><i class="tag icon"></i> {{.TagName}}</a>
|
<a href="{{$.RepoLink}}/src/{{.TagName}}" rel="nofollow"><i class="tag icon"></i> {{.TagName}}</a>
|
||||||
</span>
|
</span>
|
||||||
|
<span class="commit">
|
||||||
|
<a href="{{$.RepoLink}}/src/{{.Sha1}}" rel="nofollow"><i class="code icon"></i> {{ShortSha .Sha1}}</a>
|
||||||
|
</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
<span class="commit">
|
|
||||||
<a href="{{$.RepoLink}}/src/{{.Sha1}}" rel="nofollow"><i class="code icon"></i> {{ShortSha .Sha1}}</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="ui twelve wide column detail">
|
<div class="ui twelve wide column detail">
|
||||||
{{if .PublisherID}}
|
{{if .IsTag}}
|
||||||
|
<h4>
|
||||||
|
<a href="{{$.RepoLink}}/src/{{.TagName}}" rel="nofollow"><i class="tag icon"></i> {{.TagName}}</a>
|
||||||
|
</h4>
|
||||||
|
<div class="download">
|
||||||
|
<a href="{{$.RepoLink}}/src/{{.Sha1}}" rel="nofollow"><i class="code icon"></i> {{ShortSha .Sha1}}</a>
|
||||||
|
<a href="{{$.RepoLink}}/archive/{{.TagName}}.zip" rel="nofollow"><i class="octicon octicon-file-zip"></i> ZIP</a>
|
||||||
|
<a href="{{$.RepoLink}}/archive/{{.TagName}}.tar.gz"><i class="octicon octicon-file-zip"></i> TAR.GZ</a>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
<h3>
|
<h3>
|
||||||
<a href="{{$.RepoLink}}/src/{{.TagName}}">{{.Title}}</a>
|
<a href="{{$.RepoLink}}/src/{{.TagName}}">{{.Title}}</a>
|
||||||
{{if $.IsRepositoryWriter}}<small>(<a href="{{$.RepoLink}}/releases/edit/{{.TagName}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)</small>{{end}}
|
{{if $.IsRepositoryWriter}}<small>(<a href="{{$.RepoLink}}/releases/edit/{{.TagName}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)</small>{{end}}
|
||||||
@@ -70,14 +81,6 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
|
||||||
<h4>
|
|
||||||
<a href="{{$.RepoLink}}/src/{{.TagName}}" rel="nofollow"><i class="tag icon"></i> {{.TagName}}</a>
|
|
||||||
</h4>
|
|
||||||
<div class="download">
|
|
||||||
<a href="{{$.RepoLink}}/archive/{{.TagName}}.zip" rel="nofollow"><i class="octicon octicon-file-zip"></i> ZIP</a>
|
|
||||||
<a href="{{$.RepoLink}}/archive/{{.TagName}}.tar.gz"><i class="octicon octicon-file-zip"></i> TAR.GZ</a>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
<span class="dot"> </span>
|
<span class="dot"> </span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,8 +36,8 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
<div class="file-view {{if .IsMarkdown}}markdown{{else if .IsTextFile}}code-view{{end}} has-emoji">
|
<div class="file-view {{if .IsRenderedHTML}}markdown{{else if .IsTextFile}}code-view{{end}} has-emoji">
|
||||||
{{if .IsMarkdown}}
|
{{if .IsRenderedHTML}}
|
||||||
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
|
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
|
||||||
{{else if not .IsTextFile}}
|
{{else if not .IsTextFile}}
|
||||||
<div class="view-raw ui center">
|
<div class="view-raw ui center">
|
||||||
|
|||||||
@@ -4,14 +4,16 @@
|
|||||||
<th class="four wide">
|
<th class="four wide">
|
||||||
{{if .LatestCommitUser}}
|
{{if .LatestCommitUser}}
|
||||||
<img class="ui avatar image img-12" src="{{.LatestCommitUser.RelAvatarLink}}" />
|
<img class="ui avatar image img-12" src="{{.LatestCommitUser.RelAvatarLink}}" />
|
||||||
{{if .LatestCommitUser.FullName}}
|
{{if .LatestCommitUser.FullName}}
|
||||||
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
|
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommit.Author.Name}}</strong></a>
|
<a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<img class="ui avatar image img-12" src="{{AvatarLink .LatestCommit.Author.Email}}" />
|
{{if .LatestCommit.Author}}
|
||||||
<strong>{{.LatestCommit.Author.Name}}</strong>
|
<img class="ui avatar image img-12" src="{{AvatarLink .LatestCommit.Author.Email}}" />
|
||||||
|
<strong>{{.LatestCommit.Author.Name}}</strong>
|
||||||
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
<a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified {{end}}{{end}}" href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
|
<a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified {{end}}{{end}}" href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
|
||||||
{{ShortSha .LatestCommit.ID.String}}
|
{{ShortSha .LatestCommit.ID.String}}
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
</th>
|
</th>
|
||||||
<th class="nine wide">
|
<th class="nine wide">
|
||||||
</th>
|
</th>
|
||||||
<th class="three wide text grey right age">{{TimeSince .LatestCommit.Author.When $.Lang}}</th>
|
<th class="three wide text grey right age">{{if .LatestCommit.Author}}{{TimeSince .LatestCommit.Author.When $.Lang}}{{end}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
2
vendor/code.gitea.io/git/MAINTAINERS
generated
vendored
2
vendor/code.gitea.io/git/MAINTAINERS
generated
vendored
@@ -15,3 +15,5 @@ Thomas Boerger <thomas@webhippie.de> (@tboerger)
|
|||||||
Lauris Bukšis-Haberkorns <lauris@nix.lv> (@lafriks)
|
Lauris Bukšis-Haberkorns <lauris@nix.lv> (@lafriks)
|
||||||
Antoine Girard <sapk@sapk.fr> (@sapk)
|
Antoine Girard <sapk@sapk.fr> (@sapk)
|
||||||
Jonas Östanbäck <jonas.ostanback@gmail.com> (@cez81)
|
Jonas Östanbäck <jonas.ostanback@gmail.com> (@cez81)
|
||||||
|
David Schneiderbauer <dschneiderbauer@gmail.com> (@daviian)
|
||||||
|
Peter Žeby <morlinest@gmail.com> (@morlinest)
|
||||||
|
|||||||
13
vendor/code.gitea.io/git/commit.go
generated
vendored
13
vendor/code.gitea.io/git/commit.go
generated
vendored
@@ -12,8 +12,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mcuadros/go-version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commit represents a git commit.
|
// Commit represents a git commit.
|
||||||
@@ -160,13 +158,7 @@ func CommitChanges(repoPath string, opts CommitChangesOptions) error {
|
|||||||
|
|
||||||
func commitsCount(repoPath, revision, relpath string) (int64, error) {
|
func commitsCount(repoPath, revision, relpath string) (int64, error) {
|
||||||
var cmd *Command
|
var cmd *Command
|
||||||
isFallback := false
|
cmd = NewCommand("rev-list", "--count")
|
||||||
if version.Compare(gitVersion, "1.8.0", "<") {
|
|
||||||
isFallback = true
|
|
||||||
cmd = NewCommand("log", "--pretty=format:''")
|
|
||||||
} else {
|
|
||||||
cmd = NewCommand("rev-list", "--count")
|
|
||||||
}
|
|
||||||
cmd.AddArguments(revision)
|
cmd.AddArguments(revision)
|
||||||
if len(relpath) > 0 {
|
if len(relpath) > 0 {
|
||||||
cmd.AddArguments("--", relpath)
|
cmd.AddArguments("--", relpath)
|
||||||
@@ -177,9 +169,6 @@ func commitsCount(repoPath, revision, relpath string) (int64, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isFallback {
|
|
||||||
return int64(strings.Count(stdout, "\n")) + 1, nil
|
|
||||||
}
|
|
||||||
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
|
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
vendor/code.gitea.io/git/repo_branch.go
generated
vendored
6
vendor/code.gitea.io/git/repo_branch.go
generated
vendored
@@ -7,8 +7,6 @@ package git
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mcuadros/go-version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BranchPrefix base dir of the branch information file store on git
|
// BranchPrefix base dir of the branch information file store on git
|
||||||
@@ -56,10 +54,6 @@ func (repo *Repository) GetHEADBranch() (*Branch, error) {
|
|||||||
|
|
||||||
// SetDefaultBranch sets default branch of repository.
|
// SetDefaultBranch sets default branch of repository.
|
||||||
func (repo *Repository) SetDefaultBranch(name string) error {
|
func (repo *Repository) SetDefaultBranch(name string) error {
|
||||||
if version.Compare(gitVersion, "1.7.10", "<") {
|
|
||||||
return ErrUnsupportedVersion{"1.7.10"}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := NewCommand("symbolic-ref", "HEAD", BranchPrefix+name).RunInDir(repo.Path)
|
_, err := NewCommand("symbolic-ref", "HEAD", BranchPrefix+name).RunInDir(repo.Path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
36
vendor/code.gitea.io/git/repo_commit.go
generated
vendored
36
vendor/code.gitea.io/git/repo_commit.go
generated
vendored
@@ -10,8 +10,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mcuadros/go-version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// getRefCommitID returns the last commit ID string of given reference (branch or tag).
|
// getRefCommitID returns the last commit ID string of given reference (branch or tag).
|
||||||
@@ -248,37 +246,11 @@ func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (in
|
|||||||
|
|
||||||
// CommitsBetween returns a list that contains commits between [last, before).
|
// CommitsBetween returns a list that contains commits between [last, before).
|
||||||
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
|
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
|
||||||
if version.Compare(gitVersion, "1.8.0", ">=") {
|
stdout, err := NewCommand("rev-list", before.ID.String()+"..."+last.ID.String()).RunInDirBytes(repo.Path)
|
||||||
stdout, err := NewCommand("rev-list", before.ID.String()+"..."+last.ID.String()).RunInDirBytes(repo.Path)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
|
|
||||||
}
|
}
|
||||||
|
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
|
||||||
// Fallback to stupid solution, which iterates all commits of the repository
|
|
||||||
// if before is not an ancestor of last.
|
|
||||||
l := list.New()
|
|
||||||
if last == nil || last.ParentCount() == 0 {
|
|
||||||
return l, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
cur := last
|
|
||||||
for {
|
|
||||||
if cur.ID.Equal(before.ID) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
l.PushBack(cur)
|
|
||||||
if cur.ParentCount() == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
cur, err = cur.Parent(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return l, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitsBetweenIDs return commits between twoe commits
|
// CommitsBetweenIDs return commits between twoe commits
|
||||||
|
|||||||
25
vendor/code.gitea.io/git/signature.go
generated
vendored
25
vendor/code.gitea.io/git/signature.go
generated
vendored
@@ -32,17 +32,22 @@ func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
|
|||||||
sig.Email = string(line[emailStart+1 : emailEnd])
|
sig.Email = string(line[emailStart+1 : emailEnd])
|
||||||
|
|
||||||
// Check date format.
|
// Check date format.
|
||||||
firstChar := line[emailEnd+2]
|
if len(line) > emailEnd+2 {
|
||||||
if firstChar >= 48 && firstChar <= 57 {
|
firstChar := line[emailEnd+2]
|
||||||
timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
|
if firstChar >= 48 && firstChar <= 57 {
|
||||||
timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
|
timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
|
||||||
seconds, _ := strconv.ParseInt(timestring, 10, 64)
|
timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
|
||||||
sig.When = time.Unix(seconds, 0)
|
seconds, _ := strconv.ParseInt(timestring, 10, 64)
|
||||||
} else {
|
sig.When = time.Unix(seconds, 0)
|
||||||
sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:]))
|
} else {
|
||||||
if err != nil {
|
sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:]))
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Fall back to unix 0 time
|
||||||
|
sig.When = time.Unix(0, 0)
|
||||||
}
|
}
|
||||||
return sig, nil
|
return sig, nil
|
||||||
}
|
}
|
||||||
|
|||||||
40
vendor/code.gitea.io/git/tree_entry.go
generated
vendored
40
vendor/code.gitea.io/git/tree_entry.go
generated
vendored
@@ -116,35 +116,51 @@ func (te *TreeEntry) GetSubJumpablePathName() string {
|
|||||||
// Entries a list of entry
|
// Entries a list of entry
|
||||||
type Entries []*TreeEntry
|
type Entries []*TreeEntry
|
||||||
|
|
||||||
var sorter = []func(t1, t2 *TreeEntry) bool{
|
type customSortableEntries struct {
|
||||||
func(t1, t2 *TreeEntry) bool {
|
Comparer func(s1, s2 string) bool
|
||||||
|
Entries
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorter = []func(t1, t2 *TreeEntry, cmp func(s1, s2 string) bool) bool{
|
||||||
|
func(t1, t2 *TreeEntry, cmp func(s1, s2 string) bool) bool {
|
||||||
return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
|
return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
|
||||||
},
|
},
|
||||||
func(t1, t2 *TreeEntry) bool {
|
func(t1, t2 *TreeEntry, cmp func(s1, s2 string) bool) bool {
|
||||||
return t1.name < t2.name
|
return cmp(t1.name, t2.name)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tes Entries) Len() int { return len(tes) }
|
func (ctes customSortableEntries) Len() int { return len(ctes.Entries) }
|
||||||
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
|
|
||||||
func (tes Entries) Less(i, j int) bool {
|
func (ctes customSortableEntries) Swap(i, j int) {
|
||||||
t1, t2 := tes[i], tes[j]
|
ctes.Entries[i], ctes.Entries[j] = ctes.Entries[j], ctes.Entries[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctes customSortableEntries) Less(i, j int) bool {
|
||||||
|
t1, t2 := ctes.Entries[i], ctes.Entries[j]
|
||||||
var k int
|
var k int
|
||||||
for k = 0; k < len(sorter)-1; k++ {
|
for k = 0; k < len(sorter)-1; k++ {
|
||||||
s := sorter[k]
|
s := sorter[k]
|
||||||
switch {
|
switch {
|
||||||
case s(t1, t2):
|
case s(t1, t2, ctes.Comparer):
|
||||||
return true
|
return true
|
||||||
case s(t2, t1):
|
case s(t2, t1, ctes.Comparer):
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sorter[k](t1, t2)
|
return sorter[k](t1, t2, ctes.Comparer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort sort the list of entry
|
// Sort sort the list of entry
|
||||||
func (tes Entries) Sort() {
|
func (tes Entries) Sort() {
|
||||||
sort.Sort(tes)
|
sort.Sort(customSortableEntries{func(s1, s2 string) bool {
|
||||||
|
return s1 < s2
|
||||||
|
}, tes})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomSort customizable string comparing sort entry list
|
||||||
|
func (tes Entries) CustomSort(cmp func(s1, s2 string) bool) {
|
||||||
|
sort.Sort(customSortableEntries{cmp, tes})
|
||||||
}
|
}
|
||||||
|
|
||||||
type commitInfo struct {
|
type commitInfo struct {
|
||||||
|
|||||||
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@@ -3,10 +3,10 @@
|
|||||||
"ignore": "test appengine",
|
"ignore": "test appengine",
|
||||||
"package": [
|
"package": [
|
||||||
{
|
{
|
||||||
"checksumSHA1": "fR5YDSoG7xYv2aLO23rne95gWps=",
|
"checksumSHA1": "JN/re4+x/hCzMLGHmieUcykVDAg=",
|
||||||
"path": "code.gitea.io/git",
|
"path": "code.gitea.io/git",
|
||||||
"revision": "479f87e5d189e7b8f1fd51dbcd25faa32b632cd2",
|
"revision": "d47b98c44c9a6472e44ab80efe65235e11c6da2a",
|
||||||
"revisionTime": "2017-08-03T00:53:29Z"
|
"revisionTime": "2017-10-23T00:52:09Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Zgp5RqU+20L2p9TNl1rSsUIWEEE=",
|
"checksumSHA1": "Zgp5RqU+20L2p9TNl1rSsUIWEEE=",
|
||||||
|
|||||||
Reference in New Issue
Block a user