Compare commits

...

63 Commits

Author SHA1 Message Date
6543
59913f405c Changelog 1.10.1 (#9256)
* Changelog for 1.10.1

* format ...

* format

* add @techknowlogick s suggestion
2019-12-05 13:23:51 -05:00
6543
42dae399eb Fix max length check and limit in multiple repo forms (#9148) (#9204)
* Fix input field max length for release, label and milestone forms

* Add max length for isseu and PR title
2019-11-29 14:00:19 +08:00
6543
f36efe0b54 Properly fix displaying virtual session provider in admin panel (#9137) (#9203)
* Properly fix #7147

Although #7300 properly shadows the password from the virtual session
provider, the template displaying the provider config still presumed
that the config was JSON.

This PR updates the template and properly hides the Virtual Session
provider.

Fixes #7147

* update per @silverwind's suggestion
2019-11-29 00:28:38 -05:00
Lunny Xiao
38664d7f39 upgrade levelqueue to 0.1.0 (#9192) (#9199) 2019-11-28 17:40:49 +01:00
Lunny Xiao
c4e52d232e Fix panic when diff (#9187) (#9193)
* fix panic when diff

* improve code
2019-11-28 10:07:30 -05:00
zeripath
2b257a91de Fix #9151 - smtp logger configuration sendTos should be an arra… (#9157)
* Fix #9151 - sendTos should be an array

* trimspace from the addresses
2019-11-25 16:18:16 +01:00
Benno
c01afd584d backport v1.10 - Always show Password field on link account sign in page (#9150) 2019-11-24 18:38:05 -05:00
guillep2k
1270e2ad85 Create PR on Current Repository by Default (#8670) (#9141)
* 'update'

* Send push tag event when release created

* send tag create event while release created in UI

* update to go v1.13

* fix gofmt error

* fix #8576 create pull request on current repository by default
2019-11-24 03:08:40 +01:00
Lunny Xiao
29fa3a0f68 fix race on indexer (#9136) (#9139) 2019-11-23 20:08:49 +02:00
Koichi MATSUMOTO
65a573f3c7 Fix reCAPTCHA URL (#9119)
Fix reCAPTCHA issue
2019-11-22 14:48:58 +00:00
Jordan
ade5ec5aa7 Backport: Hide given credentials for migrated repos. (#9098)
CloneAddr was being used as OriginalURL.
Now passing OriginalURL through from the form and saving it.
2019-11-20 17:23:12 -05:00
techknowlogick
38ce87a61a backport: update golang.org/x/crypto vendor to use acme v2 (#9056) (#9085) 2019-11-20 02:12:47 -05:00
guillep2k
261b19ced7 Backport: Fix password checks on admin create/edit user (#9076) (#9081)
* Fix password checks on admin create/edit user

* Remove incorrect trimspace
2019-11-20 00:08:53 +00:00
Antoine GIRARD
6ef0ab4d96 fix: add search to reserved usernames (#9063) (#9065)
* fix: add search to reserved usernames

* Update integrations/user_test.go

Co-Authored-By: 6543 <24977596+6543@users.noreply.github.com>
2019-11-18 22:40:14 +00:00
guillep2k
ecdb4c1750 Fix permission checks for close/reopen from commit (#8875) (#9033)
* Fix checks for close/reopen from commit

* Fix permission order
2019-11-16 00:11:40 +02:00
zeripath
a0e76de75a Ensure Written is set in GZIP ProxyResponseWriter (#9018) (#9025)
Fix #9001

The GZIP ProxyReponseWriter doesn't currently respond correctly
to requests about its Written status - leading to #9001.

This PR properly reimplements these methods.
2019-11-15 15:57:57 +00:00
6543
880f26c7f0 Fix broken link to branch from issue list (#9003) (#9021)
* Fix broken link to branch from issue list

* Update templates/repo/issue/list.tmpl
2019-11-15 14:10:28 +00:00
Lunny Xiao
fd461ca555 fix wrong system notice when repository is empty (#9020) 2019-11-15 20:13:58 +08:00
zeripath
3487fb66a1 Shadow password correctly for session config (#8984) (#9002)
Fix #8718

This PR shadows passwords in session config correctly by detecting
the VirtualProvider, unmarshalling the original config and then
shadowing config within that.
2019-11-14 22:34:47 +00:00
John Olheiser
1122230d0e Update security (#8990)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2019-11-14 16:56:17 +00:00
John Olheiser
9619ccf0e5 Changelog for 1.10.0 (#8978)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2019-11-14 00:09:58 -05:00
guillep2k
023ae3c48c Hotfix for review actions and notifications (#8965) 2019-11-14 00:38:12 +00:00
John Olheiser
3227a11f71 Backport 1.9.6 (#8969)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2019-11-13 21:31:27 +00:00
zeripath
3497efac4a Add Close() method to gogitRepository (#8901) (#8956)
Backport #8901 

In investigating #7947 it has become clear that the storage component of go-git repositories needs closing.

This PR adds this Close function and adds the Close functions as necessary.

In TransferOwnership the ctx.Repo.GitRepo is closed if it is open to help prevent the risk of multiple open files.

Fixes #7947
2019-11-13 13:54:04 +00:00
mrsdizzie
43fc99a7ed Update Github Migration Tests (#8938) (#8945)
Update all Github migration tests to use a new repo created just for
these tests that won't accidentially be modified by regular users
interacting with issues.

Fixes #8895
2019-11-13 00:15:57 -05:00
guillep2k
8693e54426 Backport: Enable punctuations ending mentions (#8889) (#8894)
* Enable punctuations ending mentions

* Improve tests
2019-11-09 20:24:59 -05:00
zeripath
b27cac021f Fix issue with user.fullname (#8903) 2019-11-10 00:06:38 +00:00
guillep2k
ca69ded83e Update Github migration test (#8896)
Earlier today #716 was reopened which updated the modification time for
an old milestone (1.6.0) that we use in testing with the assumption that
it is old and won't change. This breaks all builds now, so remove this
test since we have others that test the same code and this milestone
will likely be updated again as that issue changes etc...
2019-11-09 15:15:36 -05:00
guillep2k
fbcf235633 Backport: Fix password complexity check on registration (#8887) (#8888)
* Fix registration password complexity

* Fix integration to use a complex password ;)
2019-11-09 11:52:54 +00:00
guillep2k
1275c88589 Backport: Fix require external registration password (#8885) (#8890)
* Fix require external registration password

* Fix ctx on error condition by @jolheiser
2019-11-09 08:30:24 +00:00
mrsdizzie
42d0efd1f3 Fix edit content button on migrated issue content (#8877) (#8884)
Typo on a closing span tag caused edit button not to work properly on
the original issue content for a migrated issue.

Fixes #8876
2019-11-08 23:43:51 +08:00
Lauris BH
68b7f9f3f7 Fix to close opened io resources as soon as not needed (#8839) (#8846)
* Fix to close opened io resources as soon as not needed

* Remove unneeded err checks
2019-11-05 22:14:56 +02:00
Lauris BH
26457782c1 Fix new user form for non-local users (#8826) (#8828) 2019-11-05 08:19:32 +08:00
Lauris BH
1c65ecc1c6 Fix commit expand button to not go to commit link (#8745) (#8825)
* Fix commit expand button to not go to commit link

* Fix message rendering to have correct HTML in result

* Fix check for empty commit message

* Code optimization
2019-11-04 20:59:17 +02:00
6543
c5e5063ec9 Fix SSH2 conditonal in key parsing code (#8806) (#8810)
Avoid out of bounds error by using strings.HasPrefix to check for
starting SSH2 text rather than assuming user input has at least 31
characters.

Add tests for bad input as well.

Fixes #8800
2019-11-03 22:51:32 +08:00
6543
b040a87665 add missing "d" (#8801) 2019-11-03 11:13:38 +08:00
Lunny Xiao
2236375d66 fix 500 when edit hook (#8782) (#8789) 2019-11-02 18:41:06 +02:00
zeripath
646fd8b570 On windows set core.longpaths true (#8776) (#8786) 2019-11-02 12:25:13 +01:00
zeripath
4dac8b2389 Allow to merge if file path contains " or \ (#8629) (#8771)
* if a filename in a repository contains " or \ the owner can't merge pull request with this files
because "git diff-tree" adds double quotes to that filepath
example: filepath is ab"cd but "git diff-tree" returns "ab\"cd"

now, when the owner click "Merge Pull Request" button the server returns 500
this commit fix it

Signed-off-by: Ilya Pavlov <ilux@cpan.org>

* add -z option to getDiffTree
escape spec symbols for sparse-checkout

Signed-off-by: Ilya Pavlov <ilux@cpan.org>

* go fmt

Signed-off-by: Ilya Pavlov <ilux@cpan.org>

* typo

Signed-off-by: Ilya Pavlov <ilux@cpan.org>

* escape '\'
escape all spaces and '!'

* use regexp.ReplaceAllString()

Signed-off-by: Ilya Pavlov <ilux@cpan.org>

* strings.ReplaceAll was added in go 1.12

Signed-off-by: Ilya Pavlov <ilux@cpan.org>

* add '\' to regexp.MustCompile

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
2019-11-01 13:50:59 -04:00
John Olheiser
3341aaf3f0 Changelog 1.9.5 (#8753) (#8756)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2019-10-30 20:34:13 +00:00
John Olheiser
e766f11bd3 Changelog 1.10.0-rc2 (#8750)
* 1.10.0-rc2

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Wording

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Update CHANGELOG.md

Co-Authored-By: jaqra <48099350+jaqra@users.noreply.github.com>
2019-10-30 19:27:52 +02:00
6543
432f9dd1a3 [Fix] milestone close timestamp (#8728) (#8730)
* BugFix: Update closed_date_unix colum on milestone table on close

* go fmt
2019-10-29 03:11:24 +00:00
David Svantesson
8caf05989f Fix deadline on update issue or PR via API (#8698) 2019-10-28 01:36:59 +02:00
Monty Taylor
9bde52ffc1 Fix 500 when getting user as unauthenticated user (#8653) (#8663)
Backport #8653

When doing GET /api/v1/users/{user} as an unauthenticated user,
gitea throws a 500 because it's trying to dereference elements
from the context user. It wants to do this to see whether to
show the primary email and will do that if the logged in user
is admin or the user in question. However, if ctx.User is nil there is a panic
2019-10-25 13:09:15 +01:00
jaqra
fa03af8456 make call createMilestoneComment on newIssue func (#8678) (#8681)
* make call createMilestoneComment on newIssue func

* make OldMilestoneID 0 instead of -1
2019-10-25 11:09:19 +01:00
Lunny Xiao
14ebda6fd5 Hide some user information via API if user have no enough permission (#8655) (#8657)
* Hide some user information via API if user have no enough permission

* fix test
2019-10-24 08:59:53 +03:00
zeripath
1d10747514 Use AppSubUrl for more redirections (#8647) (#8651)
Partial backport without changes to locale files.

Fix #8461 - fix misspelling of {{AppSubUrl}} and other misspelling in template
Fixes /explore and organisation redirection
2019-10-23 18:27:10 -04:00
John Olheiser
83c90e9ba0 Add SubURL to redirect path (#8632) (#8634)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2019-10-22 22:16:20 +01:00
John Olheiser
2fbd5ae2e5 Fix template error on account page (#8562) (#8622) 2019-10-22 10:08:59 +01:00
guillep2k
0032278a46 Allow externalID to be UUID (#8551) (#8624)
Signed-off-by: Wenxuan Zhao <viz@linux.com>
2019-10-22 09:12:10 +01:00
guillep2k
ccf5298a2c Prevent .code-view from overriding font on icon fonts (#8614) (#8627) 2019-10-22 14:39:40 +08:00
zeripath
ece768ab6e Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528) (#8618)
* Expose db.SetMaxOpenConns and allow other dbs to set their connection params
* Add note about port exhaustion

Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com>
2019-10-22 07:00:37 +01:00
guillep2k
bac9424a62 fix emoji panel be removed bug in issue page, when the sub issue summit the duplicate emoji (#8609) (#8623) 2019-10-22 02:17:25 +03:00
zeripath
afeab941b3 Update heatmap fixtures to restore tests (#8615) (#8616)
* Update heatmap fixtures to restore tests
* Add hint to check the fixture age on fail
2019-10-21 22:15:55 +01:00
6543
cf35355db8 Ensure that diff stats can scroll independently of the diff (#8581) (#8611)
This PR ensures that once opened the diff stats detail box can be scrolled independently of the diff on the compare page.

Fixes #5532 

Details:

* make diff-detail-box the main container
* move file diff at the same level as diff-stats
* make diff-view options sticy again
* make diff-stats scroll if to mouch
* rm useless css info
* less: mv diff-stats to own class
* use new css class
* cleanup less file
* diff-counter: margin-right: 15px;
* make CI work
* make numbers colorful
* add sign (-/+) to numbers
2019-10-21 16:53:34 +08:00
Viktor Szakats
8e9265c402 webhook: set Content-Type for application/x-www-form-urlencoded (#8600)
This header is missing since switching http client from GiteaServer (`code.gitea.io/gitea/modules/httplib`) to Go-http-client/1.1 (`net.http`). The header [was added by default](https://github.com/go-gitea/gitea/blob/release/v1.8/modules/httplib/httplib.go#L301) by the former, but this is no longer true with `net.http`, so it needs to be done explicitly.

Closes: #7700
2019-10-20 18:18:05 +01:00
6543
435ce92935 Fix #8582 by handling empty repos (#8587) (#8594)
* Fix #8582 by handling empty repos

Signed-off-by: Jonas Franz <info@jonasfranz.software>

* Fix tests

Signed-off-by: Jonas Franz <info@jonasfranz.software>
2019-10-19 21:35:22 +01:00
Lunny Xiao
22cea96c18 Fix bug on pull requests when transfer head repository (#8564) (#8569)
* fix bug on pull requests when transfer head repository

* add migration and fix lint

* fix tests and add a cache check on LoadBaseRepo
2019-10-19 08:29:35 +01:00
6543
7565ac02c2 Allow more than 255 characters for tokens in external_login_user tabl… (#8585)
* Allow more than 255 characters for tokens in external_login_user table (#8554)

Signed-off-by: Wenxuan Zhao <viz@linux.com>

* use old xorm repo
2019-10-19 12:54:09 +08:00
zeripath
4e85c8e0d8 Add missed close in ServeBlobLFS (#8527) (#8542) 2019-10-16 20:32:15 +01:00
zeripath
34b8becef0 Ensure that GitRepo is set on Empty repositories (#8539) (#8541)
Both issues/new and settings/hooks/git expect `ctx.Repo.GitRepo` to be set.
This PR changes the context code to open the GitRepo.

Fixes #8538
2019-10-17 00:03:25 +08:00
6543
0752a3895a Fix migrate mirror 500 bug (#8526) (#8530)
* fix migrate mirror 500 bug

* update backport
2019-10-16 10:48:45 +01:00
guillep2k
595033f78e Fix password complexity regex for special characters (backport for v1.10.0) (#8524)
* Fix extra space

* Fix regular expression

* Fix error template name

* Simplify check code, fix default values, add test

* Fix router tests

* Fix fmt

* Fix setting and lint

* Move cleaning up code to test, improve comments

* Tidy up variable declaration
2019-10-16 11:09:27 +08:00
241 changed files with 5856 additions and 3967 deletions

View File

@@ -4,12 +4,41 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io). been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.10.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.10.0-rc1) - 2019-10-14 ## [1.10.1](https://github.com/go-gitea/gitea/releases/tag/v1.10.1) - 2019-12-05
* BUGFIXES
* Fix max length check and limit in multiple repo forms (#9148) (#9204)
* Properly fix displaying virtual session provider in admin panel (#9137) (#9203)
* Upgrade levelqueue to 0.1.0 (#9192) (#9199)
* Fix panic when diff (#9187) (#9193)
* Smtp logger configuration sendTos should be an array (#9154) (#9157)
* Always Show Password Field on Link Account Sign-in Page (#9150)
* Create PR on Current Repository by Default (#8670) (#9141)
* Fix race on indexer (#9136) (#9139)
* Fix reCAPTCHA URL (#9119)
* Hide migrated credentials (#9098)
* Update golang.org/x/crypto vendor to use acme v2 (#9056) (#9085)
* Fix password checks on admin create/edit user (#9076) (#9081)
* Fix add search as a reserved username (#9063) (#9065)
* Fix permission checks for close/reopen from commit (#8875) (#9033)
* Ensure Written is set in GZIP ProxyResponseWriter (#9018) (#9025)
* Fix broken link to branch from issue list (#9003) (#9021)
* Fix wrong system notice when repository is empty (#9020)
* Shadow password correctly for session config (#8984) (#9002)
## [1.10.0](https://github.com/go-gitea/gitea/releases/tag/v1.10.0) - 2019-11-13
* BREAKING * BREAKING
* Fix deadline on update issue or PR via API (#8698)
* Hide some user information via API if user doesn't have enough permission (#8655) (#8657)
* Remove legacy handling of drone token (#8191) * Remove legacy handling of drone token (#8191)
* Change repo search to use exact match for topic search. (#7941) * Change repo search to use exact match for topic search. (#7941)
* Add pagination for admin api get orgs and fix only list public orgs bug (#7742) * Add pagination for admin api get orgs and fix only list public orgs bug (#7742)
* Implement the ability to change the ssh port to match what is in the gitea config (#7286) * Implement the ability to change the ssh port to match what is in the gitea config (#7286)
* SECURITY
* Fix issue with user.fullname (#8903)
* Ignore mentions for users with no access (#8395)
* Be more strict with git arguments (#7715)
* Extract the username and password from the mirror url (#7651)
* reserve .well-known username (#7637)
* FEATURE * FEATURE
* Org/Members: display 2FA members states + optimize sql requests (#7621) * Org/Members: display 2FA members states + optimize sql requests (#7621)
* SetDefaultBranch on pushing to empty repository (#7610) * SetDefaultBranch on pushing to empty repository (#7610)
@@ -19,6 +48,41 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* Add option to initialize repository with labels (#6061) * Add option to initialize repository with labels (#6061)
* Add additional password hash algorithms (#6023) * Add additional password hash algorithms (#6023)
* BUGFIXES * BUGFIXES
* Allow to merge if file path contains " or \ (#8629) (#8771)
* On windows set core.longpaths true (#8776) (#8786)
* Fix 500 when edit hook (#8782) (#8789)
* Fix Checkbox at RepoSettings Protected Branch (#8799) (#8801)
* Fix SSH2 conditional in key parsing code (#8806) (#8810)
* Fix commit expand button to not go to commit link (#8745) (#8825)
* Fix new user form for non-local users (#8826) (#8828)
* Fix to close opened io resources as soon as not needed (#8839) (#8846)
* Fix edit content button on migrated issue content (#8877) (#8884)
* Fix require external registration password (#8885) (#8890)
* Fix password complexity check on registration (#8887) (#8888)
* Update Github Migration Tests (#8896) (#8938) (#8945)
* Enable punctuations ending mentions (#8889) (#8894)
* Add Close() method to gogitRepository (#8901) (#8956)
* Hotfix for review actions and notifications (#8965)
* Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528) (#8618)
* Fix milestone close timestamp (#8728) (#8730)
* Fix 500 when getting user as unauthenticated user (#8653) (#8663)
* Fix 'New Issue Missing Milestone Comment' (#8678) (#8681)
* Use AppSubUrl for more redirections (#8647) (#8651)
* Add SubURL to redirect path (#8632) (#8634)
* Fix template error on account page (#8562) (#8622)
* Allow externalID to be UUID (#8551) (#8624)
* Prevent removal of non-empty emoji panel following selection of duplicate (#8609) (#8623)
* Update heatmap fixtures to restore tests (#8615) (#8616)
* Ensure that diff stats can scroll independently of the diff (#8581) (#8621)
* Webhook: set Content-Type for application/x-www-form-urlencoded (#8600)
* Fix #8582 by handling empty repos (#8587) (#8594)
* Fix bug on pull requests when transfer head repository (#8564) (#8569)
* Add missed close in ServeBlobLFS (#8527) (#8542)
* Ensure that GitRepo is set on Empty repositories (#8539) (#8541)
* Fix migrate mirror 500 bug (#8526) (#8530)
* Fix password complexity regex for special characters (#8524)
* Prevent .code-view from overriding font on icon fonts (#8614) (#8627)
* Allow more than 255 characters for tokens in external_login_user table (#8554)
* Fix errors in create org UI regarding team access permission (#8506) * Fix errors in create org UI regarding team access permission (#8506)
* Fix bug on FindExternalUsersByProvider (#8504) * Fix bug on FindExternalUsersByProvider (#8504)
* Create .ssh dir as necessary (#8486) * Create .ssh dir as necessary (#8486)
@@ -218,10 +282,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* Support setting cookie domain (#6288) * Support setting cookie domain (#6288)
* Move migrating repository from frontend to backend (#6200) * Move migrating repository from frontend to backend (#6200)
* Delete releases attachments if release is deleted (#6068) * Delete releases attachments if release is deleted (#6068)
* SECURITY
* Ignore mentions for users with no access (#8395)
* Be more strict with git arguments (#7715)
* reserve .well-known username (#7637)
* TRANSLATION * TRANSLATION
* Latvian translation for home page (#8468) * Latvian translation for home page (#8468)
* Add home template italian translation (#8352) * Add home template italian translation (#8352)
@@ -250,7 +310,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* Fix global search result CSS, misc CSS tweaks (#7789) * Fix global search result CSS, misc CSS tweaks (#7789)
* Tweak label border CSS (#7739) * Tweak label border CSS (#7739)
* Fix create menu item widths (#7708) * Fix create menu item widths (#7708)
* Extract the username and password from the mirror url (#7651)
* [Branch View] Delete duplicate protection symbol (#7624) * [Branch View] Delete duplicate protection symbol (#7624)
* [Branch View] Delete Table Header (#7622) * [Branch View] Delete Table Header (#7622)
* [Branch View] icons to buttons (#7602) * [Branch View] icons to buttons (#7602)
@@ -263,6 +322,38 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* wiki - editor - add buttons 'inline code', 'empty checkbox', 'checked checkbox' (#7243) * wiki - editor - add buttons 'inline code', 'empty checkbox', 'checked checkbox' (#7243)
* Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141) * Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141)
## [1.9.6](https://github.com/go-gitea/gitea/releases/tag/v1.9.6) - 2019-11-13
* BUGFIXES
* Allow to merge if file path contains " or \ (#8629) (#8772)
* Fix 500 when edit hook (#8782) (#8790)
* Fix issue with user.fullname (#8904)
* Update Github Migration Test (#8897) (#8946)
* Add Close() method to gogitRepository (#8901) (#8958)
## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30
* BREAKING
* Hide some user information via API if user doesn't have enough permission (#8655) (#8658)
* BUGFIXES
* Fix milestone close timestamp (#8728) (#8731)
* Fix deadline on update issue or PR via API (#8699)
* Fix 'New Issue Missing Milestone Comment' (#8678) (#8682)
* Fix 500 when getting user as unauthenticated user (#8653) (#8662)
* Use AppSubUrl for more redirections (#8647) (#8652)
* Add SubURL to redirect path (#8632) (#8634) (#8640)
* Fix #8582 by handling empty repos (#8587) (#8593)
* Fix bug on pull requests when transfer head repository (#8571)
* Add missed close in ServeBlobLFS (#8527) (#8543)
* Return false if provided branch name is empty for IsBranchExist (#8485) (#8492)
* Create .ssh dir as necessary (#8369) (#8486) (#8489)
* Restore functionality for early gits (#7775) (#8476)
* Add check for empty set when dropping indexes during migration (#8475)
* Ensure Request Body Readers are closed in LFS server (#8454) (#8459)
* Ensure that LFS files are relative to the LFS content path (#8455) (#8458)
* SECURITY
* Ignore mentions for users with no access (#8395) (#8484)
* TESTING
* Update heatmap fixtures to restore tests (#8615) (#8617)
## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08 ## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08
* BUGFIXES * BUGFIXES
* Highlight issue references (#8101) (#8404) * Highlight issue references (#8101) (#8404)

View File

@@ -375,17 +375,20 @@ func runRepoSyncReleases(c *cli.Context) error {
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil { if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
log.Warn(" SyncReleasesWithTags: %v", err) log.Warn(" SyncReleasesWithTags: %v", err)
gitRepo.Close()
continue continue
} }
count, err = getReleaseCount(repo.ID) count, err = getReleaseCount(repo.ID)
if err != nil { if err != nil {
log.Warn(" GetReleaseCountByRepoID: %v", err) log.Warn(" GetReleaseCountByRepoID: %v", err)
gitRepo.Close()
continue continue
} }
log.Trace(" repo %s releases synchronized to tags: from %d to %d", log.Trace(" repo %s releases synchronized to tags: from %d to %d",
repo.FullName(), oldnum, count) repo.FullName(), oldnum, count)
gitRepo.Close()
} }
} }

View File

@@ -277,10 +277,12 @@ LOG_SQL = true
DB_RETRIES = 10 DB_RETRIES = 10
; Backoff time per DB retry (time.Duration) ; Backoff time per DB retry (time.Duration)
DB_RETRY_BACKOFF = 3s DB_RETRY_BACKOFF = 3s
; Max idle database connections on connnection pool, default is 0 ; Max idle database connections on connnection pool, default is 2
MAX_IDLE_CONNS = 0 MAX_IDLE_CONNS = 2
; Database connection max life time, default is 3s ; Database connection max life time, default is 0 or 3s mysql (See #6804 & #7071 for reasoning)
CONN_MAX_LIFETIME = 3s CONN_MAX_LIFETIME = 3s
; Database maximum number of open connections, default is 0 meaning no maximum
MAX_OPEN_CONNS = 0
[indexer] [indexer]
; Issue indexer type, currently support: bleve or db, default is bleve ; Issue indexer type, currently support: bleve or db, default is bleve
@@ -333,7 +335,8 @@ IMPORT_LOCAL_PATHS = false
; Set to true to prevent all users (including admin) from creating custom git hooks ; Set to true to prevent all users (including admin) from creating custom git hooks
DISABLE_GIT_HOOKS = false DISABLE_GIT_HOOKS = false
;Comma separated list of character classes required to pass minimum complexity. ;Comma separated list of character classes required to pass minimum complexity.
;If left empty or no valid values are specified, the default values (`lower,upper,digit,spec`) will be used. ;If left empty or no valid values are specified, the default values ("lower,upper,digit,spec") will be used.
;Use "off" to disable checking.
PASSWORD_COMPLEXITY = lower,upper,digit,spec PASSWORD_COMPLEXITY = lower,upper,digit,spec
; Password Hash algorithm, either "pbkdf2", "argon2", "scrypt" or "bcrypt" ; Password Hash algorithm, either "pbkdf2", "argon2", "scrypt" or "bcrypt"
PASSWORD_HASH_ALGO = pbkdf2 PASSWORD_HASH_ALGO = pbkdf2
@@ -822,6 +825,6 @@ TOKEN =
QUEUE_TYPE = channel QUEUE_TYPE = channel
; Task queue length, available only when `QUEUE_TYPE` is `channel`. ; Task queue length, available only when `QUEUE_TYPE` is `channel`.
QUEUE_LENGTH = 1000 QUEUE_LENGTH = 1000
; Task queue connction string, available only when `QUEUE_TYPE` is `redis`. ; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
; If there is a password of redis, use `addrs=127.0.0.1:6379 password=123 db=0`. ; If there is a password of redis, use `addrs=127.0.0.1:6379 password=123 db=0`.
QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0" QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"

View File

@@ -167,8 +167,12 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
- `LOG_SQL`: **true**: Log the executed SQL. - `LOG_SQL`: **true**: Log the executed SQL.
- `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed. - `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed.
- `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured. - `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured.
- `MAX_IDLE_CONNS` **0**: Max idle database connections on connnection pool, default is 0 - `MAX_OPEN_CONNS` **0**: Database maximum open connections - default is 0, meaning there is no limit.
- `CONN_MAX_LIFETIME` **3s**: Database connection max lifetime - `MAX_IDLE_CONNS` **2**: Max idle database connections on connnection pool, default is 2 - this will be capped to `MAX_OPEN_CONNS`.
- `CONN_MAX_LIFETIME` **0 or 3s**: Sets the maximum amount of time a DB connection may be reused - default is 0, meaning there is no limit (except on MySQL where it is 3s - see #6804 & #7071).
Please see #8540 & #8273 for further discussion of the appropriate values for `MAX_OPEN_CONNS`, `MAX_IDLE_CONNS` & `CONN_MAX_LIFETIME` and their
relation to port exhaustion.
## Indexer (`indexer`) ## Indexer (`indexer`)
@@ -212,7 +216,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
- lower - use one or more lower latin characters - lower - use one or more lower latin characters
- upper - use one or more upper latin characters - upper - use one or more upper latin characters
- digit - use one or more digits - digit - use one or more digits
- spec - use one or more special characters as ``][!"#$%&'()*+,./:;<=>?@\^_{|}~`-`` and space symbol. - spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~``
- off - do not check password complexity
## OpenID (`openid`) ## OpenID (`openid`)

View File

@@ -68,6 +68,7 @@ type Uploader interface {
CreateComment(issueNumber int64, comment *Comment) error CreateComment(issueNumber int64, comment *Comment) error
CreatePullRequest(pr *PullRequest) error CreatePullRequest(pr *PullRequest) error
Rollback() error Rollback() error
Close()
} }
``` ```

4
go.mod
View File

@@ -4,6 +4,7 @@ go 1.13
require ( require (
cloud.google.com/go v0.45.0 // indirect cloud.google.com/go v0.45.0 // indirect
gitea.com/lunny/levelqueue v0.1.0
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76
gitea.com/macaron/captcha v0.0.0-20190822015246-daa973478bae gitea.com/macaron/captcha v0.0.0-20190822015246-daa973478bae
@@ -67,7 +68,6 @@ require (
github.com/lafriks/xormstore v1.3.1 github.com/lafriks/xormstore v1.3.1
github.com/lib/pq v1.2.0 github.com/lib/pq v1.2.0
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e
github.com/mailru/easyjson v0.7.0 // indirect github.com/mailru/easyjson v0.7.0 // indirect
github.com/markbates/goth v1.56.0 github.com/markbates/goth v1.56.0
github.com/mattn/go-isatty v0.0.7 github.com/mattn/go-isatty v0.0.7
@@ -104,7 +104,7 @@ require (
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.20.0
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b golang.org/x/net v0.0.0-20190909003024-a7b16738d86b
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b

6
go.sum
View File

@@ -12,6 +12,8 @@ cloud.google.com/go v0.45.0 h1:bALuGBSgE+BD4rxsopAYlqjcwqcQtye6pWG4bC3N/k0=
cloud.google.com/go v0.45.0/go.mod h1:452BcPOeI9AZfbvDw0Tbo7D32wA+WX9WME8AZwMEDZU= cloud.google.com/go v0.45.0/go.mod h1:452BcPOeI9AZfbvDw0Tbo7D32wA+WX9WME8AZwMEDZU=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
gitea.com/lunny/levelqueue v0.1.0 h1:7wMk0VH6mvKN6vZEZCy9nUDgRmdPLgeNrm1NkW8EHNk=
gitea.com/lunny/levelqueue v0.1.0/go.mod h1:G7hVb908t0Bl0uk7zGSg14fyzNtxgtD9Shf04wkMK7s=
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b h1:vXt85uYV17KURaUlhU7v4GbCShkqRZDSfo0TkC0YCjQ= gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b h1:vXt85uYV17KURaUlhU7v4GbCShkqRZDSfo0TkC0YCjQ=
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b/go.mod h1:Cxadig6POWpPYYSfg23E7jo35Yf0yvsdC1lifoKWmPo= gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b/go.mod h1:Cxadig6POWpPYYSfg23E7jo35Yf0yvsdC1lifoKWmPo=
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 h1:mMsMEg90c5KXQgRWsH8D6GHXfZIW1RAe5S9VYIb12lM= gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 h1:mMsMEg90c5KXQgRWsH8D6GHXfZIW1RAe5S9VYIb12lM=
@@ -391,8 +393,6 @@ github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY= github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY=
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:mmIfjCSQlGYXmJ95jFN84AkQFnVABtKuJL8IrzwvUKQ= github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:mmIfjCSQlGYXmJ95jFN84AkQFnVABtKuJL8IrzwvUKQ=
github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e h1:GSprKUrG9wNgwQgROvjPGXmcZrg4OLslOuZGB0uJjx8=
github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e/go.mod h1:rQZVENnBOiVakCs97XvclbwJRTAv77CRFWcYVNDkVf8=
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk= github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk=
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ= github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ= github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ=
@@ -627,6 +627,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49N
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ=
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=

View File

@@ -51,6 +51,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
gitRepo, err := git.OpenRepository(repo.RepoPath()) gitRepo, err := git.OpenRepository(repo.RepoPath())
assert.NoError(t, err) assert.NoError(t, err)
defer gitRepo.Close()
err = gitRepo.CreateTag("v0.0.1", "master") err = gitRepo.CreateTag("v0.0.1", "master")
assert.NoError(t, err) assert.NoError(t, err)
@@ -112,6 +113,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
gitRepo, err := git.OpenRepository(repo.RepoPath()) gitRepo, err := git.OpenRepository(repo.RepoPath())
assert.NoError(t, err) assert.NoError(t, err)
defer gitRepo.Close()
err = gitRepo.CreateTag("v0.0.1", "master") err = gitRepo.CreateTag("v0.0.1", "master")
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -139,6 +139,7 @@ func TestAPICreateFile(t *testing.T) {
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL) assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email) assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name) assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
gitRepo.Close()
} }
// Test creating a file in a new branch // Test creating a file in a new branch

View File

@@ -143,6 +143,7 @@ func TestAPIUpdateFile(t *testing.T) {
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL) assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email) assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name) assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
gitRepo.Close()
} }
// Test updating a file in a new branch // Test updating a file in a new branch

View File

@@ -74,6 +74,8 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
repo1.CreateNewBranch(user2, repo1.DefaultBranch, newBranch) repo1.CreateNewBranch(user2, repo1.DefaultBranch, newBranch)
// Get the commit ID of the default branch // Get the commit ID of the default branch
gitRepo, _ := git.OpenRepository(repo1.RepoPath()) gitRepo, _ := git.OpenRepository(repo1.RepoPath())
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch) commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch)
// Make a new tag in repo1 // Make a new tag in repo1
newTag := "test_tag" newTag := "test_tag"

View File

@@ -75,6 +75,8 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
repo1.CreateNewBranch(user2, repo1.DefaultBranch, newBranch) repo1.CreateNewBranch(user2, repo1.DefaultBranch, newBranch)
// Get the commit ID of the default branch // Get the commit ID of the default branch
gitRepo, _ := git.OpenRepository(repo1.RepoPath()) gitRepo, _ := git.OpenRepository(repo1.RepoPath())
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch) commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch)
// Make a new tag in repo1 // Make a new tag in repo1
newTag := "test_tag" newTag := "test_tag"

View File

@@ -29,6 +29,8 @@ func TestAPIGitTags(t *testing.T) {
git.NewCommand("config", "user.email", user.Email).RunInDir(repo.RepoPath()) git.NewCommand("config", "user.email", user.Email).RunInDir(repo.RepoPath())
gitRepo, _ := git.OpenRepository(repo.RepoPath()) gitRepo, _ := git.OpenRepository(repo.RepoPath())
defer gitRepo.Close()
commit, _ := gitRepo.GetBranchCommit("master") commit, _ := gitRepo.GetBranchCommit("master")
lTagName := "lightweightTag" lTagName := "lightweightTag"
gitRepo.CreateTag(lTagName, commit.ID.String()) gitRepo.CreateTag(lTagName, commit.ID.String())

View File

@@ -29,7 +29,6 @@ func TestAPITeamUser(t *testing.T) {
var user2 *api.User var user2 *api.User
DecodeJSON(t, resp, &user2) DecodeJSON(t, resp, &user2)
user2.Created = user2.Created.In(time.Local) user2.Created = user2.Created.In(time.Local)
user2.LastLogin = user2.LastLogin.In(time.Local)
user := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User) user := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User)
assert.Equal(t, convert.ToUser(user, true, false), user2) assert.Equal(t, convert.ToUser(user, true, false), user2)

View File

@@ -26,7 +26,7 @@ func TestUserHeatmap(t *testing.T) {
var heatmap []*models.UserHeatmapData var heatmap []*models.UserHeatmapData
DecodeJSON(t, resp, &heatmap) DecodeJSON(t, resp, &heatmap)
var dummyheatmap []*models.UserHeatmapData var dummyheatmap []*models.UserHeatmapData
dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1540080000, Contributions: 1}) dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1571616000, Contributions: 1})
assert.Equal(t, dummyheatmap, heatmap) assert.Equal(t, dummyheatmap, heatmap)
} }

View File

@@ -73,6 +73,7 @@ func testDeleteRepoFile(t *testing.T, u *url.URL) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User
opts := getDeleteRepoFileOptions(repo) opts := getDeleteRepoFileOptions(repo)
@@ -111,6 +112,8 @@ func testDeleteRepoFileWithoutBranchNames(t *testing.T, u *url.URL) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User
opts := getDeleteRepoFileOptions(repo) opts := getDeleteRepoFileOptions(repo)
@@ -139,6 +142,8 @@ func TestDeleteRepoFileErrors(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User

View File

@@ -191,6 +191,8 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User
opts := getCreateRepoFileOptions(repo) opts := getCreateRepoFileOptions(repo)
@@ -201,6 +203,8 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
// asserts // asserts
assert.Nil(t, err) assert.Nil(t, err)
gitRepo, _ := git.OpenRepository(repo.RepoPath()) gitRepo, _ := git.OpenRepository(repo.RepoPath())
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID) expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID)
assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
@@ -220,6 +224,8 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User
opts := getUpdateRepoFileOptions(repo) opts := getUpdateRepoFileOptions(repo)
@@ -230,6 +236,8 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
// asserts // asserts
assert.Nil(t, err) assert.Nil(t, err)
gitRepo, _ := git.OpenRepository(repo.RepoPath()) gitRepo, _ := git.OpenRepository(repo.RepoPath())
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath) expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath)
assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
@@ -249,6 +257,8 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User
opts := getUpdateRepoFileOptions(repo) opts := getUpdateRepoFileOptions(repo)
@@ -261,6 +271,8 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
// asserts // asserts
assert.Nil(t, err) assert.Nil(t, err)
gitRepo, _ := git.OpenRepository(repo.RepoPath()) gitRepo, _ := git.OpenRepository(repo.RepoPath())
defer gitRepo.Close()
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath) expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath)
// assert that the old file no longer exists in the last commit of the branch // assert that the old file no longer exists in the last commit of the branch
@@ -288,6 +300,8 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User
opts := getUpdateRepoFileOptions(repo) opts := getUpdateRepoFileOptions(repo)
@@ -300,6 +314,8 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
// asserts // asserts
assert.Nil(t, err) assert.Nil(t, err)
gitRepo, _ := git.OpenRepository(repo.RepoPath()) gitRepo, _ := git.OpenRepository(repo.RepoPath())
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(repo.DefaultBranch) commitID, _ := gitRepo.GetBranchCommitID(repo.DefaultBranch)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath) expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath)
assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
@@ -315,6 +331,8 @@ func TestCreateOrUpdateRepoFileErrors(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
doer := ctx.User doer := ctx.User

View File

@@ -19,8 +19,8 @@ func TestSignup(t *testing.T) {
req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{ req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
"user_name": "exampleUser", "user_name": "exampleUser",
"email": "exampleUser@example.com", "email": "exampleUser@example.com",
"password": "examplePassword", "password": "examplePassword!1",
"retype": "examplePassword", "retype": "examplePassword!1",
}) })
MakeRequest(t, req, http.StatusFound) MakeRequest(t, req, http.StatusFound)

View File

@@ -90,6 +90,7 @@ func TestRenameReservedUsername(t *testing.T) {
"repo", "repo",
"template", "template",
"user", "user",
"search",
} }
session := loginUser(t, "user2") session := loginUser(t, "user2")

View File

@@ -533,34 +533,47 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit, bra
} }
refMarked[key] = true refMarked[key] = true
// only create comments for issues if user has permission for it // FIXME: this kind of condition is all over the code, it should be consolidated in a single place
if perm.IsAdmin() || perm.IsOwner() || perm.CanWrite(UnitTypeIssues) { canclose := perm.IsAdmin() || perm.IsOwner() || perm.CanWrite(UnitTypeIssues) || refIssue.PosterID == doer.ID
cancomment := canclose || perm.CanRead(UnitTypeIssues)
// Don't proceed if the user can't comment
if !cancomment {
continue
}
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, html.EscapeString(c.Message)) message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, html.EscapeString(c.Message))
if err = CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil { if err = CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil {
return err return err
} }
// Only issues can be closed/reopened this way, and user needs the correct permissions
if refIssue.IsPull || !canclose {
continue
} }
// Process closing/reopening keywords // Only process closing/reopening keywords
if ref.Action != references.XRefActionCloses && ref.Action != references.XRefActionReopens { if ref.Action != references.XRefActionCloses && ref.Action != references.XRefActionReopens {
continue continue
} }
// Change issue status only if the commit has been pushed to the default branch. if !repo.CloseIssuesViaCommitInAnyBranch {
// and if the repo is configured to allow only that // If the issue was specified to be in a particular branch, don't allow commits in other branches to close it
// FIXME: we should be using Issue.ref if set instead of repo.DefaultBranch if refIssue.Ref != "" {
if repo.DefaultBranch != branchName && !repo.CloseIssuesViaCommitInAnyBranch { if branchName != refIssue.Ref {
continue continue
} }
// Otherwise, only process commits to the default branch
} else if branchName != repo.DefaultBranch {
continue
}
}
// only close issues in another repo if user has push access
if perm.IsAdmin() || perm.IsOwner() || perm.CanWrite(UnitTypeCode) {
if err := changeIssueStatus(refRepo, refIssue, doer, ref.Action == references.XRefActionCloses); err != nil { if err := changeIssueStatus(refRepo, refIssue, doer, ref.Action == references.XRefActionCloses); err != nil {
return err return err
} }
} }
} }
}
return nil return nil
} }

View File

@@ -219,7 +219,7 @@ func TestUpdateIssuesCommit(t *testing.T) {
PosterID: user.ID, PosterID: user.ID,
IssueID: 1, IssueID: 1,
} }
issueBean := &Issue{RepoID: repo.ID, Index: 2} issueBean := &Issue{RepoID: repo.ID, Index: 4}
AssertNotExistsBean(t, commentBean) AssertNotExistsBean(t, commentBean)
AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1") AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
@@ -273,7 +273,7 @@ func TestUpdateIssuesCommit_Colon(t *testing.T) {
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
repo.Owner = user repo.Owner = user
issueBean := &Issue{RepoID: repo.ID, Index: 2} issueBean := &Issue{RepoID: repo.ID, Index: 4}
AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1") AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))

View File

@@ -28,9 +28,9 @@ type ExternalLoginUser struct {
Description string Description string
AvatarURL string AvatarURL string
Location string Location string
AccessToken string AccessToken string `xorm:"TEXT"`
AccessTokenSecret string AccessTokenSecret string `xorm:"TEXT"`
RefreshToken string RefreshToken string `xorm:"TEXT"`
ExpiresAt time.Time ExpiresAt time.Time
} }
@@ -168,7 +168,7 @@ func FindExternalUsersByProvider(opts FindExternalUserOptions) ([]ExternalLoginU
} }
// UpdateMigrationsByType updates all migrated repositories' posterid from gitServiceType to replace originalAuthorID to posterID // UpdateMigrationsByType updates all migrated repositories' posterid from gitServiceType to replace originalAuthorID to posterID
func UpdateMigrationsByType(tp structs.GitServiceType, externalUserID, userID int64) error { func UpdateMigrationsByType(tp structs.GitServiceType, externalUserID string, userID int64) error {
if err := UpdateIssuesMigrationsByType(tp, externalUserID, userID); err != nil { if err := UpdateIssuesMigrationsByType(tp, externalUserID, userID); err != nil {
return err return err
} }

View File

@@ -5,7 +5,7 @@
act_user_id: 2 act_user_id: 2
repo_id: 2 repo_id: 2
is_private: true is_private: true
created_unix: 1540139562 created_unix: 1571686356
- -
id: 2 id: 2

View File

@@ -6,7 +6,6 @@
index: 2 index: 2
head_repo_id: 1 head_repo_id: 1
base_repo_id: 1 base_repo_id: 1
head_user_name: user1
head_branch: branch1 head_branch: branch1
base_branch: master base_branch: master
merge_base: 1234567890abcdef merge_base: 1234567890abcdef
@@ -21,7 +20,6 @@
index: 3 index: 3
head_repo_id: 1 head_repo_id: 1
base_repo_id: 1 base_repo_id: 1
head_user_name: user1
head_branch: branch2 head_branch: branch2
base_branch: master base_branch: master
merge_base: fedcba9876543210 merge_base: fedcba9876543210
@@ -35,7 +33,6 @@
index: 1 index: 1
head_repo_id: 11 head_repo_id: 11
base_repo_id: 10 base_repo_id: 10
head_user_name: user13
head_branch: branch2 head_branch: branch2
base_branch: master base_branch: master
merge_base: 0abcb056019adb83 merge_base: 0abcb056019adb83

View File

@@ -17,6 +17,7 @@ func BenchmarkGetCommitGraph(b *testing.B) {
if err != nil { if err != nil {
b.Error("Could not open repository") b.Error("Could not open repository")
} }
defer currentRepo.Close()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
graph, err := GetCommitGraph(currentRepo) graph, err := GetCommitGraph(currentRepo)

View File

@@ -1072,6 +1072,10 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
if _, err = e.Exec("UPDATE `milestone` SET num_issues=num_issues+1 WHERE id=?", opts.Issue.MilestoneID); err != nil { if _, err = e.Exec("UPDATE `milestone` SET num_issues=num_issues+1 WHERE id=?", opts.Issue.MilestoneID); err != nil {
return err return err
} }
if _, err = createMilestoneComment(e, doer, opts.Repo, opts.Issue, 0, opts.Issue.MilestoneID); err != nil {
return err
}
} }
// Insert the assignees // Insert the assignees
@@ -1950,7 +1954,7 @@ func (issue *Issue) ResolveMentionsByVisibility(ctx DBContext, doer *User, menti
} }
// UpdateIssuesMigrationsByType updates all migrated repositories' issues from gitServiceType to replace originalAuthorID to posterID // UpdateIssuesMigrationsByType updates all migrated repositories' issues from gitServiceType to replace originalAuthorID to posterID
func UpdateIssuesMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID, posterID int64) error { func UpdateIssuesMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID string, posterID int64) error {
_, err := x.Table("issue"). _, err := x.Table("issue").
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType). Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
And("original_author_id = ?", originalAuthorID). And("original_author_id = ?", originalAuthorID).

View File

@@ -538,6 +538,10 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
switch opts.Type { switch opts.Type {
case CommentTypeCode: case CommentTypeCode:
if comment.ReviewID != 0 { if comment.ReviewID != 0 {
// Hotfix for 1.10.0 as the Review object has not yet been committed in the other session
if opts.Review != nil {
comment.Review = opts.Review
}
if comment.Review == nil { if comment.Review == nil {
if err := comment.loadReview(e); err != nil { if err := comment.loadReview(e); err != nil {
return err return err
@@ -596,6 +600,12 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
if err = opts.Issue.updateClosedNum(e); err != nil { if err = opts.Issue.updateClosedNum(e); err != nil {
return err return err
} }
case CommentTypeReview:
// Hotfix for 1.10.0; make sure a dashboard entry is created
if opts.Content == "" {
return nil
}
act.OpType = ActionCommentIssue
} }
// update the issue's updated_unix column // update the issue's updated_unix column
if err = updateIssueCols(e, opts.Issue, "updated_unix"); err != nil { if err = updateIssueCols(e, opts.Issue, "updated_unix"); err != nil {
@@ -756,6 +766,7 @@ type CreateCommentOptions struct {
Repo *Repository Repo *Repository
Issue *Issue Issue *Issue
Label *Label Label *Label
Review *Review
DependentIssueID int64 DependentIssueID int64
OldMilestoneID int64 OldMilestoneID int64
@@ -1025,7 +1036,7 @@ func FetchCodeComments(issue *Issue, currentUser *User) (CodeComments, error) {
} }
// UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id // UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id
func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID, posterID int64) error { func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID string, posterID int64) error {
_, err := x.Table("comment"). _, err := x.Table("comment").
Where(builder.In("issue_id", Where(builder.In("issue_id",
builder.Select("issue.id"). builder.Select("issue.id").

View File

@@ -306,7 +306,11 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
} }
m.IsClosed = isClosed m.IsClosed = isClosed
if _, err := sess.ID(m.ID).Cols("is_closed").Update(m); err != nil { if isClosed {
m.ClosedDateUnix = timeutil.TimeStampNow()
}
if _, err := sess.ID(m.ID).Cols("is_closed", "closed_date_unix").Update(m); err != nil {
return err return err
} }

View File

@@ -256,6 +256,10 @@ var migrations = []Migration{
NewMigration("add task table and status column for repository table", addTaskTable), NewMigration("add task table and status column for repository table", addTaskTable),
// v100 -> v101 // v100 -> v101
NewMigration("update migration repositories' service type", updateMigrationServiceTypes), NewMigration("update migration repositories' service type", updateMigrationServiceTypes),
// v101 -> v102
NewMigration("change length of some external login users columns", changeSomeColumnsLengthOfExternalLoginUser),
// v102 -> v103
NewMigration("update migration repositories' service type", dropColumnHeadUserNameOnPullRequest),
} }
// Migrate database to current version // Migrate database to current version

19
models/migrations/v101.go Normal file
View File

@@ -0,0 +1,19 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"github.com/go-xorm/xorm"
)
func changeSomeColumnsLengthOfExternalLoginUser(x *xorm.Engine) error {
type ExternalLoginUser struct {
AccessToken string `xorm:"TEXT"`
AccessTokenSecret string `xorm:"TEXT"`
RefreshToken string `xorm:"TEXT"`
}
return x.Sync2(new(ExternalLoginUser))
}

15
models/migrations/v102.go Normal file
View File

@@ -0,0 +1,15 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"github.com/go-xorm/xorm"
)
func dropColumnHeadUserNameOnPullRequest(x *xorm.Engine) error {
sess := x.NewSession()
defer sess.Close()
return dropTableColumns(sess, "pull_request", "head_user_name")
}

View File

@@ -47,6 +47,7 @@ func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil { if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
log.Warn("SyncReleasesWithTags: %v", err) log.Warn("SyncReleasesWithTags: %v", err)
} }
gitRepo.Close()
} }
if len(repos) < pageSize { if len(repos) < pageSize {
break break

View File

@@ -91,6 +91,7 @@ func fixReleaseSha1OnReleaseTable(x *xorm.Engine) error {
if err != nil { if err != nil {
return err return err
} }
defer gitRepo.Close()
gitRepoCache[release.RepoID] = gitRepo gitRepoCache[release.RepoID] = gitRepo
} }

View File

@@ -157,11 +157,9 @@ func SetEngine() (err error) {
// so use log file to instead print to stdout. // so use log file to instead print to stdout.
x.SetLogger(NewXORMLogger(setting.Database.LogSQL)) x.SetLogger(NewXORMLogger(setting.Database.LogSQL))
x.ShowSQL(setting.Database.LogSQL) x.ShowSQL(setting.Database.LogSQL)
if setting.Database.UseMySQL { x.SetMaxOpenConns(setting.Database.MaxOpenConns)
x.SetMaxIdleConns(setting.Database.MaxIdleConns) x.SetMaxIdleConns(setting.Database.MaxIdleConns)
x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime) x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
}
return nil return nil
} }

View File

@@ -66,7 +66,6 @@ type PullRequest struct {
HeadRepo *Repository `xorm:"-"` HeadRepo *Repository `xorm:"-"`
BaseRepoID int64 `xorm:"INDEX"` BaseRepoID int64 `xorm:"INDEX"`
BaseRepo *Repository `xorm:"-"` BaseRepo *Repository `xorm:"-"`
HeadUserName string
HeadBranch string HeadBranch string
BaseBranch string BaseBranch string
ProtectedBranch *ProtectedBranch `xorm:"-"` ProtectedBranch *ProtectedBranch `xorm:"-"`
@@ -79,6 +78,15 @@ type PullRequest struct {
MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"` MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"`
} }
// MustHeadUserName returns the HeadRepo's username if failed return blank
func (pr *PullRequest) MustHeadUserName() string {
if err := pr.LoadHeadRepo(); err != nil {
log.Error("LoadHeadRepo: %v", err)
return ""
}
return pr.HeadRepo.MustOwnerName()
}
// Note: don't try to get Issue because will end up recursive querying. // Note: don't try to get Issue because will end up recursive querying.
func (pr *PullRequest) loadAttributes(e Engine) (err error) { func (pr *PullRequest) loadAttributes(e Engine) (err error) {
if pr.HasMerged && pr.Merger == nil { if pr.HasMerged && pr.Merger == nil {
@@ -102,6 +110,10 @@ func (pr *PullRequest) LoadAttributes() error {
// LoadBaseRepo loads pull request base repository from database // LoadBaseRepo loads pull request base repository from database
func (pr *PullRequest) LoadBaseRepo() error { func (pr *PullRequest) LoadBaseRepo() error {
if pr.BaseRepo == nil { if pr.BaseRepo == nil {
if pr.HeadRepoID == pr.BaseRepoID && pr.HeadRepo != nil {
pr.BaseRepo = pr.HeadRepo
return nil
}
var repo Repository var repo Repository
if has, err := x.ID(pr.BaseRepoID).Get(&repo); err != nil { if has, err := x.ID(pr.BaseRepoID).Get(&repo); err != nil {
return err return err
@@ -113,6 +125,24 @@ func (pr *PullRequest) LoadBaseRepo() error {
return nil return nil
} }
// LoadHeadRepo loads pull request head repository from database
func (pr *PullRequest) LoadHeadRepo() error {
if pr.HeadRepo == nil {
if pr.HeadRepoID == pr.BaseRepoID && pr.BaseRepo != nil {
pr.HeadRepo = pr.BaseRepo
return nil
}
var repo Repository
if has, err := x.ID(pr.HeadRepoID).Get(&repo); err != nil {
return err
} else if !has {
return ErrRepoNotExist{ID: pr.BaseRepoID}
}
pr.HeadRepo = &repo
}
return nil
}
// LoadIssue loads issue information from database // LoadIssue loads issue information from database
func (pr *PullRequest) LoadIssue() (err error) { func (pr *PullRequest) LoadIssue() (err error) {
return pr.loadIssue(x) return pr.loadIssue(x)
@@ -152,7 +182,7 @@ func (pr *PullRequest) GetDefaultMergeMessage() string {
return "" return ""
} }
} }
return fmt.Sprintf("Merge branch '%s' of %s/%s into %s", pr.HeadBranch, pr.HeadUserName, pr.HeadRepo.Name, pr.BaseBranch) return fmt.Sprintf("Merge branch '%s' of %s/%s into %s", pr.HeadBranch, pr.MustHeadUserName(), pr.HeadRepo.Name, pr.BaseBranch)
} }
// GetDefaultSquashMessage returns default message used when squash and merging pull request // GetDefaultSquashMessage returns default message used when squash and merging pull request
@@ -352,6 +382,7 @@ func (pr *PullRequest) GetLastCommitStatus() (status *CommitStatus, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer headGitRepo.Close()
lastCommitID, err := headGitRepo.GetBranchCommitID(pr.HeadBranch) lastCommitID, err := headGitRepo.GetBranchCommitID(pr.HeadBranch)
if err != nil { if err != nil {
@@ -541,6 +572,7 @@ func (pr *PullRequest) getMergeCommit() (*git.Commit, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err) return nil, fmt.Errorf("OpenRepository: %v", err)
} }
defer gitRepo.Close()
commit, err := gitRepo.GetCommit(mergeCommit[:40]) commit, err := gitRepo.GetCommit(mergeCommit[:40])
if err != nil { if err != nil {
@@ -925,6 +957,7 @@ func (pr *PullRequest) UpdatePatch() (err error) {
if err != nil { if err != nil {
return fmt.Errorf("OpenRepository: %v", err) return fmt.Errorf("OpenRepository: %v", err)
} }
defer headGitRepo.Close()
// Add a temporary remote. // Add a temporary remote.
tmpRemote := com.ToStr(time.Now().UnixNano()) tmpRemote := com.ToStr(time.Now().UnixNano())
@@ -966,6 +999,7 @@ func (pr *PullRequest) PushToBaseRepo() (err error) {
if err != nil { if err != nil {
return fmt.Errorf("OpenRepository: %v", err) return fmt.Errorf("OpenRepository: %v", err)
} }
defer headGitRepo.Close()
tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID) tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID)
if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil { if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil {
@@ -1155,22 +1189,11 @@ func checkForInvalidation(requests PullRequestList, repoID int64, doer *User, br
if err != nil { if err != nil {
log.Error("PullRequestList.InvalidateCodeComments: %v", err) log.Error("PullRequestList.InvalidateCodeComments: %v", err)
} }
gitRepo.Close()
}() }()
return nil return nil
} }
// ChangeUsernameInPullRequests changes the name of head_user_name
func ChangeUsernameInPullRequests(oldUserName, newUserName string) error {
pr := PullRequest{
HeadUserName: strings.ToLower(newUserName),
}
_, err := x.
Cols("head_user_name").
Where("head_user_name = ?", strings.ToLower(oldUserName)).
Update(pr)
return err
}
// checkAndUpdateStatus checks if pull request is possible to leaving checking status, // checkAndUpdateStatus checks if pull request is possible to leaving checking status,
// and set to be either conflict or mergeable. // and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() { func (pr *PullRequest) checkAndUpdateStatus() {

View File

@@ -232,20 +232,6 @@ func TestPullRequestList_LoadAttributes(t *testing.T) {
// TODO TestAddTestPullRequestTask // TODO TestAddTestPullRequestTask
func TestChangeUsernameInPullRequests(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
const newUsername = "newusername"
assert.NoError(t, ChangeUsernameInPullRequests("user1", newUsername))
prs := make([]*PullRequest, 0, 10)
assert.NoError(t, x.Where("head_user_name = ?", newUsername).Find(&prs))
assert.Len(t, prs, 2)
for _, pr := range prs {
assert.Equal(t, newUsername, pr.HeadUserName)
}
CheckConsistencyFor(t, &PullRequest{})
}
func TestPullRequest_IsWorkInProgress(t *testing.T) { func TestPullRequest_IsWorkInProgress(t *testing.T) {
assert.NoError(t, PrepareTestDatabase()) assert.NoError(t, PrepareTestDatabase())

View File

@@ -369,7 +369,7 @@ func SyncReleasesWithTags(repo *Repository, gitRepo *git.Repository) error {
} }
// UpdateReleasesMigrationsByType updates all migrated repositories' releases from gitServiceType to replace originalAuthorID to posterID // UpdateReleasesMigrationsByType updates all migrated repositories' releases from gitServiceType to replace originalAuthorID to posterID
func UpdateReleasesMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID, posterID int64) error { func UpdateReleasesMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID string, posterID int64) error {
_, err := x.Table("release"). _, err := x.Table("release").
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType). Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
And("original_author_id = ?", originalAuthorID). And("original_author_id = ?", originalAuthorID).

View File

@@ -998,6 +998,7 @@ func MigrateRepositoryGitData(doer, u *User, repo *Repository, opts api.MigrateR
if err != nil { if err != nil {
return repo, fmt.Errorf("OpenRepository: %v", err) return repo, fmt.Errorf("OpenRepository: %v", err)
} }
defer gitRepo.Close()
repo.IsEmpty, err = gitRepo.IsEmpty() repo.IsEmpty, err = gitRepo.IsEmpty()
if err != nil { if err != nil {
@@ -1430,6 +1431,7 @@ func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err
IsFsckEnabled: !opts.IsMirror, IsFsckEnabled: !opts.IsMirror,
CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch, CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch,
Status: opts.Status, Status: opts.Status,
IsEmpty: !opts.AutoInit,
} }
sess := x.NewSession() sess := x.NewSession()

View File

@@ -64,6 +64,8 @@ func GetActivityStats(repo *Repository, timeFrom time.Time, releases, issues, pr
if err != nil { if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err) return nil, fmt.Errorf("OpenRepository: %v", err)
} }
defer gitRepo.Close()
code, err := gitRepo.GetCodeActivityStats(timeFrom, repo.DefaultBranch) code, err := gitRepo.GetCodeActivityStats(timeFrom, repo.DefaultBranch)
if err != nil { if err != nil {
return nil, fmt.Errorf("FillFromGit: %v", err) return nil, fmt.Errorf("FillFromGit: %v", err)
@@ -79,6 +81,8 @@ func GetActivityStatsTopAuthors(repo *Repository, timeFrom time.Time, count int)
if err != nil { if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err) return nil, fmt.Errorf("OpenRepository: %v", err)
} }
defer gitRepo.Close()
code, err := gitRepo.GetCodeActivityStats(timeFrom, "") code, err := gitRepo.GetCodeActivityStats(timeFrom, "")
if err != nil { if err != nil {
return nil, fmt.Errorf("FillFromGit: %v", err) return nil, fmt.Errorf("FillFromGit: %v", err)

View File

@@ -23,6 +23,7 @@ func (repo *Repository) GetBranch(branch string) (*git.Branch, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close()
return gitRepo.GetBranch(branch) return gitRepo.GetBranch(branch)
} }
@@ -38,6 +39,7 @@ func (repo *Repository) CheckBranchName(name string) error {
if err != nil { if err != nil {
return err return err
} }
defer gitRepo.Close()
branches, err := repo.GetBranches() branches, err := repo.GetBranches()
if err != nil { if err != nil {
@@ -94,6 +96,7 @@ func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName st
log.Error("Unable to open temporary repository: %s (%v)", basePath, err) log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
} }
defer gitRepo.Close()
if err = gitRepo.CreateBranch(branchName, oldBranchName); err != nil { if err = gitRepo.CreateBranch(branchName, oldBranchName); err != nil {
log.Error("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err) log.Error("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err)
@@ -140,6 +143,7 @@ func (repo *Repository) CreateNewBranchFromCommit(doer *User, commit, branchName
log.Error("Unable to open temporary repository: %s (%v)", basePath, err) log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
} }
defer gitRepo.Close()
if err = gitRepo.CreateBranch(branchName, commit); err != nil { if err = gitRepo.CreateBranch(branchName, commit); err != nil {
log.Error("Unable to create branch: %s from %s. (%v)", branchName, commit, err) log.Error("Unable to create branch: %s from %s. (%v)", branchName, commit, err)

View File

@@ -58,7 +58,7 @@ func (repo *Repository) updateIndexerStatus(sha string) error {
} }
type repoIndexerOperation struct { type repoIndexerOperation struct {
repo *Repository repoID int64
deleted bool deleted bool
watchers []chan<- error watchers []chan<- error
} }
@@ -122,7 +122,7 @@ func populateRepoIndexer(maxRepoID int64) {
} }
for _, repo := range repos { for _, repo := range repos {
repoIndexerOperationQueue <- repoIndexerOperation{ repoIndexerOperationQueue <- repoIndexerOperation{
repo: repo, repoID: repo.ID,
deleted: false, deleted: false,
} }
maxRepoID = repo.ID - 1 maxRepoID = repo.ID - 1
@@ -131,7 +131,12 @@ func populateRepoIndexer(maxRepoID int64) {
log.Info("Done populating the repo indexer with existing repositories") log.Info("Done populating the repo indexer with existing repositories")
} }
func updateRepoIndexer(repo *Repository) error { func updateRepoIndexer(repoID int64) error {
repo, err := getRepositoryByID(x, repoID)
if err != nil {
return err
}
sha, err := getDefaultBranchSha(repo) sha, err := getDefaultBranchSha(repo)
if err != nil { if err != nil {
return err return err
@@ -339,11 +344,11 @@ func processRepoIndexerOperationQueue() {
op := <-repoIndexerOperationQueue op := <-repoIndexerOperationQueue
var err error var err error
if op.deleted { if op.deleted {
if err = indexer.DeleteRepoFromIndexer(op.repo.ID); err != nil { if err = indexer.DeleteRepoFromIndexer(op.repoID); err != nil {
log.Error("DeleteRepoFromIndexer: %v", err) log.Error("DeleteRepoFromIndexer: %v", err)
} }
} else { } else {
if err = updateRepoIndexer(op.repo); err != nil { if err = updateRepoIndexer(op.repoID); err != nil {
log.Error("updateRepoIndexer: %v", err) log.Error("updateRepoIndexer: %v", err)
} }
} }
@@ -355,12 +360,12 @@ func processRepoIndexerOperationQueue() {
// DeleteRepoFromIndexer remove all of a repository's entries from the indexer // DeleteRepoFromIndexer remove all of a repository's entries from the indexer
func DeleteRepoFromIndexer(repo *Repository, watchers ...chan<- error) { func DeleteRepoFromIndexer(repo *Repository, watchers ...chan<- error) {
addOperationToQueue(repoIndexerOperation{repo: repo, deleted: true, watchers: watchers}) addOperationToQueue(repoIndexerOperation{repoID: repo.ID, deleted: true, watchers: watchers})
} }
// UpdateRepoIndexer update a repository's entries in the indexer // UpdateRepoIndexer update a repository's entries in the indexer
func UpdateRepoIndexer(repo *Repository, watchers ...chan<- error) { func UpdateRepoIndexer(repo *Repository, watchers ...chan<- error) {
addOperationToQueue(repoIndexerOperation{repo: repo, deleted: false, watchers: watchers}) addOperationToQueue(repoIndexerOperation{repoID: repo.ID, deleted: false, watchers: watchers})
} }
func addOperationToQueue(op repoIndexerOperation) { func addOperationToQueue(op repoIndexerOperation) {

View File

@@ -1,24 +0,0 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"code.gitea.io/gitea/modules/git"
)
// GetTagsByPath returns repo tags by its path
func GetTagsByPath(path string) ([]*git.Tag, error) {
gitRepo, err := git.OpenRepository(path)
if err != nil {
return nil, err
}
return gitRepo.GetTagInfos()
}
// GetTags return repo's tags
func (repo *Repository) GetTags() ([]*git.Tag, error) {
return GetTagsByPath(repo.RepoPath())
}

View File

@@ -135,6 +135,7 @@ func (r *Review) publish(e *xorm.Engine) error {
Repo: review.Issue.Repo, Repo: review.Issue.Repo,
Type: comm.Type, Type: comm.Type,
Content: comm.Content, Content: comm.Content,
Review: r,
}, comm); err != nil { }, comm); err != nil {
log.Warn("sendCreateCommentAction: %v", err) log.Warn("sendCreateCommentAction: %v", err)
} }

View File

@@ -107,7 +107,7 @@ func parseKeyString(content string) (string, error) {
var keyType, keyContent, keyComment string var keyType, keyContent, keyComment string
if content[:len(ssh2keyStart)] == ssh2keyStart { if strings.HasPrefix(content, ssh2keyStart) {
// Parse SSH2 file format. // Parse SSH2 file format.
// Transform all legal line endings to a single "\n". // Transform all legal line endings to a single "\n".

View File

@@ -131,6 +131,19 @@ AAAAC3NzaC1lZDI1NTE5AAAAICV0MGX/W9IvLA4FXpIuUcdDcbj5KX4syHgsTy7soVgf
_, err := CheckPublicKeyString(test.content) _, err := CheckPublicKeyString(test.content)
assert.NoError(t, err) assert.NoError(t, err)
} }
for _, invalidKeys := range []struct {
content string
}{
{"test"},
{"---- NOT A REAL KEY ----"},
{"bad\nkey"},
{"\t\t:)\t\r\n"},
{"\r\ntest \r\ngitea\r\n\r\n"},
} {
_, err := CheckPublicKeyString(invalidKeys.content)
assert.Error(t, err)
}
} }
func Test_calcFingerprint(t *testing.T) { func Test_calcFingerprint(t *testing.T) {

View File

@@ -196,7 +196,7 @@ func CreateMigrateTask(doer, u *User, opts base.MigrateOptions) (*Task, error) {
repo, err := CreateRepository(doer, u, CreateRepoOptions{ repo, err := CreateRepository(doer, u, CreateRepoOptions{
Name: opts.RepoName, Name: opts.RepoName,
Description: opts.Description, Description: opts.Description,
OriginalURL: opts.CloneAddr, OriginalURL: opts.OriginalURL,
IsPrivate: opts.Private, IsPrivate: opts.Private,
IsMirror: opts.Mirror, IsMirror: opts.Mirror,
Status: RepositoryBeingMigrated, Status: RepositoryBeingMigrated,

View File

@@ -822,6 +822,7 @@ var (
".", ".",
"..", "..",
".well-known", ".well-known",
"search",
} }
reservedUserPatterns = []string{"*.keys", "*.gpg"} reservedUserPatterns = []string{"*.keys", "*.gpg"}
) )
@@ -994,10 +995,6 @@ func ChangeUserName(u *User, newUserName string) (err error) {
return ErrUserAlreadyExist{newUserName} return ErrUserAlreadyExist{newUserName}
} }
if err = ChangeUsernameInPullRequests(u.Name, newUserName); err != nil {
return fmt.Errorf("ChangeUsernameInPullRequests: %v", err)
}
// Do not fail if directory does not exist // Do not fail if directory does not exist
if err = os.Rename(UserPath(u.Name), UserPath(newUserName)); err != nil && !os.IsNotExist(err) { if err = os.Rename(UserPath(u.Name), UserPath(newUserName)); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("Rename user directory: %v", err) return fmt.Errorf("Rename user directory: %v", err)

View File

@@ -17,7 +17,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
CountResult int CountResult int
JSONResult string JSONResult string
}{ }{
{2, 1, `[{"timestamp":1540080000,"contributions":1}]`}, {2, 1, `[{"timestamp":1571616000,"contributions":1}]`},
{3, 0, `[]`}, {3, 0, `[]`},
} }
// Prepare // Prepare
@@ -41,7 +41,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
// Get the heatmap and compare // Get the heatmap and compare
heatmap, err := GetUserHeatmapDataByUser(user) heatmap, err := GetUserHeatmapDataByUser(user)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, len(actions), len(heatmap)) assert.Equal(t, len(actions), len(heatmap), "invalid action count: did the test data became too old?")
assert.Equal(t, tc.CountResult, len(heatmap)) assert.Equal(t, tc.CountResult, len(heatmap))
//Test JSON rendering //Test JSON rendering

View File

@@ -833,6 +833,8 @@ func (t *HookTask) deliver() error {
return err return err
} }
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
} }
case http.MethodGet: case http.MethodGet:
u, err := url.Parse(t.URL) u, err := url.Parse(t.URL)

View File

@@ -140,6 +140,7 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
log.Error("Unable to open temporary repository: %s (%v)", basePath, err) log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
} }
defer gitRepo.Close()
if hasMasterBranch { if hasMasterBranch {
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil { if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
@@ -276,6 +277,7 @@ func (repo *Repository) DeleteWikiPage(doer *User, wikiName string) (err error)
log.Error("Unable to open temporary repository: %s (%v)", basePath, err) log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
} }
defer gitRepo.Close()
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil { if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err) log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)

View File

@@ -161,6 +161,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
// Now need to show that the page has been added: // Now need to show that the page has been added:
gitRepo, err := git.OpenRepository(repo.WikiPath()) gitRepo, err := git.OpenRepository(repo.WikiPath())
assert.NoError(t, err) assert.NoError(t, err)
defer gitRepo.Close()
masterTree, err := gitRepo.GetTree("master") masterTree, err := gitRepo.GetTree("master")
assert.NoError(t, err) assert.NoError(t, err)
wikiPath := WikiNameToFilename(wikiName) wikiPath := WikiNameToFilename(wikiName)
@@ -214,6 +215,7 @@ func TestRepository_EditWikiPage(t *testing.T) {
_, err := masterTree.GetTreeEntryByPath("Home.md") _, err := masterTree.GetTreeEntryByPath("Home.md")
assert.Error(t, err) assert.Error(t, err)
} }
gitRepo.Close()
} }
} }
@@ -226,6 +228,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
// Now need to show that the page has been added: // Now need to show that the page has been added:
gitRepo, err := git.OpenRepository(repo.WikiPath()) gitRepo, err := git.OpenRepository(repo.WikiPath())
assert.NoError(t, err) assert.NoError(t, err)
defer gitRepo.Close()
masterTree, err := gitRepo.GetTree("master") masterTree, err := gitRepo.GetTree("master")
assert.NoError(t, err) assert.NoError(t, err)
wikiPath := WikiNameToFilename("Home") wikiPath := WikiNameToFilename("Home")

View File

@@ -499,9 +499,9 @@ func (f SubmitReviewForm) HasEmptyContent() bool {
// NewReleaseForm form for creating release // NewReleaseForm form for creating release
type NewReleaseForm struct { type NewReleaseForm struct {
TagName string `binding:"Required;GitRefName"` TagName string `binding:"Required;GitRefName;MaxSize(255)"`
Target string `form:"tag_target" binding:"Required"` Target string `form:"tag_target" binding:"Required;MaxSize(255)"`
Title string `binding:"Required"` Title string `binding:"Required;MaxSize(255)"`
Content string Content string
Draft string Draft string
Prerelease bool Prerelease bool
@@ -515,7 +515,7 @@ func (f *NewReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bin
// EditReleaseForm form for changing release // EditReleaseForm form for changing release
type EditReleaseForm struct { type EditReleaseForm struct {
Title string `form:"title" binding:"Required"` Title string `form:"title" binding:"Required;MaxSize(255)"`
Content string `form:"content"` Content string `form:"content"`
Draft string `form:"draft"` Draft string `form:"draft"`
Prerelease bool `form:"prerelease"` Prerelease bool `form:"prerelease"`

View File

@@ -186,7 +186,16 @@ func ReferencesGitRepo(allowEmpty bool) macaron.Handler {
return return
} }
ctx.Repo.GitRepo = gitRepo ctx.Repo.GitRepo = gitRepo
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
} }
}()
}
ctx.Next()
} }
} }

View File

@@ -63,7 +63,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
// Force redirection when username is actually a user. // Force redirection when username is actually a user.
if !org.IsOrganization() { if !org.IsOrganization() {
ctx.Redirect("/" + org.Name) ctx.Redirect(setting.AppSubURL + "/" + org.Name)
return return
} }

View File

@@ -236,7 +236,7 @@ func RedirectToRepo(ctx *Context, redirectRepoID int64) {
if ctx.Req.URL.RawQuery != "" { if ctx.Req.URL.RawQuery != "" {
redirectPath += "?" + ctx.Req.URL.RawQuery redirectPath += "?" + ctx.Req.URL.RawQuery
} }
ctx.Redirect(redirectPath) ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
} }
func repoAssignment(ctx *Context, repo *models.Repository) { func repoAssignment(ctx *Context, repo *models.Repository) {
@@ -414,8 +414,8 @@ func RepoAssignment() macaron.Handler {
} }
} }
// repo is empty and display enable // Disable everything when the repo is being created
if ctx.Repo.Repository.IsEmpty || ctx.Repo.Repository.IsBeingCreated() { if ctx.Repo.Repository.IsBeingCreated() {
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
return return
} }
@@ -427,6 +427,21 @@ func RepoAssignment() macaron.Handler {
} }
ctx.Repo.GitRepo = gitRepo ctx.Repo.GitRepo = gitRepo
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
}
}()
// Stop at this point when the repo is empty.
if ctx.Repo.Repository.IsEmpty {
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
ctx.Next()
return
}
tags, err := ctx.Repo.GitRepo.GetTags() tags, err := ctx.Repo.GitRepo.GetTags()
if err != nil { if err != nil {
ctx.ServerError("GetTags", err) ctx.ServerError("GetTags", err)
@@ -482,6 +497,7 @@ func RepoAssignment() macaron.Handler {
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}"
} }
ctx.Next()
} }
} }
@@ -587,6 +603,13 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
ctx.ServerError("RepoRef Invalid repo "+repoPath, err) ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
return return
} }
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
}
}()
} }
// Get default branch. // Get default branch.
@@ -675,6 +698,8 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
return return
} }
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
ctx.Next()
} }
} }

View File

@@ -87,10 +87,11 @@ func (r *BlameReader) Close() error {
// CreateBlameReader creates reader for given repository, commit and file // CreateBlameReader creates reader for given repository, commit and file
func CreateBlameReader(repoPath, commitID, file string) (*BlameReader, error) { func CreateBlameReader(repoPath, commitID, file string) (*BlameReader, error) {
_, err := OpenRepository(repoPath) gitRepo, err := OpenRepository(repoPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
gitRepo.Close()
return createBlameReader(repoPath, GitExecutable, "blame", commitID, "--porcelain", "--", file) return createBlameReader(repoPath, GitExecutable, "blame", commitID, "--porcelain", "--", file)
} }

View File

@@ -37,6 +37,8 @@ THE SOFTWARE.
` `
repo, err := OpenRepository("../../.git") repo, err := OpenRepository("../../.git")
assert.NoError(t, err) assert.NoError(t, err)
defer repo.Close()
testBlob, err := repo.GetBlob("a8d4b49dd073a4a38a7e58385eeff7cc52568697") testBlob, err := repo.GetBlob("a8d4b49dd073a4a38a7e58385eeff7cc52568697")
assert.NoError(t, err) assert.NoError(t, err)
@@ -55,6 +57,8 @@ func Benchmark_Blob_Data(b *testing.B) {
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
defer repo.Close()
testBlob, err := repo.GetBlob("a8d4b49dd073a4a38a7e58385eeff7cc52568697") testBlob, err := repo.GetBlob("a8d4b49dd073a4a38a7e58385eeff7cc52568697")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)

View File

@@ -77,6 +77,8 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
testGetCommitsInfo(t, bareRepo1) testGetCommitsInfo(t, bareRepo1)
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestEntries_GetCommitsInfo") clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestEntries_GetCommitsInfo")
@@ -84,6 +86,8 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
defer os.RemoveAll(clonedPath) defer os.RemoveAll(clonedPath)
clonedRepo1, err := OpenRepository(clonedPath) clonedRepo1, err := OpenRepository(clonedPath)
assert.NoError(t, err) assert.NoError(t, err)
defer clonedRepo1.Close()
testGetCommitsInfo(t, clonedRepo1) testGetCommitsInfo(t, clonedRepo1)
} }
@@ -101,13 +105,16 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
for _, benchmark := range benchmarks { for _, benchmark := range benchmarks {
var commit *Commit var commit *Commit
var entries Entries var entries Entries
var repo *Repository
if repoPath, err := cloneRepo(benchmark.url, benchmarkReposDir, benchmark.name); err != nil { if repoPath, err := cloneRepo(benchmark.url, benchmarkReposDir, benchmark.name); err != nil {
b.Fatal(err) b.Fatal(err)
} else if repo, err := OpenRepository(repoPath); err != nil { } else if repo, err = OpenRepository(repoPath); err != nil {
b.Fatal(err) b.Fatal(err)
} else if commit, err = repo.GetBranchCommit("master"); err != nil { } else if commit, err = repo.GetBranchCommit("master"); err != nil {
repo.Close()
b.Fatal(err) b.Fatal(err)
} else if entries, err = commit.Tree.ListEntries(); err != nil { } else if entries, err = commit.Tree.ListEntries(); err != nil {
repo.Close()
b.Fatal(err) b.Fatal(err)
} }
entries.Sort() entries.Sort()
@@ -120,5 +127,6 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
} }
} }
}) })
repo.Close()
} }
} }

View File

@@ -8,6 +8,7 @@ package git
import ( import (
"fmt" "fmt"
"os/exec" "os/exec"
"runtime"
"strings" "strings"
"time" "time"
@@ -133,6 +134,13 @@ func Init() error {
return fmt.Errorf("Failed to execute 'git config --global gc.writeCommitGraph true': %s", stderr) return fmt.Errorf("Failed to execute 'git config --global gc.writeCommitGraph true': %s", stderr)
} }
} }
if runtime.GOOS == "windows" {
if _, stderr, err := process.GetManager().Exec("git.Init(git config --global core.longpaths true)",
GitExecutable, "config", "--global", "core.longpaths", "true"); err != nil {
return fmt.Errorf("Failed to execute 'git config --global core.longpaths true': %s", stderr)
}
}
return nil return nil
} }

View File

@@ -90,6 +90,11 @@ func (h *Hook) Update() error {
h.IsActive = false h.IsActive = false
return nil return nil
} }
d := filepath.Dir(h.path)
if err := os.MkdirAll(d, os.ModePerm); err != nil {
return err
}
err := ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm) err := ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
if err != nil { if err != nil {
return err return err

View File

@@ -15,6 +15,7 @@ func TestGetNotes(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
note := Note{} note := Note{}
err = GetNote(bareRepo1, "95bb4d39648ee7e325106df01a621c530863a653", &note) err = GetNote(bareRepo1, "95bb4d39648ee7e325106df01a621c530863a653", &note)
@@ -27,6 +28,7 @@ func TestGetNestedNotes(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo3_notes") repoPath := filepath.Join(testReposDir, "repo3_notes")
repo, err := OpenRepository(repoPath) repo, err := OpenRepository(repoPath)
assert.NoError(t, err) assert.NoError(t, err)
defer repo.Close()
note := Note{} note := Note{}
err = GetNote(repo, "3e668dbfac39cbc80a9ff9c61eb565d944453ba4", &note) err = GetNote(repo, "3e668dbfac39cbc80a9ff9c61eb565d944453ba4", &note)

View File

@@ -17,6 +17,7 @@ import (
"strings" "strings"
"time" "time"
gitealog "code.gitea.io/gitea/modules/log"
"github.com/unknwon/com" "github.com/unknwon/com"
"gopkg.in/src-d/go-billy.v4/osfs" "gopkg.in/src-d/go-billy.v4/osfs"
gogit "gopkg.in/src-d/go-git.v4" gogit "gopkg.in/src-d/go-git.v4"
@@ -107,6 +108,21 @@ func OpenRepository(repoPath string) (*Repository, error) {
}, nil }, nil
} }
// Close this repository, in particular close the underlying gogitStorage if this is not nil
func (repo *Repository) Close() {
if repo == nil || repo.gogitStorage == nil {
return
}
if err := repo.gogitStorage.Close(); err != nil {
gitealog.Error("Error closing storage: %v", err)
}
}
// GoGitRepo gets the go-git repo representation
func (repo *Repository) GoGitRepo() *gogit.Repository {
return repo.gogitRepo
}
// IsEmpty Check if repository is empty. // IsEmpty Check if repository is empty.
func (repo *Repository) IsEmpty() (bool, error) { func (repo *Repository) IsEmpty() (bool, error) {
var errbuf strings.Builder var errbuf strings.Builder

View File

@@ -17,6 +17,7 @@ func TestRepository_GetBlob_Found(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo1_bare") repoPath := filepath.Join(testReposDir, "repo1_bare")
r, err := OpenRepository(repoPath) r, err := OpenRepository(repoPath)
assert.NoError(t, err) assert.NoError(t, err)
defer r.Close()
testCases := []struct { testCases := []struct {
OID string OID string
@@ -44,6 +45,7 @@ func TestRepository_GetBlob_NotExist(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo1_bare") repoPath := filepath.Join(testReposDir, "repo1_bare")
r, err := OpenRepository(repoPath) r, err := OpenRepository(repoPath)
assert.NoError(t, err) assert.NoError(t, err)
defer r.Close()
testCase := "0000000000000000000000000000000000000000" testCase := "0000000000000000000000000000000000000000"
testError := ErrNotExist{testCase, ""} testError := ErrNotExist{testCase, ""}
@@ -57,6 +59,7 @@ func TestRepository_GetBlob_NoId(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo1_bare") repoPath := filepath.Join(testReposDir, "repo1_bare")
r, err := OpenRepository(repoPath) r, err := OpenRepository(repoPath)
assert.NoError(t, err) assert.NoError(t, err)
defer r.Close()
testCase := "" testCase := ""
testError := fmt.Errorf("Length must be 40: %s", testCase) testError := fmt.Errorf("Length must be 40: %s", testCase)

View File

@@ -108,6 +108,7 @@ func GetBranchesByPath(path string) ([]*Branch, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close()
brs, err := gitRepo.GetBranches() brs, err := gitRepo.GetBranches()
if err != nil { if err != nil {

View File

@@ -15,6 +15,7 @@ func TestRepository_GetBranches(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
branches, err := bareRepo1.GetBranches() branches, err := bareRepo1.GetBranches()
@@ -29,6 +30,7 @@ func BenchmarkRepository_GetBranches(b *testing.B) {
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
defer bareRepo1.Close()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err := bareRepo1.GetBranches() _, err := bareRepo1.GetBranches()

View File

@@ -15,6 +15,7 @@ func TestRepository_GetCommitBranches(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
// these test case are specific to the repo1_bare test repo // these test case are specific to the repo1_bare test repo
testCases := []struct { testCases := []struct {
@@ -41,6 +42,7 @@ func TestGetTagCommitWithSignature(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
commit, err := bareRepo1.GetCommit("3ad28a9149a2864384548f3d17ed7f38014c9e8a") commit, err := bareRepo1.GetCommit("3ad28a9149a2864384548f3d17ed7f38014c9e8a")
assert.NoError(t, err) assert.NoError(t, err)
@@ -54,6 +56,7 @@ func TestGetCommitWithBadCommitID(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
commit, err := bareRepo1.GetCommit("bad_branch") commit, err := bareRepo1.GetCommit("bad_branch")
assert.Nil(t, commit) assert.Nil(t, commit)

View File

@@ -20,6 +20,7 @@ func TestGetFormatPatch(t *testing.T) {
defer os.RemoveAll(clonedPath) defer os.RemoveAll(clonedPath)
repo, err := OpenRepository(clonedPath) repo, err := OpenRepository(clonedPath)
assert.NoError(t, err) assert.NoError(t, err)
defer repo.Close()
rd, err := repo.GetFormatPatch("8d92fc95^", "8d92fc95") rd, err := repo.GetFormatPatch("8d92fc95^", "8d92fc95")
assert.NoError(t, err) assert.NoError(t, err)
patchb, err := ioutil.ReadAll(rd) patchb, err := ioutil.ReadAll(rd)

View File

@@ -15,6 +15,7 @@ func TestRepository_GetRefs(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
refs, err := bareRepo1.GetRefs() refs, err := bareRepo1.GetRefs()
@@ -38,6 +39,7 @@ func TestRepository_GetRefsFiltered(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
refs, err := bareRepo1.GetRefsFiltered(TagPrefix) refs, err := bareRepo1.GetRefsFiltered(TagPrefix)

View File

@@ -16,6 +16,7 @@ func TestRepository_GetCodeActivityStats(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
timeFrom, err := time.Parse(time.RFC3339, "2016-01-01T00:00:00+00:00") timeFrom, err := time.Parse(time.RFC3339, "2016-01-01T00:00:00+00:00")
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -16,6 +16,7 @@ func TestRepository_GetTags(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path) bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
tags, err := bareRepo1.GetTagInfos() tags, err := bareRepo1.GetTagInfos()
assert.NoError(t, err) assert.NoError(t, err)
@@ -34,6 +35,7 @@ func TestRepository_GetTag(t *testing.T) {
bareRepo1, err := OpenRepository(clonedPath) bareRepo1, err := OpenRepository(clonedPath)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1" lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
lTagName := "lightweightTag" lTagName := "lightweightTag"
@@ -83,6 +85,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
bareRepo1, err := OpenRepository(clonedPath) bareRepo1, err := OpenRepository(clonedPath)
assert.NoError(t, err) assert.NoError(t, err)
defer bareRepo1.Close()
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1" lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
lTagName := "lightweightTag" lTagName := "lightweightTag"

View File

@@ -30,6 +30,7 @@ func TestRepoIsEmpty(t *testing.T) {
emptyRepo2Path := filepath.Join(testReposDir, "repo2_empty") emptyRepo2Path := filepath.Join(testReposDir, "repo2_empty")
repo, err := OpenRepository(emptyRepo2Path) repo, err := OpenRepository(emptyRepo2Path)
assert.NoError(t, err) assert.NoError(t, err)
defer repo.Close()
isEmpty, err := repo.IsEmpty() isEmpty, err := repo.IsEmpty()
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, isEmpty) assert.True(t, isEmpty)

View File

@@ -56,6 +56,7 @@ func TestEntriesCustomSort(t *testing.T) {
func TestFollowLink(t *testing.T) { func TestFollowLink(t *testing.T) {
r, err := OpenRepository("tests/repos/repo1_bare") r, err := OpenRepository("tests/repos/repo1_bare")
assert.NoError(t, err) assert.NoError(t, err)
defer r.Close()
commit, err := r.GetCommit("37991dec2c8e592043f47155ce4808d4580f9123") commit, err := r.GetCommit("37991dec2c8e592043f47155ce4808d4580f9123")
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -123,7 +123,7 @@ func Middleware(options ...Options) macaron.Handler {
// OK we should proxy the response writer // OK we should proxy the response writer
// We are still not necessarily going to compress... // We are still not necessarily going to compress...
proxyWriter := &ProxyResponseWriter{ proxyWriter := &ProxyResponseWriter{
ResponseWriter: ctx.Resp, internal: ctx.Resp,
} }
defer proxyWriter.Close() defer proxyWriter.Close()
@@ -137,19 +137,52 @@ func Middleware(options ...Options) macaron.Handler {
} }
ctx.Next() ctx.Next()
ctx.Resp = proxyWriter.internal
} }
} }
// ProxyResponseWriter is a wrapped macaron ResponseWriter that may compress its contents // ProxyResponseWriter is a wrapped macaron ResponseWriter that may compress its contents
type ProxyResponseWriter struct { type ProxyResponseWriter struct {
writer io.WriteCloser writer io.WriteCloser
macaron.ResponseWriter internal macaron.ResponseWriter
stopped bool stopped bool
code int code int
buf []byte buf []byte
} }
// Header returns the header map
func (proxy *ProxyResponseWriter) Header() http.Header {
return proxy.internal.Header()
}
// Status returns the status code of the response or 0 if the response has not been written.
func (proxy *ProxyResponseWriter) Status() int {
if proxy.code != 0 {
return proxy.code
}
return proxy.internal.Status()
}
// Written returns whether or not the ResponseWriter has been written.
func (proxy *ProxyResponseWriter) Written() bool {
if proxy.code != 0 {
return true
}
return proxy.internal.Written()
}
// Size returns the size of the response body.
func (proxy *ProxyResponseWriter) Size() int {
return proxy.internal.Size()
}
// Before allows for a function to be called before the ResponseWriter has been written to. This is
// useful for setting headers or any other operations that must happen before a response has been written.
func (proxy *ProxyResponseWriter) Before(before macaron.BeforeFunc) {
proxy.internal.Before(before)
}
// Write appends data to the proxied gzip writer. // Write appends data to the proxied gzip writer.
func (proxy *ProxyResponseWriter) Write(b []byte) (int, error) { func (proxy *ProxyResponseWriter) Write(b []byte) (int, error) {
// if writer is initialized, use the writer // if writer is initialized, use the writer
@@ -210,7 +243,7 @@ func (proxy *ProxyResponseWriter) startGzip() error {
// Write the header to gzip response. // Write the header to gzip response.
if proxy.code != 0 { if proxy.code != 0 {
proxy.ResponseWriter.WriteHeader(proxy.code) proxy.internal.WriteHeader(proxy.code)
// Ensure that no other WriteHeader's happen // Ensure that no other WriteHeader's happen
proxy.code = 0 proxy.code = 0
} }
@@ -220,7 +253,7 @@ func (proxy *ProxyResponseWriter) startGzip() error {
// write the gzip header even if nothing was ever written. // write the gzip header even if nothing was ever written.
if len(proxy.buf) > 0 { if len(proxy.buf) > 0 {
// Initialize the GZIP response. // Initialize the GZIP response.
proxy.writer = writerPool.Get(proxy.ResponseWriter) proxy.writer = writerPool.Get(proxy.internal)
return proxy.writeBuf() return proxy.writeBuf()
} }
@@ -229,11 +262,11 @@ func (proxy *ProxyResponseWriter) startGzip() error {
func (proxy *ProxyResponseWriter) startPlain() error { func (proxy *ProxyResponseWriter) startPlain() error {
if proxy.code != 0 { if proxy.code != 0 {
proxy.ResponseWriter.WriteHeader(proxy.code) proxy.internal.WriteHeader(proxy.code)
proxy.code = 0 proxy.code = 0
} }
proxy.stopped = true proxy.stopped = true
proxy.writer = noopCloser{proxy.ResponseWriter} proxy.writer = noopCloser{proxy.internal}
return proxy.writeBuf() return proxy.writeBuf()
} }
@@ -295,13 +328,13 @@ func (proxy *ProxyResponseWriter) Flush() {
gw.Flush() gw.Flush()
} }
proxy.ResponseWriter.Flush() proxy.internal.Flush()
} }
// Hijack implements http.Hijacker. If the underlying ResponseWriter is a // Hijack implements http.Hijacker. If the underlying ResponseWriter is a
// Hijacker, its Hijack method is returned. Otherwise an error is returned. // Hijacker, its Hijack method is returned. Otherwise an error is returned.
func (proxy *ProxyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { func (proxy *ProxyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := proxy.ResponseWriter.(http.Hijacker) hijacker, ok := proxy.internal.(http.Hijacker)
if !ok { if !ok {
return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
} }

View File

@@ -10,7 +10,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"github.com/lunny/levelqueue" "gitea.com/lunny/levelqueue"
) )
var ( var (

View File

@@ -17,4 +17,5 @@ type Uploader interface {
CreateComments(comments ...*Comment) error CreateComments(comments ...*Comment) error
CreatePullRequests(prs ...*PullRequest) error CreatePullRequests(prs ...*PullRequest) error
Rollback() error Rollback() error
Close()
} }

View File

@@ -131,6 +131,13 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
return err return err
} }
// Close closes this uploader
func (g *GiteaLocalUploader) Close() {
if g.gitRepo != nil {
g.gitRepo.Close()
}
}
// CreateTopics creates topics // CreateTopics creates topics
func (g *GiteaLocalUploader) CreateTopics(topics ...string) error { func (g *GiteaLocalUploader) CreateTopics(topics ...string) error {
return models.SaveTopics(g.repo.ID, topics...) return models.SaveTopics(g.repo.ID, topics...)
@@ -252,6 +259,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
} }
// download attachment // download attachment
err = func() error {
resp, err := http.Get(asset.URL) resp, err := http.Get(asset.URL)
if err != nil { if err != nil {
return err return err
@@ -269,10 +277,12 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
} }
defer fw.Close() defer fw.Close()
if _, err := io.Copy(fw, resp.Body); err != nil { _, err = io.Copy(fw, resp.Body)
return err
}()
if err != nil {
return err return err
} }
rel.Attachments = append(rel.Attachments, &attach) rel.Attachments = append(rel.Attachments, &attach)
} }
@@ -468,21 +478,24 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
} }
// download patch file // download patch file
err := func() error {
resp, err := http.Get(pr.PatchURL) resp, err := http.Get(pr.PatchURL)
if err != nil { if err != nil {
return nil, err return err
} }
defer resp.Body.Close() defer resp.Body.Close()
pullDir := filepath.Join(g.repo.RepoPath(), "pulls") pullDir := filepath.Join(g.repo.RepoPath(), "pulls")
if err = os.MkdirAll(pullDir, os.ModePerm); err != nil { if err = os.MkdirAll(pullDir, os.ModePerm); err != nil {
return nil, err return err
} }
f, err := os.Create(filepath.Join(pullDir, fmt.Sprintf("%d.patch", pr.Number))) f, err := os.Create(filepath.Join(pullDir, fmt.Sprintf("%d.patch", pr.Number)))
if err != nil { if err != nil {
return nil, err return err
} }
defer f.Close() defer f.Close()
_, err = io.Copy(f, resp.Body) _, err = io.Copy(f, resp.Body)
return err
}()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -496,8 +509,8 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer p.Close()
_, err = p.WriteString(pr.Head.SHA) _, err = p.WriteString(pr.Head.SHA)
p.Close()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -531,8 +544,8 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer b.Close()
_, err = b.WriteString(pr.Head.SHA) _, err = b.WriteString(pr.Head.SHA)
b.Close()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -581,7 +594,6 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
var pullRequest = models.PullRequest{ var pullRequest = models.PullRequest{
HeadRepoID: g.repo.ID, HeadRepoID: g.repo.ID,
HeadBranch: head, HeadBranch: head,
HeadUserName: g.repoOwner,
BaseRepoID: g.repo.ID, BaseRepoID: g.repo.ID,
BaseBranch: pr.Base.Ref, BaseBranch: pr.Base.Ref,
MergeBase: pr.Base.SHA, MergeBase: pr.Base.SHA,

View File

@@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func assertMilestoneEqual(t *testing.T, title, dueOn, created, updated, closed, state string, ms *base.Milestone) { func assertMilestoneEqual(t *testing.T, description, title, dueOn, created, updated, closed, state string, ms *base.Milestone) {
var tmPtr *time.Time var tmPtr *time.Time
if dueOn != "" { if dueOn != "" {
tm, err := time.Parse("2006-01-02 15:04:05 -0700 MST", dueOn) tm, err := time.Parse("2006-01-02 15:04:05 -0700 MST", dueOn)
@@ -43,6 +43,7 @@ func assertMilestoneEqual(t *testing.T, title, dueOn, created, updated, closed,
} }
assert.EqualValues(t, &base.Milestone{ assert.EqualValues(t, &base.Milestone{
Description: description,
Title: title, Title: title,
Deadline: tmPtr, Deadline: tmPtr,
State: state, State: state,
@@ -52,23 +53,24 @@ func assertMilestoneEqual(t *testing.T, title, dueOn, created, updated, closed,
}, ms) }, ms)
} }
func assertLabelEqual(t *testing.T, name, color string, label *base.Label) { func assertLabelEqual(t *testing.T, name, color, description string, label *base.Label) {
assert.EqualValues(t, &base.Label{ assert.EqualValues(t, &base.Label{
Name: name, Name: name,
Color: color, Color: color,
Description: description,
}, label) }, label)
} }
func TestGitHubDownloadRepo(t *testing.T) { func TestGitHubDownloadRepo(t *testing.T) {
downloader := NewGithubDownloaderV3("", "", "go-gitea", "gitea") downloader := NewGithubDownloaderV3("", "", "go-gitea", "test_repo")
repo, err := downloader.GetRepoInfo() repo, err := downloader.GetRepoInfo()
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, &base.Repository{ assert.EqualValues(t, &base.Repository{
Name: "gitea", Name: "test_repo",
Owner: "go-gitea", Owner: "go-gitea",
Description: "Git with a cup of tea, painless self-hosted git service", Description: "Test repository for testing migration from github to gitea",
CloneURL: "https://github.com/go-gitea/gitea.git", CloneURL: "https://github.com/go-gitea/test_repo.git",
OriginalURL: "https://github.com/go-gitea/gitea", OriginalURL: "https://github.com/go-gitea/test_repo",
}, repo) }, repo)
topics, err := downloader.GetTopics() topics, err := downloader.GetTopics()
@@ -77,83 +79,46 @@ func TestGitHubDownloadRepo(t *testing.T) {
milestones, err := downloader.GetMilestones() milestones, err := downloader.GetMilestones()
assert.NoError(t, err) assert.NoError(t, err)
// before this tool release, we have 39 milestones on github.com/go-gitea/gitea assert.True(t, len(milestones) >= 2)
assert.True(t, len(milestones) >= 39)
for _, milestone := range milestones { for _, milestone := range milestones {
switch milestone.Title { switch milestone.Title {
case "1.0.0": case "1.0.0":
assertMilestoneEqual(t, "1.0.0", "2016-12-23 08:00:00 +0000 UTC", assertMilestoneEqual(t, "Milestone 1.0.0", "1.0.0", "2019-11-11 08:00:00 +0000 UTC",
"2016-11-02 18:06:55 +0000 UTC", "2019-11-12 19:37:08 +0000 UTC",
"2016-12-29 10:26:00 +0000 UTC", "2019-11-12 21:56:17 +0000 UTC",
"2016-12-24 00:40:56 +0000 UTC", "2019-11-12 19:45:49 +0000 UTC",
"closed", milestone) "closed", milestone)
case "1.1.0": case "1.1.0":
assertMilestoneEqual(t, "1.1.0", "2017-02-24 08:00:00 +0000 UTC", assertMilestoneEqual(t, "Milestone 1.1.0", "1.1.0", "2019-11-12 08:00:00 +0000 UTC",
"2016-11-03 08:40:10 +0000 UTC", "2019-11-12 19:37:25 +0000 UTC",
"2017-06-15 05:04:36 +0000 UTC", "2019-11-12 21:39:27 +0000 UTC",
"2017-03-09 21:22:21 +0000 UTC", "2019-11-12 19:45:46 +0000 UTC",
"closed", milestone)
case "1.2.0":
assertMilestoneEqual(t, "1.2.0", "2017-04-24 07:00:00 +0000 UTC",
"2016-11-03 08:40:15 +0000 UTC",
"2017-12-10 02:43:29 +0000 UTC",
"2017-10-12 08:24:28 +0000 UTC",
"closed", milestone)
case "1.3.0":
assertMilestoneEqual(t, "1.3.0", "2017-11-29 08:00:00 +0000 UTC",
"2017-03-03 08:08:59 +0000 UTC",
"2017-12-04 07:48:44 +0000 UTC",
"2017-11-29 18:39:00 +0000 UTC",
"closed", milestone)
case "1.4.0":
assertMilestoneEqual(t, "1.4.0", "2018-01-25 08:00:00 +0000 UTC",
"2017-08-23 11:02:37 +0000 UTC",
"2018-03-25 20:01:56 +0000 UTC",
"2018-03-25 20:01:56 +0000 UTC",
"closed", milestone)
case "1.5.0":
assertMilestoneEqual(t, "1.5.0", "2018-06-15 07:00:00 +0000 UTC",
"2017-12-30 04:21:56 +0000 UTC",
"2018-09-05 16:34:22 +0000 UTC",
"2018-08-11 08:45:01 +0000 UTC",
"closed", milestone)
case "1.6.0":
assertMilestoneEqual(t, "1.6.0", "2018-09-25 07:00:00 +0000 UTC",
"2018-05-11 05:37:01 +0000 UTC",
"2019-01-27 19:21:22 +0000 UTC",
"2018-11-23 13:23:16 +0000 UTC",
"closed", milestone)
case "1.7.0":
assertMilestoneEqual(t, "1.7.0", "2018-12-25 08:00:00 +0000 UTC",
"2018-08-28 14:20:14 +0000 UTC",
"2019-01-27 11:30:24 +0000 UTC",
"2019-01-23 08:58:23 +0000 UTC",
"closed", milestone) "closed", milestone)
} }
} }
labels, err := downloader.GetLabels() labels, err := downloader.GetLabels()
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, len(labels) >= 48) assert.True(t, len(labels) >= 8)
for _, l := range labels { for _, l := range labels {
switch l.Name { switch l.Name {
case "backport/v1.7": case "bug":
assertLabelEqual(t, "backport/v1.7", "fbca04", l) assertLabelEqual(t, "bug", "d73a4a", "Something isn't working", l)
case "backport/v1.8": case "documentation":
assertLabelEqual(t, "backport/v1.8", "fbca04", l) assertLabelEqual(t, "documentation", "0075ca", "Improvements or additions to documentation", l)
case "kind/api": case "duplicate":
assertLabelEqual(t, "kind/api", "5319e7", l) assertLabelEqual(t, "duplicate", "cfd3d7", "This issue or pull request already exists", l)
case "kind/breaking": case "enhancement":
assertLabelEqual(t, "kind/breaking", "fbca04", l) assertLabelEqual(t, "enhancement", "a2eeef", "New feature or request", l)
case "kind/bug": case "good first issue":
assertLabelEqual(t, "kind/bug", "ee0701", l) assertLabelEqual(t, "good first issue", "7057ff", "Good for newcomers", l)
case "kind/docs": case "help wanted":
assertLabelEqual(t, "kind/docs", "c2e0c6", l) assertLabelEqual(t, "help wanted", "008672", "Extra attention is needed", l)
case "kind/enhancement": case "invalid":
assertLabelEqual(t, "kind/enhancement", "84b6eb", l) assertLabelEqual(t, "invalid", "e4e669", "This doesn't seem right", l)
case "kind/feature": case "question":
assertLabelEqual(t, "kind/feature", "006b75", l) assertLabelEqual(t, "question", "d876e3", "Further information is requested", l)
} }
} }
@@ -163,48 +128,50 @@ func TestGitHubDownloadRepo(t *testing.T) {
{ {
TagName: "v0.9.99", TagName: "v0.9.99",
TargetCommitish: "master", TargetCommitish: "master",
Name: "fork", Name: "First Release",
Body: "Forked source from Gogs into Gitea\n", Body: "A test release",
Created: time.Date(2016, 10, 17, 02, 17, 59, 0, time.UTC), Created: time.Date(2019, 11, 9, 16, 49, 21, 0, time.UTC),
Published: time.Date(2016, 11, 17, 15, 37, 0, 0, time.UTC), Published: time.Date(2019, 11, 12, 20, 12, 10, 0, time.UTC),
PublisherID: 4726179, PublisherID: 1669571,
PublisherName: "bkcsoft", PublisherName: "mrsdizzie",
}, },
}, releases[len(releases)-1:]) }, releases[len(releases)-1:])
// downloader.GetIssues() // downloader.GetIssues()
issues, isEnd, err := downloader.GetIssues(1, 8) issues, isEnd, err := downloader.GetIssues(1, 2)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 3, len(issues)) assert.EqualValues(t, 2, len(issues))
assert.False(t, isEnd) assert.False(t, isEnd)
var ( var (
closed1 = time.Date(2018, 10, 23, 02, 57, 43, 0, time.UTC) closed1 = time.Date(2019, 11, 12, 20, 22, 22, 0, time.UTC)
closed7 = time.Date(2019, 7, 8, 8, 20, 23, 0, time.UTC) closed2 = time.Date(2019, 11, 12, 21, 1, 31, 0, time.UTC)
) )
assert.EqualValues(t, []*base.Issue{ assert.EqualValues(t, []*base.Issue{
{ {
Number: 6, Number: 1,
Title: "Contribution system: History heatmap for user", Title: "Please add an animated gif icon to the merge button",
Content: "Hi guys,\r\n\r\nI think that is a possible feature, a history heatmap similar to github or gitlab.\r\nActually exists a plugin called Calendar HeatMap. I used this on mine project to heat application log and worked fine here.\r\nThen, is only a idea, what you think? :)\r\n\r\nhttp://cal-heatmap.com/\r\nhttps://github.com/wa0x6e/cal-heatmap\r\n\r\nReference: https://github.com/gogits/gogs/issues/1640", Content: "I just want the merge button to hurt my eyes a little. \xF0\x9F\x98\x9D ",
Milestone: "1.7.0", Milestone: "1.0.0",
PosterID: 1520407, PosterID: 18600385,
PosterName: "joubertredrat", PosterName: "guillep2k",
State: "closed", State: "closed",
Created: time.Date(2016, 11, 02, 18, 51, 55, 0, time.UTC), Created: time.Date(2019, 11, 9, 17, 0, 29, 0, time.UTC),
Labels: []*base.Label{ Labels: []*base.Label{
{ {
Name: "kind/feature", Name: "bug",
Color: "006b75", Color: "d73a4a",
Description: "Something isn't working",
}, },
{ {
Name: "kind/ui", Name: "good first issue",
Color: "fef2c0", Color: "7057ff",
Description: "Good for newcomers",
}, },
}, },
Reactions: &base.Reactions{ Reactions: &base.Reactions{
TotalCount: 0, TotalCount: 1,
PlusOne: 0, PlusOne: 1,
MinusOne: 0, MinusOne: 0,
Laugh: 0, Laugh: 0,
Confused: 0, Confused: 0,
@@ -214,84 +181,48 @@ func TestGitHubDownloadRepo(t *testing.T) {
Closed: &closed1, Closed: &closed1,
}, },
{ {
Number: 7, Number: 2,
Title: "display page revisions on wiki", Title: "Test issue",
Content: "Hi guys,\r\n\r\nWiki on Gogs is very fine, I liked a lot, but I think that is good idea to be possible see other revisions from page as a page history.\r\n\r\nWhat you think?\r\n\r\nReference: https://github.com/gogits/gogs/issues/2991", Content: "This is test issue 2, do not touch!",
Milestone: "1.10.0", Milestone: "1.1.0",
PosterID: 1520407, PosterID: 1669571,
PosterName: "joubertredrat", PosterName: "mrsdizzie",
State: "closed", State: "closed",
Created: time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC), Created: time.Date(2019, 11, 12, 21, 0, 6, 0, time.UTC),
Labels: []*base.Label{ Labels: []*base.Label{
{ {
Name: "kind/feature", Name: "duplicate",
Color: "006b75", Color: "cfd3d7",
}, Description: "This issue or pull request already exists",
{
Name: "reviewed/confirmed",
Color: "8d9b12",
Description: "Issue has been reviewed and confirmed to be present or accepted to be implemented",
}, },
}, },
Reactions: &base.Reactions{ Reactions: &base.Reactions{
TotalCount: 6, TotalCount: 6,
PlusOne: 5, PlusOne: 1,
MinusOne: 0, MinusOne: 1,
Laugh: 0, Laugh: 1,
Confused: 1, Confused: 1,
Heart: 0,
Hooray: 0,
},
Closed: &closed7,
},
{
Number: 8,
Title: "audit logs",
Content: "Hi,\r\n\r\nI think that is good idea to have user operation log to admin see what the user is doing at Gogs. Similar to example below\r\n\r\n| user | operation | information |\r\n| --- | --- | --- |\r\n| joubertredrat | repo.create | Create repo MyProjectData |\r\n| joubertredrat | user.settings | Edit settings |\r\n| tboerger | repo.fork | Create Fork from MyProjectData to ForkMyProjectData |\r\n| bkcsoft | repo.remove | Remove repo MySource |\r\n| tboerger | admin.auth | Edit auth LDAP org-connection |\r\n\r\nThis resource can be used on user page too, as user activity, set that log row is public (repo._) or private (user._, admin.*) and display only public activity.\r\n\r\nWhat you think?\r\n\r\n[Chat summary from March 14, 2017](https://github.com/go-gitea/gitea/issues/8#issuecomment-286463807)\r\n\r\nReferences:\r\nhttps://github.com/gogits/gogs/issues/3016",
Milestone: "1.x.x",
PosterID: 1520407,
PosterName: "joubertredrat",
State: "open",
Created: time.Date(2016, 11, 02, 18, 59, 20, 0, time.UTC),
Labels: []*base.Label{
{
Name: "kind/feature",
Color: "006b75",
},
{
Name: "kind/proposal",
Color: "5319e7",
},
},
Reactions: &base.Reactions{
TotalCount: 9,
PlusOne: 8,
MinusOne: 0,
Laugh: 0,
Confused: 0,
Heart: 1, Heart: 1,
Hooray: 0, Hooray: 1,
}, },
Closed: &closed2,
}, },
}, issues) }, issues)
// downloader.GetComments() // downloader.GetComments()
comments, err := downloader.GetComments(6) comments, err := downloader.GetComments(2)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 35, len(comments)) assert.EqualValues(t, 2, len(comments))
assert.EqualValues(t, []*base.Comment{ assert.EqualValues(t, []*base.Comment{
{ {
IssueIndex: 6, IssueIndex: 2,
PosterID: 4726179, PosterID: 1669571,
PosterName: "bkcsoft", PosterName: "mrsdizzie",
Created: time.Date(2016, 11, 02, 18, 59, 48, 0, time.UTC), Created: time.Date(2019, 11, 12, 21, 0, 13, 0, time.UTC),
Content: `I would prefer a solution that is in the backend, unless it's required to have it update without reloading. Unfortunately I can't seem to find anything that does that :unamused: Content: "This is a comment",
Also this would _require_ caching, since it will fetch huge amounts of data from disk...
`,
Reactions: &base.Reactions{ Reactions: &base.Reactions{
TotalCount: 2, TotalCount: 1,
PlusOne: 2, PlusOne: 1,
MinusOne: 0, MinusOne: 0,
Laugh: 0, Laugh: 0,
Confused: 0, Confused: 0,
@@ -300,14 +231,11 @@ Also this would _require_ caching, since it will fetch huge amounts of data from
}, },
}, },
{ {
IssueIndex: 6, IssueIndex: 2,
PosterID: 1520407, PosterID: 1669571,
PosterName: "joubertredrat", PosterName: "mrsdizzie",
Created: time.Date(2016, 11, 02, 19, 16, 56, 0, time.UTC), Created: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC),
Content: `Yes, this plugin build on front-end, with backend I don't know too, but we can consider make component for this. Content: "A second comment",
In my case I use ajax to get data, but build on frontend anyway
`,
Reactions: &base.Reactions{ Reactions: &base.Reactions{
TotalCount: 0, TotalCount: 0,
PlusOne: 0, PlusOne: 0,
@@ -318,154 +246,85 @@ In my case I use ajax to get data, but build on frontend anyway
Hooray: 0, Hooray: 0,
}, },
}, },
{ }, comments[:2])
IssueIndex: 6,
PosterID: 1799009,
PosterName: "xinity",
Created: time.Date(2016, 11, 03, 13, 04, 56, 0, time.UTC),
Content: `following @bkcsoft retention strategy in cache is a must if we don't want gitea to waste ressources.
something like in the latest 15days could be enough don't you think ?
`,
Reactions: &base.Reactions{
TotalCount: 2,
PlusOne: 2,
MinusOne: 0,
Laugh: 0,
Confused: 0,
Heart: 0,
Hooray: 0,
},
},
}, comments[:3])
// downloader.GetPullRequests() // downloader.GetPullRequests()
prs, err := downloader.GetPullRequests(1, 3) prs, err := downloader.GetPullRequests(1, 2)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 3, len(prs)) assert.EqualValues(t, 2, len(prs))
closed1 = time.Date(2016, 11, 02, 18, 22, 21, 0, time.UTC) closed1 = time.Date(2019, 11, 12, 21, 39, 27, 0, time.UTC)
var ( var merged1 = time.Date(2019, 11, 12, 21, 39, 27, 0, time.UTC)
closed2 = time.Date(2016, 11, 03, 8, 06, 27, 0, time.UTC)
closed3 = time.Date(2016, 11, 02, 18, 22, 31, 0, time.UTC)
)
var (
merged1 = time.Date(2016, 11, 02, 18, 22, 21, 0, time.UTC)
merged2 = time.Date(2016, 11, 03, 8, 06, 27, 0, time.UTC)
merged3 = time.Date(2016, 11, 02, 18, 22, 31, 0, time.UTC)
)
assert.EqualValues(t, []*base.PullRequest{ assert.EqualValues(t, []*base.PullRequest{
{ {
Number: 1, Number: 3,
Title: "Rename import paths: \"github.com/gogits/gogs\" -> \"github.com/go-gitea/gitea\"", Title: "Update README.md",
Content: "", Content: "add warning to readme",
Milestone: "1.0.0", Milestone: "1.1.0",
PosterID: 7011819, PosterID: 1669571,
PosterName: "andreynering", PosterName: "mrsdizzie",
State: "closed", State: "closed",
Created: time.Date(2016, 11, 02, 17, 01, 19, 0, time.UTC), Created: time.Date(2019, 11, 12, 21, 21, 43, 0, time.UTC),
Labels: []*base.Label{ Labels: []*base.Label{
{ {
Name: "kind/enhancement", Name: "documentation",
Color: "84b6eb", Color: "0075ca",
}, Description: "Improvements or additions to documentation",
{
Name: "lgtm/done",
Color: "0e8a16",
}, },
}, },
PatchURL: "https://github.com/go-gitea/gitea/pull/1.patch", PatchURL: "https://github.com/go-gitea/test_repo/pull/3.patch",
Head: base.PullRequestBranch{ Head: base.PullRequestBranch{
Ref: "import-paths", Ref: "master",
SHA: "1b0ec3208db8501acba44a137c009a5a126ebaa9", CloneURL: "https://github.com/mrsdizzie/test_repo.git",
OwnerName: "andreynering", SHA: "076160cf0b039f13e5eff19619932d181269414b",
RepoName: "test_repo",
OwnerName: "mrsdizzie",
}, },
Base: base.PullRequestBranch{ Base: base.PullRequestBranch{
Ref: "master", Ref: "master",
SHA: "6bcff7828f117af8d51285ce3acba01a7e40a867", SHA: "72866af952e98d02a73003501836074b286a78f6",
OwnerName: "go-gitea", OwnerName: "go-gitea",
RepoName: "gitea", RepoName: "test_repo",
}, },
Closed: &closed1, Closed: &closed1,
Merged: true, Merged: true,
MergedTime: &merged1, MergedTime: &merged1,
MergeCommitSHA: "142d35e8d2baec230ddb565d1265940d59141fab", MergeCommitSHA: "f32b0a9dfd09a60f616f29158f772cedd89942d2",
}, },
{ {
Number: 2, Number: 4,
Title: "Fix sender of issue notifications", Title: "Test branch",
Content: "It is the FROM field in mailer configuration that needs be used,\r\nnot the USER field, which is for authentication.\r\n\r\nMigrated from https://github.com/gogits/gogs/pull/3616\r\n", Content: "do not merge this PR",
Milestone: "1.0.0", Milestone: "1.0.0",
PosterID: 289678, PosterID: 1669571,
PosterName: "strk", PosterName: "mrsdizzie",
State: "closed", State: "open",
Created: time.Date(2016, 11, 02, 17, 24, 19, 0, time.UTC), Created: time.Date(2019, 11, 12, 21, 54, 18, 0, time.UTC),
Labels: []*base.Label{ Labels: []*base.Label{
{ {
Name: "kind/bug", Name: "bug",
Color: "ee0701", Color: "d73a4a",
}, Description: "Something isn't working",
{
Name: "lgtm/done",
Color: "0e8a16",
}, },
}, },
PatchURL: "https://github.com/go-gitea/gitea/pull/2.patch", PatchURL: "https://github.com/go-gitea/test_repo/pull/4.patch",
Head: base.PullRequestBranch{ Head: base.PullRequestBranch{
Ref: "proper-from-on-issue-mail", Ref: "test-branch",
SHA: "af03d00780a6ee70c58e135c6679542cde4f8d50", SHA: "2be9101c543658591222acbee3eb799edfc3853d",
RepoName: "gogs", RepoName: "test_repo",
OwnerName: "strk", OwnerName: "mrsdizzie",
CloneURL: "https://github.com/strk/gogs.git", CloneURL: "https://github.com/mrsdizzie/test_repo.git",
}, },
Base: base.PullRequestBranch{ Base: base.PullRequestBranch{
Ref: "develop", Ref: "master",
SHA: "5c5424301443ffa3659737d12de48ab1dfe39a00", SHA: "f32b0a9dfd09a60f616f29158f772cedd89942d2",
OwnerName: "go-gitea", OwnerName: "go-gitea",
RepoName: "gitea", RepoName: "test_repo",
}, },
Closed: &closed2, Merged: false,
Merged: true, MergeCommitSHA: "565d1208f5fffdc1c5ae1a2436491eb9a5e4ebae",
MergedTime: &merged2,
MergeCommitSHA: "d8de2beb5b92d02a0597ba7c7803839380666653",
},
{
Number: 3,
Title: "Use proper url for libravatar dep",
Content: "Fetch go-libravatar from its official source, rather than from an unmaintained fork\r\n",
Milestone: "1.0.0",
PosterID: 289678,
PosterName: "strk",
State: "closed",
Created: time.Date(2016, 11, 02, 17, 34, 31, 0, time.UTC),
Labels: []*base.Label{
{
Name: "kind/enhancement",
Color: "84b6eb",
},
{
Name: "lgtm/done",
Color: "0e8a16",
},
},
PatchURL: "https://github.com/go-gitea/gitea/pull/3.patch",
Head: base.PullRequestBranch{
Ref: "libravatar-proper-url",
SHA: "d59a48a2550abd4129b96d38473941b895a4859b",
RepoName: "gogs",
OwnerName: "strk",
CloneURL: "https://github.com/strk/gogs.git",
},
Base: base.PullRequestBranch{
Ref: "develop",
SHA: "6bcff7828f117af8d51285ce3acba01a7e40a867",
OwnerName: "go-gitea",
RepoName: "gitea",
},
Closed: &closed3,
Merged: true,
MergedTime: &merged3,
MergeCommitSHA: "5c5424301443ffa3659737d12de48ab1dfe39a00",
}, },
}, prs) }, prs)
} }

View File

@@ -94,6 +94,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
if err := uploader.CreateRepo(repo, opts); err != nil { if err := uploader.CreateRepo(repo, opts); err != nil {
return err return err
} }
defer uploader.Close()
log.Trace("migrating topics") log.Trace("migrating topics")
topics, err := downloader.GetTopics() topics, err := downloader.GetTopics()

View File

@@ -5,8 +5,6 @@
package migrations package migrations
import ( import (
"strconv"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
@@ -40,11 +38,7 @@ func updateMigrationPosterIDByGitService(tp structs.GitServiceType) error {
} }
for _, user := range users { for _, user := range users {
externalUserID, err := strconv.ParseInt(user.ExternalID, 10, 64) externalUserID := user.ExternalID
if err != nil {
log.Warn("Parse externalUser %#v 's userID failed: %v", user, err)
continue
}
if err := models.UpdateMigrationsByType(tp, externalUserID, user.UserID); err != nil { if err := models.UpdateMigrationsByType(tp, externalUserID, user.UserID); err != nil {
log.Error("UpdateMigrationsByType type %s external user id %v to local user id %v failed: %v", tp.Name(), user.ExternalID, user.UserID, err) log.Error("UpdateMigrationsByType type %s external user id %v to local user id %v failed: %v", tp.Name(), user.ExternalID, user.UserID, err)
} }

View File

@@ -7,45 +7,60 @@ package password
import ( import (
"crypto/rand" "crypto/rand"
"math/big" "math/big"
"regexp" "strings"
"sync" "sync"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
) )
var matchComplexities = map[string]regexp.Regexp{} var (
var matchComplexityOnce sync.Once matchComplexityOnce sync.Once
var validChars string validChars string
var validComplexities = map[string]string{ requiredChars []string
"lower": "abcdefghijklmnopqrstuvwxyz",
"upper": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", charComplexities = map[string]string{
"digit": "0123456789", "lower": `abcdefghijklmnopqrstuvwxyz`,
"spec": `][ !"#$%&'()*+,./:;<=>?@\^_{|}~` + "`-", "upper": `ABCDEFGHIJKLMNOPQRSTUVWXYZ`,
} "digit": `0123456789`,
"spec": ` !"#$%&'()*+,-./:;<=>?@[\]^_{|}~` + "`",
}
)
// NewComplexity for preparation // NewComplexity for preparation
func NewComplexity() { func NewComplexity() {
matchComplexityOnce.Do(func() { matchComplexityOnce.Do(func() {
if len(setting.PasswordComplexity) > 0 { setupComplexity(setting.PasswordComplexity)
for key, val := range setting.PasswordComplexity {
matchComplexity := regexp.MustCompile(val)
matchComplexities[key] = *matchComplexity
validChars += validComplexities[key]
}
} else {
for _, val := range validComplexities {
validChars += val
}
}
}) })
} }
// IsComplexEnough return True if password is Complexity func setupComplexity(values []string) {
if len(values) != 1 || values[0] != "off" {
for _, val := range values {
if chars, ok := charComplexities[val]; ok {
validChars += chars
requiredChars = append(requiredChars, chars)
}
}
if len(requiredChars) == 0 {
// No valid character classes found; use all classes as default
for _, chars := range charComplexities {
validChars += chars
requiredChars = append(requiredChars, chars)
}
}
}
if validChars == "" {
// No complexities to check; provide a sensible default for password generation
validChars = charComplexities["lower"] + charComplexities["upper"] + charComplexities["digit"]
}
}
// IsComplexEnough return True if password meets complexity settings
func IsComplexEnough(pwd string) bool { func IsComplexEnough(pwd string) bool {
if len(setting.PasswordComplexity) > 0 {
NewComplexity() NewComplexity()
for _, val := range matchComplexities { if len(validChars) > 0 {
if !val.MatchString(pwd) { for _, req := range requiredChars {
if !strings.ContainsAny(req, pwd) {
return false return false
} }
} }

View File

@@ -0,0 +1,75 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package password
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestComplexity_IsComplexEnough(t *testing.T) {
matchComplexityOnce.Do(func() {})
testlist := []struct {
complexity []string
truevalues []string
falsevalues []string
}{
{[]string{"lower"}, []string{"abc", "abc!"}, []string{"ABC", "123", "=!$", ""}},
{[]string{"upper"}, []string{"ABC"}, []string{"abc", "123", "=!$", "abc!", ""}},
{[]string{"digit"}, []string{"123"}, []string{"abc", "ABC", "=!$", "abc!", ""}},
{[]string{"spec"}, []string{"=!$", "abc!"}, []string{"abc", "ABC", "123", ""}},
{[]string{"off"}, []string{"abc", "ABC", "123", "=!$", "abc!", ""}, nil},
{[]string{"lower", "spec"}, []string{"abc!"}, []string{"abc", "ABC", "123", "=!$", "abcABC123", ""}},
{[]string{"lower", "upper", "digit"}, []string{"abcABC123"}, []string{"abc", "ABC", "123", "=!$", "abc!", ""}},
}
for _, test := range testlist {
testComplextity(test.complexity)
for _, val := range test.truevalues {
assert.True(t, IsComplexEnough(val))
}
for _, val := range test.falsevalues {
assert.False(t, IsComplexEnough(val))
}
}
// Remove settings for other tests
testComplextity([]string{"off"})
}
func TestComplexity_Generate(t *testing.T) {
matchComplexityOnce.Do(func() {})
const maxCount = 50
const pwdLen = 50
test := func(t *testing.T, modes []string) {
testComplextity(modes)
for i := 0; i < maxCount; i++ {
pwd, err := Generate(pwdLen)
assert.NoError(t, err)
assert.Equal(t, pwdLen, len(pwd))
assert.True(t, IsComplexEnough(pwd), "Failed complexities with modes %+v for generated: %s", modes, pwd)
}
}
test(t, []string{"lower"})
test(t, []string{"upper"})
test(t, []string{"lower", "upper", "spec"})
test(t, []string{"off"})
test(t, []string{""})
// Remove settings for other tests
testComplextity([]string{"off"})
}
func testComplextity(values []string) {
// Cleanup previous values
validChars = ""
requiredChars = make([]string, 0, len(values))
setupComplexity(values)
}

View File

@@ -24,7 +24,7 @@ type Response struct {
ErrorCodes []string `json:"error-codes"` ErrorCodes []string `json:"error-codes"`
} }
const apiURL = "/api/siteverify" const apiURL = "api/siteverify"
// Verify calls Google Recaptcha API to verify token // Verify calls Google Recaptcha API to verify token
func Verify(response string) (bool, error) { func Verify(response string) (bool, error) {

View File

@@ -26,7 +26,7 @@ var (
// TODO: fix invalid linking issue // TODO: fix invalid linking issue
// mentionPattern matches all mentions in the form of "@user" // mentionPattern matches all mentions in the form of "@user"
mentionPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(@[0-9a-zA-Z-_\.]+)(?:\s|$|\)|\])`) mentionPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(@[0-9a-zA-Z-_]+|@[0-9a-zA-Z-_][0-9a-zA-Z-_.]+[0-9a-zA-Z-_])(?:\s|[:,;.?!]\s|[:,;.?!]?$|\)|\])`)
// issueNumericPattern matches string that references to a numeric issue, e.g. #1287 // issueNumericPattern matches string that references to a numeric issue, e.g. #1287
issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(#[0-9]+)(?:\s|$|\)|\]|:|\.(\s|$))`) issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(#[0-9]+)(?:\s|$|\)|\]|:|\.(\s|$))`)
// issueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234 // issueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234

View File

@@ -204,14 +204,32 @@ func TestFindAllIssueReferences(t *testing.T) {
} }
func TestRegExp_mentionPattern(t *testing.T) { func TestRegExp_mentionPattern(t *testing.T) {
trueTestCases := []string{ trueTestCases := []struct {
"@Unknwon", pat string
"@ANT_123", exp string
"@xxx-DiN0-z-A..uru..s-xxx", }{
" @lol ", {"@Unknwon", "@Unknwon"},
" @Te-st", {"@ANT_123", "@ANT_123"},
"(@gitea)", {"@xxx-DiN0-z-A..uru..s-xxx", "@xxx-DiN0-z-A..uru..s-xxx"},
"[@gitea]", {" @lol ", "@lol"},
{" @Te-st", "@Te-st"},
{"(@gitea)", "@gitea"},
{"[@gitea]", "@gitea"},
{"@gitea! this", "@gitea"},
{"@gitea? this", "@gitea"},
{"@gitea. this", "@gitea"},
{"@gitea, this", "@gitea"},
{"@gitea; this", "@gitea"},
{"@gitea!\nthis", "@gitea"},
{"\n@gitea?\nthis", "@gitea"},
{"\t@gitea.\nthis", "@gitea"},
{"@gitea,\nthis", "@gitea"},
{"@gitea;\nthis", "@gitea"},
{"@gitea!", "@gitea"},
{"@gitea?", "@gitea"},
{"@gitea.", "@gitea"},
{"@gitea,", "@gitea"},
{"@gitea;", "@gitea"},
} }
falseTestCases := []string{ falseTestCases := []string{
"@ 0", "@ 0",
@@ -219,17 +237,24 @@ func TestRegExp_mentionPattern(t *testing.T) {
"@", "@",
"", "",
"ABC", "ABC",
"@.ABC",
"/home/gitea/@gitea", "/home/gitea/@gitea",
"\"@gitea\"", "\"@gitea\"",
"@@gitea",
"@gitea!this",
"@gitea?this",
"@gitea,this",
"@gitea;this",
} }
for _, testCase := range trueTestCases { for _, testCase := range trueTestCases {
res := mentionPattern.MatchString(testCase) found := mentionPattern.FindStringSubmatch(testCase.pat)
assert.True(t, res) assert.Len(t, found, 2)
assert.Equal(t, testCase.exp, found[1])
} }
for _, testCase := range falseTestCases { for _, testCase := range falseTestCases {
res := mentionPattern.MatchString(testCase) res := mentionPattern.MatchString(testCase)
assert.False(t, res) assert.False(t, res, "[%s] should be false", testCase)
} }
} }

View File

@@ -53,9 +53,11 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
} }
if err := gitRepo.SetDefaultBranch(repo.DefaultBranch); err != nil { if err := gitRepo.SetDefaultBranch(repo.DefaultBranch); err != nil {
if !git.IsErrUnsupportedVersion(err) { if !git.IsErrUnsupportedVersion(err) {
gitRepo.Close()
return err return err
} }
} }
gitRepo.Close()
} }
} }
@@ -132,8 +134,10 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
shaSum, err = gitRepo.GetBranchCommitID(refName) shaSum, err = gitRepo.GetBranchCommitID(refName)
if err != nil { if err != nil {
gitRepo.Close()
log.Error("GetBranchCommitID[%s]: %v", opts.RefFullName, err) log.Error("GetBranchCommitID[%s]: %v", opts.RefFullName, err)
} }
gitRepo.Close()
if err = models.PrepareWebhooks(repo, models.HookEventCreate, &api.CreatePayload{ if err = models.PrepareWebhooks(repo, models.HookEventCreate, &api.CreatePayload{
Ref: refName, Ref: refName,
Sha: shaSum, Sha: shaSum,
@@ -167,8 +171,10 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
} }
shaSum, err = gitRepo.GetTagCommitID(refName) shaSum, err = gitRepo.GetTagCommitID(refName)
if err != nil { if err != nil {
gitRepo.Close()
log.Error("GetTagCommitID[%s]: %v", opts.RefFullName, err) log.Error("GetTagCommitID[%s]: %v", opts.RefFullName, err)
} }
gitRepo.Close()
if err = models.PrepareWebhooks(repo, models.HookEventCreate, &api.CreatePayload{ if err = models.PrepareWebhooks(repo, models.HookEventCreate, &api.CreatePayload{
Ref: refName, Ref: refName,
Sha: shaSum, Sha: shaSum,

View File

@@ -17,6 +17,7 @@ func GetBlobBySHA(repo *models.Repository, sha string) (*api.GitBlobResponse, er
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close()
gitBlob, err := gitRepo.GetBlob(sha) gitBlob, err := gitRepo.GetBlob(sha)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -21,6 +21,8 @@ func TestGetBlobBySHA(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d" sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
ctx.SetParams(":id", "1") ctx.SetParams(":id", "1")
ctx.SetParams(":sha", sha) ctx.SetParams(":sha", sha)

View File

@@ -23,8 +23,10 @@ func CreateCommitStatus(repo *models.Repository, creator *models.User, sha strin
return fmt.Errorf("OpenRepository[%s]: %v", repoPath, err) return fmt.Errorf("OpenRepository[%s]: %v", repoPath, err)
} }
if _, err := gitRepo.GetCommit(sha); err != nil { if _, err := gitRepo.GetCommit(sha); err != nil {
gitRepo.Close()
return fmt.Errorf("GetCommit[%s]: %v", sha, err) return fmt.Errorf("GetCommit[%s]: %v", sha, err)
} }
gitRepo.Close()
if err := models.NewCommitStatus(models.NewCommitStatusOptions{ if err := models.NewCommitStatus(models.NewCommitStatusOptions{
Repo: repo, Repo: repo,

View File

@@ -38,6 +38,9 @@ func (ct *ContentType) String() string {
// GetContentsOrList gets the meta data of a file's contents (*ContentsResponse) if treePath not a tree // GetContentsOrList gets the meta data of a file's contents (*ContentsResponse) if treePath not a tree
// directory, otherwise a listing of file contents ([]*ContentsResponse). Ref can be a branch, commit or tag // directory, otherwise a listing of file contents ([]*ContentsResponse). Ref can be a branch, commit or tag
func GetContentsOrList(repo *models.Repository, treePath, ref string) (interface{}, error) { func GetContentsOrList(repo *models.Repository, treePath, ref string) (interface{}, error) {
if repo.IsEmpty {
return make([]interface{}, 0), nil
}
if ref == "" { if ref == "" {
ref = repo.DefaultBranch ref = repo.DefaultBranch
} }
@@ -56,6 +59,7 @@ func GetContentsOrList(repo *models.Repository, treePath, ref string) (interface
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close()
// Get the commit object for the ref // Get the commit object for the ref
commit, err := gitRepo.GetCommit(ref) commit, err := gitRepo.GetCommit(ref)
@@ -114,6 +118,7 @@ func GetContents(repo *models.Repository, treePath, ref string, forList bool) (*
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close()
// Get the commit object for the ref // Get the commit object for the ref
commit, err := gitRepo.GetCommit(ref) commit, err := gitRepo.GetCommit(ref)

View File

@@ -56,6 +56,8 @@ func TestGetContents(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
treePath := "README.md" treePath := "README.md"
ref := ctx.Repo.Repository.DefaultBranch ref := ctx.Repo.Repository.DefaultBranch
@@ -82,6 +84,8 @@ func TestGetContentsOrListForDir(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
treePath := "" // root dir treePath := "" // root dir
ref := ctx.Repo.Repository.DefaultBranch ref := ctx.Repo.Repository.DefaultBranch
@@ -115,6 +119,8 @@ func TestGetContentsOrListForFile(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
treePath := "README.md" treePath := "README.md"
ref := ctx.Repo.Repository.DefaultBranch ref := ctx.Repo.Repository.DefaultBranch
@@ -141,6 +147,8 @@ func TestGetContentsErrors(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
treePath := "README.md" treePath := "README.md"
ref := repo.DefaultBranch ref := repo.DefaultBranch
@@ -170,6 +178,8 @@ func TestGetContentsOrListErrors(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
treePath := "README.md" treePath := "README.md"
ref := repo.DefaultBranch ref := repo.DefaultBranch
@@ -190,3 +200,21 @@ func TestGetContentsOrListErrors(t *testing.T) {
assert.Nil(t, fileContentResponse) assert.Nil(t, fileContentResponse)
}) })
} }
func TestGetContentsOrListOfEmptyRepos(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo15")
ctx.SetParams(":id", "15")
test.LoadRepo(t, ctx, 15)
test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository
t.Run("empty repo", func(t *testing.T) {
contents, err := GetContentsOrList(repo, "", "")
assert.NoError(t, err)
assert.Empty(t, contents)
})
}

View File

@@ -22,6 +22,8 @@ func TestGetDiffPreview(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
branch := ctx.Repo.Repository.DefaultBranch branch := ctx.Repo.Repository.DefaultBranch
treePath := "README.md" treePath := "README.md"
content := "# repo1\n\nDescription for repo1\nthis is a new line" content := "# repo1\n\nDescription for repo1\nthis is a new line"
@@ -119,6 +121,8 @@ func TestGetDiffPreviewErrors(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
branch := ctx.Repo.Repository.DefaultBranch branch := ctx.Repo.Repository.DefaultBranch
treePath := "README.md" treePath := "README.md"
content := "# repo1\n\nDescription for repo1\nthis is a new line" content := "# repo1\n\nDescription for repo1\nthis is a new line"

View File

@@ -88,10 +88,13 @@ func TestGetFileResponseFromCommit(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
branch := repo.DefaultBranch branch := repo.DefaultBranch
treePath := "README.md" treePath := "README.md"
gitRepo, _ := git.OpenRepository(repo.RepoPath()) gitRepo, _ := git.OpenRepository(repo.RepoPath())
defer gitRepo.Close()
commit, _ := gitRepo.GetBranchCommit(branch) commit, _ := gitRepo.GetBranchCommit(branch)
expectedFileResponse := getExpectedFileResponse() expectedFileResponse := getExpectedFileResponse()

View File

@@ -44,6 +44,7 @@ func NewTemporaryUploadRepository(repo *models.Repository) (*TemporaryUploadRepo
// Close the repository cleaning up all files // Close the repository cleaning up all files
func (t *TemporaryUploadRepository) Close() { func (t *TemporaryUploadRepository) Close() {
defer t.gitRepo.Close()
if err := models.RemoveTemporaryPath(t.basePath); err != nil { if err := models.RemoveTemporaryPath(t.basePath); err != nil {
log.Error("Failed to remove temporary path %s: %v", t.basePath, err) log.Error("Failed to remove temporary path %s: %v", t.basePath, err)
} }

View File

@@ -19,6 +19,7 @@ func GetTreeBySHA(repo *models.Repository, sha string, page, perPage int, recurs
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close()
gitTree, err := gitRepo.GetTree(sha) gitTree, err := gitRepo.GetTree(sha)
if err != nil || gitTree == nil { if err != nil || gitTree == nil {
return nil, models.ErrSHANotFound{ return nil, models.ErrSHANotFound{

View File

@@ -21,6 +21,8 @@ func TestGetTreeBySHA(t *testing.T) {
test.LoadRepoCommit(t, ctx) test.LoadRepoCommit(t, ctx)
test.LoadUser(t, ctx, 2) test.LoadUser(t, ctx, 2)
test.LoadGitRepo(t, ctx) test.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
sha := ctx.Repo.Repository.DefaultBranch sha := ctx.Repo.Repository.DefaultBranch
page := 1 page := 1
perPage := 10 perPage := 10

View File

@@ -429,6 +429,7 @@ func PushUpdate(repo *models.Repository, branch string, opts models.PushUpdateOp
if err != nil { if err != nil {
return fmt.Errorf("OpenRepository: %v", err) return fmt.Errorf("OpenRepository: %v", err)
} }
defer gitRepo.Close()
if err = repo.UpdateSize(); err != nil { if err = repo.UpdateSize(); err != nil {
log.Error("Failed to update size for repository: %v", err) log.Error("Failed to update size for repository: %v", err)

View File

@@ -42,12 +42,11 @@ var (
DBConnectRetries int DBConnectRetries int
DBConnectBackoff time.Duration DBConnectBackoff time.Duration
MaxIdleConns int MaxIdleConns int
MaxOpenConns int
ConnMaxLifetime time.Duration ConnMaxLifetime time.Duration
IterateBufferSize int IterateBufferSize int
}{ }{
Timeout: 500, Timeout: 500,
MaxIdleConns: 0,
ConnMaxLifetime: 3 * time.Second,
} }
) )
@@ -80,8 +79,13 @@ func InitDBConfig() {
Database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"}) Database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"})
Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db")) Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db"))
Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500)
Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(0) Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(2)
if Database.UseMySQL {
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second) Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second)
} else {
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(0)
}
Database.MaxOpenConns = sec.Key("MAX_OPEN_CONNS").MustInt(0)
Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50) Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50)
Database.LogSQL = sec.Key("LOG_SQL").MustBool(true) Database.LogSQL = sec.Key("LOG_SQL").MustBool(true)

View File

@@ -128,7 +128,11 @@ func generateLogConfig(sec *ini.Section, name string, defaults defaultLogOptions
logConfig["username"] = sec.Key("USER").MustString("example@example.com") logConfig["username"] = sec.Key("USER").MustString("example@example.com")
logConfig["password"] = sec.Key("PASSWD").MustString("******") logConfig["password"] = sec.Key("PASSWD").MustString("******")
logConfig["host"] = sec.Key("HOST").MustString("127.0.0.1:25") logConfig["host"] = sec.Key("HOST").MustString("127.0.0.1:25")
logConfig["sendTos"] = sec.Key("RECEIVERS").MustString("[]") sendTos := strings.Split(sec.Key("RECEIVERS").MustString(""), ",")
for i, address := range sendTos {
sendTos[i] = strings.TrimSpace(address)
}
logConfig["sendTos"] = sendTos
logConfig["subject"] = sec.Key("SUBJECT").MustString("Diagnostic message from Gitea") logConfig["subject"] = sec.Key("SUBJECT").MustString("Diagnostic message from Gitea")
} }

View File

@@ -146,7 +146,7 @@ var (
MinPasswordLength int MinPasswordLength int
ImportLocalPaths bool ImportLocalPaths bool
DisableGitHooks bool DisableGitHooks bool
PasswordComplexity map[string]string PasswordComplexity []string
PasswordHashAlgo string PasswordHashAlgo string
// UI settings // UI settings
@@ -775,26 +775,14 @@ func NewContext() {
InternalToken = loadInternalToken(sec) InternalToken = loadInternalToken(sec)
var dictPC = map[string]string{
"lower": "[a-z]+",
"upper": "[A-Z]+",
"digit": "[0-9]+",
"spec": `][ !"#$%&'()*+,./:;<=>?@\\^_{|}~` + "`-",
}
PasswordComplexity = make(map[string]string)
cfgdata := sec.Key("PASSWORD_COMPLEXITY").Strings(",") cfgdata := sec.Key("PASSWORD_COMPLEXITY").Strings(",")
for _, y := range cfgdata { PasswordComplexity = make([]string, 0, len(cfgdata))
ts := strings.TrimSpace(y) for _, name := range cfgdata {
for a := range dictPC { name := strings.ToLower(strings.Trim(name, `"`))
if strings.ToLower(ts) == a { if name != "" {
PasswordComplexity[ts] = dictPC[ts] PasswordComplexity = append(PasswordComplexity, name)
break
} }
} }
}
if len(PasswordComplexity) == 0 {
PasswordComplexity = dictPC
}
sec = Cfg.Section("attachment") sec = Cfg.Section("attachment")
AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments")) AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments"))

View File

@@ -19,6 +19,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"time" "time"
"unicode"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@@ -331,34 +332,46 @@ func RenderCommitMessageLink(msg, urlPrefix, urlDefault string, metas map[string
// RenderCommitMessageLinkSubject renders commit message as a XXS-safe link to // RenderCommitMessageLinkSubject renders commit message as a XXS-safe link to
// the provided default url, handling for special links without email to links. // the provided default url, handling for special links without email to links.
func RenderCommitMessageLinkSubject(msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML { func RenderCommitMessageLinkSubject(msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML {
cleanMsg := template.HTMLEscapeString(msg) msgLine := strings.TrimLeftFunc(msg, unicode.IsSpace)
// we can safely assume that it will not return any error, since there lineEnd := strings.IndexByte(msgLine, '\n')
// shouldn't be any special HTML. if lineEnd > 0 {
fullMessage, err := markup.RenderCommitMessageSubject([]byte(cleanMsg), urlPrefix, urlDefault, metas) msgLine = msgLine[:lineEnd]
if err != nil {
log.Error("RenderCommitMessageSubject: %v", err)
return ""
} }
msgLines := strings.Split(strings.TrimSpace(string(fullMessage)), "\n") msgLine = strings.TrimRightFunc(msgLine, unicode.IsSpace)
if len(msgLines) == 0 { if len(msgLine) == 0 {
return template.HTML("") return template.HTML("")
} }
return template.HTML(msgLines[0])
// we can safely assume that it will not return any error, since there
// shouldn't be any special HTML.
renderedMessage, err := markup.RenderCommitMessageSubject([]byte(template.HTMLEscapeString(msgLine)), urlPrefix, urlDefault, metas)
if err != nil {
log.Error("RenderCommitMessageSubject: %v", err)
return template.HTML("")
}
return template.HTML(renderedMessage)
} }
// RenderCommitBody extracts the body of a commit message without its title. // RenderCommitBody extracts the body of a commit message without its title.
func RenderCommitBody(msg, urlPrefix string, metas map[string]string) template.HTML { func RenderCommitBody(msg, urlPrefix string, metas map[string]string) template.HTML {
cleanMsg := template.HTMLEscapeString(msg) msgLine := strings.TrimRightFunc(msg, unicode.IsSpace)
fullMessage, err := markup.RenderCommitMessage([]byte(cleanMsg), urlPrefix, "", metas) lineEnd := strings.IndexByte(msgLine, '\n')
if lineEnd > 0 {
msgLine = msgLine[lineEnd+1:]
} else {
return template.HTML("")
}
msgLine = strings.TrimLeftFunc(msgLine, unicode.IsSpace)
if len(msgLine) == 0 {
return template.HTML("")
}
renderedMessage, err := markup.RenderCommitMessage([]byte(template.HTMLEscapeString(msgLine)), urlPrefix, "", metas)
if err != nil { if err != nil {
log.Error("RenderCommitMessage: %v", err) log.Error("RenderCommitMessage: %v", err)
return "" return ""
} }
body := strings.Split(strings.TrimSpace(string(fullMessage)), "\n") return template.HTML(renderedMessage)
if len(body) == 0 {
return template.HTML("")
}
return template.HTML(strings.Join(body[1:], "\n"))
} }
// RenderNote renders the contents of a git-notes file as a commit message. // RenderNote renders the contents of a git-notes file as a commit message.

Some files were not shown because too many files have changed in this diff Show More