Compare commits

...

27 Commits

Author SHA1 Message Date
Lunny Xiao
0da8bc9ec0 add changelog of v1.6.0 (#5379)
* add changelog of v1.6.0

* improve changelog
2018-11-22 22:53:58 -05:00
Lunny Xiao
5d69703d3c dont' send assign webhooks when creating issue (#5365) (#5369) 2018-11-21 23:12:17 +08:00
Florian Eitel
ffc0c7f611 Migration fixes 5318 1.6 backport (#5355)
* Remove field from migration to support upgrades from older version

That will ensure the field does not get queried in the Select if it does
not exist yet:

```
[I] [SQL] SELECT "id", "repo_id", "index", "poster_id", "name", "content", "milestone_id", "priority", "assignee_id", "is_closed", "is_pull", "num_comments", "ref", "deadline_unix", "created_unix", "updated_unix
[...itea/routers/init.go:60 GlobalInit()] [E] Failed to initialize ORM engine: migrate: do migrate: pq: column "ref" does not exist
```

see #5318

* Skip remove stale watcher migration if not required

Otherwise the migration will fail if executed from a older database
version without multiple IssueWatch feature.

```
2018/11/11 23:51:14 [I] [SQL] SELECT DISTINCT "issue_watch"."user_id", "issue"."repo_id" FROM "issue_watch" INNER JOIN issue ON issue_watch.issue_id = issue.id WHERE (issue_watch.is_watching = $1) LIMIT 50 []int
[...itea/routers/init.go:60 GlobalInit()] [E] Failed to initialize ORM engine: migrate: do migrate: pq: relation "issue_watch" does not exist
```

see #5318
2018-11-18 22:34:14 +02:00
Lunny Xiao
8670decafb Fix create team, update team missing units (#5188) (#5313) 2018-11-11 12:43:56 -05:00
Lauris BH
297e619074 Fix file edit change preview functionality (#5300) (#5311) 2018-11-10 16:12:58 +02:00
Lunny Xiao
e9b984e162 fix bug when users have serval teams with different units on different repositories (#5307) (#5308) 2018-11-09 17:46:38 +08:00
Lauris BH
5995b65175 Fix U2F if gitea is configured in subpath (#5302) (#5306) 2018-11-09 13:45:50 +08:00
Lauris BH
996ce8cc03 Fix markdown image with link (#4675) (#5299)
* Fix markdown image with link

* Add gitea copyright notice

* add a test for markdown image with link

* remove svg related variables
2018-11-08 17:47:24 -05:00
Lauris BH
fe7cef0e1f Add changelog for 1.5.3 release (#5227) (#5298) 2018-11-08 17:20:10 -05:00
Lauris BH
464dcd1b66 Remove maxlines option for file logger (#5282) (#5287) 2018-11-07 09:14:44 +02:00
Lauris BH
68938d5dc4 Backport fix broken translation (#5284) 2018-11-07 06:50:52 +02:00
techknowlogick
9c11fafdb0 1.6.0-RC2 Changelog (#5275) 2018-11-04 17:07:08 -05:00
zeripath
c0bbbdd30b Backport #5250 on v1.6: Fix Issue 5249 and protect /api/v1/admin routes with CSRF token (#5272)
* Add CSRF checking to reqToken and place CSRF in the post for deadline creation

Fixes #5226, #5249

* /api/v1/admin/users routes should have reqToken middleware
2018-11-04 10:42:15 -05:00
kolaente
f95c966770 Backported wrong api request url for instances running in subfolders (#5247) (#5261) 2018-11-03 17:43:11 -04:00
Peter Hoffmann
14a074f979 fix: Accept web-command cli flags if web-command is commited (#5245)
* Added flags of default cmd CmdWeb to app-wide flags
* If command *is* specified app-wide flags are ignored

Backport of #5200
Signed-off-by: Berengar W. Lehr <Berengar.Lehr@kompetenztest.de>
2018-11-01 11:24:23 -04:00
Lunny Xiao
3786369356 This commit will reduce join star, repo_topic, topic tables on repo search, so that fix extra columns problem on mssql (#5136) (#5229)
* This commit will reduce join star, repo_topic, topic tables on repo search, so that fix extra columns problem on mssql

* fix tests
2018-10-31 20:21:31 -04:00
Lunny Xiao
79464216d9 fix data race on migrate repository (#5224) (#5230) 2018-10-31 20:23:13 +08:00
Peter Hoffmann
e28801ff1a fix: Add secret to all webhook's payload where it has been missing (#5208)
* Updated dependency manager via `dep ensure -update code.gitea.io/sdk`
* Gopkg.toml was not changed as sdk version is set to "master"
* affects webhooks for: Delete, Fork, IssueComment, Release
* also contains changes from go-gitea/go-sdk#125 and hence a swagger update

Signed-off-by: Berengar W. Lehr <Berengar.Lehr@kompetenztest.de>
Resolves: #4732, #5173
2018-10-30 17:14:12 +02:00
Lunny Xiao
478ba7f318 fix sqlite lock (#5210) (#5223) 2018-10-30 14:21:55 +08:00
Kim "BKC" Carlbäcker
582213a858 Update go-macaron/session to latest mast to fix RCE-bug (#5195) 2018-10-30 13:36:50 +08:00
Lunny Xiao
4d66de684f Fix race on updatesize (#5190) (#5215)
* fix race on updatesize

* fix more repoPath
2018-10-30 09:20:18 +08:00
Rodrigo Villablanca Vásquez
d220a3d772 fix to 3819 - Backport (#5219) 2018-10-29 15:56:21 -04:00
Lunny Xiao
7022957b15 fix sqlite and mssql lock (#5214) (#5218) 2018-10-29 14:10:50 -04:00
Lunny Xiao
e7128e8c41 Fix sqlite lock (#5176) (#5179)
* fix sqlite lock

* fix sqlite lock on getUnitType
2018-10-25 17:30:25 +03:00
Jonas Franz
274ff0d011 Add comment replies (#5147)
*         Add comment replies

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

* Use review.ID instead

Signed-off-by: Jonas Franz <info@jonasfranz.software>
2018-10-23 10:38:06 -04:00
Filip Navara
7238bb329a Fix SQL quoting (#5137)
`show` is keyword in MySQL and has to be quoted to reference a column name. Use grave accents (ASCII code 96) for quoting to match rest of the source code. It's non-standard SQL, but it's supported by SQLite and MySQL.

Signed-off-by: Filip Navara <navara@emclient.com>
2018-10-22 14:46:47 -04:00
kolaente
49d666f99a Fix regex to support optional end line of old section in diff hunk (#5097)
+ Named groups in reges for easier group parsing
2018-10-18 09:57:35 +08:00
48 changed files with 514 additions and 267 deletions

View File

@@ -4,12 +4,19 @@ 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.6.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.6.0-rc1) - 2018-10-17 ## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
* BREAKING * BREAKING
* Respect email privacy option in user search via API (#4512) * Respect email privacy option in user search via API (#4512)
* Simply remove tidb and deps (#3993) * Simply remove tidb and deps (#3993)
* Swagger.v1.json template (#3572) * 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 * FEATURE
* Add comment replies (#5147) (#5104)
* Pull request review/approval and comment on code (#3748) * Pull request review/approval and comment on code (#3748)
* Added dependencies for issues (#2196) (#2531) * Added dependencies for issues (#2196) (#2531)
* Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198) * Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198)
@@ -21,63 +28,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* Add push webhook support for mirrored repositories (#4127) * Add push webhook support for mirrored repositories (#4127)
* Add csv file render support defaultly (#4105) * Add csv file render support defaultly (#4105)
* Add Recaptcha functionality to Gitea (#4044) * 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 * ENHANCEMENT
* Fix milestones sorted wrongly (#4987) * Fix milestones sorted wrongly (#4987)
* Allow api to create tags for releases if they don't exist (#4890) * Allow api to create tags for releases if they don't exist (#4890)
@@ -130,15 +80,87 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* Added front-end topics validation (#4316) * Added front-end topics validation (#4316)
* Don't display buttons if there are no system notifications (#4280) * Don't display buttons if there are no system notifications (#4280)
* Issue due date api (#3890) * Issue due date api (#3890)
* SECURITY * BUGFIXES
* Improve URL validation for external wiki and external issues (#4710) * dont' send assign webhooks when creating issue (#5365)
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706) * Fix create team, update team missing units (#5188)
* Don't disclose emails of all users when sending out emails (#4664) * Fix file edit change preview functionality (#5300)
* Check that repositories can only be migrated to own user or organizations (#4366) * *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 * TRANSLATION
* Fix punctuation in English translation (#4958) * Fix punctuation in English translation (#4958)
* Fix translation (#4355) * 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 ## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
* SECURITY * SECURITY
* Enforce token on api routes (#4840) (#4905) * Enforce token on api routes (#4840) (#4905)

9
Gopkg.lock generated
View File

@@ -11,11 +11,11 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:5e7f14543006a44047fb1d0df16da08b2ebc2428f1fd53bd8af26a2b34928b11" digest = "1:b194da40b41ae99546dfeec5a85f1fec2a6c51350d438e511ef90f4293c6dcd7"
name = "code.gitea.io/sdk" name = "code.gitea.io/sdk"
packages = ["gitea"] packages = ["gitea"]
pruneopts = "NUT" pruneopts = "NUT"
revision = "021567c9c12fe289b8980c34e81e6684434dd082" revision = "4f96d9ac89886e78c50de8c835ebe87461578a5e"
[[projects]] [[projects]]
digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195" digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195"
@@ -342,14 +342,15 @@
revision = "d8a0b8677191f4380287cfebd08e462217bac7ad" revision = "d8a0b8677191f4380287cfebd08e462217bac7ad"
[[projects]] [[projects]]
digest = "1:b327ca585509a889130a8f51f43704a8fe03cb5cd281dbf1bc6405f5a7ea4702" branch = "master"
digest = "1:8fea5718d84af17762195beb6fe92a0d6c1048452a1dbc464d227f12e0cff0cc"
name = "github.com/go-macaron/session" name = "github.com/go-macaron/session"
packages = [ packages = [
".", ".",
"redis", "redis",
] ]
pruneopts = "NUT" pruneopts = "NUT"
revision = "66031fcb37a0fff002a1f028eb0b3a815c78306b" revision = "330e4e4d8beb7b00111ac34539561f46f94c4458"
[[projects]] [[projects]]
digest = "1:758d2371fcdee6d02565901b348729053c636055e67ef6e17aa466c7ff6cc57c" digest = "1:758d2371fcdee6d02565901b348729053c636055e67ef6e17aa466c7ff6cc57c"

View File

@@ -39,8 +39,8 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
OwnerID: keyOwner.ID, OwnerID: keyOwner.ID,
}) })
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token="+token, req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
keyOwner.Name, newPublicKey.ID) keyOwner.Name, newPublicKey.ID, token)
session.MakeRequest(t, req, http.StatusNoContent) session.MakeRequest(t, req, http.StatusNoContent)
models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID}) models.AssertNotExistsBean(t, &models.PublicKey{ID: newPublicKey.ID})
} }
@@ -51,7 +51,7 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
session := loginUser(t, "user1") session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session) 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) session.MakeRequest(t, req, http.StatusNotFound)
} }
@@ -73,8 +73,8 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
session = loginUser(t, normalUsername) session = loginUser(t, normalUsername)
token = getTokenForLoggedInUser(t, session) token = getTokenForLoggedInUser(t, session)
req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token="+token, req = NewRequestf(t, "DELETE", "/api/v1/admin/users/%s/keys/%d?token=%s",
adminUsername, newPublicKey.ID) adminUsername, newPublicKey.ID, token)
session.MakeRequest(t, req, http.StatusForbidden) session.MakeRequest(t, req, http.StatusForbidden)
} }

View File

@@ -143,7 +143,8 @@ func TestGit(t *testing.T) {
session := loginUser(t, "user1") session := loginUser(t, "user1")
keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User) 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") dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -48,7 +48,7 @@ arguments - which can alternatively be run by running the subcommand web.`
cmd.CmdAdmin, cmd.CmdAdmin,
cmd.CmdGenerate, cmd.CmdGenerate,
} }
app.Flags = append(app.Flags, []cli.Flag{}...) app.Flags = append(app.Flags, cmd.CmdWeb.Flags...)
app.Action = cmd.CmdWeb.Action app.Action = cmd.CmdWeb.Action
err := app.Run(os.Args) err := app.Run(os.Args)
if err != nil { if err != nil {

View File

@@ -273,7 +273,7 @@ func (diff *Diff) NumFiles() int {
} }
// Example: @@ -1,8 +1,9 @@ => [..., 1, 8, 1, 9] // 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 { func isHeader(lof string) bool {
return strings.HasPrefix(lof, cmdDiffHead) || strings.HasPrefix(lof, "---") || strings.HasPrefix(lof, "+++") 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 { if len(hunk) > headerLines {
break 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 { if old {
begin = com.StrTo(groups[1]).MustInt64() begin = com.StrTo(groups["beginOld"]).MustInt64()
end = com.StrTo(groups[2]).MustInt64() end = com.StrTo(groups["endOld"]).MustInt64()
// init otherLine with begin of opposite side // init otherLine with begin of opposite side
otherLine = com.StrTo(groups[3]).MustInt64() otherLine = com.StrTo(groups["beginNew"]).MustInt64()
} else { } else {
begin = com.StrTo(groups[3]).MustInt64() begin = com.StrTo(groups["beginNew"]).MustInt64()
if groups[5] != "" { if groups["endNew"] != "" {
end = com.StrTo(groups[5]).MustInt64() end = com.StrTo(groups["endNew"]).MustInt64()
} else { } else {
end = 0 end = 0
} }
// init otherLine with begin of opposite side // 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 end += begin // end is for real only the number of lines in hunk
// lof is between begin and end // lof is between begin and end

View File

@@ -159,12 +159,13 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
return fmt.Errorf("createAssigneeComment: %v", err) 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) mode, _ := accessLevel(sess, doer.ID, issue.Repo)
if issue.IsPull { 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 { if err = issue.loadPullRequest(sess); err != nil {
return fmt.Errorf("loadPullRequest: %v", err) return fmt.Errorf("loadPullRequest: %v", err)
} }

View File

@@ -26,7 +26,6 @@ func addMultipleAssignees(x *xorm.Engine) error {
IsClosed bool `xorm:"INDEX"` IsClosed bool `xorm:"INDEX"`
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not. IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
NumComments int NumComments int
Ref string
DeadlineUnix util.TimeStamp `xorm:"INDEX"` DeadlineUnix util.TimeStamp `xorm:"INDEX"`
CreatedUnix util.TimeStamp `xorm:"INDEX created"` CreatedUnix util.TimeStamp `xorm:"INDEX created"`

View File

@@ -5,6 +5,8 @@
package migrations package migrations
import ( import (
"fmt"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
@@ -70,6 +72,13 @@ func removeStaleWatches(x *xorm.Engine) error {
return err 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) repoCache := make(map[int64]*Repository)
err := x.BufferSize(setting.IterateBufferSize).Iterate(new(Watch), err := x.BufferSize(setting.IterateBufferSize).Iterate(new(Watch),
func(idx int, bean interface{}) error { func(idx int, bean interface{}) error {

View File

@@ -123,10 +123,10 @@ func createOrUpdateIssueNotifications(e Engine, issue *Issue, notificationAuthor
for _, watch := range watches { for _, watch := range watches {
issue.Repo.Units = nil 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 continue
} }
if !issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypeIssues) { if !issue.IsPull && !issue.Repo.checkUnitUser(e, watch.UserID, false, UnitTypeIssues) {
continue continue
} }

View File

@@ -460,21 +460,21 @@ func removeOrgUser(sess *xorm.Session, orgID, userID int64) error {
return nil return nil
} }
org, err := GetUserByID(orgID) org, err := getUserByID(sess, orgID)
if err != nil { if err != nil {
return fmt.Errorf("GetUserByID [%d]: %v", orgID, err) return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
} }
// Check if the user to delete is the last member in owner team. // 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 return err
} else if isOwner { } else if isOwner {
t, err := org.GetOwnerTeam() t, err := org.getOwnerTeam(sess)
if err != nil { if err != nil {
return err return err
} }
if t.NumMembers == 1 { if t.NumMembers == 1 {
if err := t.GetMembers(); err != nil { if err := t.getMembers(sess); err != nil {
return err return err
} }
if t.Members[0].ID == userID { 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. // Delete all repository accesses and unwatch them.
env, err := org.AccessibleReposEnv(userID) env, err := org.accessibleReposEnv(sess, userID)
if err != nil { if err != nil {
return fmt.Errorf("AccessibleReposEnv: %v", err) return fmt.Errorf("AccessibleReposEnv: %v", err)
} }
@@ -618,16 +618,26 @@ type accessibleReposEnv struct {
org *User org *User
userID int64 userID int64
teamIDs []int64 teamIDs []int64
e Engine
} }
// AccessibleReposEnv an AccessibleReposEnvironment for the repositories in `org` // AccessibleReposEnv an AccessibleReposEnvironment for the repositories in `org`
// that are accessible to the specified user. // that are accessible to the specified user.
func (org *User) AccessibleReposEnv(userID int64) (AccessibleReposEnvironment, error) { 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 { if err != nil {
return nil, err 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 { func (env *accessibleReposEnv) cond() builder.Cond {
@@ -642,7 +652,7 @@ func (env *accessibleReposEnv) cond() builder.Cond {
} }
func (env *accessibleReposEnv) CountRepos() (int64, error) { func (env *accessibleReposEnv) CountRepos() (int64, error) {
repoCount, err := x. repoCount, err := env.e.
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id"). Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
Where(env.cond()). Where(env.cond()).
Distinct("`repository`.id"). Distinct("`repository`.id").
@@ -659,7 +669,7 @@ func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
} }
repoIDs := make([]int64, 0, pageSize) repoIDs := make([]int64, 0, pageSize)
return repoIDs, x. return repoIDs, env.e.
Table("repository"). Table("repository").
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id"). Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
Where(env.cond()). Where(env.cond()).
@@ -681,14 +691,14 @@ func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*Repository, error)
return repos, nil return repos, nil
} }
return repos, x. return repos, env.e.
In("`repository`.id", repoIDs). In("`repository`.id", repoIDs).
Find(&repos) Find(&repos)
} }
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) { func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
repoIDs := make([]int64, 0, 10) repoIDs := make([]int64, 0, 10)
return repoIDs, x. return repoIDs, env.e.
Table("repository"). Table("repository").
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true). Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
Where(env.cond()). Where(env.cond()).
@@ -709,7 +719,7 @@ func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) {
return repos, nil return repos, nil
} }
return repos, x. return repos, env.e.
In("`repository`.id", repoIDs). In("`repository`.id", repoIDs).
Find(&repos) Find(&repos)
} }

View File

@@ -40,6 +40,14 @@ func (t *Team) getUnits(e Engine) (err error) {
return err 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. // HasWriteAccess returns true if team has at least write level access mode.
func (t *Team) HasWriteAccess() bool { func (t *Team) HasWriteAccess() bool {
return t.Authorize >= AccessModeWrite 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 // UnitEnabled returns if the team has the given unit type enabled
func (t *Team) UnitEnabled(tp UnitType) bool { 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()) 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) 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. // Update access for team members if needed.
if authChanged { if authChanged {
if err = t.getRepositories(sess); err != nil { if err = t.getRepositories(sess); err != nil {
@@ -521,6 +551,16 @@ func getUserTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
Find(&teams) 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. // GetUserTeams returns all teams that user belongs to in given organization.
func GetUserTeams(orgID, userID int64) ([]*Team, error) { func GetUserTeams(orgID, userID int64) ([]*Team, error) {
return getUserTeams(x, orgID, userID) return getUserTeams(x, orgID, userID)

View File

@@ -321,7 +321,11 @@ func (repo *Repository) getUnits(e Engine) (err error) {
// CheckUnitUser check whether user could visit the unit of this repository // CheckUnitUser check whether user could visit the unit of this repository
func (repo *Repository) CheckUnitUser(userID int64, isAdmin bool, unitType UnitType) bool { 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 return false
} }
@@ -360,7 +364,7 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
return nil return nil
} }
teams, err := getUserTeams(e, repo.OwnerID, userID) teams, err := getUserRepoTeams(e, repo.OwnerID, userID, repo.ID)
if err != nil { if err != nil {
return err return err
} }
@@ -369,7 +373,7 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units)) var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units))
for _, u := range repo.Units { for _, u := range repo.Units {
for _, team := range teams { for _, team := range teams {
if team.UnitEnabled(u.Type) { if team.unitEnabled(e, u.Type) {
newRepoUnits = append(newRepoUnits, u) newRepoUnits = append(newRepoUnits, u)
break break
} }
@@ -677,7 +681,7 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
} }
func (repo *Repository) updateSize(e Engine) error { func (repo *Repository) updateSize(e Engine) error {
repoInfoSize, err := git.GetRepoSize(repo.RepoPath()) repoInfoSize, err := git.GetRepoSize(repo.repoPath(e))
if err != nil { if err != nil {
return fmt.Errorf("UpdateSize: %v", err) return fmt.Errorf("UpdateSize: %v", err)
} }
@@ -1031,7 +1035,6 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
if err = SyncReleasesWithTags(repo, gitRepo); err != nil { if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
log.Error(4, "Failed to synchronize tags to releases for repository: %v", err) log.Error(4, "Failed to synchronize tags to releases for repository: %v", err)
} }
UpdateRepoIndexer(repo)
} }
if err = repo.UpdateSize(); err != nil { if err = repo.UpdateSize(); err != nil {
@@ -1049,10 +1052,16 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
} }
repo.IsMirror = true 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". // cleanUpMigrateGitConfig removes mirror info which prevents "push --all".
@@ -1705,7 +1714,7 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
} }
// Create/Remove git-daemon-export-ok for git-daemon... // 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 repo.IsPrivate && com.IsExist(daemonExportFile) {
if err = os.Remove(daemonExportFile); err != nil { if err = os.Remove(daemonExportFile); err != nil {
log.Error(4, "Failed to remove %s: %v", daemonExportFile, err) log.Error(4, "Failed to remove %s: %v", daemonExportFile, err)
@@ -2447,7 +2456,7 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
repoPath := RepoPath(u.Name, repo.Name) repoPath := RepoPath(u.Name, repo.Name)
_, stderr, err := process.GetManager().ExecTimeout(10*time.Minute, _, stderr, err := process.GetManager().ExecTimeout(10*time.Minute,
fmt.Sprintf("ForkRepository(git clone): %s/%s", u.Name, repo.Name), 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 { if err != nil {
return nil, fmt.Errorf("git clone: %v", stderr) return nil, fmt.Errorf("git clone: %v", stderr)
} }

View File

@@ -173,11 +173,9 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
cond = cond.And(builder.Eq{"is_private": false}) cond = cond.And(builder.Eq{"is_private": false})
} }
var starred bool
if opts.OwnerID > 0 { if opts.OwnerID > 0 {
if opts.Starred { if opts.Starred {
starred = true cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.OwnerID})))
cond = builder.Eq{"star.uid": opts.OwnerID}
} else { } else {
var accessCond = builder.NewCond() var accessCond = builder.NewCond()
if opts.Collaborate != util.OptionalBoolTrue { if opts.Collaborate != util.OptionalBoolTrue {
@@ -204,12 +202,23 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
} }
if opts.Keyword != "" { if opts.Keyword != "" {
var keywordCond = builder.NewCond() // separate keyword
if opts.TopicOnly { var subQueryCond = builder.NewCond()
keywordCond = keywordCond.Or(builder.Like{"topic.name", strings.ToLower(opts.Keyword)}) for _, v := range strings.Split(opts.Keyword, ",") {
} else { subQueryCond = subQueryCond.Or(builder.Like{"topic.name", strings.ToLower(v)})
keywordCond = keywordCond.Or(builder.Like{"lower_name", strings.ToLower(opts.Keyword)}) }
keywordCond = keywordCond.Or(builder.Like{"topic.name", strings.ToLower(opts.Keyword)}) 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) cond = cond.And(keywordCond)
} }
@@ -229,15 +238,6 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
sess := x.NewSession() sess := x.NewSession()
defer sess.Close() 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. count, err := sess.
Where(cond). Where(cond).
Count(new(Repository)) Count(new(Repository))
@@ -246,27 +246,10 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
return nil, 0, fmt.Errorf("Count: %v", 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) repos := make(RepositoryList, 0, opts.PageSize)
if err = sess. if err = sess.
Where(cond). Where(cond).
OrderBy(opts.OrderBy.String()).
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).
Find(&repos); err != nil { Find(&repos); err != nil {
return nil, 0, fmt.Errorf("Repo: %v", err) return nil, 0, fmt.Errorf("Repo: %v", err)

View File

@@ -237,6 +237,9 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
{name: "AllPublic/OnlySearchPublicRepositoriesFromTopic", {name: "AllPublic/OnlySearchPublicRepositoriesFromTopic",
opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true}, opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true},
count: 1}, count: 1},
{name: "AllPublic/OnlySearchMultipleKeywordPublicRepositoriesFromTopic",
opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true},
count: 2},
} }
for _, testCase := range testCases { for _, testCase := range testCases {

View File

@@ -197,14 +197,15 @@ func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error {
return fmt.Errorf("newCommitStatus[nil, %s]: no repository specified", opts.SHA) return fmt.Errorf("newCommitStatus[nil, %s]: no repository specified", opts.SHA)
} }
opts.CommitStatus.RepoID = opts.Repo.ID opts.CommitStatus.RepoID = opts.Repo.ID
repoPath := opts.Repo.repoPath(sess)
if opts.Creator == nil { 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 { 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 { if _, err := gitRepo.GetCommit(opts.SHA); err != nil {
return fmt.Errorf("GetCommit[%s]: %v", opts.SHA, err) 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) has, err := sess.Desc("index").Limit(1).Get(lastCommitStatus)
if err != nil { if err != nil {
sess.Rollback() 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 { 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 nextIndex = lastCommitStatus.Index
} }
opts.CommitStatus.Index = nextIndex + 1 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 // Insert new CommitStatus
if _, err = sess.Insert(opts.CommitStatus); err != nil { if _, err = sess.Insert(opts.CommitStatus); err != nil {
sess.Rollback() 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 return nil

View File

@@ -4,6 +4,10 @@
package models package models
import (
"strings"
)
// UnitType is Unit's Type // UnitType is Unit's Type
type UnitType int type UnitType int
@@ -137,3 +141,16 @@ var (
UnitTypeExternalWiki: UnitExternalWiki, 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
}

View File

@@ -93,7 +93,7 @@ func DeleteUserOpenID(openid *UserOpenID) (err error) {
// ToggleUserOpenIDVisibility toggles visibility of an openid address of given user. // ToggleUserOpenIDVisibility toggles visibility of an openid address of given user.
func ToggleUserOpenIDVisibility(id int64) (err error) { 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 return err
} }

View File

@@ -377,6 +377,7 @@ type CodeCommentForm struct {
Line int64 Line int64
TreePath string `form:"path" binding:"Required"` TreePath string `form:"path" binding:"Required"`
IsReview bool `form:"is_review"` IsReview bool `form:"is_review"`
Reply int64 `form:"reply"`
} }
// Validate validates the fields // Validate validates the fields

View File

@@ -8,6 +8,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/go-macaron/csrf"
"code.gitea.io/git" "code.gitea.io/git"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "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 // APIContexter returns apicontext as macaron middleware
func APIContexter() macaron.Handler { func APIContexter() macaron.Handler {
return func(c *Context) { return func(c *Context) {

View File

@@ -8,7 +8,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
@@ -25,9 +24,6 @@ type FileLogWriter struct {
// The opened file // The opened file
Filename string `json:"filename"` Filename string `json:"filename"`
Maxlines int `json:"maxlines"`
maxlinesCurlines int
// Rotate at size // Rotate at size
Maxsize int `json:"maxsize"` Maxsize int `json:"maxsize"`
maxsizeCursize int maxsizeCursize int
@@ -69,7 +65,6 @@ func (l *MuxWriter) SetFd(fd *os.File) {
func NewFileWriter() LoggerInterface { func NewFileWriter() LoggerInterface {
w := &FileLogWriter{ w := &FileLogWriter{
Filename: "", Filename: "",
Maxlines: 1000000,
Maxsize: 1 << 28, //256 MB Maxsize: 1 << 28, //256 MB
Daily: true, Daily: true,
Maxdays: 7, Maxdays: 7,
@@ -87,7 +82,6 @@ func NewFileWriter() LoggerInterface {
// config like: // config like:
// { // {
// "filename":"log/gogs.log", // "filename":"log/gogs.log",
// "maxlines":10000,
// "maxsize":1<<30, // "maxsize":1<<30,
// "daily":true, // "daily":true,
// "maxdays":15, // "maxdays":15,
@@ -116,15 +110,13 @@ func (w *FileLogWriter) StartLogger() error {
func (w *FileLogWriter) docheck(size int) { func (w *FileLogWriter) docheck(size int) {
w.startLock.Lock() w.startLock.Lock()
defer w.startLock.Unlock() defer w.startLock.Unlock()
if w.Rotate && ((w.Maxlines > 0 && w.maxlinesCurlines >= w.Maxlines) || if w.Rotate && ((w.Maxsize > 0 && w.maxsizeCursize >= w.Maxsize) ||
(w.Maxsize > 0 && w.maxsizeCursize >= w.Maxsize) ||
(w.Daily && time.Now().Day() != w.dailyOpenDate)) { (w.Daily && time.Now().Day() != w.dailyOpenDate)) {
if err := w.DoRotate(); err != nil { if err := w.DoRotate(); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err) fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
return return
} }
} }
w.maxlinesCurlines++
w.maxsizeCursize += size w.maxsizeCursize += size
} }
@@ -152,15 +144,6 @@ func (w *FileLogWriter) initFd() error {
} }
w.maxsizeCursize = int(finfo.Size()) w.maxsizeCursize = int(finfo.Size())
w.dailyOpenDate = time.Now().Day() w.dailyOpenDate = time.Now().Day()
if finfo.Size() > 0 {
content, err := ioutil.ReadFile(w.Filename)
if err != nil {
return err
}
w.maxlinesCurlines = len(strings.Split(string(content), "\n"))
} else {
w.maxlinesCurlines = 0
}
return nil return nil
} }

View File

@@ -1,4 +1,5 @@
// Copyright 2014 The Gogs Authors. All rights reserved. // Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@@ -38,7 +39,16 @@ func (r *Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content []
link = []byte(mLink) link = []byte(mLink)
} }
r.Renderer.Link(out, link, title, content) if len(content) > 10 && string(content[0:9]) == "<a href=\"" && bytes.Contains(content[9:], []byte("<img")) {
// Image with link case: markdown `[![]()]()`
// If the content is an image, then we change the original href around it
// which points to itself to a new address "link"
rightQuote := bytes.Index(content[9:], []byte("\""))
content = bytes.Replace(content, content[9:9+rightQuote], link, 1)
out.Write(content)
} else {
r.Renderer.Link(out, link, title, content)
}
} }
// List renders markdown bullet or digit lists to HTML // List renders markdown bullet or digit lists to HTML
@@ -90,13 +100,6 @@ func (r *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
r.Renderer.ListItem(out, text, flags) r.Renderer.ListItem(out, text, flags)
} }
// Note: this section is for purpose of increase performance and
// reduce memory allocation at runtime since they are constant literals.
var (
svgSuffix = []byte(".svg")
svgSuffixWithMark = []byte(".svg?")
)
// Image defines how images should be processed to produce corresponding HTML elements. // Image defines how images should be processed to produce corresponding HTML elements.
func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
prefix := r.URLPrefix prefix := r.URLPrefix
@@ -104,22 +107,14 @@ func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byt
prefix = util.URLJoin(prefix, "wiki", "raw") prefix = util.URLJoin(prefix, "wiki", "raw")
} }
prefix = strings.Replace(prefix, "/src/", "/raw/", 1) prefix = strings.Replace(prefix, "/src/", "/raw/", 1)
if len(link) > 0 { if len(link) > 0 && !markup.IsLink(link) {
if markup.IsLink(link) { lnk := string(link)
// External link with .svg suffix usually means CI status. lnk = util.URLJoin(prefix, lnk)
// TODO: define a keyword to allow non-svg images render as external link. lnk = strings.Replace(lnk, " ", "+", -1)
if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) { link = []byte(lnk)
r.Renderer.Image(out, link, title, alt)
return
}
} else {
lnk := string(link)
lnk = util.URLJoin(prefix, lnk)
lnk = strings.Replace(lnk, " ", "+", -1)
link = []byte(lnk)
}
} }
// Put a link around it pointing to itself by default
out.WriteString(`<a href="`) out.WriteString(`<a href="`)
out.Write(link) out.Write(link)
out.WriteString(`">`) out.WriteString(`">`)

View File

@@ -73,6 +73,7 @@ func TestRender_Images(t *testing.T) {
url := "../../.images/src/02/train.jpg" url := "../../.images/src/02/train.jpg"
title := "Train" title := "Train"
href := "https://gitea.io"
result := util.URLJoin(AppSubURL, url) result := util.URLJoin(AppSubURL, url)
test( test(
@@ -82,6 +83,9 @@ func TestRender_Images(t *testing.T) {
test( test(
"[["+title+"|"+url+"]]", "[["+title+"|"+url+"]]",
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`) `<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
test(
"[!["+title+"]("+url+")]("+href+")",
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
} }
func testAnswers(baseURLContent, baseURLImages string) []string { func testAnswers(baseURLContent, baseURLImages string) []string {

View File

@@ -1325,10 +1325,9 @@ func newLogService() {
} }
LogConfigs[i] = fmt.Sprintf( LogConfigs[i] = fmt.Sprintf(
`{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level, `{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
logPath, logPath,
sec.Key("LOG_ROTATE").MustBool(true), sec.Key("LOG_ROTATE").MustBool(true),
sec.Key("MAX_LINES").MustInt(1000000),
1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)), 1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
sec.Key("DAILY_ROTATE").MustBool(true), sec.Key("DAILY_ROTATE").MustBool(true),
sec.Key("MAX_DAYS").MustInt(7)) sec.Key("MAX_DAYS").MustInt(7))
@@ -1391,10 +1390,9 @@ func NewXORMLogService(disableConsole bool) {
logPath = path.Join(filepath.Dir(logPath), "xorm.log") logPath = path.Join(filepath.Dir(logPath), "xorm.log")
logConfigs = fmt.Sprintf( logConfigs = fmt.Sprintf(
`{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level, `{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
logPath, logPath,
sec.Key("LOG_ROTATE").MustBool(true), sec.Key("LOG_ROTATE").MustBool(true),
sec.Key("MAX_LINES").MustInt(1000000),
1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)), 1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
sec.Key("DAILY_ROTATE").MustBool(true), sec.Key("DAILY_ROTATE").MustBool(true),
sec.Key("MAX_DAYS").MustInt(7)) sec.Key("MAX_DAYS").MustInt(7))

View File

@@ -457,7 +457,7 @@ issues.next=Página Siguiente
issues.open_title=Abierta issues.open_title=Abierta
issues.closed_title=Cerrada issues.closed_title=Cerrada
issues.num_comments=%d comentarios issues.num_comments=%d comentarios
issues.commented_at=`comentado <a href="#%s"> %s`</a> issues.commented_at=`comentado <a href="#%s">%s</a>`
issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario? issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario?
issues.no_content=Aún no existe contenido. issues.no_content=Aún no existe contenido.
issues.close_issue=Cerrar issues.close_issue=Cerrar

View File

@@ -1530,7 +1530,7 @@ function initU2FAuth() {
} }
u2fApi.ensureSupport() u2fApi.ensureSupport()
.then(function () { .then(function () {
$.getJSON('/user/u2f/challenge').success(function(req) { $.getJSON(suburl + '/user/u2f/challenge').success(function(req) {
u2fApi.sign(req.appId, req.challenge, req.registeredKeys, 30) u2fApi.sign(req.appId, req.challenge, req.registeredKeys, 30)
.then(u2fSigned) .then(u2fSigned)
.catch(function (err) { .catch(function (err) {
@@ -1543,16 +1543,16 @@ function initU2FAuth() {
}); });
}).catch(function () { }).catch(function () {
// Fallback in case browser do not support U2F // Fallback in case browser do not support U2F
window.location.href = "/user/two_factor" window.location.href = suburl + "/user/two_factor"
}) })
} }
function u2fSigned(resp) { function u2fSigned(resp) {
$.ajax({ $.ajax({
url:'/user/u2f/sign', url: suburl + '/user/u2f/sign',
type:"POST", type: "POST",
headers: {"X-Csrf-Token": csrf}, headers: {"X-Csrf-Token": csrf},
data: JSON.stringify(resp), data: JSON.stringify(resp),
contentType:"application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
}).done(function(res){ }).done(function(res){
window.location.replace(res); window.location.replace(res);
}).fail(function (xhr, textStatus) { }).fail(function (xhr, textStatus) {
@@ -1565,11 +1565,11 @@ function u2fRegistered(resp) {
return; return;
} }
$.ajax({ $.ajax({
url:'/user/settings/security/u2f/register', url: suburl + '/user/settings/security/u2f/register',
type:"POST", type: "POST",
headers: {"X-Csrf-Token": csrf}, headers: {"X-Csrf-Token": csrf},
data: JSON.stringify(resp), data: JSON.stringify(resp),
contentType:"application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
success: function(){ success: function(){
window.location.reload(); window.location.reload();
}, },
@@ -1623,7 +1623,7 @@ function initU2FRegister() {
} }
function u2fRegisterRequest() { function u2fRegisterRequest() {
$.post("/user/settings/security/u2f/request_register", { $.post(suburl + "/user/settings/security/u2f/request_register", {
"_csrf": csrf, "_csrf": csrf,
"name": $('#nickname').val() "name": $('#nickname').val()
}).success(function(req) { }).success(function(req) {
@@ -2590,6 +2590,10 @@ function updateDeadline(deadlineString) {
data: JSON.stringify({ data: JSON.stringify({
'due_date': realDeadline, 'due_date': realDeadline,
}), }),
headers: {
'X-Csrf-Token': csrf,
'X-Remote': true,
},
contentType: 'application/json', contentType: 'application/json',
type: 'POST', type: 'POST',
success: function () { success: function () {
@@ -2621,7 +2625,7 @@ function initIssueList() {
$('.new-dependency-drop-list') $('.new-dependency-drop-list')
.dropdown({ .dropdown({
apiSettings: { apiSettings: {
url: '/api/v1/repos' + repolink + '/issues?q={query}', url: suburl + '/api/v1/repos' + repolink + '/issues?q={query}',
onResponse: function(response) { onResponse: function(response) {
var filteredResponse = {'success': true, 'results': []}; var filteredResponse = {'success': true, 'results': []};
// Parse the response from the api to work with our dropdown // Parse the response from the api to work with our dropdown

View File

@@ -174,11 +174,15 @@ func repoAssignment() macaron.Handler {
// Contexter middleware already checks token for user sign in process. // Contexter middleware already checks token for user sign in process.
func reqToken() macaron.Handler { func reqToken() macaron.Handler {
return func(ctx *context.Context) { return func(ctx *context.APIContext) {
if true != ctx.Data["IsApiToken"] { if true == ctx.Data["IsApiToken"] {
ctx.Error(401)
return return
} }
if ctx.IsSigned {
ctx.RequireCSRF()
return
}
ctx.Context.Error(401)
} }
} }
@@ -627,7 +631,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo)
}) })
}) })
}, reqAdmin()) }, reqToken(), reqAdmin())
m.Group("/topics", func() { m.Group("/topics", func() {
m.Get("/search", repo.TopicSearch) m.Get("/search", repo.TopicSearch)

View File

@@ -196,5 +196,6 @@ func ToTeam(team *models.Team) *api.Team {
Name: team.Name, Name: team.Name,
Description: team.Description, Description: team.Description,
Permission: team.Authorize.String(), Permission: team.Authorize.String(),
Units: team.GetUnitNames(),
} }
} }

View File

@@ -89,6 +89,20 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) {
Description: form.Description, Description: form.Description,
Authorize: models.ParseAccessMode(form.Permission), Authorize: models.ParseAccessMode(form.Permission),
} }
unitTypes := models.FindUnitTypes(form.Units...)
if team.Authorize < models.AccessModeOwner {
var units = make([]*models.TeamUnit, 0, len(form.Units))
for _, tp := range unitTypes {
units = append(units, &models.TeamUnit{
OrgID: ctx.Org.Organization.ID,
Type: tp,
})
}
team.Units = units
}
if err := models.NewTeam(team); err != nil { if err := models.NewTeam(team); err != nil {
if models.IsErrTeamAlreadyExist(err) { if models.IsErrTeamAlreadyExist(err) {
ctx.Error(422, "", err) ctx.Error(422, "", err)
@@ -127,6 +141,19 @@ func EditTeam(ctx *context.APIContext, form api.EditTeamOption) {
team.Name = form.Name team.Name = form.Name
team.Description = form.Description team.Description = form.Description
team.Authorize = models.ParseAccessMode(form.Permission) team.Authorize = models.ParseAccessMode(form.Permission)
unitTypes := models.FindUnitTypes(form.Units...)
if team.Authorize < models.AccessModeOwner {
var units = make([]*models.TeamUnit, 0, len(form.Units))
for _, tp := range unitTypes {
units = append(units, &models.TeamUnit{
OrgID: ctx.Org.Organization.ID,
Type: tp,
})
}
team.Units = units
}
if err := models.UpdateTeam(team, true); err != nil { if err := models.UpdateTeam(team, true); err != nil {
ctx.Error(500, "EditTeam", err) ctx.Error(500, "EditTeam", err)
return return

View File

@@ -63,6 +63,9 @@ func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) {
} }
} }
} }
if review.ID == 0 {
review.ID = form.Reply
}
//FIXME check if line, commit and treepath exist //FIXME check if line, commit and treepath exist
comment, err := models.CreateCodeComment( comment, err := models.CreateCodeComment(
ctx.User, ctx.User,
@@ -78,7 +81,7 @@ func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) {
return return
} }
// Send no notification if comment is pending // Send no notification if comment is pending
if !form.IsReview { if !form.IsReview || form.Reply != 0 {
notification.Service.NotifyIssue(issue, ctx.User.ID) notification.Service.NotifyIssue(issue, ctx.User.ID)
} }

View File

@@ -253,6 +253,8 @@ func Issues(ctx *context.Context) {
opts.Page = page opts.Page = page
opts.PageSize = setting.UI.IssuePagingNum opts.PageSize = setting.UI.IssuePagingNum
opts.Labels = ctx.Query("labels")
issues, err := models.Issues(opts) issues, err := models.Issues(opts)
if err != nil { if err != nil {
ctx.ServerError("Issues", err) ctx.ServerError("Issues", err)

View File

@@ -151,7 +151,7 @@
{{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}} {{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}}
</ui> </ui>
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "root" $ "comment" (index $line.Comments 0)}} {{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.Comments 0)}}
</div> </div>
{{end}} {{end}}
</td> </td>
@@ -164,7 +164,7 @@
{{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}} {{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}}
</ui> </ui>
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "root" $ "comment" (index $line.Comments 0)}} {{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.Comments 0)}}
</div> </div>
{{end}} {{end}}
</td> </td>

View File

@@ -25,19 +25,19 @@
<div class="footer"> <div class="footer">
<span class="markdown-info"><i class="octicon octicon-markdown"></i> {{$.root.i18n.Tr "repo.diff.comment.markdown_info"}}</span> <span class="markdown-info"><i class="octicon octicon-markdown"></i> {{$.root.i18n.Tr "repo.diff.comment.markdown_info"}}</span>
<div class="ui right floated"> <div class="ui right floated">
{{if not $.reply}} {{if $.reply}}
<button name="reply" value="{{$.reply}}" class="ui submit green tiny button btn-reply">{{$.root.i18n.Tr "repo.diff.comment.reply"}}</button>
{{else}}
{{if $.root.CurrentReview}} {{if $.root.CurrentReview}}
<button name="is_review" value="true" type="submit" <button name="is_review" value="true" type="submit"
class="ui submit green tiny button btn-add-comment">{{$.root.i18n.Tr "repo.diff.comment.add_review_comment"}}</button> class="ui submit green tiny button btn-add-comment">{{$.root.i18n.Tr "repo.diff.comment.add_review_comment"}}</button>
{{else}} {{else}}
<button name="is_review" value="true" type="submit" <button name="is_review" value="true" type="submit"
class="ui submit green tiny button btn-start-review">{{$.root.i18n.Tr "repo.diff.comment.start_review"}}</button> class="ui submit green tiny button btn-start-review">{{$.root.i18n.Tr "repo.diff.comment.start_review"}}</button>
<button type="submit"
class="ui submit tiny basic button btn-add-single">{{$.root.i18n.Tr "repo.diff.comment.add_single_comment"}}</button>
{{end}} {{end}}
{{end}} {{end}}
{{if not $.root.CurrentReview}}
<button type="submit"
class="ui submit tiny basic button btn-add-single">{{$.root.i18n.Tr "repo.diff.comment.add_single_comment"}}</button>
{{end}}
{{if or (not $.HasComments) $.hidden}} {{if or (not $.HasComments) $.hidden}}
<button type="button" class="ui submit tiny basic button btn-cancel" onclick="cancelCodeComment(this);">{{$.root.i18n.Tr "cancel"}}</button> <button type="button" class="ui submit tiny basic button btn-cancel" onclick="cancelCodeComment(this);">{{$.root.i18n.Tr "cancel"}}</button>
{{end}} {{end}}

View File

@@ -32,7 +32,7 @@
{{ template "repo/diff/comments" dict "root" $.root "comments" $line.Comments}} {{ template "repo/diff/comments" dict "root" $.root "comments" $line.Comments}}
</ui> </ui>
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "root" $.root "comment" (index $line.Comments 0)}} {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $line.Comments 0).ReviewID "root" $.root "comment" (index $line.Comments 0)}}
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -3,9 +3,7 @@
<div class="file-body file-code code-view code-diff"> <div class="file-body file-code code-view code-diff">
<table> <table>
<tbody> <tbody>
{{with .File}} {{template "repo/diff/section_unified" dict "file" .File "root" $}}
{{template "repo/diff/section_unified" .}}
{{end}}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@@ -30,7 +30,7 @@
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff"> <div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
<a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a> <a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a>
{{if not .IsNewFile}} {{if not .IsNewFile}}
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "repo.release.preview"}}</a> <a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "preview"}}</a>
<a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.editor.preview_changes"}}</a> <a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.editor.preview_changes"}}</a>
{{end}} {{end}}
</div> </div>

View File

@@ -342,7 +342,7 @@
</div> </div>
{{end}} {{end}}
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" true "root" $ "comment" (index $comms 0)}} {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $comms 0).ReviewID "root" $ "comment" (index $comms 0)}}
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@@ -6128,6 +6128,22 @@
"admin" "admin"
], ],
"x-go-name": "Permission" "x-go-name": "Permission"
},
"units": {
"type": "array",
"enum": [
"repo.code",
"repo.issues",
"repo.ext_issues",
"repo.wiki",
"repo.pulls",
"repo.releases",
"repo.ext_wiki"
],
"items": {
"type": "string"
},
"x-go-name": "Units"
} }
}, },
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" "x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"
@@ -6198,6 +6214,10 @@
"format": "date-time", "format": "date-time",
"x-go-name": "Created" "x-go-name": "Created"
}, },
"fingerprint": {
"type": "string",
"x-go-name": "Fingerprint"
},
"id": { "id": {
"type": "integer", "type": "integer",
"format": "int64", "format": "int64",
@@ -6207,10 +6227,18 @@
"type": "string", "type": "string",
"x-go-name": "Key" "x-go-name": "Key"
}, },
"key_id": {
"type": "integer",
"format": "int64",
"x-go-name": "KeyID"
},
"read_only": { "read_only": {
"type": "boolean", "type": "boolean",
"x-go-name": "ReadOnly" "x-go-name": "ReadOnly"
}, },
"repository": {
"$ref": "#/definitions/Repository"
},
"title": { "title": {
"type": "string", "type": "string",
"x-go-name": "Title" "x-go-name": "Title"
@@ -6491,6 +6519,22 @@
"admin" "admin"
], ],
"x-go-name": "Permission" "x-go-name": "Permission"
},
"units": {
"type": "array",
"enum": [
"repo.code",
"repo.issues",
"repo.ext_issues",
"repo.wiki",
"repo.pulls",
"repo.releases",
"repo.ext_wiki"
],
"items": {
"type": "string"
},
"x-go-name": "Units"
} }
}, },
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" "x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"
@@ -7092,6 +7136,14 @@
"type": "string", "type": "string",
"x-go-name": "Key" "x-go-name": "Key"
}, },
"key_type": {
"type": "string",
"x-go-name": "KeyType"
},
"read_only": {
"type": "boolean",
"x-go-name": "ReadOnly"
},
"title": { "title": {
"type": "string", "type": "string",
"x-go-name": "Title" "x-go-name": "Title"
@@ -7099,6 +7151,9 @@
"url": { "url": {
"type": "string", "type": "string",
"x-go-name": "URL" "x-go-name": "URL"
},
"user": {
"$ref": "#/definitions/User"
} }
}, },
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" "x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"
@@ -7313,6 +7368,10 @@
"description": "Repository represents a repository", "description": "Repository represents a repository",
"type": "object", "type": "object",
"properties": { "properties": {
"archived": {
"type": "boolean",
"x-go-name": "Archived"
},
"clone_url": { "clone_url": {
"type": "string", "type": "string",
"x-go-name": "CloneURL" "x-go-name": "CloneURL"
@@ -7523,6 +7582,22 @@
"owner" "owner"
], ],
"x-go-name": "Permission" "x-go-name": "Permission"
},
"units": {
"type": "array",
"enum": [
"repo.code",
"repo.issues",
"repo.ext_issues",
"repo.wiki",
"repo.pulls",
"repo.releases",
"repo.ext_wiki"
],
"items": {
"type": "string"
},
"x-go-name": "Units"
} }
}, },
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" "x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"

View File

@@ -71,7 +71,7 @@
especially on mobile views. */}} especially on mobile views. */}}
<span style="line-height: 2.5"> <span style="line-height: 2.5">
{{range .}} {{range .}}
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a> <a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&repo={{$.RepoID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
{{end}} {{end}}
</span> </span>
{{end}} {{end}}

View File

@@ -42,17 +42,17 @@ type EditUserOption struct {
FullName string `json:"full_name" binding:"MaxSize(100)"` FullName string `json:"full_name" binding:"MaxSize(100)"`
// required: true // required: true
// swagger:strfmt email // swagger:strfmt email
Email string `json:"email" binding:"Required;Email;MaxSize(254)"` Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
Password string `json:"password" binding:"MaxSize(255)"` Password string `json:"password" binding:"MaxSize(255)"`
Website string `json:"website" binding:"MaxSize(50)"` Website string `json:"website" binding:"MaxSize(50)"`
Location string `json:"location" binding:"MaxSize(50)"` Location string `json:"location" binding:"MaxSize(50)"`
Active *bool `json:"active"` Active *bool `json:"active"`
Admin *bool `json:"admin"` Admin *bool `json:"admin"`
AllowGitHook *bool `json:"allow_git_hook"` AllowGitHook *bool `json:"allow_git_hook"`
AllowImportLocal *bool `json:"allow_import_local"` AllowImportLocal *bool `json:"allow_import_local"`
MaxRepoCreation *int `json:"max_repo_creation"` MaxRepoCreation *int `json:"max_repo_creation"`
ProhibitLogin *bool `json:"prohibit_login"` ProhibitLogin *bool `json:"prohibit_login"`
AllowCreateOrganization *bool `json:"allow_create_organization"` AllowCreateOrganization *bool `json:"allow_create_organization"`
} }
// AdminEditUser modify user informations // AdminEditUser modify user informations

View File

@@ -199,7 +199,7 @@ type CreatePayload struct {
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret FIXME // SetSecret modifies the secret of the CreatePayload
func (p *CreatePayload) SetSecret(secret string) { func (p *CreatePayload) SetSecret(secret string) {
p.Secret = secret p.Secret = secret
} }
@@ -246,6 +246,7 @@ const (
// DeletePayload represents delete payload // DeletePayload represents delete payload
type DeletePayload struct { type DeletePayload struct {
Secret string `json:"secret"`
Ref string `json:"ref"` Ref string `json:"ref"`
RefType string `json:"ref_type"` RefType string `json:"ref_type"`
PusherType PusherType `json:"pusher_type"` PusherType PusherType `json:"pusher_type"`
@@ -253,8 +254,9 @@ type DeletePayload struct {
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret implements Payload // SetSecret modifies the secret of the DeletePayload
func (p *DeletePayload) SetSecret(secret string) { func (p *DeletePayload) SetSecret(secret string) {
p.Secret = secret
} }
// JSONPayload implements Payload // JSONPayload implements Payload
@@ -271,13 +273,15 @@ func (p *DeletePayload) JSONPayload() ([]byte, error) {
// ForkPayload represents fork payload // ForkPayload represents fork payload
type ForkPayload struct { type ForkPayload struct {
Secret string `json:"secret"`
Forkee *Repository `json:"forkee"` Forkee *Repository `json:"forkee"`
Repo *Repository `json:"repository"` Repo *Repository `json:"repository"`
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret implements Payload // SetSecret modifies the secret of the ForkPayload
func (p *ForkPayload) SetSecret(secret string) { func (p *ForkPayload) SetSecret(secret string) {
p.Secret = secret
} }
// JSONPayload implements Payload // JSONPayload implements Payload
@@ -297,6 +301,7 @@ const (
// IssueCommentPayload represents a payload information of issue comment event. // IssueCommentPayload represents a payload information of issue comment event.
type IssueCommentPayload struct { type IssueCommentPayload struct {
Secret string `json:"secret"`
Action HookIssueCommentAction `json:"action"` Action HookIssueCommentAction `json:"action"`
Issue *Issue `json:"issue"` Issue *Issue `json:"issue"`
Comment *Comment `json:"comment"` Comment *Comment `json:"comment"`
@@ -305,8 +310,9 @@ type IssueCommentPayload struct {
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret implements Payload // SetSecret modifies the secret of the IssueCommentPayload
func (p *IssueCommentPayload) SetSecret(secret string) { func (p *IssueCommentPayload) SetSecret(secret string) {
p.Secret = secret
} }
// JSONPayload implements Payload // JSONPayload implements Payload
@@ -333,14 +339,16 @@ const (
// ReleasePayload represents a payload information of release event. // ReleasePayload represents a payload information of release event.
type ReleasePayload struct { type ReleasePayload struct {
Secret string `json:"secret"`
Action HookReleaseAction `json:"action"` Action HookReleaseAction `json:"action"`
Release *Release `json:"release"` Release *Release `json:"release"`
Repository *Repository `json:"repository"` Repository *Repository `json:"repository"`
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret implements Payload // SetSecret modifies the secret of the ReleasePayload
func (p *ReleasePayload) SetSecret(secret string) { func (p *ReleasePayload) SetSecret(secret string) {
p.Secret = secret
} }
// JSONPayload implements Payload // JSONPayload implements Payload
@@ -368,7 +376,7 @@ type PushPayload struct {
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret FIXME // SetSecret modifies the secret of the PushPayload
func (p *PushPayload) SetSecret(secret string) { func (p *PushPayload) SetSecret(secret string) {
p.Secret = secret p.Secret = secret
} }
@@ -520,7 +528,7 @@ type RepositoryPayload struct {
Sender *User `json:"sender"` Sender *User `json:"sender"`
} }
// SetSecret set the payload's secret // SetSecret modifies the secret of the RepositoryPayload
func (p *RepositoryPayload) SetSecret(secret string) { func (p *RepositoryPayload) SetSecret(secret string) {
p.Secret = secret p.Secret = secret
} }

View File

@@ -152,3 +152,9 @@ type IssueDeadline struct {
// swagger:strfmt date-time // swagger:strfmt date-time
Deadline *time.Time `json:"due_date"` Deadline *time.Time `json:"due_date"`
} }
// EditPriorityOption options for updating priority
type EditPriorityOption struct {
// required:true
Priority int `json:"priority"`
}

View File

@@ -1,4 +1,5 @@
// Copyright 2016 The Gogs Authors. All rights reserved. // Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@@ -11,6 +12,8 @@ type Team struct {
Description string `json:"description"` Description string `json:"description"`
// enum: none,read,write,admin,owner // enum: none,read,write,admin,owner
Permission string `json:"permission"` Permission string `json:"permission"`
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
Units []string `json:"units"`
} }
// CreateTeamOption options for creating a team // CreateTeamOption options for creating a team
@@ -20,6 +23,8 @@ type CreateTeamOption struct {
Description string `json:"description" binding:"MaxSize(255)"` Description string `json:"description" binding:"MaxSize(255)"`
// enum: read,write,admin // enum: read,write,admin
Permission string `json:"permission"` Permission string `json:"permission"`
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
Units []string `json:"units"`
} }
// EditTeamOption options for editing a team // EditTeamOption options for editing a team
@@ -29,4 +34,6 @@ type EditTeamOption struct {
Description string `json:"description" binding:"MaxSize(255)"` Description string `json:"description" binding:"MaxSize(255)"`
// enum: read,write,admin // enum: read,write,admin
Permission string `json:"permission"` Permission string `json:"permission"`
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
Units []string `json:"units"`
} }

View File

@@ -40,6 +40,7 @@ type Repository struct {
Watchers int `json:"watchers_count"` Watchers int `json:"watchers_count"`
OpenIssues int `json:"open_issues_count"` OpenIssues int `json:"open_issues_count"`
DefaultBranch string `json:"default_branch"` DefaultBranch string `json:"default_branch"`
Archived bool `json:"archived"`
// swagger:strfmt date-time // swagger:strfmt date-time
Created time.Time `json:"created_at"` Created time.Time `json:"created_at"`
// swagger:strfmt date-time // swagger:strfmt date-time

View File

@@ -13,13 +13,16 @@ import (
// DeployKey a deploy key // DeployKey a deploy key
type DeployKey struct { type DeployKey struct {
ID int64 `json:"id"` ID int64 `json:"id"`
Key string `json:"key"` KeyID int64 `json:"key_id"`
URL string `json:"url"` Key string `json:"key"`
Title string `json:"title"` URL string `json:"url"`
Title string `json:"title"`
Fingerprint string `json:"fingerprint"`
// swagger:strfmt date-time // swagger:strfmt date-time
Created time.Time `json:"created_at"` Created time.Time `json:"created_at"`
ReadOnly bool `json:"read_only"` ReadOnly bool `json:"read_only"`
Repository *Repository `json:"repository,omitempty"`
} }
// ListDeployKeys list all the deploy keys of one repository // ListDeployKeys list all the deploy keys of one repository

View File

@@ -19,7 +19,10 @@ type PublicKey struct {
Title string `json:"title,omitempty"` Title string `json:"title,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"` Fingerprint string `json:"fingerprint,omitempty"`
// swagger:strfmt date-time // swagger:strfmt date-time
Created time.Time `json:"created_at,omitempty"` Created time.Time `json:"created_at,omitempty"`
Owner *User `json:"user,omitempty"`
ReadOnly bool `json:"read_only,omitempty"`
KeyType string `json:"key_type,omitempty"`
} }
// ListPublicKeys list all the public keys of the user // ListPublicKeys list all the public keys of the user

View File

@@ -86,7 +86,7 @@ func (s *FileStore) Release() error {
return err return err
} }
return ioutil.WriteFile(s.p.filepath(s.sid), data, os.ModePerm) return ioutil.WriteFile(s.p.filepath(s.sid), data, 0600)
} }
// Flush deletes all session data. // Flush deletes all session data.
@@ -121,7 +121,7 @@ func (p *FileProvider) filepath(sid string) string {
// Read returns raw session store by session ID. // Read returns raw session store by session ID.
func (p *FileProvider) Read(sid string) (_ RawStore, err error) { func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
filename := p.filepath(sid) filename := p.filepath(sid)
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil { if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
return nil, err return nil, err
} }
p.lock.RLock() p.lock.RLock()
@@ -129,7 +129,7 @@ func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
var f *os.File var f *os.File
if com.IsFile(filename) { if com.IsFile(filename) {
f, err = os.OpenFile(filename, os.O_RDWR, os.ModePerm) f, err = os.OpenFile(filename, os.O_RDONLY, 0600)
} else { } else {
f, err = os.Create(filename) f, err = os.Create(filename)
} }
@@ -187,15 +187,15 @@ func (p *FileProvider) regenerate(oldsid, sid string) (err error) {
if err != nil { if err != nil {
return err return err
} }
if err = os.MkdirAll(path.Dir(oldname), os.ModePerm); err != nil { if err = os.MkdirAll(path.Dir(oldname), 0700); err != nil {
return err return err
} }
if err = ioutil.WriteFile(oldname, data, os.ModePerm); err != nil { if err = ioutil.WriteFile(oldname, data, 0600); err != nil {
return err return err
} }
} }
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil { if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
return err return err
} }
if err = os.Rename(oldname, filename); err != nil { if err = os.Rename(oldname, filename); err != nil {

View File

@@ -18,15 +18,17 @@ package session
import ( import (
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"strings"
"time" "time"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
) )
const _VERSION = "0.3.0" const _VERSION = "0.4.0"
func Version() string { func Version() string {
return _VERSION return _VERSION
@@ -245,8 +247,8 @@ func NewManager(name string, opt Options) (*Manager, error) {
return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig) return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig)
} }
// sessionId generates a new session ID with rand string, unix nano time, remote addr by hash function. // sessionID generates a new session ID with rand string, unix nano time, remote addr by hash function.
func (m *Manager) sessionId() string { func (m *Manager) sessionID() string {
return hex.EncodeToString(generateRandomKey(m.opt.IDLength / 2)) return hex.EncodeToString(generateRandomKey(m.opt.IDLength / 2))
} }
@@ -255,10 +257,10 @@ func (m *Manager) sessionId() string {
func (m *Manager) Start(ctx *macaron.Context) (RawStore, error) { func (m *Manager) Start(ctx *macaron.Context) (RawStore, error) {
sid := ctx.GetCookie(m.opt.CookieName) sid := ctx.GetCookie(m.opt.CookieName)
if len(sid) > 0 && m.provider.Exist(sid) { if len(sid) > 0 && m.provider.Exist(sid) {
return m.provider.Read(sid) return m.Read(sid)
} }
sid = m.sessionId() sid = m.sessionID()
sess, err := m.provider.Read(sid) sess, err := m.provider.Read(sid)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -282,6 +284,12 @@ func (m *Manager) Start(ctx *macaron.Context) (RawStore, error) {
// Read returns raw session store by session ID. // Read returns raw session store by session ID.
func (m *Manager) Read(sid string) (RawStore, error) { func (m *Manager) Read(sid string) (RawStore, error) {
// No slashes or dots "./" should ever occur in the sid and to prevent session file forgery bug.
// See https://github.com/gogs/gogs/issues/5469
if strings.ContainsAny(sid, "./") {
return nil, errors.New("invalid 'sid': " + sid)
}
return m.provider.Read(sid) return m.provider.Read(sid)
} }
@@ -308,7 +316,7 @@ func (m *Manager) Destory(ctx *macaron.Context) error {
// RegenerateId regenerates a session store from old session ID to new one. // RegenerateId regenerates a session store from old session ID to new one.
func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) { func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) {
sid := m.sessionId() sid := m.sessionID()
oldsid := ctx.GetCookie(m.opt.CookieName) oldsid := ctx.GetCookie(m.opt.CookieName)
sess, err = m.provider.Regenerate(oldsid, sid) sess, err = m.provider.Regenerate(oldsid, sid)
if err != nil { if err != nil {