Compare commits
49 Commits
v1.7.0-rc3
...
v1.6.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 30560b0f9b | |||
| 6076674d3a | |||
| 28cc3bd662 | |||
| 2631f7f64d | |||
| af4626a270 | |||
| 21c70e1ed2 | |||
| b45d58805a | |||
| 200b974e19 | |||
| 800271ee1f | |||
| e6362f3d23 | |||
| 716c2918be | |||
| 60d7b614fe | |||
| 9cf9a54dca | |||
| 2b4f87da46 | |||
| ad9f9cdc30 | |||
| 8237fd4a2d | |||
| 8e4a0a978a | |||
| c1275e2ba6 | |||
| 7bc1faabdb | |||
| e406dc058d | |||
| 328e38ebc7 | |||
| 773addf727 | |||
| 0da8bc9ec0 | |||
| 5d69703d3c | |||
| ffc0c7f611 | |||
| 8670decafb | |||
| 297e619074 | |||
| e9b984e162 | |||
| 5995b65175 | |||
| 996ce8cc03 | |||
| fe7cef0e1f | |||
| 464dcd1b66 | |||
| 68938d5dc4 | |||
| 9c11fafdb0 | |||
| c0bbbdd30b | |||
| f95c966770 | |||
| 14a074f979 | |||
| 3786369356 | |||
| 79464216d9 | |||
| e28801ff1a | |||
| 478ba7f318 | |||
| 582213a858 | |||
| 4d66de684f | |||
| d220a3d772 | |||
| 7022957b15 | |||
| e7128e8c41 | |||
| 274ff0d011 | |||
| 7238bb329a | |||
| 49d666f99a |
+115
-63
@@ -4,12 +4,49 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.6.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.6.0-rc1) - 2018-10-17
|
||||
## [1.6.3](https://github.com/go-gitea/gitea/releases/tag/v1.6.3) - 2019-01-04
|
||||
* SECURITY
|
||||
* Prevent DeleteFilePost doing arbitrary deletion (#5631)
|
||||
* BUGFIX
|
||||
* Fix wrong text getting saved on editing second comment on an issue (#5608)
|
||||
|
||||
## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
|
||||
* SECURITY
|
||||
* Sanitize uploaded file names (#5571) (#5573)
|
||||
* HTMLEncode user added text (#5570) (#5575)
|
||||
* BUGFIXES
|
||||
* Fix indexer reindex bug when gitea restart (#5563) (#5564)
|
||||
* Remove a double slash in the HTTPS redirect with Let's Encrypt (#5537) (#5539)
|
||||
* Fix bug when a read perm user to edit his issue (#5516) (#5534)
|
||||
* Detect force push failure on deletion of protected branches (#5522) (#5531)
|
||||
* Let's Encrypt handler listens on correct port for certificate validation (#5525) (#5527)
|
||||
* Fix forgot deletion of notification when delete repository (#5506) (#5514)
|
||||
* Fix undeleted content when deleting user (#5429) (#5509)
|
||||
* Fix empty wiki (#5504) (#5508)
|
||||
|
||||
## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
|
||||
* BUGFIXES
|
||||
* Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
|
||||
* API: '/orgs/:org/repos': return private repos with read access (#5393)
|
||||
* Fix repository deletion when there is large number of issues in it (#5426) (#5434)
|
||||
* Word-break the WebHook url to prevent a ui-break (#5445)
|
||||
* Admin should be able to delete repos via the API even if they are not a member of the organization (#5443) (#5447)
|
||||
* Ensure that the `closed_at` is set for closed (#5450)
|
||||
* Fix topic name length on database (#5493) (#5495)
|
||||
|
||||
## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
|
||||
* BREAKING
|
||||
* Respect email privacy option in user search via API (#4512)
|
||||
* Simply remove tidb and deps (#3993)
|
||||
* Swagger.v1.json template (#3572)
|
||||
* SECURITY
|
||||
* Add CSRF checking to reqToken and add reqToken to admin API routes (#5272) (#5250)
|
||||
* Improve URL validation for external wiki and external issues (#4710)
|
||||
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
|
||||
* Don't disclose emails of all users when sending out emails (#4664)
|
||||
* Check that repositories can only be migrated to own user or organizations (#4366)
|
||||
* FEATURE
|
||||
* Add comment replies (#5147) (#5104)
|
||||
* Pull request review/approval and comment on code (#3748)
|
||||
* Added dependencies for issues (#2196) (#2531)
|
||||
* Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198)
|
||||
@@ -21,63 +58,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Add push webhook support for mirrored repositories (#4127)
|
||||
* Add csv file render support defaultly (#4105)
|
||||
* Add Recaptcha functionality to Gitea (#4044)
|
||||
* BUGFIXES
|
||||
* Fix release creation via API (#5076)
|
||||
* Remove links from topics in edit mode (#5026)
|
||||
* Fix missing AppSubUrl in few more templates (fixup) (#5021)
|
||||
* Fix missing AppSubUrl in some templates (#5020)
|
||||
* Hide outdated comments in file view (#5017)
|
||||
* Upgrade gopkg.in/testfixtures.v2 (#4999)
|
||||
* Disable debug routes unless PPROF is enabled in configuration (#4995)
|
||||
* Fix user menu item styling (#4985)
|
||||
* Fix layout of the topics editing form (#4971)
|
||||
* Fix null pointer dereference in ParseCommitWithSignature (#4962)
|
||||
* Fix url in discord webhook (#4953)
|
||||
* Detect charset and convert non UTF-8 files for display (#4950)
|
||||
* Make sure to catch the right error so it is displayed on the UI (#4945)
|
||||
* Fix(topics): don't redirect to explore page. (#4938)
|
||||
* Fix bug forget to remove Stopwatch when remove repository (#4928)
|
||||
* Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
|
||||
* Fix: Let's Encrypt configuration settings (#4911)
|
||||
* Fix: Crippled diff (#4726) (#4900)
|
||||
* Fix trimming of markup section names (#4863)
|
||||
* Issues api allow pulls and fix #4832 (#4852)
|
||||
* Do not autocreate directory for new users/orgs (#4828) (#4849)
|
||||
* Fix redirect with non-ascii branch names (#4764) (#4810)
|
||||
* Fix missing release title in webhook (#4783) (#4796)
|
||||
* User shouldn't be able to approve or reject his/her own PR (#4729)
|
||||
* Make sure to reset commit count in the cache on mirror syncing (#4720)
|
||||
* Fixed bug where team with admin privelege type doesn't get any unit (#4719)
|
||||
* Fix incorrect caption of webhook setting (#4701) (#4717)
|
||||
* Allow WIP marker to contains < or > (#4709)
|
||||
* Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
|
||||
* Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
|
||||
* Fix custom templates being ignored (#4638)
|
||||
* Fix starring icon after semantic ui update (#4628)
|
||||
* Fix Split-View line adjustment (#4622)
|
||||
* Fix integer constant overflows in tests (#4616)
|
||||
* Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
|
||||
* Fix bugs when too many IN variables (#4594)
|
||||
* Fix failure on creating pull request with assignees (#4419) (#4583)
|
||||
* Fix panic issue on update avatar email (#4580) (#4581)
|
||||
* Fix status code label for a successful webhook (#4540)
|
||||
* An inactive user shouldn't be able to be added as a collaborator (#4535)
|
||||
* Don't fail silently if trying to add a collaborator twice (#4533)
|
||||
* Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
|
||||
* Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
|
||||
* Fix migration from older releases (#4495)
|
||||
* Accept 'Data:' in commit graph (#4487)
|
||||
* Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
|
||||
* Relative URLs for LibreJS page (#4460)
|
||||
* Redirect to correct page after using scratch token (#4458)
|
||||
* Fix column droping for MSSQL that need new transaction for that (#4440)
|
||||
* Replace src with raw to fix image paths (#4377)
|
||||
* Add default merge options when creating new repository (#4369)
|
||||
* Fix docker build (#4358)
|
||||
* Fixes repo membership check in API (#4341)
|
||||
* Dep upgrade mysql lib (#4161)
|
||||
* Fix some issues with special chars in branch names (#3767)
|
||||
* Responsive design fixes (#4508)
|
||||
* ENHANCEMENT
|
||||
* Fix milestones sorted wrongly (#4987)
|
||||
* Allow api to create tags for releases if they don't exist (#4890)
|
||||
@@ -130,15 +110,87 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Added front-end topics validation (#4316)
|
||||
* Don't display buttons if there are no system notifications (#4280)
|
||||
* Issue due date api (#3890)
|
||||
* SECURITY
|
||||
* Improve URL validation for external wiki and external issues (#4710)
|
||||
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
|
||||
* Don't disclose emails of all users when sending out emails (#4664)
|
||||
* Check that repositories can only be migrated to own user or organizations (#4366)
|
||||
* BUGFIXES
|
||||
* dont' send assign webhooks when creating issue (#5365)
|
||||
* Fix create team, update team missing units (#5188)
|
||||
* Fix file edit change preview functionality (#5300)
|
||||
* *ix bug when users have serval teams with different units on different repositories (#5307)
|
||||
* Fix U2F if gitea is configured in subpath (#5302)
|
||||
* Fix markdown image with link (#4675)
|
||||
* Remove maxlines option for file logger (#5282)
|
||||
* Fix wrong api request url for instances running in subfolders (#5261) (#5247)
|
||||
* Accept web-command cli flags if web-command is commited (#5245) (#5200)
|
||||
* Reduce join star, repo_topic, topic tables on repo search, to resolve extra columns problem on MSSQL (#5136) (#5229)
|
||||
* Fix data race on migrate repository (#5224) (#5230)
|
||||
* Add secret to all webhook's payload where it has been missing (#5208) (#5199)
|
||||
* Fix sqlite and MSSQL lock (#5210) (#5223) (#5214) (#5218) (#5176) (#5179)
|
||||
* Fix race on updatesize (#5190) (#5215)
|
||||
* Fix filtering issues by tags on main screen issues (#5219) (#3824)
|
||||
* Fix SQL quoting (#5137) (#5117)
|
||||
* Fix regex to support optional end line of old section in diff hunk (#5097) (#5096)
|
||||
* Fix release creation via API (#5076)
|
||||
* Remove links from topics in edit mode (#5026)
|
||||
* Fix missing AppSubUrl in few more templates (fixup) (#5021)
|
||||
* Fix missing AppSubUrl in some templates (#5020)
|
||||
* Hide outdated comments in file view (#5017)
|
||||
* Upgrade gopkg.in/testfixtures.v2 (#4999)
|
||||
* Disable debug routes unless PPROF is enabled in configuration (#4995)
|
||||
* Fix user menu item styling (#4985)
|
||||
* Fix layout of the topics editing form (#4971)
|
||||
* Fix null pointer dereference in ParseCommitWithSignature (#4962)
|
||||
* Fix url in discord webhook (#4953)
|
||||
* Detect charset and convert non UTF-8 files for display (#4950)
|
||||
* Make sure to catch the right error so it is displayed on the UI (#4945)
|
||||
* Fix(topics): don't redirect to explore page. (#4938)
|
||||
* Fix bug forget to remove Stopwatch when remove repository (#4928)
|
||||
* Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
|
||||
* Fix: Crippled diff (#4726) (#4900)
|
||||
* Fix trimming of markup section names (#4863)
|
||||
* Issues api allow pulls and fix #4832 (#4852)
|
||||
* Do not autocreate directory for new users/orgs (#4828) (#4849)
|
||||
* Fix redirect with non-ascii branch names (#4764) (#4810)
|
||||
* Fix missing release title in webhook (#4783) (#4796)
|
||||
* User shouldn't be able to approve or reject his/her own PR (#4729)
|
||||
* Make sure to reset commit count in the cache on mirror syncing (#4720)
|
||||
* Fixed bug where team with admin privelege type doesn't get any unit (#4719)
|
||||
* Fix incorrect caption of webhook setting (#4701) (#4717)
|
||||
* Allow WIP marker to contains < or > (#4709)
|
||||
* Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
|
||||
* Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
|
||||
* Fix custom templates being ignored (#4638)
|
||||
* Fix starring icon after semantic ui update (#4628)
|
||||
* Fix Split-View line adjustment (#4622)
|
||||
* Fix integer constant overflows in tests (#4616)
|
||||
* Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
|
||||
* Fix bugs when too many IN variables (#4594)
|
||||
* Fix failure on creating pull request with assignees (#4419) (#4583)
|
||||
* Fix panic issue on update avatar email (#4580) (#4581)
|
||||
* Fix status code label for a successful webhook (#4540)
|
||||
* An inactive user shouldn't be able to be added as a collaborator (#4535)
|
||||
* Don't fail silently if trying to add a collaborator twice (#4533)
|
||||
* Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
|
||||
* Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
|
||||
* Fix migration from older releases (#4495)
|
||||
* Accept 'Data:' in commit graph (#4487)
|
||||
* Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
|
||||
* Relative URLs for LibreJS page (#4460)
|
||||
* Redirect to correct page after using scratch token (#4458)
|
||||
* Fix column droping for MSSQL that need new transaction for that (#4440)
|
||||
* Replace src with raw to fix image paths (#4377)
|
||||
* Add default merge options when creating new repository (#4369)
|
||||
* Fix docker build (#4358)
|
||||
* Fixes repo membership check in API (#4341)
|
||||
* Dep upgrade mysql lib (#4161)
|
||||
* Fix some issues with special chars in branch names (#3767)
|
||||
* Responsive design fixes (#4508)
|
||||
* TRANSLATION
|
||||
* Fix punctuation in English translation (#4958)
|
||||
* Fix translation (#4355)
|
||||
|
||||
## [1.5.3](https://github.com/go-gitea/gitea/releases/tag/v1.5.3) - 2018-10-31
|
||||
* SECURITY
|
||||
* Fix remote command execution vulnerability in upstream library (#5177) (#5196)
|
||||
|
||||
## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
|
||||
* SECURITY
|
||||
* Enforce token on api routes (#4840) (#4905)
|
||||
|
||||
Generated
+5
-4
@@ -11,11 +11,11 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:5e7f14543006a44047fb1d0df16da08b2ebc2428f1fd53bd8af26a2b34928b11"
|
||||
digest = "1:b194da40b41ae99546dfeec5a85f1fec2a6c51350d438e511ef90f4293c6dcd7"
|
||||
name = "code.gitea.io/sdk"
|
||||
packages = ["gitea"]
|
||||
pruneopts = "NUT"
|
||||
revision = "021567c9c12fe289b8980c34e81e6684434dd082"
|
||||
revision = "4f96d9ac89886e78c50de8c835ebe87461578a5e"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195"
|
||||
@@ -342,14 +342,15 @@
|
||||
revision = "d8a0b8677191f4380287cfebd08e462217bac7ad"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b327ca585509a889130a8f51f43704a8fe03cb5cd281dbf1bc6405f5a7ea4702"
|
||||
branch = "master"
|
||||
digest = "1:8fea5718d84af17762195beb6fe92a0d6c1048452a1dbc464d227f12e0cff0cc"
|
||||
name = "github.com/go-macaron/session"
|
||||
packages = [
|
||||
".",
|
||||
"redis",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "66031fcb37a0fff002a1f028eb0b3a815c78306b"
|
||||
revision = "330e4e4d8beb7b00111ac34539561f46f94c4458"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:758d2371fcdee6d02565901b348729053c636055e67ef6e17aa466c7ff6cc57c"
|
||||
|
||||
+12
-12
@@ -112,10 +112,15 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
|
||||
if err != nil {
|
||||
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
||||
fail("Internal error", fmt.Sprintf("retrieve protected branches information failed: %v", err))
|
||||
}
|
||||
|
||||
if protectBranch != nil && protectBranch.IsProtected() {
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
}
|
||||
|
||||
// detect force push
|
||||
if git.EmptySHA != oldCommitID {
|
||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
||||
@@ -126,17 +131,12 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
} else {
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -80,7 +80,13 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
|
||||
Cache: autocert.DirCache(directory),
|
||||
Email: email,
|
||||
}
|
||||
go http.ListenAndServe(listenAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validatio happens here)
|
||||
go func() {
|
||||
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||
var err = http.ListenAndServe(setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||
}
|
||||
}()
|
||||
server := &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: m,
|
||||
@@ -96,7 +102,10 @@ func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
target := setting.AppURL + r.URL.RequestURI()
|
||||
// Remove the trailing slash at the end of setting.AppURL, the request
|
||||
// URI always contains a leading slash, which would result in a double
|
||||
// slash
|
||||
target := strings.TrimRight(setting.AppURL, "/") + r.URL.RequestURI()
|
||||
http.Redirect(w, r, target, http.StatusFound)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
|
||||
OwnerID: keyOwner.ID,
|
||||
})
|
||||
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token="+token,
|
||||
keyOwner.Name, newPublicKey.ID)
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
|
||||
keyOwner.Name, newPublicKey.ID, token)
|
||||
session.MakeRequest(t, req, http.StatusNoContent)
|
||||
models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID})
|
||||
}
|
||||
@@ -51,7 +51,7 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token="+token, models.NonexistentID)
|
||||
req := NewRequestf(t, "DELETE", "/api/v1/admin/users/user1/keys/%d?token=%s", models.NonexistentID, token)
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
|
||||
|
||||
session = loginUser(t, normalUsername)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token="+token,
|
||||
adminUsername, newPublicKey.ID)
|
||||
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
|
||||
adminUsername, newPublicKey.ID, token)
|
||||
session.MakeRequest(t, req, http.StatusForbidden)
|
||||
}
|
||||
|
||||
|
||||
@@ -212,21 +212,46 @@ func TestAPIViewRepo(t *testing.T) {
|
||||
func TestAPIOrgRepos(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
|
||||
user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User)
|
||||
// User3 is an Org. Check their repos.
|
||||
sourceOrg := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiRepos []*api.Repository
|
||||
DecodeJSON(t, resp, &apiRepos)
|
||||
expectedLen := models.GetCount(t, models.Repository{OwnerID: sourceOrg.ID},
|
||||
models.Cond("is_private = ?", false))
|
||||
assert.Len(t, apiRepos, expectedLen)
|
||||
for _, repo := range apiRepos {
|
||||
assert.False(t, repo.Private)
|
||||
expectedResults := map[*models.User]struct {
|
||||
count int
|
||||
includesPrivate bool
|
||||
}{
|
||||
nil: {count: 1},
|
||||
user: {count: 2, includesPrivate: true},
|
||||
user2: {count: 3, includesPrivate: true},
|
||||
user3: {count: 1},
|
||||
}
|
||||
|
||||
for userToLogin, expected := range expectedResults {
|
||||
var session *TestSession
|
||||
var testName string
|
||||
var token string
|
||||
if userToLogin != nil && userToLogin.ID > 0 {
|
||||
testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||
session = loginUser(t, userToLogin.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
} else {
|
||||
testName = "AnonymousUser"
|
||||
session = emptyTestSession(t)
|
||||
}
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiRepos []*api.Repository
|
||||
DecodeJSON(t, resp, &apiRepos)
|
||||
assert.Len(t, apiRepos, expected.count)
|
||||
for _, repo := range apiRepos {
|
||||
if !expected.includesPrivate {
|
||||
assert.False(t, repo.Private)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,8 @@ func TestGit(t *testing.T) {
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", keyOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys?token=%s", keyOwner.Name, token)
|
||||
|
||||
dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -48,7 +48,7 @@ arguments - which can alternatively be run by running the subcommand web.`
|
||||
cmd.CmdAdmin,
|
||||
cmd.CmdGenerate,
|
||||
}
|
||||
app.Flags = append(app.Flags, []cli.Flag{}...)
|
||||
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...)
|
||||
app.Action = cmd.CmdWeb.Action
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
|
||||
+16
-9
@@ -273,7 +273,7 @@ func (diff *Diff) NumFiles() int {
|
||||
}
|
||||
|
||||
// Example: @@ -1,8 +1,9 @@ => [..., 1, 8, 1, 9]
|
||||
var hunkRegex = regexp.MustCompile(`^@@ -([0-9]+),([0-9]+) \+([0-9]+)(,([0-9]+))? @@`)
|
||||
var hunkRegex = regexp.MustCompile(`^@@ -(?P<beginOld>[0-9]+)(,(?P<endOld>[0-9]+))? \+(?P<beginNew>[0-9]+)(,(?P<endNew>[0-9]+))? @@`)
|
||||
|
||||
func isHeader(lof string) bool {
|
||||
return strings.HasPrefix(lof, cmdDiffHead) || strings.HasPrefix(lof, "---") || strings.HasPrefix(lof, "+++")
|
||||
@@ -311,21 +311,28 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi
|
||||
if len(hunk) > headerLines {
|
||||
break
|
||||
}
|
||||
groups := hunkRegex.FindStringSubmatch(lof)
|
||||
// A map with named groups of our regex to recognize them later more easily
|
||||
submatches := hunkRegex.FindStringSubmatch(lof)
|
||||
groups := make(map[string]string)
|
||||
for i, name := range hunkRegex.SubexpNames() {
|
||||
if i != 0 && name != "" {
|
||||
groups[name] = submatches[i]
|
||||
}
|
||||
}
|
||||
if old {
|
||||
begin = com.StrTo(groups[1]).MustInt64()
|
||||
end = com.StrTo(groups[2]).MustInt64()
|
||||
begin = com.StrTo(groups["beginOld"]).MustInt64()
|
||||
end = com.StrTo(groups["endOld"]).MustInt64()
|
||||
// init otherLine with begin of opposite side
|
||||
otherLine = com.StrTo(groups[3]).MustInt64()
|
||||
otherLine = com.StrTo(groups["beginNew"]).MustInt64()
|
||||
} else {
|
||||
begin = com.StrTo(groups[3]).MustInt64()
|
||||
if groups[5] != "" {
|
||||
end = com.StrTo(groups[5]).MustInt64()
|
||||
begin = com.StrTo(groups["beginNew"]).MustInt64()
|
||||
if groups["endNew"] != "" {
|
||||
end = com.StrTo(groups["endNew"]).MustInt64()
|
||||
} else {
|
||||
end = 0
|
||||
}
|
||||
// init otherLine with begin of opposite side
|
||||
otherLine = com.StrTo(groups[1]).MustInt64()
|
||||
otherLine = com.StrTo(groups["beginOld"]).MustInt64()
|
||||
}
|
||||
end += begin // end is for real only the number of lines in hunk
|
||||
// lof is between begin and end
|
||||
|
||||
@@ -325,6 +325,10 @@ func (issue *Issue) APIFormat() *api.Issue {
|
||||
Updated: issue.UpdatedUnix.AsTime(),
|
||||
}
|
||||
|
||||
if issue.ClosedUnix != 0 {
|
||||
apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
|
||||
}
|
||||
|
||||
if issue.Milestone != nil {
|
||||
apiIssue.Milestone = issue.Milestone.APIFormat()
|
||||
}
|
||||
|
||||
@@ -159,12 +159,13 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
|
||||
return fmt.Errorf("createAssigneeComment: %v", err)
|
||||
}
|
||||
|
||||
// if issue/pull is in the middle of creation - don't call webhook
|
||||
if isCreate {
|
||||
return nil
|
||||
}
|
||||
|
||||
mode, _ := accessLevel(sess, doer.ID, issue.Repo)
|
||||
if issue.IsPull {
|
||||
// if pull request is in the middle of creation - don't call webhook
|
||||
if isCreate {
|
||||
return nil
|
||||
}
|
||||
if err = issue.loadPullRequest(sess); err != nil {
|
||||
return fmt.Errorf("loadPullRequest: %v", err)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ func addMultipleAssignees(x *xorm.Engine) error {
|
||||
IsClosed bool `xorm:"INDEX"`
|
||||
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
|
||||
NumComments int
|
||||
Ref string
|
||||
|
||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
@@ -70,6 +72,13 @@ func removeStaleWatches(x *xorm.Engine) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var issueWatch IssueWatch
|
||||
if exist, err := sess.IsTableExist(&issueWatch); err != nil {
|
||||
return fmt.Errorf("IsExist IssueWatch: %v", err)
|
||||
} else if !exist {
|
||||
return nil
|
||||
}
|
||||
|
||||
repoCache := make(map[int64]*Repository)
|
||||
err := x.BufferSize(setting.IterateBufferSize).Iterate(new(Watch),
|
||||
func(idx int, bean interface{}) error {
|
||||
|
||||
@@ -25,7 +25,7 @@ func reformatAndRemoveIncorrectTopics(x *xorm.Engine) (err error) {
|
||||
|
||||
type Topic struct {
|
||||
ID int64
|
||||
Name string `xorm:"UNIQUE"`
|
||||
Name string `xorm:"UNIQUE VARCHAR(25)"`
|
||||
RepoCount int
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
|
||||
@@ -123,10 +123,10 @@ func createOrUpdateIssueNotifications(e Engine, issue *Issue, notificationAuthor
|
||||
|
||||
for _, watch := range watches {
|
||||
issue.Repo.Units = nil
|
||||
if issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypePullRequests) {
|
||||
if issue.IsPull && !issue.Repo.checkUnitUser(e, watch.UserID, false, UnitTypePullRequests) {
|
||||
continue
|
||||
}
|
||||
if !issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypeIssues) {
|
||||
if !issue.IsPull && !issue.Repo.checkUnitUser(e, watch.UserID, false, UnitTypeIssues) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
+22
-12
@@ -460,21 +460,21 @@ func removeOrgUser(sess *xorm.Session, orgID, userID int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
org, err := GetUserByID(orgID)
|
||||
org, err := getUserByID(sess, orgID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
|
||||
}
|
||||
|
||||
// Check if the user to delete is the last member in owner team.
|
||||
if isOwner, err := IsOrganizationOwner(orgID, userID); err != nil {
|
||||
if isOwner, err := isOrganizationOwner(sess, orgID, userID); err != nil {
|
||||
return err
|
||||
} else if isOwner {
|
||||
t, err := org.GetOwnerTeam()
|
||||
t, err := org.getOwnerTeam(sess)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t.NumMembers == 1 {
|
||||
if err := t.GetMembers(); err != nil {
|
||||
if err := t.getMembers(sess); err != nil {
|
||||
return err
|
||||
}
|
||||
if t.Members[0].ID == userID {
|
||||
@@ -490,7 +490,7 @@ func removeOrgUser(sess *xorm.Session, orgID, userID int64) error {
|
||||
}
|
||||
|
||||
// Delete all repository accesses and unwatch them.
|
||||
env, err := org.AccessibleReposEnv(userID)
|
||||
env, err := org.accessibleReposEnv(sess, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("AccessibleReposEnv: %v", err)
|
||||
}
|
||||
@@ -618,16 +618,26 @@ type accessibleReposEnv struct {
|
||||
org *User
|
||||
userID int64
|
||||
teamIDs []int64
|
||||
e Engine
|
||||
}
|
||||
|
||||
// AccessibleReposEnv an AccessibleReposEnvironment for the repositories in `org`
|
||||
// that are accessible to the specified user.
|
||||
func (org *User) AccessibleReposEnv(userID int64) (AccessibleReposEnvironment, error) {
|
||||
teamIDs, err := org.GetUserTeamIDs(userID)
|
||||
return org.accessibleReposEnv(x, userID)
|
||||
}
|
||||
|
||||
func (org *User) accessibleReposEnv(e Engine, userID int64) (AccessibleReposEnvironment, error) {
|
||||
teamIDs, err := org.getUserTeamIDs(e, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &accessibleReposEnv{org: org, userID: userID, teamIDs: teamIDs}, nil
|
||||
return &accessibleReposEnv{
|
||||
org: org,
|
||||
userID: userID,
|
||||
teamIDs: teamIDs,
|
||||
e: e,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) cond() builder.Cond {
|
||||
@@ -642,7 +652,7 @@ func (env *accessibleReposEnv) cond() builder.Cond {
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
||||
repoCount, err := x.
|
||||
repoCount, err := env.e.
|
||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||
Where(env.cond()).
|
||||
Distinct("`repository`.id").
|
||||
@@ -659,7 +669,7 @@ func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
||||
}
|
||||
|
||||
repoIDs := make([]int64, 0, pageSize)
|
||||
return repoIDs, x.
|
||||
return repoIDs, env.e.
|
||||
Table("repository").
|
||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||
Where(env.cond()).
|
||||
@@ -681,14 +691,14 @@ func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*Repository, error)
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
return repos, x.
|
||||
return repos, env.e.
|
||||
In("`repository`.id", repoIDs).
|
||||
Find(&repos)
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
||||
repoIDs := make([]int64, 0, 10)
|
||||
return repoIDs, x.
|
||||
return repoIDs, env.e.
|
||||
Table("repository").
|
||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
||||
Where(env.cond()).
|
||||
@@ -709,7 +719,7 @@ func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) {
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
return repos, x.
|
||||
return repos, env.e.
|
||||
In("`repository`.id", repoIDs).
|
||||
Find(&repos)
|
||||
}
|
||||
|
||||
+41
-1
@@ -40,6 +40,14 @@ func (t *Team) getUnits(e Engine) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// GetUnitNames returns the team units names
|
||||
func (t *Team) GetUnitNames() (res []string) {
|
||||
for _, u := range t.Units {
|
||||
res = append(res, Units[u.Type].NameKey)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HasWriteAccess returns true if team has at least write level access mode.
|
||||
func (t *Team) HasWriteAccess() bool {
|
||||
return t.Authorize >= AccessModeWrite
|
||||
@@ -215,7 +223,11 @@ func (t *Team) RemoveRepository(repoID int64) error {
|
||||
|
||||
// UnitEnabled returns if the team has the given unit type enabled
|
||||
func (t *Team) UnitEnabled(tp UnitType) bool {
|
||||
if err := t.getUnits(x); err != nil {
|
||||
return t.unitEnabled(x, tp)
|
||||
}
|
||||
|
||||
func (t *Team) unitEnabled(e Engine, tp UnitType) bool {
|
||||
if err := t.getUnits(e); err != nil {
|
||||
log.Warn("Error loading repository (ID: %d) units: %s", t.ID, err.Error())
|
||||
}
|
||||
|
||||
@@ -363,6 +375,24 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
|
||||
return fmt.Errorf("update: %v", err)
|
||||
}
|
||||
|
||||
// update units for team
|
||||
if len(t.Units) > 0 {
|
||||
for _, unit := range t.Units {
|
||||
unit.TeamID = t.ID
|
||||
}
|
||||
// Delete team-unit.
|
||||
if _, err := sess.
|
||||
Where("team_id=?", t.ID).
|
||||
Delete(new(TeamUnit)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(&t.Units); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update access for team members if needed.
|
||||
if authChanged {
|
||||
if err = t.getRepositories(sess); err != nil {
|
||||
@@ -521,6 +551,16 @@ func getUserTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
|
||||
Find(&teams)
|
||||
}
|
||||
|
||||
func getUserRepoTeams(e Engine, orgID, userID, repoID int64) (teams []*Team, err error) {
|
||||
return teams, e.
|
||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||
Where("team.org_id = ?", orgID).
|
||||
And("team_user.uid=?", userID).
|
||||
And("team_repo.repo_id=?", repoID).
|
||||
Find(&teams)
|
||||
}
|
||||
|
||||
// GetUserTeams returns all teams that user belongs to in given organization.
|
||||
func GetUserTeams(orgID, userID int64) ([]*Team, error) {
|
||||
return getUserTeams(x, orgID, userID)
|
||||
|
||||
+59
-48
@@ -32,6 +32,7 @@ import (
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/builder"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/mcuadros/go-version"
|
||||
"gopkg.in/ini.v1"
|
||||
@@ -321,7 +322,11 @@ func (repo *Repository) getUnits(e Engine) (err error) {
|
||||
|
||||
// CheckUnitUser check whether user could visit the unit of this repository
|
||||
func (repo *Repository) CheckUnitUser(userID int64, isAdmin bool, unitType UnitType) bool {
|
||||
if err := repo.getUnitsByUserID(x, userID, isAdmin); err != nil {
|
||||
return repo.checkUnitUser(x, userID, isAdmin, unitType)
|
||||
}
|
||||
|
||||
func (repo *Repository) checkUnitUser(e Engine, userID int64, isAdmin bool, unitType UnitType) bool {
|
||||
if err := repo.getUnitsByUserID(e, userID, isAdmin); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -360,7 +365,7 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
|
||||
return nil
|
||||
}
|
||||
|
||||
teams, err := getUserTeams(e, repo.OwnerID, userID)
|
||||
teams, err := getUserRepoTeams(e, repo.OwnerID, userID, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -369,7 +374,7 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
|
||||
var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units))
|
||||
for _, u := range repo.Units {
|
||||
for _, team := range teams {
|
||||
if team.UnitEnabled(u.Type) {
|
||||
if team.unitEnabled(e, u.Type) {
|
||||
newRepoUnits = append(newRepoUnits, u)
|
||||
break
|
||||
}
|
||||
@@ -677,7 +682,7 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
|
||||
}
|
||||
|
||||
func (repo *Repository) updateSize(e Engine) error {
|
||||
repoInfoSize, err := git.GetRepoSize(repo.RepoPath())
|
||||
repoInfoSize, err := git.GetRepoSize(repo.repoPath(e))
|
||||
if err != nil {
|
||||
return fmt.Errorf("UpdateSize: %v", err)
|
||||
}
|
||||
@@ -1031,7 +1036,6 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
|
||||
if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||
log.Error(4, "Failed to synchronize tags to releases for repository: %v", err)
|
||||
}
|
||||
UpdateRepoIndexer(repo)
|
||||
}
|
||||
|
||||
if err = repo.UpdateSize(); err != nil {
|
||||
@@ -1049,10 +1053,16 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
|
||||
}
|
||||
|
||||
repo.IsMirror = true
|
||||
return repo, UpdateRepository(repo, false)
|
||||
err = UpdateRepository(repo, false)
|
||||
} else {
|
||||
repo, err = CleanUpMigrateInfo(repo)
|
||||
}
|
||||
|
||||
return CleanUpMigrateInfo(repo)
|
||||
if err != nil && !repo.IsBare {
|
||||
UpdateRepoIndexer(repo)
|
||||
}
|
||||
|
||||
return repo, err
|
||||
}
|
||||
|
||||
// cleanUpMigrateGitConfig removes mirror info which prevents "push --all".
|
||||
@@ -1705,7 +1715,7 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
|
||||
}
|
||||
|
||||
// Create/Remove git-daemon-export-ok for git-daemon...
|
||||
daemonExportFile := path.Join(repo.RepoPath(), `git-daemon-export-ok`)
|
||||
daemonExportFile := path.Join(repo.repoPath(e), `git-daemon-export-ok`)
|
||||
if repo.IsPrivate && com.IsExist(daemonExportFile) {
|
||||
if err = os.Remove(daemonExportFile); err != nil {
|
||||
log.Error(4, "Failed to remove %s: %v", daemonExportFile, err)
|
||||
@@ -1828,55 +1838,56 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||
&RepoRedirect{RedirectRepoID: repoID},
|
||||
&Webhook{RepoID: repoID},
|
||||
&HookTask{RepoID: repoID},
|
||||
&Notification{RepoID: repoID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
|
||||
// Delete comments and attachments.
|
||||
issueIDs := make([]int64, 0, 25)
|
||||
attachmentPaths := make([]string, 0, len(issueIDs))
|
||||
if err = sess.
|
||||
Table("issue").
|
||||
Cols("id").
|
||||
Where("repo_id=?", repoID).
|
||||
Find(&issueIDs); err != nil {
|
||||
deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repoID})
|
||||
// Delete comments and attachments
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Comment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(issueIDs) > 0 {
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Comment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&IssueUser{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Reaction{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&IssueWatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Stopwatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueUser{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attachments := make([]*Attachment, 0, 5)
|
||||
if err = sess.
|
||||
In("issue_id", issueIDs).
|
||||
Find(&attachments); err != nil {
|
||||
return err
|
||||
}
|
||||
for j := range attachments {
|
||||
attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Reaction{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Attachment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueWatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Stopwatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attachmentPaths := make([]string, 0, 20)
|
||||
attachments := make([]*Attachment, 0, len(attachmentPaths))
|
||||
if err = sess.Join("INNER", "issue", "issue.id = attachment.issue_id").
|
||||
Where("issue.repo_id = ?", repoID).
|
||||
Find(&attachments); err != nil {
|
||||
return err
|
||||
}
|
||||
for j := range attachments {
|
||||
attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Attachment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
|
||||
@@ -2447,7 +2458,7 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
|
||||
repoPath := RepoPath(u.Name, repo.Name)
|
||||
_, stderr, err := process.GetManager().ExecTimeout(10*time.Minute,
|
||||
fmt.Sprintf("ForkRepository(git clone): %s/%s", u.Name, repo.Name),
|
||||
"git", "clone", "--bare", oldRepo.RepoPath(), repoPath)
|
||||
"git", "clone", "--bare", oldRepo.repoPath(sess), repoPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("git clone: %v", stderr)
|
||||
}
|
||||
|
||||
+19
-36
@@ -173,11 +173,9 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
|
||||
cond = cond.And(builder.Eq{"is_private": false})
|
||||
}
|
||||
|
||||
var starred bool
|
||||
if opts.OwnerID > 0 {
|
||||
if opts.Starred {
|
||||
starred = true
|
||||
cond = builder.Eq{"star.uid": opts.OwnerID}
|
||||
cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.OwnerID})))
|
||||
} else {
|
||||
var accessCond = builder.NewCond()
|
||||
if opts.Collaborate != util.OptionalBoolTrue {
|
||||
@@ -204,12 +202,23 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
|
||||
}
|
||||
|
||||
if opts.Keyword != "" {
|
||||
var keywordCond = builder.NewCond()
|
||||
if opts.TopicOnly {
|
||||
keywordCond = keywordCond.Or(builder.Like{"topic.name", strings.ToLower(opts.Keyword)})
|
||||
} else {
|
||||
keywordCond = keywordCond.Or(builder.Like{"lower_name", strings.ToLower(opts.Keyword)})
|
||||
keywordCond = keywordCond.Or(builder.Like{"topic.name", strings.ToLower(opts.Keyword)})
|
||||
// separate keyword
|
||||
var subQueryCond = builder.NewCond()
|
||||
for _, v := range strings.Split(opts.Keyword, ",") {
|
||||
subQueryCond = subQueryCond.Or(builder.Like{"topic.name", strings.ToLower(v)})
|
||||
}
|
||||
subQuery := builder.Select("repo_topic.repo_id").From("repo_topic").
|
||||
Join("INNER", "topic", "topic.id = repo_topic.topic_id").
|
||||
Where(subQueryCond).
|
||||
GroupBy("repo_topic.repo_id")
|
||||
|
||||
var keywordCond = builder.In("id", subQuery)
|
||||
if !opts.TopicOnly {
|
||||
var likes = builder.NewCond()
|
||||
for _, v := range strings.Split(opts.Keyword, ",") {
|
||||
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
|
||||
}
|
||||
keywordCond = keywordCond.Or(likes)
|
||||
}
|
||||
cond = cond.And(keywordCond)
|
||||
}
|
||||
@@ -229,15 +238,6 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if starred {
|
||||
sess.Join("INNER", "star", "star.repo_id = repository.id")
|
||||
}
|
||||
|
||||
if opts.Keyword != "" {
|
||||
sess.Join("LEFT", "repo_topic", "repo_topic.repo_id = repository.id")
|
||||
sess.Join("LEFT", "topic", "repo_topic.topic_id = topic.id")
|
||||
}
|
||||
|
||||
count, err := sess.
|
||||
Where(cond).
|
||||
Count(new(Repository))
|
||||
@@ -246,27 +246,10 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
|
||||
return nil, 0, fmt.Errorf("Count: %v", err)
|
||||
}
|
||||
|
||||
// Set again after reset by Count()
|
||||
if starred {
|
||||
sess.Join("INNER", "star", "star.repo_id = repository.id")
|
||||
}
|
||||
|
||||
if opts.Keyword != "" {
|
||||
sess.Join("LEFT", "repo_topic", "repo_topic.repo_id = repository.id")
|
||||
sess.Join("LEFT", "topic", "repo_topic.topic_id = topic.id")
|
||||
}
|
||||
|
||||
if opts.Keyword != "" {
|
||||
sess.Select("repository.*")
|
||||
sess.GroupBy("repository.id")
|
||||
sess.OrderBy("repository." + opts.OrderBy.String())
|
||||
} else {
|
||||
sess.OrderBy(opts.OrderBy.String())
|
||||
}
|
||||
|
||||
repos := make(RepositoryList, 0, opts.PageSize)
|
||||
if err = sess.
|
||||
Where(cond).
|
||||
OrderBy(opts.OrderBy.String()).
|
||||
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).
|
||||
Find(&repos); err != nil {
|
||||
return nil, 0, fmt.Errorf("Repo: %v", err)
|
||||
|
||||
@@ -237,6 +237,9 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
|
||||
{name: "AllPublic/OnlySearchPublicRepositoriesFromTopic",
|
||||
opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true},
|
||||
count: 1},
|
||||
{name: "AllPublic/OnlySearchMultipleKeywordPublicRepositoriesFromTopic",
|
||||
opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true},
|
||||
count: 2},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
+6
-1
@@ -535,6 +535,7 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
||||
if err = sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
sess.Close()
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
@@ -543,6 +544,10 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
||||
// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
|
||||
// outside any session scope independently.
|
||||
func RewriteAllPublicKeys() error {
|
||||
return rewriteAllPublicKeys(x)
|
||||
}
|
||||
|
||||
func rewriteAllPublicKeys(e Engine) error {
|
||||
//Don't rewrite key if internal server
|
||||
if setting.SSH.StartBuiltinServer {
|
||||
return nil
|
||||
@@ -569,7 +574,7 @@ func RewriteAllPublicKeys() error {
|
||||
}
|
||||
}
|
||||
|
||||
err = x.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
err = e.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||
return err
|
||||
})
|
||||
|
||||
+8
-7
@@ -197,14 +197,15 @@ func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error {
|
||||
return fmt.Errorf("newCommitStatus[nil, %s]: no repository specified", opts.SHA)
|
||||
}
|
||||
opts.CommitStatus.RepoID = opts.Repo.ID
|
||||
repoPath := opts.Repo.repoPath(sess)
|
||||
|
||||
if opts.Creator == nil {
|
||||
return fmt.Errorf("newCommitStatus[%s, %s]: no user specified", opts.Repo.RepoPath(), opts.SHA)
|
||||
return fmt.Errorf("newCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA)
|
||||
}
|
||||
|
||||
gitRepo, err := git.OpenRepository(opts.Repo.RepoPath())
|
||||
gitRepo, err := git.OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OpenRepository[%s]: %v", opts.Repo.RepoPath(), err)
|
||||
return fmt.Errorf("OpenRepository[%s]: %v", repoPath, err)
|
||||
}
|
||||
if _, err := gitRepo.GetCommit(opts.SHA); err != nil {
|
||||
return fmt.Errorf("GetCommit[%s]: %v", opts.SHA, err)
|
||||
@@ -219,19 +220,19 @@ func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error {
|
||||
has, err := sess.Desc("index").Limit(1).Get(lastCommitStatus)
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return fmt.Errorf("newCommitStatus[%s, %s]: %v", opts.Repo.RepoPath(), opts.SHA, err)
|
||||
return fmt.Errorf("newCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err)
|
||||
}
|
||||
if has {
|
||||
log.Debug("newCommitStatus[%s, %s]: found", opts.Repo.RepoPath(), opts.SHA)
|
||||
log.Debug("newCommitStatus[%s, %s]: found", repoPath, opts.SHA)
|
||||
nextIndex = lastCommitStatus.Index
|
||||
}
|
||||
opts.CommitStatus.Index = nextIndex + 1
|
||||
log.Debug("newCommitStatus[%s, %s]: %d", opts.Repo.RepoPath(), opts.SHA, opts.CommitStatus.Index)
|
||||
log.Debug("newCommitStatus[%s, %s]: %d", repoPath, opts.SHA, opts.CommitStatus.Index)
|
||||
|
||||
// Insert new CommitStatus
|
||||
if _, err = sess.Insert(opts.CommitStatus); err != nil {
|
||||
sess.Rollback()
|
||||
return fmt.Errorf("newCommitStatus[%s, %s]: %v", opts.Repo.RepoPath(), opts.SHA, err)
|
||||
return fmt.Errorf("newCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ var topicPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
|
||||
// Topic represents a topic of repositories
|
||||
type Topic struct {
|
||||
ID int64
|
||||
Name string `xorm:"UNIQUE"`
|
||||
Name string `xorm:"UNIQUE VARCHAR(25)"`
|
||||
RepoCount int
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UnitType is Unit's Type
|
||||
type UnitType int
|
||||
|
||||
@@ -137,3 +141,16 @@ var (
|
||||
UnitTypeExternalWiki: UnitExternalWiki,
|
||||
}
|
||||
)
|
||||
|
||||
// FindUnitTypes give the unit key name and return unit
|
||||
func FindUnitTypes(nameKeys ...string) (res []UnitType) {
|
||||
for _, key := range nameKeys {
|
||||
for t, u := range Units {
|
||||
if strings.EqualFold(key, u.NameKey) {
|
||||
res = append(res, t)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
+12
-10
@@ -1038,25 +1038,26 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
&EmailAddress{UID: u.ID},
|
||||
&UserOpenID{UID: u.ID},
|
||||
&Reaction{UserID: u.ID},
|
||||
&TeamUser{UID: u.ID},
|
||||
&Collaboration{UserID: u.ID},
|
||||
&Stopwatch{UserID: u.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
|
||||
// ***** START: PublicKey *****
|
||||
keys := make([]*PublicKey, 0, 10)
|
||||
if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("get all public keys: %v", err)
|
||||
}
|
||||
|
||||
keyIDs := make([]int64, len(keys))
|
||||
for i := range keys {
|
||||
keyIDs[i] = keys[i].ID
|
||||
}
|
||||
if err = deletePublicKeys(e, keyIDs...); err != nil {
|
||||
if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||
}
|
||||
rewriteAllPublicKeys(e)
|
||||
// ***** END: PublicKey *****
|
||||
|
||||
// ***** START: GPGPublicKey *****
|
||||
if _, err = e.Delete(&GPGKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("deleteGPGKeys: %v", err)
|
||||
}
|
||||
// ***** END: GPGPublicKey *****
|
||||
|
||||
// Clear assignee.
|
||||
if err = clearAssigneeByUserID(e, u.ID); err != nil {
|
||||
return fmt.Errorf("clear assignee: %v", err)
|
||||
@@ -1110,6 +1111,7 @@ func DeleteUser(u *User) (err error) {
|
||||
if err = sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
sess.Close()
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func DeleteUserOpenID(openid *UserOpenID) (err error) {
|
||||
|
||||
// ToggleUserOpenIDVisibility toggles visibility of an openid address of given user.
|
||||
func ToggleUserOpenIDVisibility(id int64) (err error) {
|
||||
_, err = x.Exec("update user_open_id set show = not show where id = ?", id)
|
||||
_, err = x.Exec("update `user_open_id` set `show` = not `show` where `id` = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -377,6 +377,7 @@ type CodeCommentForm struct {
|
||||
Line int64
|
||||
TreePath string `form:"path" binding:"Required"`
|
||||
IsReview bool `form:"is_review"`
|
||||
Reply int64 `form:"reply"`
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-macaron/csrf"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
@@ -97,6 +99,17 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
|
||||
}
|
||||
}
|
||||
|
||||
// RequireCSRF requires a validated a CSRF token
|
||||
func (ctx *APIContext) RequireCSRF() {
|
||||
headerToken := ctx.Req.Header.Get(ctx.csrf.GetHeaderName())
|
||||
formValueToken := ctx.Req.FormValue(ctx.csrf.GetFormName())
|
||||
if len(headerToken) > 0 || len(formValueToken) > 0 {
|
||||
csrf.Validate(ctx.Context.Context, ctx.csrf)
|
||||
} else {
|
||||
ctx.Context.Error(401)
|
||||
}
|
||||
}
|
||||
|
||||
// APIContexter returns apicontext as macaron middleware
|
||||
func APIContexter() macaron.Handler {
|
||||
return func(c *Context) {
|
||||
|
||||
@@ -60,7 +60,7 @@ func InitIssueIndexer(populateIndexer func() error) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = createIssueIndexer(); err != nil {
|
||||
if err = createIssueIndexer(setting.Indexer.IssuePath, issueIndexerLatestVersion); err != nil {
|
||||
log.Fatal(4, "InitIssuesIndexer: create index, %v", err)
|
||||
}
|
||||
if err = populateIndexer(); err != nil {
|
||||
@@ -69,7 +69,7 @@ func InitIssueIndexer(populateIndexer func() error) {
|
||||
}
|
||||
|
||||
// createIssueIndexer create an issue indexer if one does not already exist
|
||||
func createIssueIndexer() error {
|
||||
func createIssueIndexer(path string, latestVersion int) error {
|
||||
mapping := bleve.NewIndexMapping()
|
||||
docMapping := bleve.NewDocumentMapping()
|
||||
|
||||
@@ -100,8 +100,14 @@ func createIssueIndexer() error {
|
||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||
|
||||
var err error
|
||||
issueIndexer, err = bleve.New(setting.Indexer.IssuePath, mapping)
|
||||
return err
|
||||
issueIndexer, err = bleve.New(path, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
|
||||
Version: latestVersion,
|
||||
})
|
||||
}
|
||||
|
||||
// IssueIndexerBatch batch to add updates to
|
||||
|
||||
@@ -84,7 +84,7 @@ func InitRepoIndexer(populateIndexer func() error) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = createRepoIndexer(); err != nil {
|
||||
if err = createRepoIndexer(setting.Indexer.RepoPath, repoIndexerLatestVersion); err != nil {
|
||||
log.Fatal(4, "CreateRepoIndexer: %v", err)
|
||||
}
|
||||
if err = populateIndexer(); err != nil {
|
||||
@@ -93,7 +93,7 @@ func InitRepoIndexer(populateIndexer func() error) {
|
||||
}
|
||||
|
||||
// createRepoIndexer create a repo indexer if one does not already exist
|
||||
func createRepoIndexer() error {
|
||||
func createRepoIndexer(path string, latestVersion int) error {
|
||||
var err error
|
||||
docMapping := bleve.NewDocumentMapping()
|
||||
numericFieldMapping := bleve.NewNumericFieldMapping()
|
||||
@@ -119,8 +119,13 @@ func createRepoIndexer() error {
|
||||
mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
|
||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||
|
||||
repoIndexer, err = bleve.New(setting.Indexer.RepoPath, mapping)
|
||||
return err
|
||||
repoIndexer, err = bleve.New(path, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
|
||||
Version: latestVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func filenameIndexerID(repoID int64, filename string) string {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user