From 43ab9324c579a393f778d6842c577a872d0e4265 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Thu, 17 Nov 2022 18:55:15 +0100 Subject: [PATCH 01/14] Fix setting HTTP headers after write (#21833) The headers can't be modified after it was send to the client. --- modules/context/context.go | 66 +++++++++++++++-------- routers/api/packages/rubygems/rubygems.go | 8 ++- routers/common/repo.go | 41 ++++++-------- routers/web/feed/profile.go | 2 - routers/web/web.go | 5 +- 5 files changed, 68 insertions(+), 54 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index 4b6a21b217c3b..697eb769045a1 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -34,6 +34,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/translation" + "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web/middleware" "code.gitea.io/gitea/services/auth" @@ -322,9 +323,9 @@ func (ctx *Context) plainTextInternal(skip, status int, bs []byte) { if statusPrefix == 4 || statusPrefix == 5 { log.Log(skip, log.TRACE, "plainTextInternal (status=%d): %s", status, string(bs)) } - ctx.Resp.WriteHeader(status) ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff") + ctx.Resp.WriteHeader(status) if _, err := ctx.Resp.Write(bs); err != nil { log.ErrorWithSkip(skip, "plainTextInternal (status=%d): write bytes failed: %v", status, err) } @@ -345,36 +346,55 @@ func (ctx *Context) RespHeader() http.Header { return ctx.Resp.Header() } +type ServeHeaderOptions struct { + ContentType string // defaults to "application/octet-stream" + ContentTypeCharset string + Disposition string // defaults to "attachment" + Filename string + CacheDuration time.Duration // defaults to 5 minutes +} + // SetServeHeaders sets necessary content serve headers -func (ctx *Context) SetServeHeaders(filename string) { - ctx.Resp.Header().Set("Content-Description", "File Transfer") - ctx.Resp.Header().Set("Content-Type", "application/octet-stream") - ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+filename) - ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary") - ctx.Resp.Header().Set("Expires", "0") - ctx.Resp.Header().Set("Cache-Control", "must-revalidate") - ctx.Resp.Header().Set("Pragma", "public") - ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition") +func (ctx *Context) SetServeHeaders(opts *ServeHeaderOptions) { + header := ctx.Resp.Header() + + contentType := typesniffer.ApplicationOctetStream + if opts.ContentType != "" { + if opts.ContentTypeCharset != "" { + contentType = opts.ContentType + "; charset=" + strings.ToLower(opts.ContentTypeCharset) + } else { + contentType = opts.ContentType + } + } + header.Set("Content-Type", contentType) + header.Set("X-Content-Type-Options", "nosniff") + + if opts.Filename != "" { + disposition := opts.Disposition + if disposition == "" { + disposition = "attachment" + } + + backslashEscapedName := strings.ReplaceAll(strings.ReplaceAll(opts.Filename, `\`, `\\`), `"`, `\"`) // \ -> \\, " -> \" + header.Set("Content-Disposition", fmt.Sprintf(`%s; filename="%s"; filename*=UTF-8''%s`, disposition, backslashEscapedName, url.PathEscape(opts.Filename))) + header.Set("Access-Control-Expose-Headers", "Content-Disposition") + } + + duration := opts.CacheDuration + if duration == 0 { + duration = 5 * time.Minute + } + httpcache.AddCacheControlToHeader(header, duration) } // ServeContent serves content to http request func (ctx *Context) ServeContent(name string, r io.ReadSeeker, modTime time.Time) { - ctx.SetServeHeaders(name) + ctx.SetServeHeaders(&ServeHeaderOptions{ + Filename: name, + }) http.ServeContent(ctx.Resp, ctx.Req, name, modTime, r) } -// ServeFile serves given file to response. -func (ctx *Context) ServeFile(file string, names ...string) { - var name string - if len(names) > 0 { - name = names[0] - } else { - name = path.Base(file) - } - ctx.SetServeHeaders(name) - http.ServeFile(ctx.Resp, ctx.Req, file) -} - // UploadStream returns the request body or the first form file // Only form files need to get closed. func (ctx *Context) UploadStream() (rd io.ReadCloser, needToClose bool, err error) { diff --git a/routers/api/packages/rubygems/rubygems.go b/routers/api/packages/rubygems/rubygems.go index eeae21146cbe8..4adfb15731bac 100644 --- a/routers/api/packages/rubygems/rubygems.go +++ b/routers/api/packages/rubygems/rubygems.go @@ -77,7 +77,9 @@ func enumeratePackages(ctx *context.Context, filename string, pvs []*packages_mo }) } - ctx.SetServeHeaders(filename + ".gz") + ctx.SetServeHeaders(&context.ServeHeaderOptions{ + Filename: filename + ".gz", + }) zw := gzip.NewWriter(ctx.Resp) defer zw.Close() @@ -115,7 +117,9 @@ func ServePackageSpecification(ctx *context.Context) { return } - ctx.SetServeHeaders(filename) + ctx.SetServeHeaders(&context.ServeHeaderOptions{ + Filename: filename, + }) zw := zlib.NewWriter(ctx.Resp) defer zw.Close() diff --git a/routers/common/repo.go b/routers/common/repo.go index a9e80fad48c8d..f4b813d6b490b 100644 --- a/routers/common/repo.go +++ b/routers/common/repo.go @@ -7,7 +7,6 @@ package common import ( "fmt" "io" - "net/url" "path" "path/filepath" "strings" @@ -53,50 +52,44 @@ func ServeData(ctx *context.Context, filePath string, size int64, reader io.Read buf = buf[:n] } - httpcache.AddCacheControlToHeader(ctx.Resp.Header(), 5*time.Minute) - if size >= 0 { ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", size)) } else { log.Error("ServeData called to serve data: %s with size < 0: %d", filePath, size) } - fileName := path.Base(filePath) + opts := &context.ServeHeaderOptions{ + Filename: path.Base(filePath), + } + sniffedType := typesniffer.DetectContentType(buf) isPlain := sniffedType.IsText() || ctx.FormBool("render") - mimeType := "" - charset := "" if setting.MimeTypeMap.Enabled { - fileExtension := strings.ToLower(filepath.Ext(fileName)) - mimeType = setting.MimeTypeMap.Map[fileExtension] + fileExtension := strings.ToLower(filepath.Ext(filePath)) + opts.ContentType = setting.MimeTypeMap.Map[fileExtension] } - if mimeType == "" { + if opts.ContentType == "" { if sniffedType.IsBrowsableBinaryType() { - mimeType = sniffedType.GetMimeType() + opts.ContentType = sniffedType.GetMimeType() } else if isPlain { - mimeType = "text/plain" + opts.ContentType = "text/plain" } else { - mimeType = typesniffer.ApplicationOctetStream + opts.ContentType = typesniffer.ApplicationOctetStream } } if isPlain { + var charset string charset, err = charsetModule.DetectEncoding(buf) if err != nil { log.Error("Detect raw file %s charset failed: %v, using by default utf-8", filePath, err) charset = "utf-8" } + opts.ContentTypeCharset = strings.ToLower(charset) } - if charset != "" { - ctx.Resp.Header().Set("Content-Type", mimeType+"; charset="+strings.ToLower(charset)) - } else { - ctx.Resp.Header().Set("Content-Type", mimeType) - } - ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff") - isSVG := sniffedType.IsSvgImage() // serve types that can present a security risk with CSP @@ -109,16 +102,12 @@ func ServeData(ctx *context.Context, filePath string, size int64, reader io.Read ctx.Resp.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'") } - disposition := "inline" + opts.Disposition = "inline" if isSVG && !setting.UI.SVG.Enabled { - disposition = "attachment" + opts.Disposition = "attachment" } - // encode filename per https://datatracker.ietf.org/doc/html/rfc5987 - encodedFileName := `filename*=UTF-8''` + url.PathEscape(fileName) - - ctx.Resp.Header().Set("Content-Disposition", disposition+"; "+encodedFileName) - ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition") + ctx.SetServeHeaders(opts) _, err = ctx.Resp.Write(buf) if err != nil { diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go index 0e11f210cefe9..ffa34572bced7 100644 --- a/routers/web/feed/profile.go +++ b/routers/web/feed/profile.go @@ -5,7 +5,6 @@ package feed import ( - "net/http" "time" activities_model "code.gitea.io/gitea/models/activities" @@ -59,7 +58,6 @@ func showUserFeed(ctx *context.Context, formatType string) { // writeFeed write a feeds.Feed as atom or rss to ctx.Resp func writeFeed(ctx *context.Context, feed *feeds.Feed, formatType string) { - ctx.Resp.WriteHeader(http.StatusOK) if formatType == "atom" { ctx.Resp.Header().Set("Content-Type", "application/atom+xml;charset=utf-8") if err := feed.WriteAtom(ctx.Resp); err != nil { diff --git a/routers/web/web.go b/routers/web/web.go index d0ee9c5eac0ca..5fefbad88a4f3 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -604,7 +604,10 @@ func RegisterRoutes(m *web.Route) { m.Group("", func() { m.Get("/favicon.ico", func(ctx *context.Context) { - ctx.ServeFile(path.Join(setting.StaticRootPath, "public/img/favicon.png")) + ctx.SetServeHeaders(&context.ServeHeaderOptions{ + Filename: "favicon.png", + }) + http.ServeFile(ctx.Resp, ctx.Req, path.Join(setting.StaticRootPath, "public/img/favicon.png")) }) m.Group("/{username}", func() { m.Get(".png", func(ctx *context.Context) { ctx.Error(http.StatusNotFound) }) From 88d5275614a82f01ddf728435803ff6000a2262e Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Thu, 17 Nov 2022 20:29:33 +0100 Subject: [PATCH 02/14] Do not allow Ghost access to limited visible user/org (#21849) The Ghost user should not be allowed to have access to a limited visible user/org. Co-authored-by: Lauris BH --- models/organization/org.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/models/organization/org.go b/models/organization/org.go index af9c1f307c012..6bb982b2814f3 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -458,8 +458,9 @@ func CountOrgs(opts FindOrgOptions) (int64, error) { // HasOrgOrUserVisible tells if the given user can see the given org or user func HasOrgOrUserVisible(ctx context.Context, orgOrUser, user *user_model.User) bool { - // Not SignedUser - if user == nil { + // If user is nil, it's an anonymous user/request. + // The Ghost user is handled like an anonymous user. + if user == nil || user.IsGhost() { return orgOrUser.Visibility == structs.VisibleTypePublic } From 6dbcf724accbd4041b655861db9083199ded4967 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Nov 2022 21:32:59 -0500 Subject: [PATCH 03/14] Bump loader-utils from 2.0.3 to 2.0.4 (#21852) Bumps [loader-utils](https://github.com/webpack/loader-utils) from 2.0.3 to 2.0.4.
Release notes

Sourced from loader-utils's releases.

v2.0.4

2.0.4 (2022-11-11)

Bug Fixes

Changelog

Sourced from loader-utils's changelog.

2.0.4 (2022-11-11)

Bug Fixes

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=loader-utils&package-manager=npm_and_yarn&previous-version=2.0.3&new-version=2.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/go-gitea/gitea/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf8d4b05e2fc0..d46d3a15cae58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6182,9 +6182,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz", - "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -14465,9 +14465,9 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" }, "loader-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz", - "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", From 0b993a0d04c9e542f1584ce00eab7ee4af0321d2 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 18 Nov 2022 14:34:39 +0800 Subject: [PATCH 04/14] Fix "build from source" document to clarify the `bindata` tag is required. (#21853) --- docs/content/doc/installation/from-source.en-us.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md index a6493598be235..01a5e1eaee8dc 100644 --- a/docs/content/doc/installation/from-source.en-us.md +++ b/docs/content/doc/installation/from-source.en-us.md @@ -94,7 +94,7 @@ are provided to keep the build process as simple as possible. Depending on requirements, the following build tags can be included. -- `bindata`: Build a single monolithic binary, with all assets included. +- `bindata`: Build a single monolithic binary, with all assets included. Required for production build. - `sqlite sqlite_unlock_notify`: Enable support for a [SQLite3](https://sqlite.org/) database. Suggested only for tiny installations. @@ -103,11 +103,10 @@ Depending on requirements, the following build tags can be included. available to PAM. - `gogit`: (EXPERIMENTAL) Use go-git variants of Git commands. -Bundling assets into the binary using the `bindata` build tag is recommended for -production deployments. It is possible to serve the static assets directly via a reverse proxy, -but in most cases it is not necessary, and assets should still be bundled in the binary. -You may want to exclude bindata while developing/testing Gitea. -To include assets, add the `bindata` tag: +Bundling all assets (JS/CSS/templates, etc) into the binary. Using the `bindata` build tag is required for +production deployments. You could exclude `bindata` when you are developing/testing Gitea or able to separate the assets correctly. + +To include all assets, use the `bindata` tag: ```bash TAGS="bindata" make build From 20385b52a3381964b3ab8b1708817b3578a76aca Mon Sep 17 00:00:00 2001 From: Gusted Date: Fri, 18 Nov 2022 15:23:34 +0100 Subject: [PATCH 05/14] Prevent dangling user redirects (#21856) - It's possible that the `user_redirect` table contains a user id that no longer exists. - Delete a user redirect upon deleting the user. - Add a check for these dangling user redirects to check-db-consistency. --- models/user.go | 1 + modules/doctor/dbconsistency.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/models/user.go b/models/user.go index 85f465127aebd..0fc28ff055a7a 100644 --- a/models/user.go +++ b/models/user.go @@ -89,6 +89,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) &user_model.UserBadge{UserID: u.ID}, &pull_model.AutoMerge{DoerID: u.ID}, &pull_model.ReviewState{UserID: u.ID}, + &user_model.Redirect{RedirectUserID: u.ID}, ); err != nil { return fmt.Errorf("deleteBeans: %w", err) } diff --git a/modules/doctor/dbconsistency.go b/modules/doctor/dbconsistency.go index 7ae349908efb4..89d974a35002d 100644 --- a/modules/doctor/dbconsistency.go +++ b/modules/doctor/dbconsistency.go @@ -205,6 +205,9 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er // find stopwatches without existing issue genericOrphanCheck("Orphaned Stopwatches without existing Issue", "stopwatch", "issue", "stopwatch.issue_id=`issue`.id"), + // find redirects without existing user. + genericOrphanCheck("Orphaned Redirects without existing redirect user", + "user_redirect", "user", "user_redirect.redirect_user_id=`user`.id"), ) for _, c := range consistencyChecks { From 6da8bc6be9fedf8956b25680077941ed3f081d75 Mon Sep 17 00:00:00 2001 From: Percy Ma Date: Sat, 19 Nov 2022 01:01:06 +0800 Subject: [PATCH 06/14] chore: add webpack export type check (#21857) add webpack export type check Co-authored-by: techknowlogick --- webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.js b/webpack.config.js index 26632429929b9..4ad5d69bbf2f0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -47,6 +47,7 @@ const filterCssImport = (url, ...args) => { return true; }; +/** @type {import("webpack").Configuration} */ export default { mode: isProduction ? 'production' : 'development', entry: { From 595d940daada0a50bf2d3e31c1849e5580810847 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 18 Nov 2022 18:54:32 +0100 Subject: [PATCH 07/14] Fix webpack license warning (#21815) #19999 introduced a indirect dependency with a license that was not on our allowlist yet which produced this warning during webpack: ```` WARNING in License: citeproc@2.4.62 has disallowed license CPAL-1.0 OR AGPL-1.0 ```` I've added both licenses to the allowed list and made it so webpack will now abort on such license errors so that we don't miss those next time. Co-authored-by: John Olheiser Co-authored-by: Lunny Xiao --- webpack.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index 4ad5d69bbf2f0..a8363051dfa2a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -229,7 +229,8 @@ export default { override: { 'jquery.are-you-sure@*': {licenseName: 'MIT'}, }, - allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC)', + emitError: true, + allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0)', ignore: [ 'font-awesome', ], From fefdb7ffd11bbfbff66dae8e88681ec840dedfde Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 19 Nov 2022 05:02:30 +0100 Subject: [PATCH 08/14] Timeline and color tweaks (#21799) Followup to https://github.com/go-gitea/gitea/pull/21784. - Restore muted effect on timeline author and issuelist comment icon - Remove whitespace inside shared user templates, fixing link hover underline - Use shared author link template more - Use `bold` class instead of CSS - Fix grey-light color being too dark on arc-green - Add missing black-light color - Fix issuelist progress bar color - Fix various other cases of missing `.muted` Screenshot 2022-11-13 at 12 15 22 Screenshot 2022-11-13 at 12 16 52 Screenshot 2022-11-13 at 12 30 55 Screenshot 2022-11-13 at 12 41 03 Screenshot 2022-11-13 at 12 52 54 Screenshot 2022-11-13 at 12 56 16 Co-authored-by: Lauris BH Co-authored-by: techknowlogick Co-authored-by: wxiaoguang --- templates/explore/repo_list.tmpl | 6 +++--- templates/org/home.tmpl | 4 ++-- templates/repo/diff/comments.tmpl | 2 +- templates/repo/issue/view_content.tmpl | 4 ++-- .../repo/issue/view_content/comments.tmpl | 20 +++++++++---------- .../repo/issue/view_content/sidebar.tmpl | 2 +- templates/shared/issuelist.tmpl | 2 +- templates/shared/user/authorlink.tmpl | 4 +--- templates/shared/user/avatarlink.tmpl | 4 +--- templates/shared/user/namelink.tmpl | 4 +--- web_src/less/_base.less | 7 +++++-- web_src/less/_repository.less | 18 +++++++---------- web_src/less/shared/issuelist.less | 8 ++++++++ web_src/less/themes/theme-arc-green.less | 9 +++++---- 14 files changed, 47 insertions(+), 47 deletions(-) diff --git a/templates/explore/repo_list.tmpl b/templates/explore/repo_list.tmpl index 2a5c444dce2f1..044af9522e6e1 100644 --- a/templates/explore/repo_list.tmpl +++ b/templates/explore/repo_list.tmpl @@ -38,10 +38,10 @@ {{end}} -
+
{{if .PrimaryLanguage}} - - {{.PrimaryLanguage.Language}} + + {{.PrimaryLanguage.Language}} {{end}} {{if not $.DisableStars}} diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index 3ff86259d53f2..448639975f895 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -68,8 +68,8 @@ {{end}} diff --git a/templates/repo/diff/comments.tmpl b/templates/repo/diff/comments.tmpl index 5d298f820c274..647c662d51ce6 100644 --- a/templates/repo/diff/comments.tmpl +++ b/templates/repo/diff/comments.tmpl @@ -11,7 +11,7 @@
{{if .OriginalAuthor}} - + {{svg (MigrationIcon $.root.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index de11846af7e94..0cb74e8182904 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -30,7 +30,7 @@
{{if .Issue.OriginalAuthor}} - + {{svg (MigrationIcon .Repository.GetOriginalURLHostname)}} {{.Issue.OriginalAuthor}} @@ -45,7 +45,7 @@ {{avatar .Issue.Poster}} - {{.Issue.Poster.GetDisplayName}} + {{template "shared/user/authorlink" .Issue.Poster}} {{.locale.Tr "repo.issues.commented_at" (.Issue.HashTag|Escape) $createdStr | Safe}} {{end}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 7ed8cf3bde5e5..e9b7172d1b324 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -25,7 +25,7 @@
{{if .OriginalAuthor}} - + {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} @@ -42,9 +42,7 @@ {{end}} - - {{.Poster.GetDisplayName}} - + {{template "shared/user/authorlink" .Poster}} {{$.locale.Tr "repo.issues.commented_at" (.HashTag|Escape) $createdStr | Safe}} {{end}} @@ -151,14 +149,14 @@ {{svg "octicon-bookmark"}} {{template "shared/user/avatarlink" .Poster}} {{if eq .RefAction 3}}{{end}} - + {{template "shared/user/authorlink" .Poster}} {{$.locale.Tr $refTr (.EventTag|Escape) $createdStr (.RefCommentHTMLURL|Escape) $refFrom | Safe}} {{if eq .RefAction 3}}{{end}}
{{else if eq .Type 4}} @@ -207,7 +205,7 @@ {{if .RemovedAssignee}} {{template "shared/user/avatarlink" .Assignee}} - {{.Assignee.GetDisplayName}} + {{template "shared/user/authorlink" .Assignee}} {{if eq .Poster.ID .Assignee.ID}} {{$.locale.Tr "repo.issues.remove_self_assignment" $createdStr | Safe}} {{else}} @@ -331,7 +329,7 @@
{{svg "octicon-plus"}} - + {{if eq .DependentIssue.RepoID .Issue.RepoID}} #{{.DependentIssue.Index}} {{.DependentIssue.Title}} {{else}} @@ -354,7 +352,7 @@
{{svg "octicon-trash"}} - + {{if eq .DependentIssue.RepoID .Issue.RepoID}} #{{.DependentIssue.Index}} {{.DependentIssue.Title}} {{else}} @@ -408,7 +406,7 @@
{{if .OriginalAuthor}} - + {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} @@ -536,7 +534,7 @@ {{end}} {{if .OriginalAuthor}} - + {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index eb95674b13d2e..af648387db58b 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -389,7 +389,7 @@ {{avatar $user}}
- {{$user.DisplayName}} + {{template "shared/user/authorlink" $user}}
{{$trackedtime}}
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl index 6fce412ffa140..e8ad8406cd2d5 100644 --- a/templates/shared/issuelist.tmpl +++ b/templates/shared/issuelist.tmpl @@ -160,7 +160,7 @@
{{if .NumComments}} - + {{svg "octicon-comment" 16 "mr-2"}}{{.NumComments}} {{end}} diff --git a/templates/shared/user/authorlink.tmpl b/templates/shared/user/authorlink.tmpl index 81c2a4ed5e508..4a6672181f43b 100644 --- a/templates/shared/user/authorlink.tmpl +++ b/templates/shared/user/authorlink.tmpl @@ -1,3 +1 @@ - - {{.GetDisplayName}} - +{{.GetDisplayName}} diff --git a/templates/shared/user/avatarlink.tmpl b/templates/shared/user/avatarlink.tmpl index 40f5ee71297fe..90f5d96700e30 100644 --- a/templates/shared/user/avatarlink.tmpl +++ b/templates/shared/user/avatarlink.tmpl @@ -1,3 +1 @@ - - {{avatar .}} - +{{avatar .}} diff --git a/templates/shared/user/namelink.tmpl b/templates/shared/user/namelink.tmpl index 25dff36a78802..a122f4f45b543 100644 --- a/templates/shared/user/namelink.tmpl +++ b/templates/shared/user/namelink.tmpl @@ -1,3 +1 @@ - - {{.GetDisplayName}} - +{{.GetDisplayName}} diff --git a/web_src/less/_base.less b/web_src/less/_base.less index dc0e69c6d1ba7..f2173d6d2b24f 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -79,6 +79,7 @@ --color-pink: #e03997; --color-brown: #a5673f; --color-grey: #888888; + --color-black: #1b1c1d; /* light variants - produced via Sass scale-color(color, $lightness: +25%) */ --color-red-light: #e45e5e; --color-orange-light: #f59555; @@ -92,9 +93,9 @@ --color-pink-light: #e86bb1; --color-brown-light: #c58b66; --color-grey-light: #a6a6a6; + --color-black-light: #525558; /* other colors */ --color-gold: #a1882b; - --color-black: #1b1c1d; --color-white: #ffffff; --color-diff-removed-word-bg: #fdb8c0; --color-diff-added-word-bg: #acf2bd; @@ -293,13 +294,15 @@ a, text-decoration-skip-ink: all; } -a.muted { +a.muted, +.muted-links a { color: inherit; } a:hover, a.muted:hover, a.muted:hover [class*="color-text"], +.muted-links a:hover, .ui.breadcrumb a:hover { color: var(--color-primary); } diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index bf1fb53e2b80e..63f1f954a0c9f 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -829,7 +829,7 @@ .timeline-avatar { position: absolute; - left: -72px; + left: -68px; img { width: 40px !important; @@ -846,7 +846,6 @@ .avatar img { width: 20px; height: 20px; - margin: 0 .25rem; vertical-align: middle; } @@ -981,10 +980,6 @@ margin-top: 4px; } - .author { - font-weight: 600; - } - .comment-form-reply .footer { padding-bottom: 1em; } @@ -1165,9 +1160,12 @@ padding-left: 15px; .detail { - font-size: .9rem; - margin-top: 5px; - margin-left: 8px; + margin-top: 4px; + margin-left: 14px; + + .svg { + margin-right: 2px; + } } .segments { @@ -2723,12 +2721,10 @@ a { color: var(--color-text); - text-decoration: none; } a:hover { color: var(--color-primary); - text-decoration: none; } } diff --git a/web_src/less/shared/issuelist.less b/web_src/less/shared/issuelist.less index 2dffe19909a28..8d4cfc46d491c 100644 --- a/web_src/less/shared/issuelist.less +++ b/web_src/less/shared/issuelist.less @@ -91,6 +91,14 @@ border-radius: 3px; vertical-align: 2px !important; } + + progress::-webkit-progress-value { + background-color: var(--color-secondary-dark-4); + } + + progress::-moz-progress-bar { + background-color: var(--color-secondary-dark-4); + } } .conflicting { diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index 370a866abb40e..b793f99509160 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -67,8 +67,9 @@ --color-purple: #b259d0; --color-pink: #d22e8b; --color-brown: #a47252; - --color-grey: #5e626a; - /* light variants */ + --color-grey: #9ea2aa; + --color-black: #1e222e; + /* light variants - produced via Sass scale-color(color, $lightness: -10%) */ --color-red-light: #c23636; --color-orange-light: #b84f0b; --color-yellow-light: #b88a03; @@ -80,9 +81,9 @@ --color-purple-light: #a742c9; --color-pink-light: #be297d; --color-brown-light: #94674a; - --color-grey-light: #55585f; + --color-grey-light: #8d919b; + --color-black-light: #1b1f29; /* other colors */ - --color-black: #1e222e; --color-gold: #b1983b; --color-white: #ffffff; --color-diff-removed-word-bg: #6f3333; From 044c754ea53f5b81f451451df53aea366f6f700a Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Sat, 19 Nov 2022 09:12:33 +0100 Subject: [PATCH 09/14] Add `context.Context` to more methods (#21546) This PR adds a context parameter to a bunch of methods. Some helper `xxxCtx()` methods got replaced with the normal name now. Co-authored-by: delvh Co-authored-by: Lunny Xiao --- cmd/admin.go | 2 +- models/activities/action.go | 18 +- models/activities/action_test.go | 10 +- models/activities/notification.go | 96 +++--- models/activities/notification_test.go | 8 +- models/db/consistency.go | 15 +- models/db/engine_test.go | 4 +- models/db/sequence.go | 5 +- models/fixture_generation.go | 2 +- models/git/protected_tag.go | 17 +- models/git/protected_tag_test.go | 19 +- models/issues/assignees.go | 9 +- models/issues/assignees_test.go | 10 +- models/issues/comment.go | 63 ++-- models/issues/comment_list.go | 30 +- models/issues/issue.go | 114 +++---- models/issues/issue_list.go | 38 +-- models/issues/issue_list_test.go | 3 +- models/issues/issue_project.go | 12 +- models/issues/issue_test.go | 4 +- models/issues/issue_xref.go | 2 +- models/issues/label.go | 44 +-- models/issues/label_test.go | 4 +- models/issues/pull.go | 66 ++-- models/issues/pull_list.go | 2 +- models/issues/pull_test.go | 30 +- models/issues/review.go | 20 +- models/issues/review_test.go | 2 +- models/org_team_test.go | 2 +- models/perm/access/access_test.go | 14 +- models/perm/access/repo_permission.go | 12 +- models/repo/attachment.go | 12 +- models/repo/pushmirror.go | 4 +- models/repo/release.go | 16 +- models/repo/repo.go | 24 +- models/repo/repo_list.go | 11 +- models/repo/repo_list_test.go | 18 +- models/repo/user_repo.go | 10 +- models/user/user.go | 12 +- models/user/user_test.go | 8 +- modules/convert/issue.go | 29 +- modules/convert/issue_comment.go | 27 +- modules/convert/pull.go | 6 +- modules/convert/pull_test.go | 9 +- modules/doctor/dbconsistency.go | 22 +- modules/indexer/issues/indexer.go | 18 +- modules/notification/action/action.go | 117 +++---- modules/notification/action/action_test.go | 3 +- modules/notification/base/notifier.go | 90 ++--- modules/notification/base/null.go | 92 ++--- modules/notification/indexer/indexer.go | 44 +-- modules/notification/mail/mail.go | 91 ++--- modules/notification/mirror/mirror.go | 14 +- modules/notification/notification.go | 180 +++++----- modules/notification/ui/ui.go | 47 +-- modules/notification/webhook/webhook.go | 321 +++++++----------- modules/repository/repo.go | 2 +- routers/api/packages/conan/conan.go | 2 +- routers/api/v1/misc/nodeinfo.go | 2 +- routers/api/v1/notify/repo.go | 8 +- routers/api/v1/notify/threads.go | 8 +- routers/api/v1/notify/user.go | 8 +- routers/api/v1/org/team.go | 8 +- routers/api/v1/repo/branch.go | 12 +- routers/api/v1/repo/fork.go | 2 +- routers/api/v1/repo/issue.go | 28 +- routers/api/v1/repo/issue_comment.go | 24 +- routers/api/v1/repo/issue_reaction.go | 4 +- routers/api/v1/repo/issue_tracked_time.go | 10 +- routers/api/v1/repo/migrate.go | 2 +- routers/api/v1/repo/pull.go | 52 +-- routers/api/v1/repo/pull_review.go | 4 +- routers/api/v1/repo/release.go | 8 +- routers/api/v1/repo/release_attachment.go | 2 +- routers/api/v1/repo/release_tags.go | 2 +- routers/api/v1/repo/repo.go | 4 +- routers/api/v1/repo/wiki.go | 6 +- routers/api/v1/user/repo.go | 6 +- routers/api/v1/user/star.go | 11 +- routers/api/v1/user/watch.go | 11 +- routers/private/hook_post_receive.go | 2 +- routers/private/hook_pre_receive.go | 4 +- routers/web/explore/repo.go | 2 +- routers/web/home.go | 2 +- routers/web/org/home.go | 2 +- routers/web/repo/branch.go | 8 +- routers/web/repo/compare.go | 4 +- routers/web/repo/issue.go | 60 ++-- routers/web/repo/issue_label.go | 2 +- routers/web/repo/projects.go | 4 +- routers/web/repo/pull.go | 30 +- routers/web/repo/pull_review.go | 4 +- routers/web/repo/release.go | 8 +- routers/web/repo/repo.go | 2 +- routers/web/repo/tag.go | 4 +- routers/web/repo/wiki.go | 6 +- routers/web/user/home.go | 6 +- routers/web/user/notification.go | 220 ++++++------ routers/web/user/profile.go | 6 +- services/agit/agit.go | 10 +- services/asymkey/sign.go | 2 +- services/automerge/automerge.go | 8 +- services/comments/comments.go | 34 +- services/issue/assignee.go | 10 +- services/issue/content.go | 3 +- services/issue/issue.go | 18 +- services/issue/label.go | 10 +- services/issue/milestone.go | 2 +- services/issue/status.go | 2 +- services/lfs/locks.go | 8 +- services/mailer/mail.go | 9 +- services/mailer/mail_issue.go | 20 +- services/mailer/mail_release.go | 2 +- services/mailer/mail_repo.go | 6 +- services/migrations/gitea_uploader_test.go | 12 +- services/mirror/mirror_pull.go | 8 +- services/packages/packages.go | 6 +- services/pull/check.go | 14 +- services/pull/commit_status.go | 4 +- services/pull/edits.go | 2 +- services/pull/merge.go | 36 +- services/pull/patch.go | 2 +- services/pull/pull.go | 48 +-- services/pull/pull_test.go | 13 +- services/pull/review.go | 18 +- services/pull/temp_repo.go | 4 +- services/pull/update.go | 8 +- services/release/release.go | 42 +-- services/release/release_test.go | 12 +- services/repository/adopt.go | 2 +- services/repository/branch.go | 5 +- services/repository/fork.go | 2 +- services/repository/push.go | 14 +- services/repository/repository.go | 4 +- services/repository/template.go | 2 +- services/repository/transfer.go | 6 +- services/task/migrate.go | 2 +- services/user/user.go | 2 +- services/webhook/webhook.go | 2 +- .../user/notification/notification_div.tmpl | 5 +- tests/integration/api_comment_test.go | 5 +- tests/integration/api_issue_reaction_test.go | 2 +- tests/integration/api_notification_test.go | 5 +- tests/integration/api_pull_commits_test.go | 9 +- tests/integration/api_pull_test.go | 5 +- tests/integration/eventsource_test.go | 3 +- tests/integration/pull_update_test.go | 8 +- tests/integration/repo_tag_test.go | 9 +- 148 files changed, 1408 insertions(+), 1561 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index d33d17a53ddf0..80b5d4853c077 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -727,7 +727,7 @@ func runRepoSyncReleases(_ *cli.Context) error { log.Trace("Synchronizing repository releases (this may take a while)") for page := 1; ; page++ { - repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: repo_model.RepositoryListDefaultPageSize, Page: page, diff --git a/models/activities/action.go b/models/activities/action.go index 5c3419c5ecf90..bbb6073265724 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -461,7 +461,8 @@ func DeleteOldActions(olderThan time.Duration) (err error) { return err } -func notifyWatchers(ctx context.Context, actions ...*Action) error { +// NotifyWatchers creates batch of actions for every watcher. +func NotifyWatchers(ctx context.Context, actions ...*Action) error { var watchers []*repo_model.Watch var repo *repo_model.Repository var err error @@ -565,11 +566,6 @@ func notifyWatchers(ctx context.Context, actions ...*Action) error { return nil } -// NotifyWatchers creates batch of actions for every watcher. -func NotifyWatchers(actions ...*Action) error { - return notifyWatchers(db.DefaultContext, actions...) -} - // NotifyWatchersActions creates batch of actions for every watcher. func NotifyWatchersActions(acts []*Action) error { ctx, committer, err := db.TxContext(db.DefaultContext) @@ -578,7 +574,7 @@ func NotifyWatchersActions(acts []*Action) error { } defer committer.Close() for _, act := range acts { - if err := notifyWatchers(ctx, act); err != nil { + if err := NotifyWatchers(ctx, act); err != nil { return err } } @@ -603,17 +599,17 @@ func DeleteIssueActions(ctx context.Context, repoID, issueID int64) error { } // CountActionCreatedUnixString count actions where created_unix is an empty string -func CountActionCreatedUnixString() (int64, error) { +func CountActionCreatedUnixString(ctx context.Context) (int64, error) { if setting.Database.UseSQLite3 { - return db.GetEngine(db.DefaultContext).Where(`created_unix = ""`).Count(new(Action)) + return db.GetEngine(ctx).Where(`created_unix = ""`).Count(new(Action)) } return 0, nil } // FixActionCreatedUnixString set created_unix to zero if it is an empty string -func FixActionCreatedUnixString() (int64, error) { +func FixActionCreatedUnixString(ctx context.Context) (int64, error) { if setting.Database.UseSQLite3 { - res, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`) + res, err := db.GetEngine(ctx).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`) if err != nil { return 0, err } diff --git a/models/activities/action_test.go b/models/activities/action_test.go index ac2a3043a6a27..b79eb0d08d06e 100644 --- a/models/activities/action_test.go +++ b/models/activities/action_test.go @@ -188,7 +188,7 @@ func TestNotifyWatchers(t *testing.T) { RepoID: 1, OpType: activities_model.ActionStarRepo, } - assert.NoError(t, activities_model.NotifyWatchers(action)) + assert.NoError(t, activities_model.NotifyWatchers(db.DefaultContext, action)) // One watchers are inactive, thus action is only created for user 8, 1, 4, 11 unittest.AssertExistsAndLoadBean(t, &activities_model.Action{ @@ -256,17 +256,17 @@ func TestConsistencyUpdateAction(t *testing.T) { // // Get rid of incorrectly set created_unix // - count, err := activities_model.CountActionCreatedUnixString() + count, err := activities_model.CountActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 1, count) - count, err = activities_model.FixActionCreatedUnixString() + count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 1, count) - count, err = activities_model.CountActionCreatedUnixString() + count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 0, count) - count, err = activities_model.FixActionCreatedUnixString() + count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 0, count) diff --git a/models/activities/notification.go b/models/activities/notification.go index 28adc8cc4efa1..10b3a76713572 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -136,49 +136,41 @@ func GetNotifications(ctx context.Context, options *FindNotificationOptions) (nl } // CountNotifications count all notifications that fit to the given options and ignore pagination. -func CountNotifications(opts *FindNotificationOptions) (int64, error) { - return db.GetEngine(db.DefaultContext).Where(opts.ToCond()).Count(&Notification{}) +func CountNotifications(ctx context.Context, opts *FindNotificationOptions) (int64, error) { + return db.GetEngine(ctx).Where(opts.ToCond()).Count(&Notification{}) } // CreateRepoTransferNotification creates notification for the user a repository was transferred to -func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_model.Repository) error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - var notify []*Notification +func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { + return db.AutoTx(ctx, func(ctx context.Context) error { + var notify []*Notification - if newOwner.IsOrganization() { - users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID) - if err != nil || len(users) == 0 { - return err - } - for i := range users { - notify = append(notify, &Notification{ - UserID: users[i].ID, + if newOwner.IsOrganization() { + users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID) + if err != nil || len(users) == 0 { + return err + } + for i := range users { + notify = append(notify, &Notification{ + UserID: users[i].ID, + RepoID: repo.ID, + Status: NotificationStatusUnread, + UpdatedBy: doer.ID, + Source: NotificationSourceRepository, + }) + } + } else { + notify = []*Notification{{ + UserID: newOwner.ID, RepoID: repo.ID, Status: NotificationStatusUnread, UpdatedBy: doer.ID, Source: NotificationSourceRepository, - }) + }} } - } else { - notify = []*Notification{{ - UserID: newOwner.ID, - RepoID: repo.ID, - Status: NotificationStatusUnread, - UpdatedBy: doer.ID, - Source: NotificationSourceRepository, - }} - } - - if err := db.Insert(ctx, notify); err != nil { - return err - } - return committer.Commit() + return db.Insert(ctx, notify) + }) } // CreateOrUpdateIssueNotifications creates an issue notification @@ -379,11 +371,7 @@ func CountUnread(ctx context.Context, userID int64) int64 { } // LoadAttributes load Repo Issue User and Comment if not loaded -func (n *Notification) LoadAttributes() (err error) { - return n.loadAttributes(db.DefaultContext) -} - -func (n *Notification) loadAttributes(ctx context.Context) (err error) { +func (n *Notification) LoadAttributes(ctx context.Context) (err error) { if err = n.loadRepo(ctx); err != nil { return } @@ -481,10 +469,10 @@ func (n *Notification) APIURL() string { type NotificationList []*Notification // LoadAttributes load Repo Issue User and Comment if not loaded -func (nl NotificationList) LoadAttributes() error { +func (nl NotificationList) LoadAttributes(ctx context.Context) error { var err error for i := 0; i < len(nl); i++ { - err = nl[i].LoadAttributes() + err = nl[i].LoadAttributes(ctx) if err != nil && !issues_model.IsErrCommentNotExist(err) { return err } @@ -504,7 +492,7 @@ func (nl NotificationList) getPendingRepoIDs() []int64 { } // LoadRepos loads repositories from database -func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error) { +func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { if len(nl) == 0 { return repo_model.RepositoryList{}, []int{}, nil } @@ -517,7 +505,7 @@ func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error) if left < limit { limit = left } - rows, err := db.GetEngine(db.DefaultContext). + rows, err := db.GetEngine(ctx). In("id", repoIDs[:limit]). Rows(new(repo_model.Repository)) if err != nil { @@ -578,7 +566,7 @@ func (nl NotificationList) getPendingIssueIDs() []int64 { } // LoadIssues loads issues from database -func (nl NotificationList) LoadIssues() ([]int, error) { +func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { if len(nl) == 0 { return []int{}, nil } @@ -591,7 +579,7 @@ func (nl NotificationList) LoadIssues() ([]int, error) { if left < limit { limit = left } - rows, err := db.GetEngine(db.DefaultContext). + rows, err := db.GetEngine(ctx). In("id", issueIDs[:limit]). Rows(new(issues_model.Issue)) if err != nil { @@ -662,7 +650,7 @@ func (nl NotificationList) getPendingCommentIDs() []int64 { } // LoadComments loads comments from database -func (nl NotificationList) LoadComments() ([]int, error) { +func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { if len(nl) == 0 { return []int{}, nil } @@ -675,7 +663,7 @@ func (nl NotificationList) LoadComments() ([]int, error) { if left < limit { limit = left } - rows, err := db.GetEngine(db.DefaultContext). + rows, err := db.GetEngine(ctx). In("id", commentIDs[:limit]). Rows(new(issues_model.Comment)) if err != nil { @@ -775,8 +763,8 @@ func SetRepoReadBy(ctx context.Context, userID, repoID int64) error { } // SetNotificationStatus change the notification status -func SetNotificationStatus(notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) { - notification, err := getNotificationByID(db.DefaultContext, notificationID) +func SetNotificationStatus(ctx context.Context, notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) { + notification, err := GetNotificationByID(ctx, notificationID) if err != nil { return notification, err } @@ -787,16 +775,12 @@ func SetNotificationStatus(notificationID int64, user *user_model.User, status N notification.Status = status - _, err = db.GetEngine(db.DefaultContext).ID(notificationID).Update(notification) + _, err = db.GetEngine(ctx).ID(notificationID).Update(notification) return notification, err } // GetNotificationByID return notification by ID -func GetNotificationByID(notificationID int64) (*Notification, error) { - return getNotificationByID(db.DefaultContext, notificationID) -} - -func getNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) { +func GetNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) { notification := new(Notification) ok, err := db.GetEngine(ctx). Where("id = ?", notificationID). @@ -813,9 +797,9 @@ func getNotificationByID(ctx context.Context, notificationID int64) (*Notificati } // UpdateNotificationStatuses updates the statuses of all of a user's notifications that are of the currentStatus type to the desiredStatus -func UpdateNotificationStatuses(user *user_model.User, currentStatus, desiredStatus NotificationStatus) error { +func UpdateNotificationStatuses(ctx context.Context, user *user_model.User, currentStatus, desiredStatus NotificationStatus) error { n := &Notification{Status: desiredStatus, UpdatedBy: user.ID} - _, err := db.GetEngine(db.DefaultContext). + _, err := db.GetEngine(ctx). Where("user_id = ? AND status = ?", user.ID, currentStatus). Cols("status", "updated_by", "updated_unix"). Update(n) diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index 4ee16af076e5a..d871891001a02 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -82,14 +82,14 @@ func TestSetNotificationStatus(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead}) - _, err := activities_model.SetNotificationStatus(notf.ID, user, activities_model.NotificationStatusPinned) + _, err := activities_model.SetNotificationStatus(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned}) - _, err = activities_model.SetNotificationStatus(1, user, activities_model.NotificationStatusRead) + _, err = activities_model.SetNotificationStatus(db.DefaultContext, 1, user, activities_model.NotificationStatusRead) assert.Error(t, err) - _, err = activities_model.SetNotificationStatus(unittest.NonexistentID, user, activities_model.NotificationStatusRead) + _, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead) assert.Error(t, err) } @@ -102,7 +102,7 @@ func TestUpdateNotificationStatuses(t *testing.T) { &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead}) notfPinned := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned}) - assert.NoError(t, activities_model.UpdateNotificationStatuses(user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) + assert.NoError(t, activities_model.UpdateNotificationStatuses(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead}) unittest.AssertExistsAndLoadBean(t, diff --git a/models/db/consistency.go b/models/db/consistency.go index 7addb174c4a43..5a7878c74dd6e 100644 --- a/models/db/consistency.go +++ b/models/db/consistency.go @@ -4,11 +4,16 @@ package db -import "xorm.io/builder" +import ( + "context" + + "xorm.io/builder" +) // CountOrphanedObjects count subjects with have no existing refobject anymore -func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) { - return GetEngine(DefaultContext).Table("`"+subject+"`"). +func CountOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) (int64, error) { + return GetEngine(ctx). + Table("`"+subject+"`"). Join("LEFT", "`"+refobject+"`", joinCond). Where(builder.IsNull{"`" + refobject + "`.id"}). Select("COUNT(`" + subject + "`.`id`)"). @@ -16,12 +21,12 @@ func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) { } // DeleteOrphanedObjects delete subjects with have no existing refobject anymore -func DeleteOrphanedObjects(subject, refobject, joinCond string) error { +func DeleteOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) error { subQuery := builder.Select("`"+subject+"`.id"). From("`"+subject+"`"). Join("LEFT", "`"+refobject+"`", joinCond). Where(builder.IsNull{"`" + refobject + "`.id"}) b := builder.Delete(builder.In("id", subQuery)).From("`" + subject + "`") - _, err := GetEngine(DefaultContext).Exec(b) + _, err := GetEngine(ctx).Exec(b) return err } diff --git a/models/db/engine_test.go b/models/db/engine_test.go index c26d94c3405e7..c2ba9614aa4ff 100644 --- a/models/db/engine_test.go +++ b/models/db/engine_test.go @@ -41,11 +41,11 @@ func TestDeleteOrphanedObjects(t *testing.T) { _, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) assert.NoError(t, err) - orphaned, err := db.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) assert.EqualValues(t, 3, orphaned) - err = db.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) diff --git a/models/db/sequence.go b/models/db/sequence.go index 48e4a8f1ac41b..0daacee70c316 100644 --- a/models/db/sequence.go +++ b/models/db/sequence.go @@ -5,6 +5,7 @@ package db import ( + "context" "fmt" "regexp" @@ -12,7 +13,7 @@ import ( ) // CountBadSequences looks for broken sequences from recreate-table mistakes -func CountBadSequences() (int64, error) { +func CountBadSequences(_ context.Context) (int64, error) { if !setting.Database.UsePostgreSQL { return 0, nil } @@ -33,7 +34,7 @@ func CountBadSequences() (int64, error) { } // FixBadSequences fixes for broken sequences from recreate-table mistakes -func FixBadSequences() error { +func FixBadSequences(_ context.Context) error { if !setting.Database.UsePostgreSQL { return nil } diff --git a/models/fixture_generation.go b/models/fixture_generation.go index f4644859eb63e..50b983fa82072 100644 --- a/models/fixture_generation.go +++ b/models/fixture_generation.go @@ -22,7 +22,7 @@ func GetYamlFixturesAccess() (string, error) { } for _, repo := range repos { - repo.MustOwner() + repo.MustOwner(db.DefaultContext) if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil { return "", err } diff --git a/models/git/protected_tag.go b/models/git/protected_tag.go index 7c3881643de7e..4640a77b20f81 100644 --- a/models/git/protected_tag.go +++ b/models/git/protected_tag.go @@ -5,6 +5,7 @@ package git import ( + "context" "regexp" "strings" @@ -69,13 +70,13 @@ func UpdateProtectedTag(pt *ProtectedTag) error { } // DeleteProtectedTag deletes a protected tag by ID -func DeleteProtectedTag(pt *ProtectedTag) error { - _, err := db.GetEngine(db.DefaultContext).ID(pt.ID).Delete(&ProtectedTag{}) +func DeleteProtectedTag(ctx context.Context, pt *ProtectedTag) error { + _, err := db.GetEngine(ctx).ID(pt.ID).Delete(&ProtectedTag{}) return err } // IsUserAllowedModifyTag returns true if the user is allowed to modify the tag -func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) { +func IsUserAllowedModifyTag(ctx context.Context, pt *ProtectedTag, userID int64) (bool, error) { if base.Int64sContains(pt.AllowlistUserIDs, userID) { return true, nil } @@ -84,7 +85,7 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) { return false, nil } - in, err := organization.IsUserInTeams(db.DefaultContext, userID, pt.AllowlistTeamIDs) + in, err := organization.IsUserInTeams(ctx, userID, pt.AllowlistTeamIDs) if err != nil { return false, err } @@ -92,9 +93,9 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) { } // GetProtectedTags gets all protected tags of the repository -func GetProtectedTags(repoID int64) ([]*ProtectedTag, error) { +func GetProtectedTags(ctx context.Context, repoID int64) ([]*ProtectedTag, error) { tags := make([]*ProtectedTag, 0) - return tags, db.GetEngine(db.DefaultContext).Find(&tags, &ProtectedTag{RepoID: repoID}) + return tags, db.GetEngine(ctx).Find(&tags, &ProtectedTag{RepoID: repoID}) } // GetProtectedTagByID gets the protected tag with the specific id @@ -112,7 +113,7 @@ func GetProtectedTagByID(id int64) (*ProtectedTag, error) { // IsUserAllowedToControlTag checks if a user can control the specific tag. // It returns true if the tag name is not protected or the user is allowed to control it. -func IsUserAllowedToControlTag(tags []*ProtectedTag, tagName string, userID int64) (bool, error) { +func IsUserAllowedToControlTag(ctx context.Context, tags []*ProtectedTag, tagName string, userID int64) (bool, error) { isAllowed := true for _, tag := range tags { err := tag.EnsureCompiledPattern() @@ -124,7 +125,7 @@ func IsUserAllowedToControlTag(tags []*ProtectedTag, tagName string, userID int6 continue } - isAllowed, err = IsUserAllowedModifyTag(tag, userID) + isAllowed, err = IsUserAllowedModifyTag(ctx, tag, userID) if err != nil { return false, err } diff --git a/models/git/protected_tag_test.go b/models/git/protected_tag_test.go index b496688b253f4..352eed00603da 100644 --- a/models/git/protected_tag_test.go +++ b/models/git/protected_tag_test.go @@ -7,6 +7,7 @@ package git_test import ( "testing" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/models/unittest" @@ -17,29 +18,29 @@ func TestIsUserAllowed(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pt := &git_model.ProtectedTag{} - allowed, err := git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err := git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.False(t, allowed) pt = &git_model.ProtectedTag{ AllowlistUserIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.True(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) assert.NoError(t, err) assert.False(t, allowed) pt = &git_model.ProtectedTag{ AllowlistTeamIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.False(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) assert.NoError(t, err) assert.True(t, allowed) @@ -47,11 +48,11 @@ func TestIsUserAllowed(t *testing.T) { AllowlistUserIDs: []int64{1}, AllowlistTeamIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.True(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) assert.NoError(t, err) assert.True(t, allowed) } @@ -135,7 +136,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) { } for n, c := range cases { - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, c.name, c.userid) + isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) assert.NoError(t, err) assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n) } @@ -157,7 +158,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) { } for n, c := range cases { - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, c.name, c.userid) + isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) assert.NoError(t, err) assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n) } diff --git a/models/issues/assignees.go b/models/issues/assignees.go index ce497b116dec1..19480fa1e1f70 100644 --- a/models/issues/assignees.go +++ b/models/issues/assignees.go @@ -48,9 +48,10 @@ func (issue *Issue) LoadAssignees(ctx context.Context) (err error) { // GetAssigneeIDsByIssue returns the IDs of users assigned to an issue // but skips joining with `user` for performance reasons. // User permissions must be verified elsewhere if required. -func GetAssigneeIDsByIssue(issueID int64) ([]int64, error) { +func GetAssigneeIDsByIssue(ctx context.Context, issueID int64) ([]int64, error) { userIDs := make([]int64, 0, 5) - return userIDs, db.GetEngine(db.DefaultContext).Table("issue_assignees"). + return userIDs, db.GetEngine(ctx). + Table("issue_assignees"). Cols("assignee_id"). Where("issue_id = ?", issueID). Distinct("assignee_id"). @@ -151,7 +152,7 @@ func toggleUserAssignee(ctx context.Context, issue *Issue, assigneeID int64) (re } // MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs -func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) { +func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) { var requestAssignees []string // Keeping the old assigning method for compatibility reasons @@ -165,7 +166,7 @@ func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string } // Get the IDs of all assignees - assigneeIDs, err = user_model.GetUserIDsByNames(requestAssignees, false) + assigneeIDs, err = user_model.GetUserIDsByNames(ctx, requestAssignees, false) return assigneeIDs, err } diff --git a/models/issues/assignees_test.go b/models/issues/assignees_test.go index 291bb673da84b..4286bdd7eebe7 100644 --- a/models/issues/assignees_test.go +++ b/models/issues/assignees_test.go @@ -71,22 +71,22 @@ func TestMakeIDsFromAPIAssigneesToAdd(t *testing.T) { _ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) _ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{""}) + IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{""}) assert.NoError(t, err) assert.Equal(t, []int64{}, IDs) - _, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"none_existing_user"}) + _, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"none_existing_user"}) assert.Error(t, err) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("user1", []string{"user1"}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user1", []string{"user1"}) assert.NoError(t, err) assert.Equal(t, []int64{1}, IDs) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("user2", []string{""}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user2", []string{""}) assert.NoError(t, err) assert.Equal(t, []int64{2}, IDs) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"user1", "user2"}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"user1", "user2"}) assert.NoError(t, err) assert.Equal(t, []int64{1, 2}, IDs) } diff --git a/models/issues/comment.go b/models/issues/comment.go index d71c675d23472..9483814a19e04 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -309,13 +309,8 @@ type PushActionContent struct { CommitIDs []string `json:"commit_ids"` } -// LoadIssue loads issue from database -func (c *Comment) LoadIssue() (err error) { - return c.LoadIssueCtx(db.DefaultContext) -} - -// LoadIssueCtx loads issue from database -func (c *Comment) LoadIssueCtx(ctx context.Context) (err error) { +// LoadIssue loads the issue reference for the comment +func (c *Comment) LoadIssue(ctx context.Context) (err error) { if c.Issue != nil { return nil } @@ -350,7 +345,8 @@ func (c *Comment) AfterLoad(session *xorm.Session) { } } -func (c *Comment) loadPoster(ctx context.Context) (err error) { +// LoadPoster loads comment poster +func (c *Comment) LoadPoster(ctx context.Context) (err error) { if c.PosterID <= 0 || c.Poster != nil { return nil } @@ -381,7 +377,7 @@ func (c *Comment) AfterDelete() { // HTMLURL formats a URL-string to the issue-comment func (c *Comment) HTMLURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -410,7 +406,7 @@ func (c *Comment) HTMLURL() string { // APIURL formats a API-string to the issue-comment func (c *Comment) APIURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -426,7 +422,7 @@ func (c *Comment) APIURL() string { // IssueURL formats a URL-string to the issue func (c *Comment) IssueURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -446,7 +442,7 @@ func (c *Comment) IssueURL() string { // PRURL formats a URL-string to the pull-request func (c *Comment) PRURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -521,10 +517,10 @@ func (c *Comment) LoadProject() error { } // LoadMilestone if comment.Type is CommentTypeMilestone, then load milestone -func (c *Comment) LoadMilestone() error { +func (c *Comment) LoadMilestone(ctx context.Context) error { if c.OldMilestoneID > 0 { var oldMilestone Milestone - has, err := db.GetEngine(db.DefaultContext).ID(c.OldMilestoneID).Get(&oldMilestone) + has, err := db.GetEngine(ctx).ID(c.OldMilestoneID).Get(&oldMilestone) if err != nil { return err } else if has { @@ -534,7 +530,7 @@ func (c *Comment) LoadMilestone() error { if c.MilestoneID > 0 { var milestone Milestone - has, err := db.GetEngine(db.DefaultContext).ID(c.MilestoneID).Get(&milestone) + has, err := db.GetEngine(ctx).ID(c.MilestoneID).Get(&milestone) if err != nil { return err } else if has { @@ -544,19 +540,14 @@ func (c *Comment) LoadMilestone() error { return nil } -// LoadPoster loads comment poster -func (c *Comment) LoadPoster() error { - return c.loadPoster(db.DefaultContext) -} - // LoadAttachments loads attachments (it never returns error, the error during `GetAttachmentsByCommentIDCtx` is ignored) -func (c *Comment) LoadAttachments() error { +func (c *Comment) LoadAttachments(ctx context.Context) error { if len(c.Attachments) > 0 { return nil } var err error - c.Attachments, err = repo_model.GetAttachmentsByCommentID(db.DefaultContext, c.ID) + c.Attachments, err = repo_model.GetAttachmentsByCommentID(ctx, c.ID) if err != nil { log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err) } @@ -598,7 +589,7 @@ func (c *Comment) LoadAssigneeUserAndTeam() error { c.Assignee = user_model.NewGhostUser() } } else if c.AssigneeTeamID > 0 && c.AssigneeTeam == nil { - if err = c.LoadIssue(); err != nil { + if err = c.LoadIssue(db.DefaultContext); err != nil { return err } @@ -740,7 +731,7 @@ func (c *Comment) UnsignedLine() uint64 { // CodeCommentURL returns the url to a comment in code func (c *Comment) CodeCommentURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -1145,7 +1136,7 @@ func UpdateComment(c *Comment, doer *user_model.User) error { if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil { return err } - if err := c.LoadIssueCtx(ctx); err != nil { + if err := c.LoadIssue(ctx); err != nil { return err } if err := c.AddCrossReferences(ctx, doer, true); err != nil { @@ -1245,7 +1236,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu return nil, err } - if err := CommentList(comments).loadPosters(ctx); err != nil { + if err := CommentList(comments).LoadPosters(ctx); err != nil { return nil, err } @@ -1363,11 +1354,11 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge { return nil, fmt.Errorf("comment type %d cannot be used to create an auto merge comment", typ) } - if err = pr.LoadIssueCtx(ctx); err != nil { + if err = pr.LoadIssue(ctx); err != nil { return } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return } @@ -1512,18 +1503,18 @@ func (c *Comment) GetExternalName() string { return c.OriginalAuthor } func (c *Comment) GetExternalID() int64 { return c.OriginalAuthorID } // CountCommentTypeLabelWithEmptyLabel count label comments with empty label -func CountCommentTypeLabelWithEmptyLabel() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment)) +func CountCommentTypeLabelWithEmptyLabel(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment)) } // FixCommentTypeLabelWithEmptyLabel count label comments with empty label -func FixCommentTypeLabelWithEmptyLabel() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment)) +func FixCommentTypeLabelWithEmptyLabel(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment)) } // CountCommentTypeLabelWithOutsideLabels count label comments with outside label -func CountCommentTypeLabelWithOutsideLabels() (int64, error) { - return db.GetEngine(db.DefaultContext).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel). +func CountCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel). Table("comment"). Join("inner", "label", "label.id = comment.label_id"). Join("inner", "issue", "issue.id = comment.issue_id "). @@ -1532,8 +1523,8 @@ func CountCommentTypeLabelWithOutsideLabels() (int64, error) { } // FixCommentTypeLabelWithOutsideLabels count label comments with outside label -func FixCommentTypeLabelWithOutsideLabels() (int64, error) { - res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM comment WHERE comment.id IN ( +func FixCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) { + res, err := db.GetEngine(ctx).Exec(`DELETE FROM comment WHERE comment.id IN ( SELECT il_too.id FROM ( SELECT com.id FROM comment AS com diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index 70105d7ff056e..e42b8605f94e2 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -24,7 +24,8 @@ func (comments CommentList) getPosterIDs() []int64 { return posterIDs.Values() } -func (comments CommentList) loadPosters(ctx context.Context) error { +// LoadPosters loads posters +func (comments CommentList) LoadPosters(ctx context.Context) error { if len(comments) == 0 { return nil } @@ -277,7 +278,8 @@ func (comments CommentList) Issues() IssueList { return issueList } -func (comments CommentList) loadIssues(ctx context.Context) error { +// LoadIssues loads issues of comments +func (comments CommentList) LoadIssues(ctx context.Context) error { if len(comments) == 0 { return nil } @@ -382,7 +384,8 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error { return nil } -func (comments CommentList) loadAttachments(ctx context.Context) (err error) { +// LoadAttachments loads attachments +func (comments CommentList) LoadAttachments(ctx context.Context) (err error) { if len(comments) == 0 { return nil } @@ -476,7 +479,7 @@ func (comments CommentList) loadReviews(ctx context.Context) error { //nolint // loadAttributes loads all attributes func (comments CommentList) loadAttributes(ctx context.Context) (err error) { - if err = comments.loadPosters(ctx); err != nil { + if err = comments.LoadPosters(ctx); err != nil { return } @@ -496,7 +499,7 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { return } - if err = comments.loadAttachments(ctx); err != nil { + if err = comments.LoadAttachments(ctx); err != nil { return } @@ -504,7 +507,7 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { return } - if err = comments.loadIssues(ctx); err != nil { + if err = comments.LoadIssues(ctx); err != nil { return } @@ -520,18 +523,3 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { func (comments CommentList) LoadAttributes() error { return comments.loadAttributes(db.DefaultContext) } - -// LoadAttachments loads attachments -func (comments CommentList) LoadAttachments() error { - return comments.loadAttachments(db.DefaultContext) -} - -// LoadPosters loads posters -func (comments CommentList) LoadPosters() error { - return comments.loadPosters(db.DefaultContext) -} - -// LoadIssues loads issues of comments -func (comments CommentList) LoadIssues() error { - return comments.loadIssues(db.DefaultContext) -} diff --git a/models/issues/issue.go b/models/issues/issue.go index c2f7cb6578006..69d6657d46454 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -241,11 +241,7 @@ func (issue *Issue) LoadLabels(ctx context.Context) (err error) { } // LoadPoster loads poster -func (issue *Issue) LoadPoster() error { - return issue.loadPoster(db.DefaultContext) -} - -func (issue *Issue) loadPoster(ctx context.Context) (err error) { +func (issue *Issue) LoadPoster(ctx context.Context) (err error) { if issue.Poster == nil { issue.Poster, err = user_model.GetUserByIDCtx(ctx, issue.PosterID) if err != nil { @@ -261,7 +257,8 @@ func (issue *Issue) loadPoster(ctx context.Context) (err error) { return err } -func (issue *Issue) loadPullRequest(ctx context.Context) (err error) { +// LoadPullRequest loads pull request info +func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) { if issue.IsPull && issue.PullRequest == nil { issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID) if err != nil { @@ -275,18 +272,13 @@ func (issue *Issue) loadPullRequest(ctx context.Context) (err error) { return nil } -// LoadPullRequest loads pull request info -func (issue *Issue) LoadPullRequest() error { - return issue.loadPullRequest(db.DefaultContext) -} - func (issue *Issue) loadComments(ctx context.Context) (err error) { return issue.loadCommentsByType(ctx, CommentTypeUnknown) } // LoadDiscussComments loads discuss comments -func (issue *Issue) LoadDiscussComments() error { - return issue.loadCommentsByType(db.DefaultContext, CommentTypeComment) +func (issue *Issue) LoadDiscussComments(ctx context.Context) error { + return issue.loadCommentsByType(ctx, CommentTypeComment) } func (issue *Issue) loadCommentsByType(ctx context.Context, tp CommentType) (err error) { @@ -357,7 +349,8 @@ func (issue *Issue) loadForeignReference(ctx context.Context) (err error) { return nil } -func (issue *Issue) loadMilestone(ctx context.Context) (err error) { +// LoadMilestone load milestone of this issue. +func (issue *Issue) LoadMilestone(ctx context.Context) (err error) { if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 { issue.Milestone, err = GetMilestoneByRepoID(ctx, issue.RepoID, issue.MilestoneID) if err != nil && !IsErrMilestoneNotExist(err) { @@ -373,7 +366,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadPoster(ctx); err != nil { + if err = issue.LoadPoster(ctx); err != nil { return } @@ -381,7 +374,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadMilestone(ctx); err != nil { + if err = issue.LoadMilestone(ctx); err != nil { return } @@ -393,7 +386,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) { + if err = issue.LoadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) { // It is possible pull request is not yet created. return err } @@ -425,11 +418,6 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return issue.loadReactions(ctx) } -// LoadMilestone load milestone of this issue. -func (issue *Issue) LoadMilestone() error { - return issue.loadMilestone(db.DefaultContext) -} - // GetIsRead load the `IsRead` field of the issue func (issue *Issue) GetIsRead(userID int64) error { issueUser := &IssueUser{IssueID: issue.ID, UID: userID} @@ -548,7 +536,7 @@ func ClearIssueLabels(issue *Issue, doer *user_model.User) (err error) { if err := issue.LoadRepo(ctx); err != nil { return err - } else if err = issue.loadPullRequest(ctx); err != nil { + } else if err = issue.LoadPullRequest(ctx); err != nil { return err } @@ -751,7 +739,7 @@ func ChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, if err := issue.LoadRepo(ctx); err != nil { return nil, err } - if err := issue.loadPoster(ctx); err != nil { + if err := issue.LoadPoster(ctx); err != nil { return nil, err } @@ -1027,7 +1015,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue return fmt.Errorf("find all labels [label_ids: %v]: %w", opts.LabelIDs, err) } - if err = opts.Issue.loadPoster(ctx); err != nil { + if err = opts.Issue.LoadPoster(ctx); err != nil { return err } @@ -1505,10 +1493,9 @@ func applySubscribedCondition(sess *xorm.Session, subscriberID int64) *xorm.Sess } // CountIssuesByRepo map from repoID to number of issues matching the options -func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) { - e := db.GetEngine(db.DefaultContext) - - sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") +func CountIssuesByRepo(ctx context.Context, opts *IssuesOptions) (map[int64]int64, error) { + sess := db.GetEngine(ctx). + Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSessionNoLimit(sess) @@ -1551,10 +1538,9 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]i } // Issues returns a list of issues by given conditions. -func Issues(opts *IssuesOptions) ([]*Issue, error) { - e := db.GetEngine(db.DefaultContext) - - sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") +func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) { + sess := db.GetEngine(ctx). + Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSessionWithLimit(sess) sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID) @@ -1572,11 +1558,11 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) { } // CountIssues number return of issues by given conditions. -func CountIssues(opts *IssuesOptions) (int64, error) { - e := db.GetEngine(db.DefaultContext) - - sess := e.Select("COUNT(issue.id) AS count").Table("issue") - sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") +func CountIssues(ctx context.Context, opts *IssuesOptions) (int64, error) { + sess := db.GetEngine(ctx). + Select("COUNT(issue.id) AS count"). + Table("issue"). + Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSessionNoLimit(sess) return sess.Count() @@ -1585,9 +1571,10 @@ func CountIssues(opts *IssuesOptions) (int64, error) { // GetParticipantsIDsByIssueID returns the IDs of all users who participated in comments of an issue, // but skips joining with `user` for performance reasons. // User permissions must be verified elsewhere if required. -func GetParticipantsIDsByIssueID(issueID int64) ([]int64, error) { +func GetParticipantsIDsByIssueID(ctx context.Context, issueID int64) ([]int64, error) { userIDs := make([]int64, 0, 5) - return userIDs, db.GetEngine(db.DefaultContext).Table("comment"). + return userIDs, db.GetEngine(ctx). + Table("comment"). Cols("poster_id"). Where("issue_id = ?", issueID). And("type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview). @@ -2426,8 +2413,9 @@ func (issue *Issue) GetExternalName() string { return issue.OriginalAuthor } func (issue *Issue) GetExternalID() int64 { return issue.OriginalAuthorID } // CountOrphanedIssues count issues without a repo -func CountOrphanedIssues() (int64, error) { - return db.GetEngine(db.DefaultContext).Table("issue"). +func CountOrphanedIssues(ctx context.Context) (int64, error) { + return db.GetEngine(ctx). + Table("issue"). Join("LEFT", "repository", "issue.repo_id=repository.id"). Where(builder.IsNull{"repository.id"}). Select("COUNT(`issue`.`id`)"). @@ -2435,35 +2423,31 @@ func CountOrphanedIssues() (int64, error) { } // DeleteOrphanedIssues delete issues without a repo -func DeleteOrphanedIssues() error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - var ids []int64 - - if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id"). - Join("LEFT", "repository", "issue.repo_id=repository.id"). - Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id"). - Find(&ids); err != nil { - return err - } - +func DeleteOrphanedIssues(ctx context.Context) error { var attachmentPaths []string - for i := range ids { - paths, err := DeleteIssuesByRepoID(ctx, ids[i]) - if err != nil { + err := db.AutoTx(ctx, func(ctx context.Context) error { + var ids []int64 + + if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id"). + Join("LEFT", "repository", "issue.repo_id=repository.id"). + Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id"). + Find(&ids); err != nil { return err } - attachmentPaths = append(attachmentPaths, paths...) - } - if err := committer.Commit(); err != nil { + for i := range ids { + paths, err := DeleteIssuesByRepoID(ctx, ids[i]) + if err != nil { + return err + } + attachmentPaths = append(attachmentPaths, paths...) + } + + return nil + }) + if err != nil { return err } - committer.Close() // Remove issue attachment files. for i := range attachmentPaths { diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index bbe2292dd1de0..d9dff4cb4d6cf 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -34,7 +34,8 @@ func (issues IssueList) getRepoIDs() []int64 { return repoIDs.Values() } -func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Repository, error) { +// LoadRepositories loads issues' all repositories +func (issues IssueList) LoadRepositories(ctx context.Context) ([]*repo_model.Repository, error) { if len(issues) == 0 { return nil, nil } @@ -73,11 +74,6 @@ func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Rep return repo_model.ValuesRepository(repoMaps), nil } -// LoadRepositories loads issues' all repositories -func (issues IssueList) LoadRepositories() ([]*repo_model.Repository, error) { - return issues.loadRepositories(db.DefaultContext) -} - func (issues IssueList) getPosterIDs() []int64 { posterIDs := make(container.Set[int64], len(issues)) for _, issue := range issues { @@ -317,7 +313,8 @@ func (issues IssueList) getPullIssueIDs() []int64 { return ids } -func (issues IssueList) loadPullRequests(ctx context.Context) error { +// LoadPullRequests loads pull requests +func (issues IssueList) LoadPullRequests(ctx context.Context) error { issuesIDs := issues.getPullIssueIDs() if len(issuesIDs) == 0 { return nil @@ -361,7 +358,8 @@ func (issues IssueList) loadPullRequests(ctx context.Context) error { return nil } -func (issues IssueList) loadAttachments(ctx context.Context) (err error) { +// LoadAttachments loads attachments +func (issues IssueList) LoadAttachments(ctx context.Context) (err error) { if len(issues) == 0 { return nil } @@ -513,8 +511,8 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) { // loadAttributes loads all attributes, expect for attachments and comments func (issues IssueList) loadAttributes(ctx context.Context) error { - if _, err := issues.loadRepositories(ctx); err != nil { - return fmt.Errorf("issue.loadAttributes: loadRepositories: %w", err) + if _, err := issues.LoadRepositories(ctx); err != nil { + return fmt.Errorf("issue.loadAttributes: LoadRepositories: %w", err) } if err := issues.loadPosters(ctx); err != nil { @@ -537,7 +535,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error { return fmt.Errorf("issue.loadAttributes: loadAssignees: %w", err) } - if err := issues.loadPullRequests(ctx); err != nil { + if err := issues.LoadPullRequests(ctx); err != nil { return fmt.Errorf("issue.loadAttributes: loadPullRequests: %w", err) } @@ -554,24 +552,14 @@ func (issues IssueList) LoadAttributes() error { return issues.loadAttributes(db.DefaultContext) } -// LoadAttachments loads attachments -func (issues IssueList) LoadAttachments() error { - return issues.loadAttachments(db.DefaultContext) -} - // LoadComments loads comments -func (issues IssueList) LoadComments() error { - return issues.loadComments(db.DefaultContext, builder.NewCond()) +func (issues IssueList) LoadComments(ctx context.Context) error { + return issues.loadComments(ctx, builder.NewCond()) } // LoadDiscussComments loads discuss comments -func (issues IssueList) LoadDiscussComments() error { - return issues.loadComments(db.DefaultContext, builder.Eq{"comment.type": CommentTypeComment}) -} - -// LoadPullRequests loads pull requests -func (issues IssueList) LoadPullRequests() error { - return issues.loadPullRequests(db.DefaultContext) +func (issues IssueList) LoadDiscussComments(ctx context.Context) error { + return issues.loadComments(ctx, builder.Eq{"comment.type": CommentTypeComment}) } // GetApprovalCounts returns a map of issue ID to slice of approval counts diff --git a/models/issues/issue_list_test.go b/models/issues/issue_list_test.go index f2cfca9bc0afc..c38a405e02a78 100644 --- a/models/issues/issue_list_test.go +++ b/models/issues/issue_list_test.go @@ -7,6 +7,7 @@ package issues_test import ( "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" @@ -23,7 +24,7 @@ func TestIssueList_LoadRepositories(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}), } - repos, err := issueList.LoadRepositories() + repos, err := issueList.LoadRepositories(db.DefaultContext) assert.NoError(t, err) assert.Len(t, repos, 2) for _, issue := range issueList { diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 0c59f4e82b713..39a27abd3e091 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -61,11 +61,11 @@ func (issue *Issue) projectBoardID(ctx context.Context) int64 { } // LoadIssuesFromBoard load issues assigned to this board -func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { +func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) { issueList := make([]*Issue, 0, 10) if b.ID != 0 { - issues, err := Issues(&IssuesOptions{ + issues, err := Issues(ctx, &IssuesOptions{ ProjectBoardID: b.ID, ProjectID: b.ProjectID, SortType: "project-column-sorting", @@ -77,7 +77,7 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { } if b.Default { - issues, err := Issues(&IssuesOptions{ + issues, err := Issues(ctx, &IssuesOptions{ ProjectBoardID: -1, // Issues without ProjectBoardID ProjectID: b.ProjectID, SortType: "project-column-sorting", @@ -88,7 +88,7 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { issueList = append(issueList, issues...) } - if err := IssueList(issueList).LoadComments(); err != nil { + if err := IssueList(issueList).LoadComments(ctx); err != nil { return nil, err } @@ -96,10 +96,10 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { } // LoadIssuesFromBoardList load issues assigned to the boards -func LoadIssuesFromBoardList(bs project_model.BoardList) (map[int64]IssueList, error) { +func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) { issuesMap := make(map[int64]IssueList, len(bs)) for i := range bs { - il, err := LoadIssuesFromBoard(bs[i]) + il, err := LoadIssuesFromBoard(ctx, bs[i]) if err != nil { return nil, err } diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go index bef5d03e8afa8..2c8728e71a3af 100644 --- a/models/issues/issue_test.go +++ b/models/issues/issue_test.go @@ -189,7 +189,7 @@ func TestIssues(t *testing.T) { []int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests }, } { - issues, err := issues_model.Issues(&test.Opts) + issues, err := issues_model.Issues(db.DefaultContext, &test.Opts) assert.NoError(t, err) if assert.Len(t, issues, len(test.ExpectedIssueIDs)) { for i, issue := range issues { @@ -556,7 +556,7 @@ func TestLoadTotalTrackedTime(t *testing.T) { func TestCountIssues(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - count, err := issues_model.CountIssues(&issues_model.IssuesOptions{}) + count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{}) assert.NoError(t, err) assert.EqualValues(t, 17, count) } diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go index e389f63d72acd..4c6601a0a2e55 100644 --- a/models/issues/issue_xref.go +++ b/models/issues/issue_xref.go @@ -235,7 +235,7 @@ func (c *Comment) AddCrossReferences(stdCtx context.Context, doer *user_model.Us if c.Type != CommentTypeCode && c.Type != CommentTypeComment { return nil } - if err := c.LoadIssueCtx(stdCtx); err != nil { + if err := c.LoadIssue(stdCtx); err != nil { return err } ctx := &crossReferencesContext{ diff --git a/models/issues/label.go b/models/issues/label.go index 0b0d1419b16b0..dc7058d643556 100644 --- a/models/issues/label.go +++ b/models/issues/label.go @@ -116,8 +116,8 @@ func (label *Label) CalOpenIssues() { } // CalOpenOrgIssues calculates the open issues of a label for a specific repo -func (label *Label) CalOpenOrgIssues(repoID, labelID int64) { - counts, _ := CountIssuesByRepo(&IssuesOptions{ +func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) { + counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{ RepoID: repoID, LabelIDs: []int64{labelID}, IsClosed: util.OptionalBoolFalse, @@ -395,9 +395,9 @@ func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder { // GetLabelsInRepoByIDs returns a list of labels by IDs in given repository, // it silently ignores label IDs that do not belong to the repository. -func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) { +func GetLabelsInRepoByIDs(ctx context.Context, repoID int64, labelIDs []int64) ([]*Label, error) { labels := make([]*Label, 0, len(labelIDs)) - return labels, db.GetEngine(db.DefaultContext). + return labels, db.GetEngine(ctx). Where("repo_id = ?", repoID). In("id", labelIDs). Asc("name"). @@ -498,9 +498,9 @@ func GetLabelIDsInOrgByNames(orgID int64, labelNames []string) ([]int64, error) // GetLabelsInOrgByIDs returns a list of labels by IDs in given organization, // it silently ignores label IDs that do not belong to the organization. -func GetLabelsInOrgByIDs(orgID int64, labelIDs []int64) ([]*Label, error) { +func GetLabelsInOrgByIDs(ctx context.Context, orgID int64, labelIDs []int64) ([]*Label, error) { labels := make([]*Label, 0, len(labelIDs)) - return labels, db.GetEngine(db.DefaultContext). + return labels, db.GetEngine(ctx). Where("org_id = ?", orgID). In("id", labelIDs). Asc("name"). @@ -746,13 +746,13 @@ func DeleteLabelsByRepoID(ctx context.Context, repoID int64) error { } // CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore -func CountOrphanedLabels() (int64, error) { - noref, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count() +func CountOrphanedLabels(ctx context.Context) (int64, error) { + noref, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count() if err != nil { return 0, err } - norepo, err := db.GetEngine(db.DefaultContext).Table("label"). + norepo, err := db.GetEngine(ctx).Table("label"). Where(builder.And( builder.Gt{"repo_id": 0}, builder.NotIn("repo_id", builder.Select("id").From("repository")), @@ -762,7 +762,7 @@ func CountOrphanedLabels() (int64, error) { return 0, err } - noorg, err := db.GetEngine(db.DefaultContext).Table("label"). + noorg, err := db.GetEngine(ctx).Table("label"). Where(builder.And( builder.Gt{"org_id": 0}, builder.NotIn("org_id", builder.Select("id").From("user")), @@ -776,14 +776,14 @@ func CountOrphanedLabels() (int64, error) { } // DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore -func DeleteOrphanedLabels() error { +func DeleteOrphanedLabels(ctx context.Context) error { // delete labels with no reference - if _, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil { + if _, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil { return err } // delete labels with none existing repos - if _, err := db.GetEngine(db.DefaultContext). + if _, err := db.GetEngine(ctx). Where(builder.And( builder.Gt{"repo_id": 0}, builder.NotIn("repo_id", builder.Select("id").From("repository")), @@ -793,7 +793,7 @@ func DeleteOrphanedLabels() error { } // delete labels with none existing orgs - if _, err := db.GetEngine(db.DefaultContext). + if _, err := db.GetEngine(ctx). Where(builder.And( builder.Gt{"org_id": 0}, builder.NotIn("org_id", builder.Select("id").From("user")), @@ -806,23 +806,23 @@ func DeleteOrphanedLabels() error { } // CountOrphanedIssueLabels return count of IssueLabels witch have no label behind anymore -func CountOrphanedIssueLabels() (int64, error) { - return db.GetEngine(db.DefaultContext).Table("issue_label"). +func CountOrphanedIssueLabels(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Table("issue_label"). NotIn("label_id", builder.Select("id").From("label")). Count() } // DeleteOrphanedIssueLabels delete IssueLabels witch have no label behind anymore -func DeleteOrphanedIssueLabels() error { - _, err := db.GetEngine(db.DefaultContext). +func DeleteOrphanedIssueLabels(ctx context.Context) error { + _, err := db.GetEngine(ctx). NotIn("label_id", builder.Select("id").From("label")). Delete(IssueLabel{}) return err } // CountIssueLabelWithOutsideLabels count label comments with outside label -func CountIssueLabelWithOutsideLabels() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")). +func CountIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")). Table("issue_label"). Join("inner", "label", "issue_label.label_id = label.id "). Join("inner", "issue", "issue.id = issue_label.issue_id "). @@ -831,8 +831,8 @@ func CountIssueLabelWithOutsideLabels() (int64, error) { } // FixIssueLabelWithOutsideLabels fix label comments with outside label -func FixIssueLabelWithOutsideLabels() (int64, error) { - res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM issue_label WHERE issue_label.id IN ( +func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) { + res, err := db.GetEngine(ctx).Exec(`DELETE FROM issue_label WHERE issue_label.id IN ( SELECT il_too.id FROM ( SELECT il_too_too.id FROM issue_label AS il_too_too diff --git a/models/issues/label_test.go b/models/issues/label_test.go index 5e6cc9a2a0895..077e0eeb67ba4 100644 --- a/models/issues/label_test.go +++ b/models/issues/label_test.go @@ -121,7 +121,7 @@ func TestGetLabelInRepoByID(t *testing.T) { func TestGetLabelsInRepoByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsInRepoByIDs(1, []int64{1, 2, unittest.NonexistentID}) + labels, err := issues_model.GetLabelsInRepoByIDs(db.DefaultContext, 1, []int64{1, 2, unittest.NonexistentID}) assert.NoError(t, err) if assert.Len(t, labels, 2) { assert.EqualValues(t, 1, labels[0].ID) @@ -212,7 +212,7 @@ func TestGetLabelInOrgByID(t *testing.T) { func TestGetLabelsInOrgByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsInOrgByIDs(3, []int64{3, 4, unittest.NonexistentID}) + labels, err := issues_model.GetLabelsInOrgByIDs(db.DefaultContext, 3, []int64{3, 4, unittest.NonexistentID}) assert.NoError(t, err) if assert.Len(t, labels, 2) { assert.EqualValues(t, 3, labels[0].ID) diff --git a/models/issues/pull.go b/models/issues/pull.go index e906407d312ab..993a1ba8bdf76 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -205,8 +205,8 @@ func DeletePullsByBaseRepoID(ctx context.Context, repoID int64) error { } // MustHeadUserName returns the HeadRepo's username if failed return blank -func (pr *PullRequest) MustHeadUserName() string { - if err := pr.LoadHeadRepo(); err != nil { +func (pr *PullRequest) MustHeadUserName(ctx context.Context) string { + if err := pr.LoadHeadRepo(ctx); err != nil { if !repo_model.IsErrRepoNotExist(err) { log.Error("LoadHeadRepo: %v", err) } else { @@ -220,8 +220,9 @@ func (pr *PullRequest) MustHeadUserName() string { return pr.HeadRepo.OwnerName } +// LoadAttributes loads pull request attributes from database // Note: don't try to get Issue because will end up recursive querying. -func (pr *PullRequest) loadAttributes(ctx context.Context) (err error) { +func (pr *PullRequest) LoadAttributes(ctx context.Context) (err error) { if pr.HasMerged && pr.Merger == nil { pr.Merger, err = user_model.GetUserByIDCtx(ctx, pr.MergerID) if user_model.IsErrUserNotExist(err) { @@ -235,13 +236,8 @@ func (pr *PullRequest) loadAttributes(ctx context.Context) (err error) { return nil } -// LoadAttributes loads pull request attributes from database -func (pr *PullRequest) LoadAttributes() error { - return pr.loadAttributes(db.DefaultContext) -} - -// LoadHeadRepoCtx loads the head repository -func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) { +// LoadHeadRepo loads the head repository +func (pr *PullRequest) LoadHeadRepo(ctx context.Context) (err error) { if !pr.isHeadRepoLoaded && pr.HeadRepo == nil && pr.HeadRepoID > 0 { if pr.HeadRepoID == pr.BaseRepoID { if pr.BaseRepo != nil { @@ -262,18 +258,8 @@ func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) { return nil } -// LoadHeadRepo loads the head repository -func (pr *PullRequest) LoadHeadRepo() error { - return pr.LoadHeadRepoCtx(db.DefaultContext) -} - // LoadBaseRepo loads the target repository -func (pr *PullRequest) LoadBaseRepo() error { - return pr.LoadBaseRepoCtx(db.DefaultContext) -} - -// LoadBaseRepoCtx loads the target repository -func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) { +func (pr *PullRequest) LoadBaseRepo(ctx context.Context) (err error) { if pr.BaseRepo != nil { return nil } @@ -296,12 +282,7 @@ func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) { } // LoadIssue loads issue information from database -func (pr *PullRequest) LoadIssue() (err error) { - return pr.LoadIssueCtx(db.DefaultContext) -} - -// LoadIssueCtx loads issue information from database -func (pr *PullRequest) LoadIssueCtx(ctx context.Context) (err error) { +func (pr *PullRequest) LoadIssue(ctx context.Context) (err error) { if pr.Issue != nil { return nil } @@ -392,7 +373,7 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error { break } - if err := review.loadReviewer(ctx); err != nil && !user_model.IsErrUserNotExist(err) { + if err := review.LoadReviewer(ctx); err != nil && !user_model.IsErrUserNotExist(err) { log.Error("Unable to LoadReviewer[%d] for PR ID %d : %v", review.ReviewerID, pr.ID, err) return err } else if review.Reviewer == nil { @@ -458,7 +439,7 @@ func (pr *PullRequest) SetMerged(ctx context.Context) (bool, error) { } pr.Issue = nil - if err := pr.LoadIssueCtx(ctx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { return false, err } @@ -541,9 +522,9 @@ func NewPullRequest(outerCtx context.Context, repo *repo_model.Repository, issue // GetUnmergedPullRequest returns a pull request that is open and has not been merged // by given head/base and repo/branch. -func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) { +func GetUnmergedPullRequest(ctx context.Context, headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) { pr := new(PullRequest) - has, err := db.GetEngine(db.DefaultContext). + has, err := db.GetEngine(ctx). Where("head_repo_id=? AND head_branch=? AND base_repo_id=? AND base_branch=? AND has_merged=? AND flow = ? AND issue.is_closed=?", headRepoID, headBranch, baseRepoID, baseBranch, false, flow, false). Join("INNER", "issue", "issue.id=pull_request.issue_id"). @@ -588,10 +569,10 @@ func GetPullRequestByIndex(ctx context.Context, repoID, index int64) (*PullReque return nil, ErrPullRequestNotExist{0, 0, 0, repoID, "", ""} } - if err = pr.loadAttributes(ctx); err != nil { + if err = pr.LoadAttributes(ctx); err != nil { return nil, err } - if err = pr.LoadIssueCtx(ctx); err != nil { + if err = pr.LoadIssue(ctx); err != nil { return nil, err } @@ -607,7 +588,7 @@ func GetPullRequestByID(ctx context.Context, id int64) (*PullRequest, error) { } else if !has { return nil, ErrPullRequestNotExist{id, 0, 0, 0, "", ""} } - return pr, pr.loadAttributes(ctx) + return pr, pr.LoadAttributes(ctx) } // GetPullRequestByIssueIDWithNoAttributes returns pull request with no attributes loaded by given issue ID. @@ -634,7 +615,7 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest, } else if !has { return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""} } - return pr, pr.loadAttributes(ctx) + return pr, pr.LoadAttributes(ctx) } // GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request @@ -664,14 +645,15 @@ func (pr *PullRequest) UpdateCols(cols ...string) error { } // UpdateColsIfNotMerged updates specific fields of a pull request if it has not been merged -func (pr *PullRequest) UpdateColsIfNotMerged(cols ...string) error { - _, err := db.GetEngine(db.DefaultContext).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr) +func (pr *PullRequest) UpdateColsIfNotMerged(ctx context.Context, cols ...string) error { + _, err := db.GetEngine(ctx).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr) return err } // IsWorkInProgress determine if the Pull Request is a Work In Progress by its title +// Issue must be set before this method can be called. func (pr *PullRequest) IsWorkInProgress() bool { - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(db.DefaultContext); err != nil { log.Error("LoadIssue: %v", err) return false } @@ -695,8 +677,8 @@ func (pr *PullRequest) IsFilesConflicted() bool { // GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress. // It returns an empty string when none were found -func (pr *PullRequest) GetWorkInProgressPrefix() string { - if err := pr.LoadIssue(); err != nil { +func (pr *PullRequest) GetWorkInProgressPrefix(ctx context.Context) string { + if err := pr.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return "" } @@ -739,7 +721,7 @@ func GetPullRequestsByHeadBranch(ctx context.Context, headBranch string, headRep // GetBaseBranchHTMLURL returns the HTML URL of the base branch func (pr *PullRequest) GetBaseBranchHTMLURL() string { - if err := pr.LoadBaseRepo(); err != nil { + if err := pr.LoadBaseRepo(db.DefaultContext); err != nil { log.Error("LoadBaseRepo: %v", err) return "" } @@ -755,7 +737,7 @@ func (pr *PullRequest) GetHeadBranchHTMLURL() string { return "" } - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(db.DefaultContext); err != nil { log.Error("LoadHeadRepo: %v", err) return "" } diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index c69f18492b4cf..6110ba77fa72f 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -79,7 +79,7 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user * for _, pr := range prs { if pr.AllowMaintainerEdit { - err = pr.LoadBaseRepo() + err = pr.LoadBaseRepo(db.DefaultContext) if err != nil { continue } diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go index fb46e3071e39f..d88f9d4f54f15 100644 --- a/models/issues/pull_test.go +++ b/models/issues/pull_test.go @@ -17,7 +17,7 @@ import ( func TestPullRequest_LoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadAttributes()) + assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) assert.NotNil(t, pr.Merger) assert.Equal(t, pr.MergerID, pr.Merger.ID) } @@ -25,10 +25,10 @@ func TestPullRequest_LoadAttributes(t *testing.T) { func TestPullRequest_LoadIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) assert.NotNil(t, pr.Issue) assert.Equal(t, int64(2), pr.Issue.ID) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) assert.NotNil(t, pr.Issue) assert.Equal(t, int64(2), pr.Issue.ID) } @@ -36,10 +36,10 @@ func TestPullRequest_LoadIssue(t *testing.T) { func TestPullRequest_LoadBaseRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) assert.NotNil(t, pr.BaseRepo) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) assert.NotNil(t, pr.BaseRepo) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) } @@ -47,7 +47,7 @@ func TestPullRequest_LoadBaseRepo(t *testing.T) { func TestPullRequest_LoadHeadRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadHeadRepo()) + assert.NoError(t, pr.LoadHeadRepo(db.DefaultContext)) assert.NotNil(t, pr.HeadRepo) assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID) } @@ -96,11 +96,11 @@ func TestPullRequestsOldest(t *testing.T) { func TestGetUnmergedPullRequest(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetUnmergedPullRequest(1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) assert.NoError(t, err) assert.Equal(t, int64(2), pr.ID) - _, err = issues_model.GetUnmergedPullRequest(1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) + _, err = issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) } @@ -228,7 +228,7 @@ func TestPullRequest_IsWorkInProgress(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - pr.LoadIssue() + pr.LoadIssue(db.DefaultContext) assert.False(t, pr.IsWorkInProgress()) @@ -243,16 +243,16 @@ func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - pr.LoadIssue() + pr.LoadIssue(db.DefaultContext) - assert.Empty(t, pr.GetWorkInProgressPrefix()) + assert.Empty(t, pr.GetWorkInProgressPrefix(db.DefaultContext)) original := pr.Issue.Title pr.Issue.Title = "WIP: " + original - assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix()) + assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix(db.DefaultContext)) pr.Issue.Title = "[wip] " + original - assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix()) + assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix(db.DefaultContext)) } func TestDeleteOrphanedObjects(t *testing.T) { @@ -264,11 +264,11 @@ func TestDeleteOrphanedObjects(t *testing.T) { _, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) assert.NoError(t, err) - orphaned, err := db.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) assert.EqualValues(t, 3, orphaned) - err = db.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) diff --git a/models/issues/review.go b/models/issues/review.go index f66c70c1fc007..5cf7d4c3da728 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -154,7 +154,8 @@ func (r *Review) loadIssue(ctx context.Context) (err error) { return err } -func (r *Review) loadReviewer(ctx context.Context) (err error) { +// LoadReviewer loads reviewer +func (r *Review) LoadReviewer(ctx context.Context) (err error) { if r.ReviewerID == 0 || r.Reviewer != nil { return } @@ -162,7 +163,8 @@ func (r *Review) loadReviewer(ctx context.Context) (err error) { return err } -func (r *Review) loadReviewerTeam(ctx context.Context) (err error) { +// LoadReviewerTeam loads reviewer team +func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) { if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil { return } @@ -171,16 +173,6 @@ func (r *Review) loadReviewerTeam(ctx context.Context) (err error) { return err } -// LoadReviewer loads reviewer -func (r *Review) LoadReviewer() error { - return r.loadReviewer(db.DefaultContext) -} - -// LoadReviewerTeam loads reviewer team -func (r *Review) LoadReviewerTeam() error { - return r.loadReviewerTeam(db.DefaultContext) -} - // LoadAttributes loads all attributes except CodeComments func (r *Review) LoadAttributes(ctx context.Context) (err error) { if err = r.loadIssue(ctx); err != nil { @@ -189,10 +181,10 @@ func (r *Review) LoadAttributes(ctx context.Context) (err error) { if err = r.LoadCodeComments(ctx); err != nil { return } - if err = r.loadReviewer(ctx); err != nil { + if err = r.LoadReviewer(ctx); err != nil { return } - if err = r.loadReviewerTeam(ctx); err != nil { + if err = r.LoadReviewerTeam(ctx); err != nil { return } return err diff --git a/models/issues/review_test.go b/models/issues/review_test.go index 46d1cc777b65b..39ad14c65fc2f 100644 --- a/models/issues/review_test.go +++ b/models/issues/review_test.go @@ -135,7 +135,7 @@ func TestGetReviewersByIssueID(t *testing.T) { allReviews, err := issues_model.GetReviewersByIssueID(issue.ID) for _, reviewer := range allReviews { - assert.NoError(t, reviewer.LoadReviewer()) + assert.NoError(t, reviewer.LoadReviewer(db.DefaultContext)) } assert.NoError(t, err) if assert.Len(t, allReviews, 3) { diff --git a/models/org_team_test.go b/models/org_team_test.go index a600d07c0c9b3..3b1fabf1c34a6 100644 --- a/models/org_team_test.go +++ b/models/org_team_test.go @@ -143,7 +143,7 @@ func TestDeleteTeam(t *testing.T) { // check that team members don't have "leftover" access to repos user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - accessMode, err := access_model.AccessLevel(user, repo) + accessMode, err := access_model.AccessLevel(db.DefaultContext, user, repo) assert.NoError(t, err) assert.True(t, accessMode < perm.AccessModeWrite) } diff --git a/models/perm/access/access_test.go b/models/perm/access/access_test.go index 7f58be4f393b5..dc707b971be96 100644 --- a/models/perm/access/access_test.go +++ b/models/perm/access/access_test.go @@ -36,34 +36,34 @@ func TestAccessLevel(t *testing.T) { // org. owned private repo repo24 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24}) - level, err := access_model.AccessLevel(user2, repo1) + level, err := access_model.AccessLevel(db.DefaultContext, user2, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeOwner, level) - level, err = access_model.AccessLevel(user2, repo3) + level, err = access_model.AccessLevel(db.DefaultContext, user2, repo3) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeOwner, level) - level, err = access_model.AccessLevel(user5, repo1) + level, err = access_model.AccessLevel(db.DefaultContext, user5, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeRead, level) - level, err = access_model.AccessLevel(user5, repo3) + level, err = access_model.AccessLevel(db.DefaultContext, user5, repo3) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeNone, level) // restricted user has no access to a public repo - level, err = access_model.AccessLevel(user29, repo1) + level, err = access_model.AccessLevel(db.DefaultContext, user29, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeNone, level) // ... unless he's a collaborator - level, err = access_model.AccessLevel(user29, repo4) + level, err = access_model.AccessLevel(db.DefaultContext, user29, repo4) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeWrite, level) // ... or a team member - level, err = access_model.AccessLevel(user29, repo24) + level, err = access_model.AccessLevel(db.DefaultContext, user29, repo24) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeRead, level) } diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 93e3bdd6d8468..3b709a3e85538 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -326,17 +326,13 @@ func IsUserRepoAdmin(ctx context.Context, repo *repo_model.Repository, user *use // AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the // user does not have access. -func AccessLevel(user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint - return AccessLevelUnit(user, repo, unit.TypeCode) +func AccessLevel(ctx context.Context, user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint + return AccessLevelUnit(ctx, user, repo, unit.TypeCode) } // AccessLevelUnit returns the Access a user has to a repository's. Will return NoneAccess if the // user does not have access. -func AccessLevelUnit(user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint - return accessLevelUnit(db.DefaultContext, user, repo, unitType) -} - -func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { +func AccessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint perm, err := GetUserRepoPermission(ctx, repo, user) if err != nil { return perm_model.AccessModeNone, err @@ -346,7 +342,7 @@ func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_mode // HasAccessUnit returns true if user has testMode to the unit of the repository func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) { - mode, err := accessLevelUnit(ctx, user, repo, unitType) + mode, err := AccessLevelUnit(ctx, user, repo, unitType) return testMode <= mode, err } diff --git a/models/repo/attachment.go b/models/repo/attachment.go index df7528df09c9c..428f370a0baa9 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -226,20 +226,20 @@ func UpdateAttachment(ctx context.Context, atta *Attachment) error { } // DeleteAttachmentsByRelease deletes all attachments associated with the given release. -func DeleteAttachmentsByRelease(releaseID int64) error { - _, err := db.GetEngine(db.DefaultContext).Where("release_id = ?", releaseID).Delete(&Attachment{}) +func DeleteAttachmentsByRelease(ctx context.Context, releaseID int64) error { + _, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Delete(&Attachment{}) return err } // CountOrphanedAttachments returns the number of bad attachments -func CountOrphanedAttachments() (int64, error) { - return db.GetEngine(db.DefaultContext).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). +func CountOrphanedAttachments(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). Count(new(Attachment)) } // DeleteOrphanedAttachments delete all bad attachments -func DeleteOrphanedAttachments() error { - _, err := db.GetEngine(db.DefaultContext).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). +func DeleteOrphanedAttachments(ctx context.Context) error { + _, err := db.GetEngine(ctx).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). Delete(new(Attachment)) return err } diff --git a/models/repo/pushmirror.go b/models/repo/pushmirror.go index 38d6e72019700..fa876ee560ac8 100644 --- a/models/repo/pushmirror.go +++ b/models/repo/pushmirror.go @@ -120,9 +120,9 @@ func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.Li } // GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits -func GetPushMirrorsSyncedOnCommit(repoID int64) ([]*PushMirror, error) { +func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMirror, error) { mirrors := make([]*PushMirror, 0, 10) - return mirrors, db.GetEngine(db.DefaultContext). + return mirrors, db.GetEngine(ctx). Where("repo_id=? AND sync_on_commit=?", repoID, true). Find(&mirrors) } diff --git a/models/repo/release.go b/models/repo/release.go index 14428f15f73f6..a92e4bb6e555b 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -90,7 +90,8 @@ func init() { db.RegisterModel(new(Release)) } -func (r *Release) loadAttributes(ctx context.Context) error { +// LoadAttributes load repo and publisher attributes for a release +func (r *Release) LoadAttributes(ctx context.Context) error { var err error if r.Repo == nil { r.Repo, err = GetRepositoryByIDCtx(ctx, r.RepoID) @@ -111,11 +112,6 @@ func (r *Release) loadAttributes(ctx context.Context) error { return GetReleaseAttachments(ctx, r) } -// LoadAttributes load repo and publisher attributes for a release -func (r *Release) LoadAttributes() error { - return r.loadAttributes(db.DefaultContext) -} - // APIURL the api url for a release. release must have attributes loaded func (r *Release) APIURL() string { return r.Repo.APIURL() + "/releases/" + strconv.FormatInt(r.ID, 10) @@ -241,8 +237,8 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { } // GetReleasesByRepoID returns a list of releases of repository. -func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, error) { - sess := db.GetEngine(db.DefaultContext). +func GetReleasesByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) ([]*Release, error) { + sess := db.GetEngine(ctx). Desc("created_unix", "id"). Where(opts.toConds(repoID)) @@ -381,8 +377,8 @@ func SortReleases(rels []*Release) { } // DeleteReleaseByID deletes a release from database by given ID. -func DeleteReleaseByID(id int64) error { - _, err := db.GetEngine(db.DefaultContext).ID(id).Delete(new(Release)) +func DeleteReleaseByID(ctx context.Context, id int64) error { + _, err := db.GetEngine(ctx).ID(id).Delete(new(Release)) return err } diff --git a/models/repo/repo.go b/models/repo/repo.go index 77e0367a5a5c7..a3dac8383f7bc 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -236,14 +236,6 @@ func (repo *Repository) AfterLoad() { repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects } -// MustOwner always returns a valid *user_model.User object to avoid -// conceptually impossible error handling. -// It creates a fake object that contains error details -// when error occurs. -func (repo *Repository) MustOwner() *user_model.User { - return repo.mustOwner(db.DefaultContext) -} - // LoadAttributes loads attributes of the repository. func (repo *Repository) LoadAttributes(ctx context.Context) error { // Load owner @@ -403,7 +395,11 @@ func (repo *Repository) GetOwner(ctx context.Context) (err error) { return err } -func (repo *Repository) mustOwner(ctx context.Context) *user_model.User { +// MustOwner always returns a valid *user_model.User object to avoid +// conceptually impossible error handling. +// It creates a fake object that contains error details +// when error occurs. +func (repo *Repository) MustOwner(ctx context.Context) *user_model.User { if err := repo.GetOwner(ctx); err != nil { return &user_model.User{ Name: "error", @@ -438,7 +434,7 @@ func (repo *Repository) ComposeMetas() map[string]string { } } - repo.MustOwner() + repo.MustOwner(db.DefaultContext) if repo.Owner.IsOrganization() { teams := make([]string, 0, 5) _ = db.GetEngine(db.DefaultContext).Table("team_repo"). @@ -792,13 +788,13 @@ func UpdateRepoIssueNumbers(ctx context.Context, repoID int64, isPull, isClosed } // CountNullArchivedRepository counts the number of repositories with is_archived is null -func CountNullArchivedRepository() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Count(new(Repository)) +func CountNullArchivedRepository(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Count(new(Repository)) } // FixNullArchivedRepository sets is_archived to false where it is null -func FixNullArchivedRepository() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{ +func FixNullArchivedRepository(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{ IsArchived: false, }) } diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 191970d275681..abfa73abb9058 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -518,14 +518,13 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { // SearchRepository returns repositories based on search options, // it returns results in given range and number of total results. -func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { +func SearchRepository(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { cond := SearchRepositoryCondition(opts) - return SearchRepositoryByCondition(opts, cond, true) + return SearchRepositoryByCondition(ctx, opts, cond, true) } // SearchRepositoryByCondition search repositories by condition -func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { - ctx := db.DefaultContext +func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { sess, count, err := searchRepositoryByCondition(ctx, opts, cond) if err != nil { return nil, 0, err @@ -652,9 +651,9 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu // SearchRepositoryByName takes keyword and part of repository name to search, // it returns results in given range and number of total results. -func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) { +func SearchRepositoryByName(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { opts.IncludeDescription = false - return SearchRepository(opts) + return SearchRepository(ctx, opts) } // SearchRepositoryIDs takes keyword and part of repository name to search, diff --git a/models/repo/repo_list_test.go b/models/repo/repo_list_test.go index f9c84a0f3f910..926ed07e9e9e3 100644 --- a/models/repo/repo_list_test.go +++ b/models/repo/repo_list_test.go @@ -20,7 +20,7 @@ func TestSearchRepository(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // test search public repository on explore page - repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -35,7 +35,7 @@ func TestSearchRepository(t *testing.T) { } assert.Equal(t, int64(1), count) - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -49,7 +49,7 @@ func TestSearchRepository(t *testing.T) { assert.Len(t, repos, 2) // test search private repository on explore page - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -65,7 +65,7 @@ func TestSearchRepository(t *testing.T) { } assert.Equal(t, int64(1), count) - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -80,14 +80,14 @@ func TestSearchRepository(t *testing.T) { assert.Len(t, repos, 3) // Test non existing owner - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) assert.NoError(t, err) assert.Empty(t, repos) assert.Equal(t, int64(0), count) // Test search within description - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -104,7 +104,7 @@ func TestSearchRepository(t *testing.T) { assert.Equal(t, int64(1), count) // Test NOT search within description - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -277,7 +277,7 @@ func TestSearchRepository(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - repos, count, err := repo_model.SearchRepositoryByName(testCase.opts) + repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) @@ -377,7 +377,7 @@ func TestSearchRepositoryByTopicName(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - _, count, err := repo_model.SearchRepositoryByName(testCase.opts) + _, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) }) diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index e7125f70f8f94..9ca367f556b71 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -17,8 +17,9 @@ import ( ) // GetStarredRepos returns the repos starred by a particular user -func GetStarredRepos(userID int64, private bool, listOptions db.ListOptions) ([]*Repository, error) { - sess := db.GetEngine(db.DefaultContext).Where("star.uid=?", userID). +func GetStarredRepos(ctx context.Context, userID int64, private bool, listOptions db.ListOptions) ([]*Repository, error) { + sess := db.GetEngine(ctx). + Where("star.uid=?", userID). Join("LEFT", "star", "`repository`.id=`star`.repo_id") if !private { sess = sess.And("is_private=?", false) @@ -36,8 +37,9 @@ func GetStarredRepos(userID int64, private bool, listOptions db.ListOptions) ([] } // GetWatchedRepos returns the repos watched by a particular user -func GetWatchedRepos(userID int64, private bool, listOptions db.ListOptions) ([]*Repository, int64, error) { - sess := db.GetEngine(db.DefaultContext).Where("watch.user_id=?", userID). +func GetWatchedRepos(ctx context.Context, userID int64, private bool, listOptions db.ListOptions) ([]*Repository, int64, error) { + sess := db.GetEngine(ctx). + Where("watch.user_id=?", userID). And("`watch`.mode<>?", WatchModeDont). Join("LEFT", "watch", "`repository`.id=`watch`.repo_id") if !private { diff --git a/models/user/user.go b/models/user/user.go index c36fc21c770ec..1a71acb0b7273 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -1042,14 +1042,15 @@ func GetUserEmailsByNames(ctx context.Context, names []string) []string { } // GetMaileableUsersByIDs gets users from ids, but only if they can receive mails -func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) { +func GetMaileableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([]*User, error) { if len(ids) == 0 { return nil, nil } ous := make([]*User, 0, len(ids)) if isMention { - return ous, db.GetEngine(db.DefaultContext).In("id", ids). + return ous, db.GetEngine(ctx). + In("id", ids). Where("`type` = ?", UserTypeIndividual). And("`prohibit_login` = ?", false). And("`is_active` = ?", true). @@ -1057,7 +1058,8 @@ func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) { Find(&ous) } - return ous, db.GetEngine(db.DefaultContext).In("id", ids). + return ous, db.GetEngine(ctx). + In("id", ids). Where("`type` = ?", UserTypeIndividual). And("`prohibit_login` = ?", false). And("`is_active` = ?", true). @@ -1090,10 +1092,10 @@ func GetUserNameByID(ctx context.Context, id int64) (string, error) { } // GetUserIDsByNames returns a slice of ids corresponds to names. -func GetUserIDsByNames(names []string, ignoreNonExistent bool) ([]int64, error) { +func GetUserIDsByNames(ctx context.Context, names []string, ignoreNonExistent bool) ([]int64, error) { ids := make([]int64, 0, len(names)) for _, name := range names { - u, err := GetUserByName(db.DefaultContext, name) + u, err := GetUserByName(ctx, name) if err != nil { if ignoreNonExistent { continue diff --git a/models/user/user_test.go b/models/user/user_test.go index 5f2ac0a60c17d..1cdfb5978c865 100644 --- a/models/user/user_test.go +++ b/models/user/user_test.go @@ -257,12 +257,12 @@ func TestGetUserIDsByNames(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // ignore non existing - IDs, err := user_model.GetUserIDsByNames([]string{"user1", "user2", "none_existing_user"}, true) + IDs, err := user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "user2", "none_existing_user"}, true) assert.NoError(t, err) assert.Equal(t, []int64{1, 2}, IDs) // ignore non existing - IDs, err = user_model.GetUserIDsByNames([]string{"user1", "do_not_exist"}, false) + IDs, err = user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "do_not_exist"}, false) assert.Error(t, err) assert.Equal(t, []int64(nil), IDs) } @@ -270,14 +270,14 @@ func TestGetUserIDsByNames(t *testing.T) { func TestGetMaileableUsersByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - results, err := user_model.GetMaileableUsersByIDs([]int64{1, 4}, false) + results, err := user_model.GetMaileableUsersByIDs(db.DefaultContext, []int64{1, 4}, false) assert.NoError(t, err) assert.Len(t, results, 1) if len(results) > 1 { assert.Equal(t, results[0].ID, 1) } - results, err = user_model.GetMaileableUsersByIDs([]int64{1, 4}, true) + results, err = user_model.GetMaileableUsersByIDs(db.DefaultContext, []int64{1, 4}, true) assert.NoError(t, err) assert.Len(t, results, 2) if len(results) > 2 { diff --git a/modules/convert/issue.go b/modules/convert/issue.go index 5364367a80964..7c11b2a89f874 100644 --- a/modules/convert/issue.go +++ b/modules/convert/issue.go @@ -5,6 +5,7 @@ package convert import ( + "context" "fmt" "net/url" "strings" @@ -22,17 +23,17 @@ import ( // it assumes some fields assigned with values: // Required - Poster, Labels, // Optional - Milestone, Assignee, PullRequest -func ToAPIIssue(issue *issues_model.Issue) *api.Issue { - if err := issue.LoadLabels(db.DefaultContext); err != nil { +func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { + if err := issue.LoadLabels(ctx); err != nil { return &api.Issue{} } - if err := issue.LoadPoster(); err != nil { + if err := issue.LoadPoster(ctx); err != nil { return &api.Issue{} } - if err := issue.LoadRepo(db.DefaultContext); err != nil { + if err := issue.LoadRepo(ctx); err != nil { return &api.Issue{} } - if err := issue.Repo.GetOwner(db.DefaultContext); err != nil { + if err := issue.Repo.GetOwner(ctx); err != nil { return &api.Issue{} } @@ -64,14 +65,14 @@ func ToAPIIssue(issue *issues_model.Issue) *api.Issue { apiIssue.Closed = issue.ClosedUnix.AsTimePtr() } - if err := issue.LoadMilestone(); err != nil { + if err := issue.LoadMilestone(ctx); err != nil { return &api.Issue{} } if issue.Milestone != nil { apiIssue.Milestone = ToAPIMilestone(issue.Milestone) } - if err := issue.LoadAssignees(db.DefaultContext); err != nil { + if err := issue.LoadAssignees(ctx); err != nil { return &api.Issue{} } if len(issue.Assignees) > 0 { @@ -81,7 +82,7 @@ func ToAPIIssue(issue *issues_model.Issue) *api.Issue { apiIssue.Assignee = ToUser(issue.Assignees[0], nil) // For compatibility, we're keeping the first assignee as `apiIssue.Assignee` } if issue.IsPull { - if err := issue.LoadPullRequest(); err != nil { + if err := issue.LoadPullRequest(ctx); err != nil { return &api.Issue{} } apiIssue.PullRequest = &api.PullRequestMeta{ @@ -99,16 +100,16 @@ func ToAPIIssue(issue *issues_model.Issue) *api.Issue { } // ToAPIIssueList converts an IssueList to API format -func ToAPIIssueList(il issues_model.IssueList) []*api.Issue { +func ToAPIIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue { result := make([]*api.Issue, len(il)) for i := range il { - result[i] = ToAPIIssue(il[i]) + result[i] = ToAPIIssue(ctx, il[i]) } return result } // ToTrackedTime converts TrackedTime to API format -func ToTrackedTime(t *issues_model.TrackedTime) (apiT *api.TrackedTime) { +func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.TrackedTime) { apiT = &api.TrackedTime{ ID: t.ID, IssueID: t.IssueID, @@ -118,7 +119,7 @@ func ToTrackedTime(t *issues_model.TrackedTime) (apiT *api.TrackedTime) { Created: t.Created, } if t.Issue != nil { - apiT.Issue = ToAPIIssue(t.Issue) + apiT.Issue = ToAPIIssue(ctx, t.Issue) } if t.User != nil { apiT.UserName = t.User.Name @@ -169,10 +170,10 @@ func ToStopWatches(sws []*issues_model.Stopwatch) (api.StopWatches, error) { } // ToTrackedTimeList converts TrackedTimeList to API format -func ToTrackedTimeList(tl issues_model.TrackedTimeList) api.TrackedTimeList { +func ToTrackedTimeList(ctx context.Context, tl issues_model.TrackedTimeList) api.TrackedTimeList { result := make([]*api.TrackedTime, 0, len(tl)) for _, t := range tl { - result = append(result, ToTrackedTime(t)) + result = append(result, ToTrackedTime(ctx, t)) } return result } diff --git a/modules/convert/issue_comment.go b/modules/convert/issue_comment.go index 73ad345fa43f9..c33cf5c1116de 100644 --- a/modules/convert/issue_comment.go +++ b/modules/convert/issue_comment.go @@ -5,7 +5,8 @@ package convert import ( - "code.gitea.io/gitea/models/db" + "context" + issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -28,8 +29,8 @@ func ToComment(c *issues_model.Comment) *api.Comment { } // ToTimelineComment converts a issues_model.Comment to the api.TimelineComment format -func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.TimelineComment { - err := c.LoadMilestone() +func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User) *api.TimelineComment { + err := c.LoadMilestone(ctx) if err != nil { log.Error("LoadMilestone: %v", err) return nil @@ -107,25 +108,25 @@ func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.Time return nil } - comment.TrackedTime = ToTrackedTime(c.Time) + comment.TrackedTime = ToTrackedTime(ctx, c.Time) } if c.RefIssueID != 0 { - issue, err := issues_model.GetIssueByID(db.DefaultContext, c.RefIssueID) + issue, err := issues_model.GetIssueByID(ctx, c.RefIssueID) if err != nil { log.Error("GetIssueByID(%d): %v", c.RefIssueID, err) return nil } - comment.RefIssue = ToAPIIssue(issue) + comment.RefIssue = ToAPIIssue(ctx, issue) } if c.RefCommentID != 0 { - com, err := issues_model.GetCommentByID(db.DefaultContext, c.RefCommentID) + com, err := issues_model.GetCommentByID(ctx, c.RefCommentID) if err != nil { log.Error("GetCommentByID(%d): %v", c.RefCommentID, err) return nil } - err = com.LoadPoster() + err = com.LoadPoster(ctx) if err != nil { log.Error("LoadPoster: %v", err) return nil @@ -138,17 +139,17 @@ func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.Time var repo *repo_model.Repository if c.Label.BelongsToOrg() { var err error - org, err = user_model.GetUserByID(c.Label.OrgID) + org, err = user_model.GetUserByIDCtx(ctx, c.Label.OrgID) if err != nil { - log.Error("GetUserByID(%d): %v", c.Label.OrgID, err) + log.Error("GetUserByIDCtx(%d): %v", c.Label.OrgID, err) return nil } } if c.Label.BelongsToRepo() { var err error - repo, err = repo_model.GetRepositoryByID(c.Label.RepoID) + repo, err = repo_model.GetRepositoryByIDCtx(ctx, c.Label.RepoID) if err != nil { - log.Error("GetRepositoryByID(%d): %v", c.Label.RepoID, err) + log.Error("GetRepositoryByIDCtx(%d): %v", c.Label.RepoID, err) return nil } } @@ -167,7 +168,7 @@ func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.Time } if c.DependentIssue != nil { - comment.DependentIssue = ToAPIIssue(c.DependentIssue) + comment.DependentIssue = ToAPIIssue(ctx, c.DependentIssue) } return comment diff --git a/modules/convert/pull.go b/modules/convert/pull.go index 9c31f9bd2c182..ca9a4c39c5a5b 100644 --- a/modules/convert/pull.go +++ b/modules/convert/pull.go @@ -33,13 +33,13 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u return nil } - apiIssue := ToAPIIssue(pr.Issue) - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + apiIssue := ToAPIIssue(ctx, pr.Issue) + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("GetRepositoryById[%d]: %v", pr.ID, err) return nil } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("GetRepositoryById[%d]: %v", pr.ID, err) return nil } diff --git a/modules/convert/pull_test.go b/modules/convert/pull_test.go index a6ccbaca5897d..a0a672d3a5178 100644 --- a/modules/convert/pull_test.go +++ b/modules/convert/pull_test.go @@ -7,6 +7,7 @@ package convert import ( "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" @@ -22,8 +23,8 @@ func TestPullRequest_APIFormat(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadAttributes()) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) apiPullRequest := ToAPIPullRequest(git.DefaultContext, pr, nil) assert.NotNil(t, apiPullRequest) assert.EqualValues(t, &structs.PRBranchInfo{ @@ -36,8 +37,8 @@ func TestPullRequest_APIFormat(t *testing.T) { // withOut HeadRepo pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadIssue()) - assert.NoError(t, pr.LoadAttributes()) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) + assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) // simulate fork deletion pr.HeadRepo = nil pr.HeadRepoID = 100000 diff --git a/modules/doctor/dbconsistency.go b/modules/doctor/dbconsistency.go index 89d974a35002d..602b2e523ed19 100644 --- a/modules/doctor/dbconsistency.go +++ b/modules/doctor/dbconsistency.go @@ -18,13 +18,13 @@ import ( type consistencyCheck struct { Name string - Counter func() (int64, error) - Fixer func() (int64, error) + Counter func(context.Context) (int64, error) + Fixer func(context.Context) (int64, error) FixedMessage string } func (c *consistencyCheck) Run(ctx context.Context, logger log.Logger, autofix bool) error { - count, err := c.Counter() + count, err := c.Counter(ctx) if err != nil { logger.Critical("Error: %v whilst counting %s", err, c.Name) return err @@ -32,7 +32,7 @@ func (c *consistencyCheck) Run(ctx context.Context, logger log.Logger, autofix b if count > 0 { if autofix { var fixed int64 - if fixed, err = c.Fixer(); err != nil { + if fixed, err = c.Fixer(ctx); err != nil { logger.Critical("Error: %v whilst fixing %s", err, c.Name) return err } @@ -54,9 +54,9 @@ func (c *consistencyCheck) Run(ctx context.Context, logger log.Logger, autofix b return nil } -func asFixer(fn func() error) func() (int64, error) { - return func() (int64, error) { - err := fn() +func asFixer(fn func(ctx context.Context) error) func(ctx context.Context) (int64, error) { + return func(ctx context.Context) (int64, error) { + err := fn(ctx) return -1, err } } @@ -64,11 +64,11 @@ func asFixer(fn func() error) func() (int64, error) { func genericOrphanCheck(name, subject, refobject, joincond string) consistencyCheck { return consistencyCheck{ Name: name, - Counter: func() (int64, error) { - return db.CountOrphanedObjects(subject, refobject, joincond) + Counter: func(ctx context.Context) (int64, error) { + return db.CountOrphanedObjects(ctx, subject, refobject, joincond) }, - Fixer: func() (int64, error) { - err := db.DeleteOrphanedObjects(subject, refobject, joincond) + Fixer: func(ctx context.Context) (int64, error) { + err := db.DeleteOrphanedObjects(ctx, subject, refobject, joincond) return -1, err }, } diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index da6a200aef2ff..5b0279d1abb62 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -291,7 +291,7 @@ func populateIssueIndexer(ctx context.Context) { return default: } - repos, _, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, _, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{Page: page, PageSize: repo_model.RepositoryListDefaultPageSize}, OrderBy: db.SearchOrderByID, Private: true, @@ -313,14 +313,14 @@ func populateIssueIndexer(ctx context.Context) { return default: } - UpdateRepoIndexer(repo) + UpdateRepoIndexer(ctx, repo) } } } // UpdateRepoIndexer add/update all issues of the repositories -func UpdateRepoIndexer(repo *repo_model.Repository) { - is, err := issues_model.Issues(&issues_model.IssuesOptions{ +func UpdateRepoIndexer(ctx context.Context, repo *repo_model.Repository) { + is, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ RepoID: repo.ID, IsClosed: util.OptionalBoolNone, IsPull: util.OptionalBoolNone, @@ -329,8 +329,8 @@ func UpdateRepoIndexer(repo *repo_model.Repository) { log.Error("Issues: %v", err) return } - if err = issues_model.IssueList(is).LoadDiscussComments(); err != nil { - log.Error("LoadComments: %v", err) + if err = issues_model.IssueList(is).LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments: %v", err) return } for _, issue := range is { @@ -360,11 +360,11 @@ func UpdateIssueIndexer(issue *issues_model.Issue) { } // DeleteRepoIssueIndexer deletes repo's all issues indexes -func DeleteRepoIssueIndexer(repo *repo_model.Repository) { +func DeleteRepoIssueIndexer(ctx context.Context, repo *repo_model.Repository) { var ids []int64 - ids, err := issues_model.GetIssueIDsByRepoID(db.DefaultContext, repo.ID) + ids, err := issues_model.GetIssueIDsByRepoID(ctx, repo.ID) if err != nil { - log.Error("getIssueIDsByRepoID failed: %v", err) + log.Error("GetIssueIDsByRepoID failed: %v", err) return } diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index 44d115f3d72a1..d029405664be5 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -5,20 +5,18 @@ package action import ( + "context" "fmt" "path" "strings" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" - "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/util" ) @@ -34,18 +32,18 @@ func NewNotifier() base.Notifier { return &actionNotifier{} } -func (a *actionNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := issue.LoadPoster(); err != nil { +func (a *actionNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := issue.LoadPoster(ctx); err != nil { log.Error("issue.LoadPoster: %v", err) return } - if err := issue.LoadRepo(db.DefaultContext); err != nil { + if err := issue.LoadRepo(ctx); err != nil { log.Error("issue.LoadRepo: %v", err) return } repo := issue.Repo - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: issue.Poster.ID, ActUser: issue.Poster, OpType: activities_model.ActionCreateIssue, @@ -59,7 +57,7 @@ func (a *actionNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*u } // NotifyIssueChangeStatus notifies close or reopen issue to notifiers -func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { +func (a *actionNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { // Compose comment action, could be plain comment, close or reopen issue/pull request. // This object will be used to notify watchers in the end of function. act := &activities_model.Action{ @@ -86,13 +84,13 @@ func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *i } // Notify watchers for whatever action comes in, ignore if no action type. - if err := activities_model.NotifyWatchers(act); err != nil { + if err := activities_model.NotifyWatchers(ctx, act); err != nil { log.Error("NotifyWatchers: %v", err) } } // NotifyCreateIssueComment notifies comment on an issue to notifiers -func (a *actionNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (a *actionNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { act := &activities_model.Action{ @@ -122,26 +120,26 @@ func (a *actionNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *r } // Notify watchers for whatever action comes in, ignore if no action type. - if err := activities_model.NotifyWatchers(act); err != nil { + if err := activities_model.NotifyWatchers(ctx, act); err != nil { log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, mentions []*user_model.User) { - if err := pull.LoadIssue(); err != nil { +func (a *actionNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) { + if err := pull.LoadIssue(ctx); err != nil { log.Error("pull.LoadIssue: %v", err) return } - if err := pull.Issue.LoadRepo(db.DefaultContext); err != nil { + if err := pull.Issue.LoadRepo(ctx); err != nil { log.Error("pull.Issue.LoadRepo: %v", err) return } - if err := pull.Issue.LoadPoster(); err != nil { + if err := pull.Issue.LoadPoster(ctx); err != nil { log.Error("pull.Issue.LoadPoster: %v", err) return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: pull.Issue.Poster.ID, ActUser: pull.Issue.Poster, OpType: activities_model.ActionCreatePullRequest, @@ -154,8 +152,8 @@ func (a *actionNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, me } } -func (a *actionNotifier) NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionRenameRepo, @@ -168,8 +166,8 @@ func (a *actionNotifier) NotifyRenameRepository(doer *user_model.User, repo *rep } } -func (a *actionNotifier) NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionTransferRepo, @@ -182,8 +180,8 @@ func (a *actionNotifier) NotifyTransferRepository(doer *user_model.User, repo *r } } -func (a *actionNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionCreateRepo, @@ -195,8 +193,8 @@ func (a *actionNotifier) NotifyCreateRepository(doer, u *user_model.User, repo * } } -func (a *actionNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionCreateRepo, @@ -208,11 +206,8 @@ func (a *actionNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, re } } -func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("actionNotifier.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - - if err := review.LoadReviewer(); err != nil { +func (a *actionNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { + if err := review.LoadReviewer(ctx); err != nil { log.Error("LoadReviewer '%d/%d': %v", review.ID, review.ReviewerID, err) return } @@ -269,8 +264,8 @@ func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r } } -func (*actionNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (*actionNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionMergePullRequest, @@ -283,8 +278,8 @@ func (*actionNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer } } -func (*actionNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (*actionNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionAutoMergePullRequest, @@ -297,12 +292,12 @@ func (*actionNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, } } -func (*actionNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +func (*actionNotifier) NotifyPullRevieweDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { reviewerName := review.Reviewer.Name if len(review.OriginalAuthor) > 0 { reviewerName = review.OriginalAuthor } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionPullReviewDismissed, @@ -317,7 +312,7 @@ func (*actionNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *i } } -func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (a *actionNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { data, err := json.Marshal(commits) if err != nil { log.Error("Marshal: %v", err) @@ -336,7 +331,7 @@ func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_m opType = activities_model.ActionDeleteBranch } - if err = activities_model.NotifyWatchers(&activities_model.Action{ + if err = activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: pusher.ID, ActUser: pusher, OpType: opType, @@ -346,17 +341,17 @@ func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_m RefName: opts.RefFullName, IsPrivate: repo.IsPrivate, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (a *actionNotifier) NotifyCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { opType := activities_model.ActionCommitRepo if refType == "tag" { // has sent same action in `NotifyPushCommits`, so skip it. return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: opType, @@ -365,17 +360,17 @@ func (a *actionNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (a *actionNotifier) NotifyDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { opType := activities_model.ActionDeleteBranch if refType == "tag" { // has sent same action in `NotifyPushCommits`, so skip it. return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: opType, @@ -384,20 +379,20 @@ func (a *actionNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (a *actionNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { data, err := json.Marshal(commits) if err != nil { log.Error("json.Marshal: %v", err) return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: repo.OwnerID, - ActUser: repo.MustOwner(), + ActUser: repo.MustOwner(ctx), OpType: activities_model.ActionMirrorSyncPush, RepoID: repo.ID, Repo: repo, @@ -405,44 +400,44 @@ func (a *actionNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *re RefName: opts.RefFullName, Content: string(data), }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifySyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: repo.OwnerID, - ActUser: repo.MustOwner(), + ActUser: repo.MustOwner(ctx), OpType: activities_model.ActionMirrorSyncCreate, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifySyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: repo.OwnerID, - ActUser: repo.MustOwner(), + ActUser: repo.MustOwner(ctx), OpType: activities_model.ActionMirrorSyncDelete, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyNewRelease(rel *repo_model.Release) { - if err := rel.LoadAttributes(); err != nil { - log.Error("NotifyNewRelease: %v", err) +func (a *actionNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + if err := rel.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: rel.PublisherID, ActUser: rel.Publisher, OpType: activities_model.ActionPublishRelease, @@ -452,6 +447,6 @@ func (a *actionNotifier) NotifyNewRelease(rel *repo_model.Release) { Content: rel.Title, RefName: rel.TagName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } diff --git a/modules/notification/action/action_test.go b/modules/notification/action/action_test.go index 79a938d6cddc6..dc31b3189b5d6 100644 --- a/modules/notification/action/action_test.go +++ b/modules/notification/action/action_test.go @@ -10,6 +10,7 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -46,7 +47,7 @@ func TestRenameRepoAction(t *testing.T) { } unittest.AssertNotExistsBean(t, actionBean) - NewNotifier().NotifyRenameRepository(user, repo, oldRepoName) + NewNotifier().NotifyRenameRepository(db.DefaultContext, user, repo, oldRepoName) unittest.AssertExistsAndLoadBean(t, actionBean) unittest.CheckConsistencyFor(t, &activities_model.Action{}) diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index 9edab8213fab4..2f7deac88e230 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -5,6 +5,8 @@ package base import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -15,50 +17,50 @@ import ( // Notifier defines an interface to notify receiver type Notifier interface { Run() - NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) - NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) - NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) - NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) - NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) - NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) - NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) - NotifyIssueChangeStatus(*user_model.User, *issues_model.Issue, *issues_model.Comment, bool) - NotifyDeleteIssue(*user_model.User, *issues_model.Issue) - NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) - NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) - NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) - NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) - NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) - NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) - NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldRef string) - NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, + NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) + NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) + NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) + NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) + NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldRepoName string) + NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) + NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) + NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) + NotifyDeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) + NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) + NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) + NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) + NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) + NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) + NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) + NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) + NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label) - NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) - NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) - NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) - NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) - NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) - NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) - NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) - NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) - NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) - NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, + NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) + NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) + NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) + NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) + NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) + NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) + NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) + NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) + NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) + NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User) - NotifyUpdateComment(*user_model.User, *issues_model.Comment, string) - NotifyDeleteComment(*user_model.User, *issues_model.Comment) - NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) - NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) - NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) - NotifyNewRelease(rel *repo_model.Release) - NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) - NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) - NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) - NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) - NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) - NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) - NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) - NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) - NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) - NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) - NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) + NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) + NotifyDeleteComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment) + NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) + NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) + NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) + NotifyNewRelease(ctx context.Context, rel *repo_model.Release) + NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) + NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) + NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) + NotifyCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) + NotifyDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) + NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) + NotifySyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) + NotifySyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) + NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) + NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) + NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) } diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index f051fbc26f461..88e0c93de1923 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -5,6 +5,8 @@ package base import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -22,179 +24,179 @@ func (*NullNotifier) Run() { } // NotifyCreateIssueComment places a place holder function -func (*NullNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (*NullNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User) { } // NotifyNewIssue places a place holder function -func (*NullNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func (*NullNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { } // NotifyIssueChangeStatus places a place holder function -func (*NullNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { +func (*NullNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { } // NotifyDeleteIssue notify when some issue deleted -func (*NullNotifier) NotifyDeleteIssue(doer *user_model.User, issue *issues_model.Issue) { +func (*NullNotifier) NotifyDeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { } // NotifyNewPullRequest places a place holder function -func (*NullNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { +func (*NullNotifier) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { } // NotifyPullRequestReview places a place holder function -func (*NullNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { +func (*NullNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { } // NotifyPullRequestCodeComment places a place holder function -func (*NullNotifier) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { +func (*NullNotifier) NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { } // NotifyMergePullRequest places a place holder function -func (*NullNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (*NullNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { } // NotifyAutoMergePullRequest places a place holder function -func (*NullNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (*NullNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { } // NotifyPullRequestSynchronized places a place holder function -func (*NullNotifier) NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { +func (*NullNotifier) NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { } // NotifyPullRequestChangeTargetBranch places a place holder function -func (*NullNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { +func (*NullNotifier) NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { } // NotifyPullRequestPushCommits notifies when push commits to pull request's head branch -func (*NullNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { +func (*NullNotifier) NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { } -// NotifyPullRevieweDismiss notifies when a review was dismissed by repo admin -func (*NullNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +// NotifyPullReviewDismiss notifies when a review was dismissed by repo admin +func (*NullNotifier) NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { } // NotifyUpdateComment places a place holder function -func (*NullNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { +func (*NullNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { } // NotifyDeleteComment places a place holder function -func (*NullNotifier) NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) { +func (*NullNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment) { } // NotifyNewWikiPage places a place holder function -func (*NullNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (*NullNotifier) NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { } // NotifyEditWikiPage places a place holder function -func (*NullNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (*NullNotifier) NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { } // NotifyDeleteWikiPage places a place holder function -func (*NullNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) { +func (*NullNotifier) NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { } // NotifyNewRelease places a place holder function -func (*NullNotifier) NotifyNewRelease(rel *repo_model.Release) { +func (*NullNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { } // NotifyUpdateRelease places a place holder function -func (*NullNotifier) NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { +func (*NullNotifier) NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { } // NotifyDeleteRelease places a place holder function -func (*NullNotifier) NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { +func (*NullNotifier) NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { } // NotifyIssueChangeMilestone places a place holder function -func (*NullNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { +func (*NullNotifier) NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { } // NotifyIssueChangeContent places a place holder function -func (*NullNotifier) NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { +func (*NullNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { } // NotifyIssueChangeAssignee places a place holder function -func (*NullNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func (*NullNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { } // NotifyPullReviewRequest places a place holder function -func (*NullNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func (*NullNotifier) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { } // NotifyIssueClearLabels places a place holder function -func (*NullNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) { +func (*NullNotifier) NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { } // NotifyIssueChangeTitle places a place holder function -func (*NullNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func (*NullNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { } // NotifyIssueChangeRef places a place holder function -func (*NullNotifier) NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func (*NullNotifier) NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { } // NotifyIssueChangeLabels places a place holder function -func (*NullNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, +func (*NullNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label) { } // NotifyCreateRepository places a place holder function -func (*NullNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { } // NotifyDeleteRepository places a place holder function -func (*NullNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { } // NotifyForkRepository places a place holder function -func (*NullNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { +func (*NullNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { } // NotifyMigrateRepository places a place holder function -func (*NullNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { } // NotifyPushCommits notifies commits pushed to notifiers -func (*NullNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (*NullNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { } // NotifyCreateRef notifies branch or tag creation to notifiers -func (*NullNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (*NullNotifier) NotifyCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { } // NotifyDeleteRef notifies branch or tag deletion to notifiers -func (*NullNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (*NullNotifier) NotifyDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { } // NotifyRenameRepository places a place holder function -func (*NullNotifier) NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { +func (*NullNotifier) NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { } // NotifyTransferRepository places a place holder function -func (*NullNotifier) NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { +func (*NullNotifier) NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { } // NotifySyncPushCommits places a place holder function -func (*NullNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (*NullNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { } // NotifySyncCreateRef places a place holder function -func (*NullNotifier) NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (*NullNotifier) NotifySyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { } // NotifySyncDeleteRef places a place holder function -func (*NullNotifier) NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (*NullNotifier) NotifySyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { } // NotifyRepoPendingTransfer places a place holder function -func (*NullNotifier) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { } // NotifyPackageCreate places a place holder function -func (*NullNotifier) NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func (*NullNotifier) NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { } // NotifyPackageDelete places a place holder function -func (*NullNotifier) NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func (*NullNotifier) NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { } diff --git a/modules/notification/indexer/indexer.go b/modules/notification/indexer/indexer.go index fc9afdd4bcf9b..2bacd5dec02e8 100644 --- a/modules/notification/indexer/indexer.go +++ b/modules/notification/indexer/indexer.go @@ -5,6 +5,8 @@ package indexer import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -29,13 +31,13 @@ func NewNotifier() base.Notifier { return &indexerNotifier{} } -func (r *indexerNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (r *indexerNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { if comment.Type == issues_model.CommentTypeComment { if issue.Comments == nil { - if err := issue.LoadDiscussComments(); err != nil { - log.Error("LoadComments failed: %v", err) + if err := issue.LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments failed: %v", err) return } } else { @@ -46,15 +48,15 @@ func (r *indexerNotifier) NotifyCreateIssueComment(doer *user_model.User, repo * } } -func (r *indexerNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func (r *indexerNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { issue_indexer.UpdateIssueIndexer(issue) } -func (r *indexerNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { +func (r *indexerNotifier) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { issue_indexer.UpdateIssueIndexer(pr.Issue) } -func (r *indexerNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { +func (r *indexerNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { if c.Type == issues_model.CommentTypeComment { var found bool if c.Issue.Comments != nil { @@ -68,8 +70,8 @@ func (r *indexerNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m } if !found { - if err := c.Issue.LoadDiscussComments(); err != nil { - log.Error("LoadComments failed: %v", err) + if err := c.Issue.LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments failed: %v", err) return } } @@ -78,9 +80,9 @@ func (r *indexerNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m } } -func (r *indexerNotifier) NotifyDeleteComment(doer *user_model.User, comment *issues_model.Comment) { +func (r *indexerNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { if comment.Type == issues_model.CommentTypeComment { - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } @@ -97,8 +99,8 @@ func (r *indexerNotifier) NotifyDeleteComment(doer *user_model.User, comment *is } if !found { - if err := comment.Issue.LoadDiscussComments(); err != nil { - log.Error("LoadComments failed: %v", err) + if err := comment.Issue.LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments failed: %v", err) return } } @@ -107,15 +109,15 @@ func (r *indexerNotifier) NotifyDeleteComment(doer *user_model.User, comment *is } } -func (r *indexerNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { - issue_indexer.DeleteRepoIssueIndexer(repo) +func (r *indexerNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { + issue_indexer.DeleteRepoIssueIndexer(ctx, repo) if setting.Indexer.RepoIndexerEnabled { code_indexer.UpdateRepoIndexer(repo) } } -func (r *indexerNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { - issue_indexer.UpdateRepoIndexer(repo) +func (r *indexerNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + issue_indexer.UpdateRepoIndexer(ctx, repo) if setting.Indexer.RepoIndexerEnabled && !repo.IsEmpty { code_indexer.UpdateRepoIndexer(repo) } @@ -124,7 +126,7 @@ func (r *indexerNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo } } -func (r *indexerNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (r *indexerNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { if setting.Indexer.RepoIndexerEnabled && opts.RefFullName == git.BranchPrefix+repo.DefaultBranch { code_indexer.UpdateRepoIndexer(repo) } @@ -133,7 +135,7 @@ func (r *indexerNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_ } } -func (r *indexerNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (r *indexerNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { if setting.Indexer.RepoIndexerEnabled && opts.RefFullName == git.BranchPrefix+repo.DefaultBranch { code_indexer.UpdateRepoIndexer(repo) } @@ -142,14 +144,14 @@ func (r *indexerNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *r } } -func (r *indexerNotifier) NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { +func (r *indexerNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { issue_indexer.UpdateIssueIndexer(issue) } -func (r *indexerNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func (r *indexerNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { issue_indexer.UpdateIssueIndexer(issue) } -func (r *indexerNotifier) NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldRef string) { +func (r *indexerNotifier) NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) { issue_indexer.UpdateIssueIndexer(issue) } diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index 54f561839d0f4..123fa0e65aefb 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -5,16 +5,15 @@ package mail import ( + "context" "fmt" activities_model "code.gitea.io/gitea/models/activities" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" - "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/services/mailer" ) @@ -29,12 +28,9 @@ func NewNotifier() base.Notifier { return &mailNotifier{} } -func (m *mailNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (m *mailNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyCreateIssueComment Issue[%d] #%d in [%d]", issue.ID, issue.Index, issue.RepoID)) - defer finished() - var act activities_model.ActionType if comment.Type == issues_model.CommentTypeClose { act = activities_model.ActionCloseIssue @@ -53,13 +49,13 @@ func (m *mailNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *rep } } -func (m *mailNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := mailer.MailParticipants(issue, issue.Poster, activities_model.ActionCreateIssue, mentions); err != nil { +func (m *mailNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := mailer.MailParticipants(ctx, issue, issue.Poster, activities_model.ActionCreateIssue, mentions); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { +func (m *mailNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { var actionType activities_model.ActionType if issue.IsPull { if isClosed { @@ -75,33 +71,30 @@ func (m *mailNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *iss } } - if err := mailer.MailParticipants(issue, doer, actionType, nil); err != nil { + if err := mailer.MailParticipants(ctx, issue, doer, actionType, nil); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { - if err := issue.LoadPullRequest(); err != nil { +func (m *mailNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + if err := issue.LoadPullRequest(ctx); err != nil { log.Error("issue.LoadPullRequest: %v", err) return } if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issue.PullRequest.IsWorkInProgress() { - if err := mailer.MailParticipants(issue, doer, activities_model.ActionPullRequestReadyForReview, nil); err != nil { + if err := mailer.MailParticipants(ctx, issue, doer, activities_model.ActionPullRequestReadyForReview, nil); err != nil { log.Error("MailParticipants: %v", err) } } } -func (m *mailNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { - if err := mailer.MailParticipants(pr.Issue, pr.Issue.Poster, activities_model.ActionCreatePullRequest, mentions); err != nil { +func (m *mailNotifier) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { + if err := mailer.MailParticipants(ctx, pr.Issue, pr.Issue.Poster, activities_model.ActionCreatePullRequest, mentions); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *mailNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { var act activities_model.ActionType if comment.Type == issues_model.CommentTypeClose { act = activities_model.ActionCloseIssue @@ -115,60 +108,54 @@ func (m *mailNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r * } } -func (m *mailNotifier) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestCodeComment Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *mailNotifier) NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { if err := mailer.MailMentionsComment(ctx, pr, comment, mentions); err != nil { log.Error("MailMentionsComment: %v", err) } } -func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func (m *mailNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { // mail only sent to added assignees and not self-assignee if !removed && doer.ID != assignee.ID && assignee.EmailNotifications() != user_model.EmailNotificationsDisabled { ct := fmt.Sprintf("Assigned #%d.", issue.Index) - if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{assignee}); err != nil { + if err := mailer.SendIssueAssignedMail(ctx, issue, doer, ct, comment, []*user_model.User{assignee}); err != nil { log.Error("Error in SendIssueAssignedMail for issue[%d] to assignee[%d]: %v", issue.ID, assignee.ID, err) } } } -func (m *mailNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func (m *mailNotifier) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { if isRequest && doer.ID != reviewer.ID && reviewer.EmailNotifications() != user_model.EmailNotificationsDisabled { ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL()) - if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil { + if err := mailer.SendIssueAssignedMail(ctx, issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil { log.Error("Error in SendIssueAssignedMail for issue[%d] to reviewer[%d]: %v", issue.ID, reviewer.ID, err) } } } -func (m *mailNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := pr.LoadIssue(); err != nil { - log.Error("pr.LoadIssue: %v", err) +func (m *mailNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - if err := mailer.MailParticipants(pr.Issue, doer, activities_model.ActionMergePullRequest, nil); err != nil { + if err := mailer.MailParticipants(ctx, pr.Issue, doer, activities_model.ActionMergePullRequest, nil); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := pr.LoadIssue(); err != nil { +func (m *mailNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { log.Error("pr.LoadIssue: %v", err) return } - if err := mailer.MailParticipants(pr.Issue, doer, activities_model.ActionAutoMergePullRequest, nil); err != nil { + if err := mailer.MailParticipants(ctx, pr.Issue, doer, activities_model.ActionAutoMergePullRequest, nil); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestPushCommits Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *mailNotifier) NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { var err error - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { log.Error("comment.LoadIssue: %v", err) return } @@ -176,35 +163,29 @@ func (m *mailNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *i log.Error("comment.Issue.LoadRepo: %v", err) return } - if err = comment.Issue.LoadPullRequest(); err != nil { + if err = comment.Issue.LoadPullRequest(ctx); err != nil { log.Error("comment.Issue.LoadPullRequest: %v", err) return } - if err = comment.Issue.PullRequest.LoadBaseRepoCtx(ctx); err != nil { + if err = comment.Issue.PullRequest.LoadBaseRepo(ctx); err != nil { log.Error("comment.Issue.PullRequest.LoadBaseRepo: %v", err) return } if err := comment.LoadPushCommits(ctx); err != nil { log.Error("comment.LoadPushCommits: %v", err) } - m.NotifyCreateIssueComment(doer, comment.Issue.Repo, comment.Issue, comment, nil) + m.NotifyCreateIssueComment(ctx, doer, comment.Issue.Repo, comment.Issue, comment, nil) } -func (m *mailNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRevieweDismiss Review[%d] in Issue[%d]", review.ID, review.IssueID)) - defer finished() - +func (m *mailNotifier) NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { if err := mailer.MailParticipantsComment(ctx, comment, activities_model.ActionPullReviewDismissed, review.Issue, nil); err != nil { log.Error("MailParticipantsComment: %v", err) } } -func (m *mailNotifier) NotifyNewRelease(rel *repo_model.Release) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyNewRelease rel[%d]%s in [%d]", rel.ID, rel.Title, rel.RepoID)) - defer finished() - - if err := rel.LoadAttributes(); err != nil { - log.Error("NotifyNewRelease: %v", err) +func (m *mailNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + if err := rel.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) return } @@ -215,8 +196,8 @@ func (m *mailNotifier) NotifyNewRelease(rel *repo_model.Release) { mailer.MailNewRelease(ctx, rel) } -func (m *mailNotifier) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { - if err := mailer.SendRepoTransferNotifyMail(doer, newOwner, repo); err != nil { - log.Error("NotifyRepoPendingTransfer: %v", err) +func (m *mailNotifier) NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { + if err := mailer.SendRepoTransferNotifyMail(ctx, doer, newOwner, repo); err != nil { + log.Error("SendRepoTransferNotifyMail: %v", err) } } diff --git a/modules/notification/mirror/mirror.go b/modules/notification/mirror/mirror.go index 646b09a4ab6e6..159c44ee6cd06 100644 --- a/modules/notification/mirror/mirror.go +++ b/modules/notification/mirror/mirror.go @@ -5,6 +5,8 @@ package mirror import ( + "context" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -24,16 +26,16 @@ func NewNotifier() base.Notifier { return &mirrorNotifier{} } -func (m *mirrorNotifier) NotifyPushCommits(_ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { - syncPushMirrorWithSyncOnCommit(repo.ID) +func (m *mirrorNotifier) NotifyPushCommits(ctx context.Context, _ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { + syncPushMirrorWithSyncOnCommit(ctx, repo.ID) } -func (m *mirrorNotifier) NotifySyncPushCommits(_ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { - syncPushMirrorWithSyncOnCommit(repo.ID) +func (m *mirrorNotifier) NotifySyncPushCommits(ctx context.Context, _ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { + syncPushMirrorWithSyncOnCommit(ctx, repo.ID) } -func syncPushMirrorWithSyncOnCommit(repoID int64) { - pushMirrors, err := repo_model.GetPushMirrorsSyncedOnCommit(repoID) +func syncPushMirrorWithSyncOnCommit(ctx context.Context, repoID int64) { + pushMirrors, err := repo_model.GetPushMirrorsSyncedOnCommit(ctx, repoID) if err != nil { log.Error("repo_model.GetPushMirrorsSyncedOnCommit failed: %v", err) return diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 7bdc0a04c4969..a117a60815b47 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -5,6 +5,8 @@ package notification import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -41,313 +43,313 @@ func NewContext() { } // NotifyNewWikiPage notifies creating new wiki pages to notifiers -func NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { for _, notifier := range notifiers { - notifier.NotifyNewWikiPage(doer, repo, page, comment) + notifier.NotifyNewWikiPage(ctx, doer, repo, page, comment) } } // NotifyEditWikiPage notifies editing or renaming wiki pages to notifiers -func NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { for _, notifier := range notifiers { - notifier.NotifyEditWikiPage(doer, repo, page, comment) + notifier.NotifyEditWikiPage(ctx, doer, repo, page, comment) } } // NotifyDeleteWikiPage notifies deleting wiki pages to notifiers -func NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) { +func NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { for _, notifier := range notifiers { - notifier.NotifyDeleteWikiPage(doer, repo, page) + notifier.NotifyDeleteWikiPage(ctx, doer, repo, page) } } // NotifyCreateIssueComment notifies issue comment related message to notifiers -func NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { for _, notifier := range notifiers { - notifier.NotifyCreateIssueComment(doer, repo, issue, comment, mentions) + notifier.NotifyCreateIssueComment(ctx, doer, repo, issue, comment, mentions) } } // NotifyNewIssue notifies new issue to notifiers -func NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyNewIssue(issue, mentions) + notifier.NotifyNewIssue(ctx, issue, mentions) } } // NotifyIssueChangeStatus notifies close or reopen issue to notifiers -func NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { +func NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeStatus(doer, issue, actionComment, closeOrReopen) + notifier.NotifyIssueChangeStatus(ctx, doer, issue, actionComment, closeOrReopen) } } // NotifyDeleteIssue notify when some issue deleted -func NotifyDeleteIssue(doer *user_model.User, issue *issues_model.Issue) { +func NotifyDeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { for _, notifier := range notifiers { - notifier.NotifyDeleteIssue(doer, issue) + notifier.NotifyDeleteIssue(ctx, doer, issue) } } // NotifyMergePullRequest notifies merge pull request to notifiers -func NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { for _, notifier := range notifiers { - notifier.NotifyMergePullRequest(pr, doer) + notifier.NotifyMergePullRequest(ctx, doer, pr) } } // NotifyAutoMergePullRequest notifies merge pull request to notifiers -func NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { for _, notifier := range notifiers { - notifier.NotifyAutoMergePullRequest(pr, doer) + notifier.NotifyAutoMergePullRequest(ctx, doer, pr) } } // NotifyNewPullRequest notifies new pull request to notifiers -func NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { +func NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyNewPullRequest(pr, mentions) + notifier.NotifyNewPullRequest(ctx, pr, mentions) } } // NotifyPullRequestSynchronized notifies Synchronized pull request -func NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { +func NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { for _, notifier := range notifiers { - notifier.NotifyPullRequestSynchronized(doer, pr) + notifier.NotifyPullRequestSynchronized(ctx, doer, pr) } } // NotifyPullRequestReview notifies new pull request review -func NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { +func NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyPullRequestReview(pr, review, comment, mentions) + notifier.NotifyPullRequestReview(ctx, pr, review, comment, mentions) } } // NotifyPullRequestCodeComment notifies new pull request code comment -func NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { +func NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyPullRequestCodeComment(pr, comment, mentions) + notifier.NotifyPullRequestCodeComment(ctx, pr, comment, mentions) } } // NotifyPullRequestChangeTargetBranch notifies when a pull request's target branch was changed -func NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { +func NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { for _, notifier := range notifiers { - notifier.NotifyPullRequestChangeTargetBranch(doer, pr, oldBranch) + notifier.NotifyPullRequestChangeTargetBranch(ctx, doer, pr, oldBranch) } } // NotifyPullRequestPushCommits notifies when push commits to pull request's head branch -func NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { +func NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyPullRequestPushCommits(doer, pr, comment) + notifier.NotifyPullRequestPushCommits(ctx, doer, pr, comment) } } -// NotifyPullRevieweDismiss notifies when a review was dismissed by repo admin -func NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +// NotifyPullReviewDismiss notifies when a review was dismissed by repo admin +func NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyPullRevieweDismiss(doer, review, comment) + notifier.NotifyPullReviewDismiss(ctx, doer, review, comment) } } // NotifyUpdateComment notifies update comment to notifiers -func NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { +func NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { for _, notifier := range notifiers { - notifier.NotifyUpdateComment(doer, c, oldContent) + notifier.NotifyUpdateComment(ctx, doer, c, oldContent) } } // NotifyDeleteComment notifies delete comment to notifiers -func NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) { +func NotifyDeleteComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyDeleteComment(doer, c) + notifier.NotifyDeleteComment(ctx, doer, c) } } // NotifyNewRelease notifies new release to notifiers -func NotifyNewRelease(rel *repo_model.Release) { +func NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { for _, notifier := range notifiers { - notifier.NotifyNewRelease(rel) + notifier.NotifyNewRelease(ctx, rel) } } // NotifyUpdateRelease notifies update release to notifiers -func NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { +func NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { for _, notifier := range notifiers { - notifier.NotifyUpdateRelease(doer, rel) + notifier.NotifyUpdateRelease(ctx, doer, rel) } } // NotifyDeleteRelease notifies delete release to notifiers -func NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { +func NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { for _, notifier := range notifiers { - notifier.NotifyDeleteRelease(doer, rel) + notifier.NotifyDeleteRelease(ctx, doer, rel) } } // NotifyIssueChangeMilestone notifies change milestone to notifiers -func NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { +func NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeMilestone(doer, issue, oldMilestoneID) + notifier.NotifyIssueChangeMilestone(ctx, doer, issue, oldMilestoneID) } } // NotifyIssueChangeContent notifies change content to notifiers -func NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { +func NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeContent(doer, issue, oldContent) + notifier.NotifyIssueChangeContent(ctx, doer, issue, oldContent) } } // NotifyIssueChangeAssignee notifies change content to notifiers -func NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeAssignee(doer, issue, assignee, removed, comment) + notifier.NotifyIssueChangeAssignee(ctx, doer, issue, assignee, removed, comment) } } // NotifyPullReviewRequest notifies Request Review change -func NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyPullReviewRequest(doer, issue, reviewer, isRequest, comment) + notifier.NotifyPullReviewRequest(ctx, doer, issue, reviewer, isRequest, comment) } } // NotifyIssueClearLabels notifies clear labels to notifiers -func NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) { +func NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { for _, notifier := range notifiers { - notifier.NotifyIssueClearLabels(doer, issue) + notifier.NotifyIssueClearLabels(ctx, doer, issue) } } // NotifyIssueChangeTitle notifies change title to notifiers -func NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeTitle(doer, issue, oldTitle) + notifier.NotifyIssueChangeTitle(ctx, doer, issue, oldTitle) } } // NotifyIssueChangeRef notifies change reference to notifiers -func NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldRef string) { +func NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeRef(doer, issue, oldRef) + notifier.NotifyIssueChangeRef(ctx, doer, issue, oldRef) } } // NotifyIssueChangeLabels notifies change labels to notifiers -func NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, +func NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label, ) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeLabels(doer, issue, addedLabels, removedLabels) + notifier.NotifyIssueChangeLabels(ctx, doer, issue, addedLabels, removedLabels) } } // NotifyCreateRepository notifies create repository to notifiers -func NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyCreateRepository(doer, u, repo) + notifier.NotifyCreateRepository(ctx, doer, u, repo) } } // NotifyMigrateRepository notifies create repository to notifiers -func NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyMigrateRepository(doer, u, repo) + notifier.NotifyMigrateRepository(ctx, doer, u, repo) } } // NotifyTransferRepository notifies create repository to notifiers -func NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, newOwnerName string) { +func NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, newOwnerName string) { for _, notifier := range notifiers { - notifier.NotifyTransferRepository(doer, repo, newOwnerName) + notifier.NotifyTransferRepository(ctx, doer, repo, newOwnerName) } } // NotifyDeleteRepository notifies delete repository to notifiers -func NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { +func NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyDeleteRepository(doer, repo) + notifier.NotifyDeleteRepository(ctx, doer, repo) } } // NotifyForkRepository notifies fork repository to notifiers -func NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { +func NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyForkRepository(doer, oldRepo, repo) + notifier.NotifyForkRepository(ctx, doer, oldRepo, repo) } } // NotifyRenameRepository notifies repository renamed -func NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldName string) { +func NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldName string) { for _, notifier := range notifiers { - notifier.NotifyRenameRepository(doer, repo, oldName) + notifier.NotifyRenameRepository(ctx, doer, repo, oldName) } } // NotifyPushCommits notifies commits pushed to notifiers -func NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { for _, notifier := range notifiers { - notifier.NotifyPushCommits(pusher, repo, opts, commits) + notifier.NotifyPushCommits(ctx, pusher, repo, opts, commits) } } // NotifyCreateRef notifies branch or tag creation to notifiers -func NotifyCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func NotifyCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { for _, notifier := range notifiers { - notifier.NotifyCreateRef(pusher, repo, refType, refFullName, refID) + notifier.NotifyCreateRef(ctx, pusher, repo, refType, refFullName, refID) } } // NotifyDeleteRef notifies branch or tag deletion to notifiers -func NotifyDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func NotifyDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { for _, notifier := range notifiers { - notifier.NotifyDeleteRef(pusher, repo, refType, refFullName) + notifier.NotifyDeleteRef(ctx, pusher, repo, refType, refFullName) } } // NotifySyncPushCommits notifies commits pushed to notifiers -func NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { for _, notifier := range notifiers { - notifier.NotifySyncPushCommits(pusher, repo, opts, commits) + notifier.NotifySyncPushCommits(ctx, pusher, repo, opts, commits) } } // NotifySyncCreateRef notifies branch or tag creation to notifiers -func NotifySyncCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func NotifySyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { for _, notifier := range notifiers { - notifier.NotifySyncCreateRef(pusher, repo, refType, refFullName, refID) + notifier.NotifySyncCreateRef(ctx, pusher, repo, refType, refFullName, refID) } } // NotifySyncDeleteRef notifies branch or tag deletion to notifiers -func NotifySyncDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func NotifySyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { for _, notifier := range notifiers { - notifier.NotifySyncDeleteRef(pusher, repo, refType, refFullName) + notifier.NotifySyncDeleteRef(ctx, pusher, repo, refType, refFullName) } } // NotifyRepoPendingTransfer notifies creation of pending transfer to notifiers -func NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { +func NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyRepoPendingTransfer(doer, newOwner, repo) + notifier.NotifyRepoPendingTransfer(ctx, doer, newOwner, repo) } } // NotifyPackageCreate notifies creation of a package to notifiers -func NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { for _, notifier := range notifiers { - notifier.NotifyPackageCreate(doer, pd) + notifier.NotifyPackageCreate(ctx, doer, pd) } } // NotifyPackageDelete notifies deletion of a package to notifiers -func NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { for _, notifier := range notifiers { - notifier.NotifyPackageDelete(doer, pd) + notifier.NotifyPackageDelete(ctx, doer, pd) } } diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index 0e2b3e67c7f6e..a38289c9768d3 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -5,6 +5,8 @@ package ui import ( + "context" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" @@ -54,7 +56,7 @@ func (ns *notificationService) Run() { graceful.GetManager().RunWithShutdownFns(ns.issueQueue.Run) } -func (ns *notificationService) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (ns *notificationService) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { opts := issueNotificationOpts{ @@ -78,7 +80,7 @@ func (ns *notificationService) NotifyCreateIssueComment(doer *user_model.User, r } } -func (ns *notificationService) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func (ns *notificationService) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: issue.ID, NotificationAuthorID: issue.Poster.ID, @@ -92,15 +94,15 @@ func (ns *notificationService) NotifyNewIssue(issue *issues_model.Issue, mention } } -func (ns *notificationService) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { +func (ns *notificationService) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: issue.ID, NotificationAuthorID: doer.ID, }) } -func (ns *notificationService) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { - if err := issue.LoadPullRequest(); err != nil { +func (ns *notificationService) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + if err := issue.LoadPullRequest(ctx); err != nil { log.Error("issue.LoadPullRequest: %v", err) return } @@ -112,24 +114,24 @@ func (ns *notificationService) NotifyIssueChangeTitle(doer *user_model.User, iss } } -func (ns *notificationService) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (ns *notificationService) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: pr.Issue.ID, NotificationAuthorID: doer.ID, }) } -func (ns *notificationService) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - ns.NotifyMergePullRequest(pr, doer) +func (ns *notificationService) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + ns.NotifyMergePullRequest(ctx, doer, pr) } -func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { - if err := pr.LoadIssue(); err != nil { +func (ns *notificationService) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { + if err := pr.LoadIssue(ctx); err != nil { log.Error("Unable to load issue: %d for pr: %d: Error: %v", pr.IssueID, pr.ID, err) return } toNotify := make(container.Set[int64], 32) - repoWatchers, err := repo_model.GetRepoWatchersIDs(db.DefaultContext, pr.Issue.RepoID) + repoWatchers, err := repo_model.GetRepoWatchersIDs(ctx, pr.Issue.RepoID) if err != nil { log.Error("GetRepoWatchersIDs: %v", err) return @@ -137,7 +139,7 @@ func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest for _, id := range repoWatchers { toNotify.Add(id) } - issueParticipants, err := issues_model.GetParticipantsIDsByIssueID(pr.IssueID) + issueParticipants, err := issues_model.GetParticipantsIDsByIssueID(ctx, pr.IssueID) if err != nil { log.Error("GetParticipantsIDsByIssueID: %v", err) return @@ -158,7 +160,7 @@ func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest } } -func (ns *notificationService) NotifyPullRequestReview(pr *issues_model.PullRequest, r *issues_model.Review, c *issues_model.Comment, mentions []*user_model.User) { +func (ns *notificationService) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, r *issues_model.Review, c *issues_model.Comment, mentions []*user_model.User) { opts := issueNotificationOpts{ IssueID: pr.Issue.ID, NotificationAuthorID: r.Reviewer.ID, @@ -180,7 +182,7 @@ func (ns *notificationService) NotifyPullRequestReview(pr *issues_model.PullRequ } } -func (ns *notificationService) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, c *issues_model.Comment, mentions []*user_model.User) { +func (ns *notificationService) NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, c *issues_model.Comment, mentions []*user_model.User) { for _, mention := range mentions { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: pr.Issue.ID, @@ -191,7 +193,7 @@ func (ns *notificationService) NotifyPullRequestCodeComment(pr *issues_model.Pul } } -func (ns *notificationService) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { +func (ns *notificationService) NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { opts := issueNotificationOpts{ IssueID: pr.IssueID, NotificationAuthorID: doer.ID, @@ -200,7 +202,7 @@ func (ns *notificationService) NotifyPullRequestPushCommits(doer *user_model.Use _ = ns.issueQueue.Push(opts) } -func (ns *notificationService) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +func (ns *notificationService) NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { opts := issueNotificationOpts{ IssueID: review.IssueID, NotificationAuthorID: doer.ID, @@ -209,7 +211,7 @@ func (ns *notificationService) NotifyPullRevieweDismiss(doer *user_model.User, r _ = ns.issueQueue.Push(opts) } -func (ns *notificationService) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func (ns *notificationService) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { if !removed && doer.ID != assignee.ID { opts := issueNotificationOpts{ IssueID: issue.ID, @@ -225,7 +227,7 @@ func (ns *notificationService) NotifyIssueChangeAssignee(doer *user_model.User, } } -func (ns *notificationService) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func (ns *notificationService) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { if isRequest { opts := issueNotificationOpts{ IssueID: issue.ID, @@ -241,8 +243,11 @@ func (ns *notificationService) NotifyPullReviewRequest(doer *user_model.User, is } } -func (ns *notificationService) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { - if err := activities_model.CreateRepoTransferNotification(doer, newOwner, repo); err != nil { - log.Error("NotifyRepoPendingTransfer: %v", err) +func (ns *notificationService) NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { + err := db.AutoTx(ctx, func(ctx context.Context) error { + return activities_model.CreateRepoTransferNotification(ctx, doer, newOwner, repo) + }) + if err != nil { + log.Error("CreateRepoTransferNotification: %v", err) } } diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index c591e1e34dbcd..37ce7661f220c 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -5,9 +5,8 @@ package webhook import ( - "fmt" + "context" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/perm" @@ -18,10 +17,8 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" - "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -39,12 +36,9 @@ func NewNotifier() base.Notifier { return &webhookNotifier{} } -func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueClearLabels User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - if err := issue.LoadPoster(); err != nil { - log.Error("loadPoster: %v", err) +func (m *webhookNotifier) NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { + if err := issue.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) return } @@ -53,10 +47,10 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i return } - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest: %v", err) return } @@ -72,7 +66,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueLabel, &api.IssuePayload{ Action: api.HookIssueLabelCleared, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -82,12 +76,12 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i } } -func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { - oldMode, _ := access_model.AccessLevel(doer, oldRepo) - mode, _ := access_model.AccessLevel(doer, repo) +func (m *webhookNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { + oldMode, _ := access_model.AccessLevel(ctx, doer, oldRepo) + mode, _ := access_model.AccessLevel(ctx, doer, repo) // forked webhook - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: oldRepo}, webhook.HookEventFork, &api.ForkPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: oldRepo}, webhook.HookEventFork, &api.ForkPayload{ Forkee: convert.ToRepo(oldRepo, oldMode), Repo: convert.ToRepo(repo, mode), Sender: convert.ToUser(doer, nil), @@ -95,11 +89,11 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err) } - u := repo.MustOwner() + u := repo.MustOwner(ctx) // Add to hook queue for created repo after session commit. if u.IsOrganization() { - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -110,9 +104,9 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r } } -func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (m *webhookNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { // Add to hook queue for created repo after session commit. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -122,22 +116,20 @@ func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo } } -func (m *webhookNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { - u := repo.MustOwner() - - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ +func (m *webhookNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoDeleted, Repository: convert.ToRepo(repo, perm.AccessModeOwner), - Organization: convert.ToUser(u, nil), + Organization: convert.ToUser(repo.MustOwner(ctx), nil), Sender: convert.ToUser(doer, nil), }); err != nil { log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) } } -func (m *webhookNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (m *webhookNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { // Add to hook queue for created repo after session commit. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -147,14 +139,11 @@ func (m *webhookNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo } } -func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeAssignee User: %s[%d] Issue[%d] #%d in [%d] Assignee %s[%d] removed: %t", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID, assignee.Name, assignee.ID, removed)) - defer finished() - +func (m *webhookNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { if issue.IsPull { - mode, _ := access_model.AccessLevelUnit(doer, issue.Repo, unit.TypePullRequests) + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypePullRequests) - if err := issue.LoadPullRequest(); err != nil { + if err := issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest failed: %v", err) return } @@ -176,10 +165,10 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue return } } else { - mode, _ := access_model.AccessLevelUnit(doer, issue.Repo, unit.TypeIssues) + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypeIssues) apiIssue := &api.IssuePayload{ Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), } @@ -196,14 +185,11 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue } } -func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeTitle User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) +func (m *webhookNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest failed: %v", err) return } @@ -229,7 +215,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *i From: oldTitle, }, }, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -240,14 +226,11 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *i } } -func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeStatus User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) +func (m *webhookNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest: %v", err) return } @@ -267,7 +250,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue * } else { apiIssue := &api.IssuePayload{ Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), } @@ -283,21 +266,21 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue * } } -func (m *webhookNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := issue.LoadRepo(db.DefaultContext); err != nil { +func (m *webhookNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := issue.LoadRepo(ctx); err != nil { log.Error("issue.LoadRepo: %v", err) return } - if err := issue.LoadPoster(); err != nil { + if err := issue.LoadPoster(ctx); err != nil { log.Error("issue.LoadPoster: %v", err) return } - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{ + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{ Action: api.HookIssueOpened, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(issue.Poster, nil), }); err != nil { @@ -305,11 +288,8 @@ func (m *webhookNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []* } } -func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyNewPullRequest Pull[%d] #%d in [%d]", pull.ID, pull.Index, pull.BaseRepoID)) - defer finished() - - if err := pull.LoadIssue(); err != nil { +func (m *webhookNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) { + if err := pull.LoadIssue(ctx); err != nil { log.Error("pull.LoadIssue: %v", err) return } @@ -317,12 +297,12 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, m log.Error("pull.Issue.LoadRepo: %v", err) return } - if err := pull.Issue.LoadPoster(); err != nil { + if err := pull.Issue.LoadPoster(ctx); err != nil { log.Error("pull.Issue.LoadPoster: %v", err) return } - mode, _ := access_model.AccessLevel(pull.Issue.Poster, pull.Issue.Repo) + mode, _ := access_model.AccessLevel(ctx, pull.Issue.Poster, pull.Issue.Repo) if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pull.Issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueOpened, Index: pull.Issue.Index, @@ -334,11 +314,8 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, m } } -func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeContent User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) +func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { issue.PullRequest.Issue = issue @@ -363,7 +340,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue From: oldContent, }, }, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -373,17 +350,17 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue } } -func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { - if err := c.LoadPoster(); err != nil { +func (m *webhookNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { + if err := c.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return } - if err := c.LoadIssue(); err != nil { + if err := c.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } - if err := c.Issue.LoadAttributes(db.DefaultContext); err != nil { + if err := c.Issue.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } @@ -395,10 +372,10 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m eventType = webhook.HookEventIssueComment } - mode, _ := access_model.AccessLevel(doer, c.Issue.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ + mode, _ := access_model.AccessLevel(ctx, doer, c.Issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentEdited, - Issue: convert.ToAPIIssue(c.Issue), + Issue: convert.ToAPIIssue(ctx, c.Issue), Comment: convert.ToComment(c), Changes: &api.ChangesPayload{ Body: &api.ChangesFromPayload{ @@ -413,7 +390,7 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m } } -func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (m *webhookNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { var eventType webhook.HookEventType @@ -423,10 +400,10 @@ func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo * eventType = webhook.HookEventIssueComment } - mode, _ := access_model.AccessLevel(doer, repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ + mode, _ := access_model.AccessLevel(ctx, doer, repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Comment: convert.ToComment(comment), Repository: convert.ToRepo(repo, mode), Sender: convert.ToUser(doer, nil), @@ -436,19 +413,19 @@ func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo * } } -func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *issues_model.Comment) { +func (m *webhookNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { var err error - if err = comment.LoadPoster(); err != nil { + if err = comment.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return } - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } - if err = comment.Issue.LoadAttributes(db.DefaultContext); err != nil { + if err = comment.Issue.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } @@ -460,10 +437,10 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is eventType = webhook.HookEventIssueComment } - mode, _ := access_model.AccessLevel(doer, comment.Issue.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ + mode, _ := access_model.AccessLevel(ctx, doer, comment.Issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentDeleted, - Issue: convert.ToAPIIssue(comment.Issue), + Issue: convert.ToAPIIssue(ctx, comment.Issue), Comment: convert.ToComment(comment), Repository: convert.ToRepo(comment.Issue.Repo, mode), Sender: convert.ToUser(doer, nil), @@ -473,9 +450,9 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is } } -func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (m *webhookNotifier) NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { // Add to hook queue for created wiki page. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ Action: api.HookWikiCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Sender: convert.ToUser(doer, nil), @@ -486,9 +463,9 @@ func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_mo } } -func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (m *webhookNotifier) NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { // Add to hook queue for edit wiki page. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ Action: api.HookWikiEdited, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Sender: convert.ToUser(doer, nil), @@ -499,9 +476,9 @@ func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_m } } -func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) { +func (m *webhookNotifier) NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { // Add to hook queue for edit wiki page. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ Action: api.HookWikiDeleted, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Sender: convert.ToUser(doer, nil), @@ -511,12 +488,9 @@ func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo } } -func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, +func (m *webhookNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label, ) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeLabels User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - var err error if err = issue.LoadRepo(ctx); err != nil { @@ -524,18 +498,18 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * return } - if err = issue.LoadPoster(); err != nil { + if err = issue.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return } - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("loadPullRequest: %v", err) return } - if err = issue.PullRequest.LoadIssue(); err != nil { + if err = issue.PullRequest.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } @@ -550,7 +524,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueLabel, &api.IssuePayload{ Action: api.HookIssueLabelUpdated, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -560,10 +534,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * } } -func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeMilestone User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - +func (m *webhookNotifier) NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { var hookAction api.HookIssueAction var err error if issue.MilestoneID > 0 { @@ -572,14 +543,14 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu hookAction = api.HookIssueDemilestoned } - if err = issue.LoadAttributes(db.DefaultContext); err != nil { + if err = issue.LoadAttributes(ctx); err != nil { log.Error("issue.LoadAttributes failed: %v", err) return } - mode, _ := access_model.AccessLevel(doer, issue.Repo) + mode, _ := access_model.AccessLevel(ctx, doer, issue.Repo) if issue.IsPull { - err = issue.PullRequest.LoadIssue() + err = issue.PullRequest.LoadIssue(ctx) if err != nil { log.Error("LoadIssue: %v", err) return @@ -595,7 +566,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueMilestone, &api.IssuePayload{ Action: hookAction, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -605,10 +576,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu } } -func (m *webhookNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPushCommits User: %s[%d] in %s[%d]", pusher.Name, pusher.ID, repo.FullName(), repo.ID)) - defer finished() - +func (m *webhookNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { apiPusher := convert.ToUser(pusher, nil) apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) if err != nil { @@ -632,23 +600,20 @@ func (m *webhookNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_ } } -func (m *webhookNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (m *webhookNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { // just redirect to the NotifyMergePullRequest - m.NotifyMergePullRequest(pr, doer) + m.NotifyMergePullRequest(ctx, doer, pr) } -func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyMergePullRequest Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (*webhookNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { // Reload pull request information. - if err := pr.LoadAttributes(); err != nil { + if err := pr.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } - if err := pr.LoadIssue(); err != nil { - log.Error("LoadAttributes: %v", err) + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } @@ -657,7 +622,7 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doe return } - mode, err := access_model.AccessLevel(doer, pr.Issue.Repo) + mode, err := access_model.AccessLevel(ctx, doer, pr.Issue.Repo) if err != nil { log.Error("models.AccessLevel: %v", err) return @@ -672,29 +637,21 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doe Action: api.HookIssueClosed, } - err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pr.Issue.Repo}, webhook.HookEventPullRequest, apiPullRequest) - if err != nil { + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pr.Issue.Repo}, webhook.HookEventPullRequest, apiPullRequest); err != nil { log.Error("PrepareWebhooks: %v", err) } } -func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPullRequestChangeTargetBranch Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - - issue := pr.Issue - if !issue.IsPull { +func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - var err error - if err = issue.LoadPullRequest(); err != nil { - log.Error("LoadPullRequest failed: %v", err) - return - } - issue.PullRequest.Issue = issue - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) - err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{ + issue := pr.Issue + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueEdited, Index: issue.Index, Changes: &api.ChangesPayload{ @@ -702,20 +659,15 @@ func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.U From: oldBranch, }, }, - PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), - }) - - if err != nil { - log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + }); err != nil { + log.Error("PrepareWebhooks [pr: %d]: %v", pr.ID, err) } } -func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *webhookNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { var reviewHookType webhook.HookEventType switch review.Type { @@ -731,12 +683,12 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, return } - if err := pr.LoadIssue(); err != nil { - log.Error("pr.LoadIssue: %v", err) + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - mode, err := access_model.AccessLevel(review.Issue.Poster, review.Issue.Repo) + mode, err := access_model.AccessLevel(ctx, review.Issue.Poster, review.Issue.Repo) if err != nil { log.Error("models.AccessLevel: %v", err) return @@ -756,12 +708,12 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, } } -func (m *webhookNotifier) NotifyCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (m *webhookNotifier) NotifyCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { apiPusher := convert.ToUser(pusher, nil) apiRepo := convert.ToRepo(repo, perm.AccessModeNone) refName := git.RefEndName(refFullName) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventCreate, &api.CreatePayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventCreate, &api.CreatePayload{ Ref: refName, Sha: refID, RefType: refType, @@ -772,15 +724,12 @@ func (m *webhookNotifier) NotifyCreateRef(pusher *user_model.User, repo *repo_mo } } -func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPullRequestSynchronized Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - - if err := pr.LoadIssue(); err != nil { - log.Error("pr.LoadIssue: %v", err) +func (m *webhookNotifier) NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - if err := pr.Issue.LoadAttributes(db.DefaultContext); err != nil { + if err := pr.Issue.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } @@ -796,12 +745,12 @@ func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *user_model.User, p } } -func (m *webhookNotifier) NotifyDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (m *webhookNotifier) NotifyDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { apiPusher := convert.ToUser(pusher, nil) apiRepo := convert.ToRepo(repo, perm.AccessModeNone) refName := git.RefEndName(refFullName) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventDelete, &api.DeletePayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventDelete, &api.DeletePayload{ Ref: refName, RefType: refType, PusherType: api.PusherTypeUser, @@ -812,14 +761,14 @@ func (m *webhookNotifier) NotifyDeleteRef(pusher *user_model.User, repo *repo_mo } } -func sendReleaseHook(doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) { - if err := rel.LoadAttributes(); err != nil { +func sendReleaseHook(ctx context.Context, doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) { + if err := rel.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } - mode, _ := access_model.AccessLevel(doer, rel.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: rel.Repo}, webhook.HookEventRelease, &api.ReleasePayload{ + mode, _ := access_model.AccessLevel(ctx, doer, rel.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: rel.Repo}, webhook.HookEventRelease, &api.ReleasePayload{ Action: action, Release: convert.ToRelease(rel), Repository: convert.ToRepo(rel.Repo, mode), @@ -829,22 +778,19 @@ func sendReleaseHook(doer *user_model.User, rel *repo_model.Release, action api. } } -func (m *webhookNotifier) NotifyNewRelease(rel *repo_model.Release) { - sendReleaseHook(rel.Publisher, rel, api.HookReleasePublished) +func (m *webhookNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + sendReleaseHook(ctx, rel.Publisher, rel, api.HookReleasePublished) } -func (m *webhookNotifier) NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { - sendReleaseHook(doer, rel, api.HookReleaseUpdated) +func (m *webhookNotifier) NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + sendReleaseHook(ctx, doer, rel, api.HookReleaseUpdated) } -func (m *webhookNotifier) NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { - sendReleaseHook(doer, rel, api.HookReleaseDeleted) +func (m *webhookNotifier) NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + sendReleaseHook(ctx, doer, rel, api.HookReleaseDeleted) } -func (m *webhookNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifySyncPushCommits User: %s[%d] in %s[%d]", pusher.Name, pusher.ID, repo.FullName(), repo.ID)) - defer finished() - +func (m *webhookNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { apiPusher := convert.ToUser(pusher, nil) apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) if err != nil { @@ -868,31 +814,28 @@ func (m *webhookNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *r } } -func (m *webhookNotifier) NotifySyncCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { - m.NotifyCreateRef(pusher, repo, refType, refFullName, refID) +func (m *webhookNotifier) NotifySyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { + m.NotifyCreateRef(ctx, pusher, repo, refType, refFullName, refID) } -func (m *webhookNotifier) NotifySyncDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { - m.NotifyDeleteRef(pusher, repo, refType, refFullName) +func (m *webhookNotifier) NotifySyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { + m.NotifyDeleteRef(ctx, pusher, repo, refType, refFullName) } -func (m *webhookNotifier) NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) { - notifyPackage(doer, pd, api.HookPackageCreated) +func (m *webhookNotifier) NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + notifyPackage(ctx, doer, pd, api.HookPackageCreated) } -func (m *webhookNotifier) NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) { - notifyPackage(doer, pd, api.HookPackageDeleted) +func (m *webhookNotifier) NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + notifyPackage(ctx, doer, pd, api.HookPackageDeleted) } -func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) { +func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) { source := webhook_services.EventSource{ Repository: pd.Repository, Owner: pd.Owner, } - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.notifyPackage Package: %s[%d]", pd.Package.Name, pd.Package.ID)) - defer finished() - apiPackage, err := convert.ToPackage(ctx, pd, sender) if err != nil { log.Error("Error converting package: %v", err) diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 1d3a4658c20ea..f1360f4478837 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -288,7 +288,7 @@ func SyncReleasesWithTags(repo *repo_model.Repository, gitRepo *git.Repository) } for page := 1; ; page++ { opts.Page = page - rels, err := repo_model.GetReleasesByRepoID(repo.ID, opts) + rels, err := repo_model.GetReleasesByRepoID(gitRepo.Ctx, repo.ID, opts) if err != nil { return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) } diff --git a/routers/api/packages/conan/conan.go b/routers/api/packages/conan/conan.go index b69a674106ce7..188cfce2879a8 100644 --- a/routers/api/packages/conan/conan.go +++ b/routers/api/packages/conan/conan.go @@ -676,7 +676,7 @@ func deleteRecipeOrPackage(apictx *context.Context, rref *conan_module.RecipeRef } if versionDeleted { - notification.NotifyPackageDelete(apictx.Doer, pd) + notification.NotifyPackageDelete(apictx, apictx.Doer, pd) } return nil diff --git a/routers/api/v1/misc/nodeinfo.go b/routers/api/v1/misc/nodeinfo.go index bd629b87ca445..a4ba440356b43 100644 --- a/routers/api/v1/misc/nodeinfo.go +++ b/routers/api/v1/misc/nodeinfo.go @@ -42,7 +42,7 @@ func NodeInfo(ctx *context.APIContext) { usersActiveMonth := int(user_model.CountUsers(&user_model.CountUserFilter{LastLoginSince: &timeOneMonthAgo})) usersActiveHalfyear := int(user_model.CountUsers(&user_model.CountUserFilter{LastLoginSince: &timeHaveYearAgo})) - allIssues, _ := issues_model.CountIssues(&issues_model.IssuesOptions{}) + allIssues, _ := issues_model.CountIssues(ctx, &issues_model.IssuesOptions{}) allComments, _ := issues_model.CountComments(&issues_model.FindCommentsOptions{}) nodeInfoUsage = structs.NodeInfoUsage{ diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index f8e1fb0865aa3..6d9664400a55d 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -109,7 +109,7 @@ func ListRepoNotifications(ctx *context.APIContext) { } opts.RepoID = ctx.Repo.Repository.ID - totalCount, err := activities_model.CountNotifications(opts) + totalCount, err := activities_model.CountNotifications(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -120,7 +120,7 @@ func ListRepoNotifications(ctx *context.APIContext) { ctx.InternalServerError(err) return } - err = nl.LoadAttributes() + err = nl.LoadAttributes(ctx) if err != nil { ctx.InternalServerError(err) return @@ -217,12 +217,12 @@ func ReadRepoNotifications(ctx *context.APIContext) { changed := make([]*structs.NotificationThread, 0, len(nl)) for _, n := range nl { - notif, err := activities_model.SetNotificationStatus(n.ID, ctx.Doer, targetStatus) + notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) if err != nil { ctx.InternalServerError(err) return } - _ = notif.LoadAttributes() + _ = notif.LoadAttributes(ctx) changed = append(changed, convert.ToNotificationThread(notif)) } ctx.JSON(http.StatusResetContent, changed) diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go index 44a1d30a55db3..f8e4960912464 100644 --- a/routers/api/v1/notify/threads.go +++ b/routers/api/v1/notify/threads.go @@ -42,7 +42,7 @@ func GetThread(ctx *context.APIContext) { if n == nil { return } - if err := n.LoadAttributes(); err != nil && !issues_model.IsErrCommentNotExist(err) { + if err := n.LoadAttributes(ctx); err != nil && !issues_model.IsErrCommentNotExist(err) { ctx.InternalServerError(err) return } @@ -89,12 +89,12 @@ func ReadThread(ctx *context.APIContext) { targetStatus = activities_model.NotificationStatusRead } - notif, err := activities_model.SetNotificationStatus(n.ID, ctx.Doer, targetStatus) + notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) if err != nil { ctx.InternalServerError(err) return } - if err = notif.LoadAttributes(); err != nil && !issues_model.IsErrCommentNotExist(err) { + if err = notif.LoadAttributes(ctx); err != nil && !issues_model.IsErrCommentNotExist(err) { ctx.InternalServerError(err) return } @@ -102,7 +102,7 @@ func ReadThread(ctx *context.APIContext) { } func getThread(ctx *context.APIContext) *activities_model.Notification { - n, err := activities_model.GetNotificationByID(ctx.ParamsInt64(":id")) + n, err := activities_model.GetNotificationByID(ctx, ctx.ParamsInt64(":id")) if err != nil { if db.IsErrNotExist(err) { ctx.Error(http.StatusNotFound, "GetNotificationByID", err) diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 1b6706e16f1c0..5f4d8b35c2d5f 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -69,7 +69,7 @@ func ListNotifications(ctx *context.APIContext) { return } - totalCount, err := activities_model.CountNotifications(opts) + totalCount, err := activities_model.CountNotifications(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -80,7 +80,7 @@ func ListNotifications(ctx *context.APIContext) { ctx.InternalServerError(err) return } - err = nl.LoadAttributes() + err = nl.LoadAttributes(ctx) if err != nil { ctx.InternalServerError(err) return @@ -162,12 +162,12 @@ func ReadNotifications(ctx *context.APIContext) { changed := make([]*structs.NotificationThread, 0, len(nl)) for _, n := range nl { - notif, err := activities_model.SetNotificationStatus(n.ID, ctx.Doer, targetStatus) + notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) if err != nil { ctx.InternalServerError(err) return } - _ = notif.LoadAttributes() + _ = notif.LoadAttributes(ctx) changed = append(changed, convert.ToNotificationThread(notif)) } diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index f3e7834a4931c..b2bcc4d586084 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -542,7 +542,7 @@ func GetTeamRepos(ctx *context.APIContext) { } repos := make([]*api.Repository, len(teamRepos)) for i, repo := range teamRepos { - access, err := access_model.AccessLevel(ctx.Doer, repo) + access, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) return @@ -593,7 +593,7 @@ func GetTeamRepo(ctx *context.APIContext) { return } - access, err := access_model.AccessLevel(ctx.Doer, repo) + access, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) return @@ -650,7 +650,7 @@ func AddTeamRepository(ctx *context.APIContext) { if ctx.Written() { return } - if access, err := access_model.AccessLevel(ctx.Doer, repo); err != nil { + if access, err := access_model.AccessLevel(ctx, ctx.Doer, repo); err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return } else if access < perm.AccessModeAdmin { @@ -700,7 +700,7 @@ func RemoveTeamRepository(ctx *context.APIContext) { if ctx.Written() { return } - if access, err := access_model.AccessLevel(ctx.Doer, repo); err != nil { + if access, err := access_model.AccessLevel(ctx, ctx.Doer, repo); err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return } else if access < perm.AccessModeAdmin { diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 84a172e92bf00..d10a308df3a79 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -427,7 +427,7 @@ func CreateBranchProtection(ctx *context.APIContext) { requiredApprovals = form.RequiredApprovals } - whitelistUsers, err := user_model.GetUserIDsByNames(form.PushWhitelistUsernames, false) + whitelistUsers, err := user_model.GetUserIDsByNames(ctx, form.PushWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -436,7 +436,7 @@ func CreateBranchProtection(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } - mergeWhitelistUsers, err := user_model.GetUserIDsByNames(form.MergeWhitelistUsernames, false) + mergeWhitelistUsers, err := user_model.GetUserIDsByNames(ctx, form.MergeWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -445,7 +445,7 @@ func CreateBranchProtection(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } - approvalsWhitelistUsers, err := user_model.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false) + approvalsWhitelistUsers, err := user_model.GetUserIDsByNames(ctx, form.ApprovalsWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -656,7 +656,7 @@ func EditBranchProtection(ctx *context.APIContext) { var whitelistUsers []int64 if form.PushWhitelistUsernames != nil { - whitelistUsers, err = user_model.GetUserIDsByNames(form.PushWhitelistUsernames, false) + whitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.PushWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -670,7 +670,7 @@ func EditBranchProtection(ctx *context.APIContext) { } var mergeWhitelistUsers []int64 if form.MergeWhitelistUsernames != nil { - mergeWhitelistUsers, err = user_model.GetUserIDsByNames(form.MergeWhitelistUsernames, false) + mergeWhitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.MergeWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -684,7 +684,7 @@ func EditBranchProtection(ctx *context.APIContext) { } var approvalsWhitelistUsers []int64 if form.ApprovalsWhitelistUsernames != nil { - approvalsWhitelistUsers, err = user_model.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false) + approvalsWhitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.ApprovalsWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index 112a9562f0fdf..c0a79d1a63286 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -59,7 +59,7 @@ func ListForks(ctx *context.APIContext) { } apiForks := make([]*api.Repository, len(forks)) for i, fork := range forks { - access, err := access_model.AccessLevel(ctx.Doer, fork) + access, err := access_model.AccessLevel(ctx, ctx.Doer, fork) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 08e3e037417c0..60f9859e107ad 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -179,7 +179,7 @@ func SearchIssues(ctx *context.APIContext) { repoCond := repo_model.SearchRepositoryCondition(opts) repoIDs, _, err := repo_model.SearchRepositoryIDs(opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err) + ctx.Error(http.StatusInternalServerError, "SearchRepositoryIDs", err) return } @@ -268,7 +268,7 @@ func SearchIssues(ctx *context.APIContext) { issuesOpt.ReviewRequestedID = ctxUserID } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err) return } @@ -276,7 +276,7 @@ func SearchIssues(ctx *context.APIContext) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "CountIssues", err) return } @@ -284,7 +284,7 @@ func SearchIssues(ctx *context.APIContext) { ctx.SetLinkHeader(int(filteredCount), limit) ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } // ListIssues list the issues of a repository @@ -477,7 +477,7 @@ func ListIssues(ctx *context.APIContext) { MentionedID: mentionedByID, } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err) return } @@ -485,7 +485,7 @@ func ListIssues(ctx *context.APIContext) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "CountIssues", err) return } @@ -493,7 +493,7 @@ func ListIssues(ctx *context.APIContext) { ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize) ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } func getUserIDForFilter(ctx *context.APIContext, queryName string) int64 { @@ -555,7 +555,7 @@ func GetIssue(ctx *context.APIContext) { } return } - ctx.JSON(http.StatusOK, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) } // CreateIssue create an issue of a repository @@ -612,7 +612,7 @@ func CreateIssue(ctx *context.APIContext) { var err error if ctx.Repo.CanWrite(unit.TypeIssues) { issue.MilestoneID = form.Milestone - assigneeIDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) + assigneeIDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(ctx, form.Assignee, form.Assignees) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) @@ -671,7 +671,7 @@ func CreateIssue(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetIssueByID", err) return } - ctx.JSON(http.StatusCreated, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue)) } // EditIssue modify an issue of a repository @@ -823,11 +823,11 @@ func EditIssue(ctx *context.APIContext) { } if titleChanged { - notification.NotifyIssueChangeTitle(ctx.Doer, issue, oldTitle) + notification.NotifyIssueChangeTitle(ctx, ctx.Doer, issue, oldTitle) } if statusChangeComment != nil { - notification.NotifyIssueChangeStatus(ctx.Doer, issue, statusChangeComment, issue.IsClosed) + notification.NotifyIssueChangeStatus(ctx, ctx.Doer, issue, statusChangeComment, issue.IsClosed) } // Refetch from database to assign some automatic values @@ -836,11 +836,11 @@ func EditIssue(ctx *context.APIContext) { ctx.InternalServerError(err) return } - if err = issue.LoadMilestone(); err != nil { + if err = issue.LoadMilestone(ctx); err != nil { ctx.InternalServerError(err) return } - ctx.JSON(http.StatusCreated, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue)) } func DeleteIssue(ctx *context.APIContext) { diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 89038e4f16304..a5da09172797e 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -91,7 +91,7 @@ func ListIssueComments(ctx *context.APIContext) { return } - if err := issues_model.CommentList(comments).LoadPosters(); err != nil { + if err := issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } @@ -178,7 +178,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { return } - if err := issues_model.CommentList(comments).LoadPosters(); err != nil { + if err := issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } @@ -187,7 +187,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { for _, comment := range comments { if comment.Type != issues_model.CommentTypeCode && isXRefCommentAccessible(ctx, ctx.Doer, comment, issue.RepoID) { comment.Issue = issue - apiComments = append(apiComments, convert.ToTimelineComment(comment, ctx.Doer)) + apiComments = append(apiComments, convert.ToTimelineComment(ctx, comment, ctx.Doer)) } } @@ -281,21 +281,21 @@ func ListRepoIssueComments(ctx *context.APIContext) { return } - if err = issues_model.CommentList(comments).LoadPosters(); err != nil { + if err = issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } apiComments := make([]*api.Comment, len(comments)) - if err := issues_model.CommentList(comments).LoadIssues(); err != nil { + if err := issues_model.CommentList(comments).LoadIssues(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssues", err) return } - if err := issues_model.CommentList(comments).LoadPosters(); err != nil { + if err := issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } - if _, err := issues_model.CommentList(comments).Issues().LoadRepositories(); err != nil { + if _, err := issues_model.CommentList(comments).Issues().LoadRepositories(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadRepositories", err) return } @@ -354,7 +354,7 @@ func CreateIssueComment(ctx *context.APIContext) { return } - comment, err := comment_service.CreateIssueComment(ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil) + comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil) if err != nil { ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err) return @@ -409,7 +409,7 @@ func GetIssueComment(ctx *context.APIContext) { return } - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { ctx.InternalServerError(err) return } @@ -423,7 +423,7 @@ func GetIssueComment(ctx *context.APIContext) { return } - if err := comment.LoadPoster(); err != nil { + if err := comment.LoadPoster(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "comment.LoadPoster", err) return } @@ -548,7 +548,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) oldContent := comment.Content comment.Content = form.Body - if err := comment_service.UpdateComment(comment, ctx.Doer, oldContent); err != nil { + if err := comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateComment", err) return } @@ -647,7 +647,7 @@ func deleteIssueComment(ctx *context.APIContext) { return } - if err = comment_service.DeleteComment(ctx.Doer, comment); err != nil { + if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil { ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err) return } diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index f4c40d2bcd828..fb7fd713b38a2 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -58,7 +58,7 @@ func GetIssueCommentReactions(ctx *context.APIContext) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "comment.LoadIssue", err) } @@ -185,7 +185,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp return } - err = comment.LoadIssue() + err = comment.LoadIssue(ctx) if err != nil { ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err) } diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index 1e26403ec827d..e3abb973be43d 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -139,7 +139,7 @@ func ListTrackedTimes(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } // AddTime add time manual to the given issue @@ -224,7 +224,7 @@ func AddTime(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToTrackedTime(trackedTime)) + ctx.JSON(http.StatusOK, convert.ToTrackedTime(ctx, trackedTime)) } // ResetIssueTime reset time manual to the given issue @@ -448,7 +448,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } // ListTrackedTimesByRepository lists all tracked times of the repository @@ -558,7 +558,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } // ListMyTrackedTimes lists all tracked times of the current user @@ -620,5 +620,5 @@ func ListMyTrackedTimes(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index ed371d787ccb6..aeef862b1f8a3 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -195,7 +195,7 @@ func Migrate(ctx *context.APIContext) { } if err == nil { - notification.NotifyMigrateRepository(ctx.Doer, repoOwner, repo) + notification.NotifyMigrateRepository(ctx, ctx.Doer, repoOwner, repo) return } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index f7e82dab37240..fba7ed646274f 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -109,19 +109,19 @@ func ListPullRequests(ctx *context.APIContext) { apiPrs := make([]*api.PullRequest, len(prs)) for i := range prs { - if err = prs[i].LoadIssue(); err != nil { + if err = prs[i].LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } - if err = prs[i].LoadAttributes(); err != nil { + if err = prs[i].LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - if err = prs[i].LoadBaseRepoCtx(ctx); err != nil { + if err = prs[i].LoadBaseRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) return } - if err = prs[i].LoadHeadRepoCtx(ctx); err != nil { + if err = prs[i].LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } @@ -173,11 +173,11 @@ func GetPullRequest(ctx *context.APIContext) { return } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) return } - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } @@ -300,7 +300,7 @@ func CreatePullRequest(ctx *context.APIContext) { defer headGitRepo.Close() // Check if another PR exists with the same targets - existingPr, err := issues_model.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch, issues_model.PullRequestFlowGithub) + existingPr, err := issues_model.GetUnmergedPullRequest(ctx, headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch, issues_model.PullRequestFlowGithub) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { ctx.Error(http.StatusInternalServerError, "GetUnmergedPullRequest", err) @@ -320,7 +320,7 @@ func CreatePullRequest(ctx *context.APIContext) { } if len(form.Labels) > 0 { - labels, err := issues_model.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) + labels, err := issues_model.GetLabelsInRepoByIDs(ctx, ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDs", err) return @@ -334,7 +334,7 @@ func CreatePullRequest(ctx *context.APIContext) { } if ctx.Repo.Owner.IsOrganization() { - orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx.Repo.Owner.ID, form.Labels) + orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx, ctx.Repo.Owner.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInOrgByIDs", err) return @@ -389,7 +389,7 @@ func CreatePullRequest(ctx *context.APIContext) { } // Get all assignee IDs - assigneeIDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) + assigneeIDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(ctx, form.Assignee, form.Assignees) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) @@ -400,7 +400,7 @@ func CreatePullRequest(ctx *context.APIContext) { } // Check if the passed assignees is assignable for _, aID := range assigneeIDs { - assignee, err := user_model.GetUserByID(aID) + assignee, err := user_model.GetUserByIDCtx(ctx, aID) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserByID", err) return @@ -483,7 +483,7 @@ func EditPullRequest(ctx *context.APIContext) { return } - err = pr.LoadIssue() + err = pr.LoadIssue(ctx) if err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return @@ -551,14 +551,14 @@ func EditPullRequest(ctx *context.APIContext) { } if ctx.Repo.CanWrite(unit.TypePullRequests) && form.Labels != nil { - labels, err := issues_model.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) + labels, err := issues_model.GetLabelsInRepoByIDs(ctx, ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDsError", err) return } if ctx.Repo.Owner.IsOrganization() { - orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx.Repo.Owner.ID, form.Labels) + orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx, ctx.Repo.Owner.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInOrgByIDs", err) return @@ -591,11 +591,11 @@ func EditPullRequest(ctx *context.APIContext) { } if titleChanged { - notification.NotifyIssueChangeTitle(ctx.Doer, issue, oldTitle) + notification.NotifyIssueChangeTitle(ctx, ctx.Doer, issue, oldTitle) } if statusChangeComment != nil { - notification.NotifyIssueChangeStatus(ctx.Doer, issue, statusChangeComment, issue.IsClosed) + notification.NotifyIssueChangeStatus(ctx, ctx.Doer, issue, statusChangeComment, issue.IsClosed) } // change pull target branch @@ -619,7 +619,7 @@ func EditPullRequest(ctx *context.APIContext) { } return } - notification.NotifyPullRequestChangeTargetBranch(ctx.Doer, pr, form.Base) + notification.NotifyPullRequestChangeTargetBranch(ctx, ctx.Doer, pr, form.Base) } // update allow edits @@ -743,12 +743,12 @@ func MergePullRequest(ctx *context.APIContext) { return } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } - if err := pr.LoadIssueCtx(ctx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } @@ -811,7 +811,7 @@ func MergePullRequest(ctx *context.APIContext) { message := strings.TrimSpace(form.MergeTitleField) if len(message) == 0 { - message, err = pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) + message, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) if err != nil { ctx.Error(http.StatusInternalServerError, "GetDefaultMergeMessage", err) return @@ -1097,7 +1097,7 @@ func UpdatePullRequest(ctx *context.APIContext) { return } - if err = pr.LoadIssue(); err != nil { + if err = pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } @@ -1107,11 +1107,11 @@ func UpdatePullRequest(ctx *context.APIContext) { return } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) return } - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } @@ -1267,7 +1267,7 @@ func GetPullRequestCommits(ctx *context.APIContext) { return } - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { ctx.InternalServerError(err) return } @@ -1383,12 +1383,12 @@ func GetPullRequestFiles(ctx *context.APIContext) { return } - if err := pr.LoadBaseRepo(); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { ctx.InternalServerError(err) return } - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { ctx.InternalServerError(err) return } diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index f36d0586ab6b9..df88e2a57bff7 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -71,7 +71,7 @@ func ListPullReviews(ctx *context.APIContext) { return } - if err = pr.LoadIssue(); err != nil { + if err = pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } @@ -476,7 +476,7 @@ func SubmitPullReview(ctx *context.APIContext) { // preparePullReviewType return ReviewType and false or nil and true if an error happen func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest, event api.ReviewStateType, body string, hasComments bool) (issues_model.ReviewType, bool) { - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return -1, true } diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index acc9696e1bef1..60cc19d5653b1 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -61,7 +61,7 @@ func GetRelease(ctx *context.APIContext) { return } - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -123,14 +123,14 @@ func ListReleases(ctx *context.APIContext) { IsPreRelease: ctx.FormOptionalBool("pre-release"), } - releases, err := repo_model.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) return } rels := make([]*api.Release, len(releases)) for i, release := range releases { - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -313,7 +313,7 @@ func EditRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) return } - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index a469877c13e56..02f85d384a32a 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -114,7 +114,7 @@ func ListReleaseAttachments(ctx *context.APIContext) { ctx.NotFound() return } - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 2cb97c58a0263..77395bb469293 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -60,7 +60,7 @@ func GetReleaseByTag(ctx *context.APIContext) { return } - if err = release.LoadAttributes(); err != nil { + if err = release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index de8a4d186489c..29febe751cb91 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -191,7 +191,7 @@ func Search(ctx *context.APIContext) { } var err error - repos, count, err := repo_model.SearchRepository(opts) + repos, count, err := repo_model.SearchRepository(ctx, opts) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, @@ -209,7 +209,7 @@ func Search(ctx *context.APIContext) { }) return } - accessMode, err := access_model.AccessLevel(ctx.Doer, repo) + accessMode, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 6d9564854278e..734a550a71559 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -86,7 +86,7 @@ func NewWikiPage(ctx *context.APIContext) { wikiPage := getWikiPage(ctx, wikiName) if !ctx.Written() { - notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) + notification.NotifyNewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) ctx.JSON(http.StatusCreated, wikiPage) } } @@ -154,7 +154,7 @@ func EditWikiPage(ctx *context.APIContext) { wikiPage := getWikiPage(ctx, newWikiName) if !ctx.Written() { - notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) + notification.NotifyEditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) ctx.JSON(http.StatusOK, wikiPage) } } @@ -245,7 +245,7 @@ func DeleteWikiPage(ctx *context.APIContext) { return } - notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName) + notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName) ctx.Status(http.StatusNoContent) } diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index 709e3a6c5457d..d1917a9938bae 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -39,7 +39,7 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { apiRepos := make([]*api.Repository, 0, len(repos)) for i := range repos { - access, err := access_model.AccessLevel(ctx.Doer, repos[i]) + access, err := access_model.AccessLevel(ctx, ctx.Doer, repos[i]) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return @@ -112,7 +112,7 @@ func ListMyRepos(ctx *context.APIContext) { } var err error - repos, count, err := repo_model.SearchRepository(opts) + repos, count, err := repo_model.SearchRepository(ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchRepository", err) return @@ -124,7 +124,7 @@ func ListMyRepos(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetOwner", err) return } - accessMode, err := access_model.AccessLevel(ctx.Doer, repo) + accessMode, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) } diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go index 9cb9ec79b8794..96748c630d6b4 100644 --- a/routers/api/v1/user/star.go +++ b/routers/api/v1/user/star.go @@ -6,6 +6,7 @@ package user import ( + std_context "context" "net/http" "code.gitea.io/gitea/models/db" @@ -20,15 +21,15 @@ import ( // getStarredRepos returns the repos that the user with the specified userID has // starred -func getStarredRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) { - starredRepos, err := repo_model.GetStarredRepos(user.ID, private, listOptions) +func getStarredRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) { + starredRepos, err := repo_model.GetStarredRepos(ctx, user.ID, private, listOptions) if err != nil { return nil, err } repos := make([]*api.Repository, len(starredRepos)) for i, starred := range starredRepos { - access, err := access_model.AccessLevel(user, starred) + access, err := access_model.AccessLevel(ctx, user, starred) if err != nil { return nil, err } @@ -63,7 +64,7 @@ func GetStarredRepos(ctx *context.APIContext) { // "$ref": "#/responses/RepositoryList" private := ctx.ContextUser.ID == ctx.Doer.ID - repos, err := getStarredRepos(ctx.ContextUser, private, utils.GetListOptions(ctx)) + repos, err := getStarredRepos(ctx, ctx.ContextUser, private, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) return @@ -93,7 +94,7 @@ func GetMyStarredRepos(ctx *context.APIContext) { // "200": // "$ref": "#/responses/RepositoryList" - repos, err := getStarredRepos(ctx.Doer, true, utils.GetListOptions(ctx)) + repos, err := getStarredRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) } diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go index 83f23db15ca03..7765a399f381e 100644 --- a/routers/api/v1/user/watch.go +++ b/routers/api/v1/user/watch.go @@ -5,6 +5,7 @@ package user import ( + std_context "context" "net/http" "code.gitea.io/gitea/models/db" @@ -18,15 +19,15 @@ import ( ) // getWatchedRepos returns the repos that the user with the specified userID is watching -func getWatchedRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) { - watchedRepos, total, err := repo_model.GetWatchedRepos(user.ID, private, listOptions) +func getWatchedRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) { + watchedRepos, total, err := repo_model.GetWatchedRepos(ctx, user.ID, private, listOptions) if err != nil { return nil, 0, err } repos := make([]*api.Repository, len(watchedRepos)) for i, watched := range watchedRepos { - access, err := access_model.AccessLevel(user, watched) + access, err := access_model.AccessLevel(ctx, user, watched) if err != nil { return nil, 0, err } @@ -61,7 +62,7 @@ func GetWatchedRepos(ctx *context.APIContext) { // "$ref": "#/responses/RepositoryList" private := ctx.ContextUser.ID == ctx.Doer.ID - repos, total, err := getWatchedRepos(ctx.ContextUser, private, utils.GetListOptions(ctx)) + repos, total, err := getWatchedRepos(ctx, ctx.ContextUser, private, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) } @@ -90,7 +91,7 @@ func GetMyWatchedRepos(ctx *context.APIContext) { // "200": // "$ref": "#/responses/RepositoryList" - repos, total, err := getWatchedRepos(ctx.Doer, true, utils.GetListOptions(ctx)) + repos, total, err := getWatchedRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) } diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 93aa450f9c3b7..1370e5302b71d 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -202,7 +202,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { continue } - pr, err := issues_model.GetUnmergedPullRequest(repo.ID, baseRepo.ID, branch, baseRepo.DefaultBranch, issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, baseRepo.ID, branch, baseRepo.DefaultBranch, issues_model.PullRequestFlowGithub) if err != nil && !issues_model.IsErrPullRequestNotExist(err) { log.Error("Failed to get active PR in: %-v Branch: %s to: %-v Branch: %s Error: %v", repo, branch, baseRepo, baseRepo.DefaultBranch, err) ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index fdd0a0bc3a042..86bdf60ab98b7 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -372,7 +372,7 @@ func preReceiveTag(ctx *preReceiveContext, oldCommitID, newCommitID, refFullName if !ctx.gotProtectedTags { var err error - ctx.protectedTags, err = git_model.GetProtectedTags(ctx.Repo.Repository.ID) + ctx.protectedTags, err = git_model.GetProtectedTags(ctx, ctx.Repo.Repository.ID) if err != nil { log.Error("Unable to get protected tags for %-v Error: %v", ctx.Repo.Repository, err) ctx.JSON(http.StatusInternalServerError, private.Response{ @@ -383,7 +383,7 @@ func preReceiveTag(ctx *preReceiveContext, oldCommitID, newCommitID, refFullName ctx.gotProtectedTags = true } - isAllowed, err := git_model.IsUserAllowedToControlTag(ctx.protectedTags, tagName, ctx.opts.UserID) + isAllowed, err := git_model.IsUserAllowedToControlTag(ctx, ctx.protectedTags, tagName, ctx.opts.UserID) if err != nil { ctx.JSON(http.StatusInternalServerError, private.Response{ Err: err.Error(), diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go index 8cb615b7bcbfa..8d4ecf1bc08bc 100644 --- a/routers/web/explore/repo.go +++ b/routers/web/explore/repo.go @@ -98,7 +98,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { language := ctx.FormTrim("language") ctx.Data["Language"] = language - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: opts.PageSize, diff --git a/routers/web/home.go b/routers/web/home.go index 0c74987ba7c47..7640243ba076f 100644 --- a/routers/web/home.go +++ b/routers/web/home.go @@ -88,7 +88,7 @@ func HomeSitemap(ctx *context.Context) { } } - _, cnt, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + _, cnt, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: 1, }, diff --git a/routers/web/org/home.go b/routers/web/org/home.go index 63243a391f0e6..6bd8a89d12371 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -99,7 +99,7 @@ func Home(ctx *context.Context) { count int64 err error ) - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index d1f1255db4656..a7588d275d4a5 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -275,14 +275,14 @@ func loadOneBranch(ctx *context.Context, rawBranch, defaultBranch *git.Branch, p mergeMovedOn := false if pr != nil { pr.HeadRepo = ctx.Repo.Repository - if err := pr.LoadIssue(); err != nil { - ctx.ServerError("pr.LoadIssue", err) + if err := pr.LoadIssue(ctx); err != nil { + ctx.ServerError("LoadIssue", err) return nil } if repo, ok := repoIDToRepo[pr.BaseRepoID]; ok { pr.BaseRepo = repo - } else if err := pr.LoadBaseRepoCtx(ctx); err != nil { - ctx.ServerError("pr.LoadBaseRepo", err) + } else if err := pr.LoadBaseRepo(ctx); err != nil { + ctx.ServerError("LoadBaseRepo", err) return nil } else { repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index db6b59471ff47..0fb8e44725245 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -747,7 +747,7 @@ func CompareDiff(ctx *context.Context) { ctx.Data["HeadTags"] = headTags if ctx.Data["PageIsComparePull"] == true { - pr, err := issues_model.GetUnmergedPullRequest(ci.HeadRepo.ID, ctx.Repo.Repository.ID, ci.HeadBranch, ci.BaseBranch, issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(ctx, ci.HeadRepo.ID, ctx.Repo.Repository.ID, ci.HeadBranch, ci.BaseBranch, issues_model.PullRequestFlowGithub) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { ctx.ServerError("GetUnmergedPullRequest", err) @@ -755,7 +755,7 @@ func CompareDiff(ctx *context.Context) { } } else { ctx.Data["HasPullRequest"] = true - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { ctx.ServerError("LoadIssue", err) return } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 38ad593c17ad2..a62084fdcac72 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -246,7 +246,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti if forceEmpty { issues = []*issues_model.Issue{} } else { - issues, err = issues_model.Issues(&issues_model.IssuesOptions{ + issues, err = issues_model.Issues(ctx, &issues_model.IssuesOptions{ ListOptions: db.ListOptions{ Page: pager.Paginater.Current(), PageSize: setting.UI.IssuePagingNum, @@ -608,7 +608,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is currentPullReviewers := make([]*repoReviewerSelection, 0, len(pullReviews)) for _, item := range pullReviews { if item.Review.ReviewerID > 0 { - if err = item.Review.LoadReviewer(); err != nil { + if err = item.Review.LoadReviewer(ctx); err != nil { if user_model.IsErrUserNotExist(err) { continue } @@ -617,7 +617,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is } item.User = item.Review.Reviewer } else if item.Review.ReviewerTeamID > 0 { - if err = item.Review.LoadReviewerTeam(); err != nil { + if err = item.Review.LoadReviewerTeam(ctx); err != nil { if organization.IsErrTeamNotExist(err) { continue } @@ -1163,7 +1163,7 @@ func getBranchData(ctx *context.Context, issue *issues_model.Issue) { pull := issue.PullRequest ctx.Data["BaseBranch"] = pull.BaseBranch ctx.Data["HeadBranch"] = pull.HeadBranch - ctx.Data["HeadUserName"] = pull.MustHeadUserName() + ctx.Data["HeadUserName"] = pull.MustHeadUserName(ctx) } } @@ -1426,13 +1426,13 @@ func ViewIssue(ctx *context.Context) { for _, comment = range issue.Comments { comment.Issue = issue - if err := comment.LoadPoster(); err != nil { + if err := comment.LoadPoster(ctx); err != nil { ctx.ServerError("LoadPoster", err) return } if comment.Type == issues_model.CommentTypeComment || comment.Type == issues_model.CommentTypeReview { - if err := comment.LoadAttachments(); err != nil { + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } @@ -1467,7 +1467,7 @@ func ViewIssue(ctx *context.Context) { return } } else if comment.Type == issues_model.CommentTypeMilestone { - if err = comment.LoadMilestone(); err != nil { + if err = comment.LoadMilestone(ctx); err != nil { ctx.ServerError("LoadMilestone", err) return } @@ -1591,7 +1591,7 @@ func ViewIssue(ctx *context.Context) { ctx.Data["AllowMerge"] = false if ctx.IsSigned { - if err := pull.LoadHeadRepoCtx(ctx); err != nil { + if err := pull.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) } else if pull.HeadRepo != nil { perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer) @@ -1613,7 +1613,7 @@ func ViewIssue(ctx *context.Context) { } } - if err := pull.LoadBaseRepoCtx(ctx); err != nil { + if err := pull.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) } perm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, ctx.Doer) @@ -1662,14 +1662,14 @@ func ViewIssue(ctx *context.Context) { ctx.Data["MergeStyle"] = mergeStyle - defaultMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pull, mergeStyle) + defaultMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, mergeStyle) if err != nil { ctx.ServerError("GetDefaultMergeMessage", err) return } ctx.Data["DefaultMergeMessage"] = defaultMergeMessage - defaultSquashMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash) + defaultSquashMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash) if err != nil { ctx.ServerError("GetDefaultSquashMergeMessage", err) return @@ -1885,7 +1885,7 @@ func GetIssueInfo(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) } // UpdateIssueTitle change issue's title @@ -2280,7 +2280,7 @@ func SearchIssues(ctx *context.Context) { repoCond := repo_model.SearchRepositoryCondition(opts) repoIDs, _, err := repo_model.SearchRepositoryIDs(opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err.Error()) + ctx.Error(http.StatusInternalServerError, "SearchRepositoryIDs", err.Error()) return } @@ -2369,7 +2369,7 @@ func SearchIssues(ctx *context.Context) { issuesOpt.ReviewRequestedID = ctxUserID } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err.Error()) return } @@ -2377,14 +2377,14 @@ func SearchIssues(ctx *context.Context) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "CountIssues", err.Error()) return } } ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } func getUserIDForFilter(ctx *context.Context, queryName string) int64 { @@ -2527,7 +2527,7 @@ func ListIssues(ctx *context.Context) { MentionedID: mentionedByID, } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } @@ -2535,14 +2535,14 @@ func ListIssues(ctx *context.Context) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } } ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } // UpdateIssueStatus change issue's status @@ -2562,7 +2562,7 @@ func UpdateIssueStatus(ctx *context.Context) { log.Warn("Unrecognized action: %s", action) } - if _, err := issues_model.IssueList(issues).LoadRepositories(); err != nil { + if _, err := issues_model.IssueList(issues).LoadRepositories(ctx); err != nil { ctx.ServerError("LoadRepositories", err) return } @@ -2646,7 +2646,7 @@ func NewComment(ctx *context.Context) { if form.Status == "reopen" && issue.IsPull { pull := issue.PullRequest var err error - pr, err = issues_model.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow) + pr, err = issues_model.GetUnmergedPullRequest(ctx, pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { ctx.ServerError("GetUnmergedPullRequest", err) @@ -2706,7 +2706,7 @@ func NewComment(ctx *context.Context) { return } - comment, err := comment_service.CreateIssueComment(ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments) + comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments) if err != nil { ctx.ServerError("CreateIssueComment", err) return @@ -2723,7 +2723,7 @@ func UpdateCommentContent(ctx *context.Context) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err) return } @@ -2746,12 +2746,12 @@ func UpdateCommentContent(ctx *context.Context) { }) return } - if err = comment_service.UpdateComment(comment, ctx.Doer, oldContent); err != nil { + if err = comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil { ctx.ServerError("UpdateComment", err) return } - if err := comment.LoadAttachments(); err != nil { + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } @@ -2789,7 +2789,7 @@ func DeleteComment(ctx *context.Context) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err) return } @@ -2802,8 +2802,8 @@ func DeleteComment(ctx *context.Context) { return } - if err = comment_service.DeleteComment(ctx.Doer, comment); err != nil { - ctx.ServerError("DeleteCommentByID", err) + if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil { + ctx.ServerError("DeleteComment", err) return } @@ -2915,7 +2915,7 @@ func ChangeCommentReaction(ctx *context.Context) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err) return } @@ -3061,7 +3061,7 @@ func GetCommentAttachments(ctx *context.Context) { } attachments := make([]*api.Attachment, 0) if comment.Type == issues_model.CommentTypeComment { - if err := comment.LoadAttachments(); err != nil { + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 7af415a8faed1..560f25a0af77f 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -75,7 +75,7 @@ func RetrieveLabels(ctx *context.Context) { return } for _, l := range orgLabels { - l.CalOpenOrgIssues(ctx.Repo.Repository.ID, l.ID) + l.CalOpenOrgIssues(ctx, ctx.Repo.Repository.ID, l.ID) } ctx.Data["OrgLabels"] = orgLabels diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index f054ad6e540bd..fb2d25a22b813 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -297,7 +297,7 @@ func ViewProject(ctx *context.Context) { boards[0].Title = ctx.Tr("repo.projects.type.uncategorized") } - issuesMap, err := issues_model.LoadIssuesFromBoardList(boards) + issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards) if err != nil { ctx.ServerError("LoadIssuesOfBoards", err) return @@ -314,7 +314,7 @@ func ViewProject(ctx *context.Context) { } if len(referencedIds) > 0 { - if linkedPrs, err := issues_model.Issues(&issues_model.IssuesOptions{ + if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ IssueIDs: referencedIds, IsPull: util.OptionalBoolTrue, }); err == nil { diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 41eac7cc39232..870bc1773b967 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -281,7 +281,7 @@ func checkPullInfo(ctx *context.Context) *issues_model.Issue { } return nil } - if err = issue.LoadPoster(); err != nil { + if err = issue.LoadPoster(ctx); err != nil { ctx.ServerError("LoadPoster", err) return nil } @@ -297,12 +297,12 @@ func checkPullInfo(ctx *context.Context) *issues_model.Issue { return nil } - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { ctx.ServerError("LoadPullRequest", err) return nil } - if err = issue.PullRequest.LoadHeadRepoCtx(ctx); err != nil { + if err = issue.PullRequest.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return nil } @@ -319,12 +319,12 @@ func checkPullInfo(ctx *context.Context) *issues_model.Issue { } func setMergeTarget(ctx *context.Context, pull *issues_model.PullRequest) { - if ctx.Repo.Owner.Name == pull.MustHeadUserName() { + if ctx.Repo.Owner.Name == pull.MustHeadUserName(ctx) { ctx.Data["HeadTarget"] = pull.HeadBranch } else if pull.HeadRepo == nil { - ctx.Data["HeadTarget"] = pull.MustHeadUserName() + ":" + pull.HeadBranch + ctx.Data["HeadTarget"] = pull.MustHeadUserName(ctx) + ":" + pull.HeadBranch } else { - ctx.Data["HeadTarget"] = pull.MustHeadUserName() + "/" + pull.HeadRepo.Name + ":" + pull.HeadBranch + ctx.Data["HeadTarget"] = pull.MustHeadUserName(ctx) + "/" + pull.HeadRepo.Name + ":" + pull.HeadBranch } ctx.Data["BaseTarget"] = pull.BaseBranch ctx.Data["HeadBranchHTMLURL"] = pull.GetHeadBranchHTMLURL() @@ -416,12 +416,12 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C repo := ctx.Repo.Repository pull := issue.PullRequest - if err := pull.LoadHeadRepoCtx(ctx); err != nil { + if err := pull.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return nil } - if err := pull.LoadBaseRepoCtx(ctx); err != nil { + if err := pull.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return nil } @@ -606,7 +606,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C if pull.IsWorkInProgress() { ctx.Data["IsPullWorkInProgress"] = true - ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix() + ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix(ctx) } if pull.IsFilesConflicted() { @@ -834,11 +834,11 @@ func UpdatePullRequest(ctx *context.Context) { rebase := ctx.FormString("style") == "rebase" - if err := issue.PullRequest.LoadBaseRepoCtx(ctx); err != nil { + if err := issue.PullRequest.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return } - if err := issue.PullRequest.LoadHeadRepoCtx(ctx); err != nil { + if err := issue.PullRequest.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return } @@ -974,7 +974,7 @@ func MergePullRequest(ctx *context.Context) { message := strings.TrimSpace(form.MergeTitleField) if len(message) == 0 { var err error - message, err = pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) + message, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) if err != nil { ctx.ServerError("GetDefaultMergeMessage", err) return @@ -1296,14 +1296,14 @@ func CleanUpPullRequest(ctx *context.Context) { return } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return } else if pr.HeadRepo == nil { // Forked repository has already been deleted ctx.NotFound("CleanUpPullRequest", nil) return - } else if err = pr.LoadBaseRepoCtx(ctx); err != nil { + } else if err = pr.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return } else if err = pr.HeadRepo.GetOwner(ctx); err != nil { @@ -1499,7 +1499,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { } return } - notification.NotifyPullRequestChangeTargetBranch(ctx.Doer, pr, targetBranch) + notification.NotifyPullRequestChangeTargetBranch(ctx, ctx.Doer, pr, targetBranch) ctx.JSON(http.StatusOK, map[string]interface{}{ "base_branch": pr.BaseBranch, diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go index bc64f35472ea4..bbaacc234c0c6 100644 --- a/routers/web/repo/pull_review.go +++ b/routers/web/repo/pull_review.go @@ -114,7 +114,7 @@ func UpdateResolveConversation(ctx *context.Context) { return } - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { ctx.ServerError("comment.LoadIssue", err) return } @@ -169,7 +169,7 @@ func renderConversation(ctx *context.Context, comment *issues_model.Comment) { ctx.Data["comments"] = comments ctx.Data["CanMarkConversation"] = true ctx.Data["Issue"] = comment.Issue - if err = comment.Issue.LoadPullRequest(); err != nil { + if err = comment.Issue.LoadPullRequest(ctx); err != nil { ctx.ServerError("comment.Issue.LoadPullRequest", err) return } diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 0cb85f37984f5..0373d5b158d1a 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -130,7 +130,7 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { opts.IncludeDrafts = writeAccess } - releases, err := repo_model.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) if err != nil { ctx.ServerError("GetReleasesByRepoID", err) return @@ -266,7 +266,7 @@ func LatestRelease(ctx *context.Context) { return } - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } @@ -289,7 +289,7 @@ func NewRelease(ctx *context.Context) { if rel != nil { rel.Repo = ctx.Repo.Repository - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } @@ -454,7 +454,7 @@ func EditRelease(ctx *context.Context) { ctx.Data["IsDraft"] = rel.IsDraft rel.Repo = ctx.Repo.Repository - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 3e746d3f058cf..7bcca1d02a9a5 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -540,7 +540,7 @@ func SearchRepo(ctx *context.Context) { } var err error - repos, count, err := repo_model.SearchRepository(opts) + repos, count, err := repo_model.SearchRepository(ctx, opts) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, diff --git a/routers/web/repo/tag.go b/routers/web/repo/tag.go index f63a50782be09..4d46716c303a5 100644 --- a/routers/web/repo/tag.go +++ b/routers/web/repo/tag.go @@ -124,7 +124,7 @@ func DeleteProtectedTagPost(ctx *context.Context) { return } - if err := git_model.DeleteProtectedTag(pt); err != nil { + if err := git_model.DeleteProtectedTag(ctx, pt); err != nil { ctx.ServerError("DeleteProtectedTag", err) return } @@ -137,7 +137,7 @@ func setTagsContext(ctx *context.Context) error { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsTags"] = true - protectedTags, err := git_model.GetProtectedTags(ctx.Repo.Repository.ID) + protectedTags, err := git_model.GetProtectedTags(ctx, ctx.Repo.Repository.ID) if err != nil { ctx.ServerError("GetProtectedTags", err) return err diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index a10e12ee63269..24d851762b248 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -706,7 +706,7 @@ func NewWikiPost(ctx *context.Context) { return } - notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) + notification.NotifyNewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName)) } @@ -750,7 +750,7 @@ func EditWikiPost(ctx *context.Context) { return } - notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) + notification.NotifyEditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName)) } @@ -767,7 +767,7 @@ func DeleteWikiPagePost(ctx *context.Context) { return } - notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName) + notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName) ctx.JSON(http.StatusOK, map[string]interface{}{ "redirect": ctx.Repo.RepoLink + "/wiki/", diff --git a/routers/web/user/home.go b/routers/web/user/home.go index 95ec1aa2fa148..e67202b284e17 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -202,7 +202,7 @@ func Milestones(ctx *context.Context) { return } - showRepos, _, err := repo_model.SearchRepositoryByCondition(&repoOpts, userRepoCond, false) + showRepos, _, err := repo_model.SearchRepositoryByCondition(ctx, &repoOpts, userRepoCond, false) if err != nil { ctx.ServerError("SearchRepositoryByCondition", err) return @@ -461,7 +461,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { // USING NON-FINAL STATE OF opts FOR A QUERY. var issueCountByRepo map[int64]int64 if !forceEmpty { - issueCountByRepo, err = issues_model.CountIssuesByRepo(opts) + issueCountByRepo, err = issues_model.CountIssuesByRepo(ctx, opts) if err != nil { ctx.ServerError("CountIssuesByRepo", err) return @@ -504,7 +504,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { // USING FINAL STATE OF opts FOR A QUERY. var issues []*issues_model.Issue if !forceEmpty { - issues, err = issues_model.Issues(opts) + issues, err = issues_model.Issues(ctx, opts) if err != nil { ctx.ServerError("Issues", err) return diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index b4753a603e8a5..323422a1b9dc1 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -33,20 +33,20 @@ const ( ) // GetNotificationCount is the middleware that sets the notification count in the context -func GetNotificationCount(c *context.Context) { - if strings.HasPrefix(c.Req.URL.Path, "/api") { +func GetNotificationCount(ctx *context.Context) { + if strings.HasPrefix(ctx.Req.URL.Path, "/api") { return } - if !c.IsSigned { + if !ctx.IsSigned { return } - c.Data["NotificationUnreadCount"] = func() int64 { - count, err := activities_model.GetNotificationCount(c, c.Doer, activities_model.NotificationStatusUnread) + ctx.Data["NotificationUnreadCount"] = func() int64 { + count, err := activities_model.GetNotificationCount(ctx, ctx.Doer, activities_model.NotificationStatusUnread) if err != nil { if err != goctx.Canceled { - log.Error("Unable to GetNotificationCount for user:%-v: %v", c.Doer, err) + log.Error("Unable to GetNotificationCount for user:%-v: %v", ctx.Doer, err) } return -1 } @@ -56,25 +56,25 @@ func GetNotificationCount(c *context.Context) { } // Notifications is the notifications page -func Notifications(c *context.Context) { - getNotifications(c) - if c.Written() { +func Notifications(ctx *context.Context) { + getNotifications(ctx) + if ctx.Written() { return } - if c.FormBool("div-only") { - c.Data["SequenceNumber"] = c.FormString("sequence-number") - c.HTML(http.StatusOK, tplNotificationDiv) + if ctx.FormBool("div-only") { + ctx.Data["SequenceNumber"] = ctx.FormString("sequence-number") + ctx.HTML(http.StatusOK, tplNotificationDiv) return } - c.HTML(http.StatusOK, tplNotification) + ctx.HTML(http.StatusOK, tplNotification) } -func getNotifications(c *context.Context) { +func getNotifications(ctx *context.Context) { var ( - keyword = c.FormTrim("q") + keyword = ctx.FormTrim("q") status activities_model.NotificationStatus - page = c.FormInt("page") - perPage = c.FormInt("perPage") + page = ctx.FormInt("page") + perPage = ctx.FormInt("perPage") ) if page < 1 { page = 1 @@ -90,74 +90,74 @@ func getNotifications(c *context.Context) { status = activities_model.NotificationStatusUnread } - total, err := activities_model.GetNotificationCount(c, c.Doer, status) + total, err := activities_model.GetNotificationCount(ctx, ctx.Doer, status) if err != nil { - c.ServerError("ErrGetNotificationCount", err) + ctx.ServerError("ErrGetNotificationCount", err) return } // redirect to last page if request page is more than total pages pager := context.NewPagination(int(total), perPage, page, 5) if pager.Paginater.Current() < page { - c.Redirect(fmt.Sprintf("%s/notifications?q=%s&page=%d", setting.AppSubURL, url.QueryEscape(c.FormString("q")), pager.Paginater.Current())) + ctx.Redirect(fmt.Sprintf("%s/notifications?q=%s&page=%d", setting.AppSubURL, url.QueryEscape(ctx.FormString("q")), pager.Paginater.Current())) return } statuses := []activities_model.NotificationStatus{status, activities_model.NotificationStatusPinned} - notifications, err := activities_model.NotificationsForUser(c, c.Doer, statuses, page, perPage) + notifications, err := activities_model.NotificationsForUser(ctx, ctx.Doer, statuses, page, perPage) if err != nil { - c.ServerError("ErrNotificationsForUser", err) + ctx.ServerError("ErrNotificationsForUser", err) return } failCount := 0 - repos, failures, err := notifications.LoadRepos() + repos, failures, err := notifications.LoadRepos(ctx) if err != nil { - c.ServerError("LoadRepos", err) + ctx.ServerError("LoadRepos", err) return } notifications = notifications.Without(failures) - if err := repos.LoadAttributes(); err != nil { - c.ServerError("LoadAttributes", err) + if err := repos.LoadAttributes(); err != nil { // TODO + ctx.ServerError("LoadAttributes", err) return } failCount += len(failures) - failures, err = notifications.LoadIssues() + failures, err = notifications.LoadIssues(ctx) if err != nil { - c.ServerError("LoadIssues", err) + ctx.ServerError("LoadIssues", err) return } notifications = notifications.Without(failures) failCount += len(failures) - failures, err = notifications.LoadComments() + failures, err = notifications.LoadComments(ctx) if err != nil { - c.ServerError("LoadComments", err) + ctx.ServerError("LoadComments", err) return } notifications = notifications.Without(failures) failCount += len(failures) if failCount > 0 { - c.Flash.Error(fmt.Sprintf("ERROR: %d notifications were removed due to missing parts - check the logs", failCount)) + ctx.Flash.Error(fmt.Sprintf("ERROR: %d notifications were removed due to missing parts - check the logs", failCount)) } - c.Data["Title"] = c.Tr("notifications") - c.Data["Keyword"] = keyword - c.Data["Status"] = status - c.Data["Notifications"] = notifications + ctx.Data["Title"] = ctx.Tr("notifications") + ctx.Data["Keyword"] = keyword + ctx.Data["Status"] = status + ctx.Data["Notifications"] = notifications - pager.SetDefaultParams(c) - c.Data["Page"] = pager + pager.SetDefaultParams(ctx) + ctx.Data["Page"] = pager } // NotificationStatusPost is a route for changing the status of a notification -func NotificationStatusPost(c *context.Context) { +func NotificationStatusPost(ctx *context.Context) { var ( - notificationID = c.FormInt64("notification_id") - statusStr = c.FormString("status") + notificationID = ctx.FormInt64("notification_id") + statusStr = ctx.FormString("status") status activities_model.NotificationStatus ) @@ -169,56 +169,56 @@ func NotificationStatusPost(c *context.Context) { case "pinned": status = activities_model.NotificationStatusPinned default: - c.ServerError("InvalidNotificationStatus", errors.New("Invalid notification status")) + ctx.ServerError("InvalidNotificationStatus", errors.New("Invalid notification status")) return } - if _, err := activities_model.SetNotificationStatus(notificationID, c.Doer, status); err != nil { - c.ServerError("SetNotificationStatus", err) + if _, err := activities_model.SetNotificationStatus(ctx, notificationID, ctx.Doer, status); err != nil { + ctx.ServerError("SetNotificationStatus", err) return } - if !c.FormBool("noredirect") { - url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, url.QueryEscape(c.FormString("page"))) - c.Redirect(url, http.StatusSeeOther) + if !ctx.FormBool("noredirect") { + url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, url.QueryEscape(ctx.FormString("page"))) + ctx.Redirect(url, http.StatusSeeOther) } - getNotifications(c) - if c.Written() { + getNotifications(ctx) + if ctx.Written() { return } - c.Data["Link"] = setting.AppURL + "notifications" - c.Data["SequenceNumber"] = c.Req.PostFormValue("sequence-number") + ctx.Data["Link"] = setting.AppURL + "notifications" + ctx.Data["SequenceNumber"] = ctx.Req.PostFormValue("sequence-number") - c.HTML(http.StatusOK, tplNotificationDiv) + ctx.HTML(http.StatusOK, tplNotificationDiv) } // NotificationPurgePost is a route for 'purging' the list of notifications - marking all unread as read -func NotificationPurgePost(c *context.Context) { - err := activities_model.UpdateNotificationStatuses(c.Doer, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead) +func NotificationPurgePost(ctx *context.Context) { + err := activities_model.UpdateNotificationStatuses(ctx, ctx.Doer, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead) if err != nil { - c.ServerError("ErrUpdateNotificationStatuses", err) + ctx.ServerError("UpdateNotificationStatuses", err) return } - c.Redirect(setting.AppSubURL+"/notifications", http.StatusSeeOther) + ctx.Redirect(setting.AppSubURL+"/notifications", http.StatusSeeOther) } // NotificationSubscriptions returns the list of subscribed issues -func NotificationSubscriptions(c *context.Context) { - page := c.FormInt("page") +func NotificationSubscriptions(ctx *context.Context) { + page := ctx.FormInt("page") if page < 1 { page = 1 } - sortType := c.FormString("sort") - c.Data["SortType"] = sortType + sortType := ctx.FormString("sort") + ctx.Data["SortType"] = sortType - state := c.FormString("state") + state := ctx.FormString("state") if !util.IsStringInSlice(state, []string{"all", "open", "closed"}, true) { state = "all" } - c.Data["State"] = state + ctx.Data["State"] = state var showClosed util.OptionalBool switch state { case "all": @@ -230,7 +230,7 @@ func NotificationSubscriptions(c *context.Context) { } var issueTypeBool util.OptionalBool - issueType := c.FormString("issueType") + issueType := ctx.FormString("issueType") switch issueType { case "issues": issueTypeBool = util.OptionalBoolFalse @@ -239,71 +239,71 @@ func NotificationSubscriptions(c *context.Context) { default: issueTypeBool = util.OptionalBoolNone } - c.Data["IssueType"] = issueType + ctx.Data["IssueType"] = issueType var labelIDs []int64 - selectedLabels := c.FormString("labels") - c.Data["Labels"] = selectedLabels + selectedLabels := ctx.FormString("labels") + ctx.Data["Labels"] = selectedLabels if len(selectedLabels) > 0 && selectedLabels != "0" { var err error labelIDs, err = base.StringsToInt64s(strings.Split(selectedLabels, ",")) if err != nil { - c.ServerError("StringsToInt64s", err) + ctx.ServerError("StringsToInt64s", err) return } } - count, err := issues_model.CountIssues(&issues_model.IssuesOptions{ - SubscriberID: c.Doer.ID, + count, err := issues_model.CountIssues(ctx, &issues_model.IssuesOptions{ + SubscriberID: ctx.Doer.ID, IsClosed: showClosed, IsPull: issueTypeBool, LabelIDs: labelIDs, }) if err != nil { - c.ServerError("CountIssues", err) + ctx.ServerError("CountIssues", err) return } - issues, err := issues_model.Issues(&issues_model.IssuesOptions{ + issues, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.IssuePagingNum, Page: page, }, - SubscriberID: c.Doer.ID, + SubscriberID: ctx.Doer.ID, SortType: sortType, IsClosed: showClosed, IsPull: issueTypeBool, LabelIDs: labelIDs, }) if err != nil { - c.ServerError("Issues", err) + ctx.ServerError("Issues", err) return } - commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(c, issues) + commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, issues) if err != nil { - c.ServerError("GetIssuesAllCommitStatus", err) + ctx.ServerError("GetIssuesAllCommitStatus", err) return } - c.Data["CommitLastStatus"] = lastStatus - c.Data["CommitStatuses"] = commitStatuses - c.Data["Issues"] = issues + ctx.Data["CommitLastStatus"] = lastStatus + ctx.Data["CommitStatuses"] = commitStatuses + ctx.Data["Issues"] = issues - c.Data["IssueRefEndNames"], c.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, "") + ctx.Data["IssueRefEndNames"], ctx.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, "") - commitStatus, err := pull_service.GetIssuesLastCommitStatus(c, issues) + commitStatus, err := pull_service.GetIssuesLastCommitStatus(ctx, issues) if err != nil { - c.ServerError("GetIssuesLastCommitStatus", err) + ctx.ServerError("GetIssuesLastCommitStatus", err) return } - c.Data["CommitStatus"] = commitStatus + ctx.Data["CommitStatus"] = commitStatus issueList := issues_model.IssueList(issues) - approvalCounts, err := issueList.GetApprovalCounts(c) + approvalCounts, err := issueList.GetApprovalCounts(ctx) if err != nil { - c.ServerError("ApprovalCounts", err) + ctx.ServerError("ApprovalCounts", err) return } - c.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 { + ctx.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 { counts, ok := approvalCounts[issueID] if !ok || len(counts) == 0 { return 0 @@ -322,32 +322,32 @@ func NotificationSubscriptions(c *context.Context) { return 0 } - c.Data["Status"] = 1 - c.Data["Title"] = c.Tr("notification.subscriptions") + ctx.Data["Status"] = 1 + ctx.Data["Title"] = ctx.Tr("notification.subscriptions") // redirect to last page if request page is more than total pages pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) if pager.Paginater.Current() < page { - c.Redirect(fmt.Sprintf("/notifications/subscriptions?page=%d", pager.Paginater.Current())) + ctx.Redirect(fmt.Sprintf("/notifications/subscriptions?page=%d", pager.Paginater.Current())) return } - pager.AddParam(c, "sort", "SortType") - pager.AddParam(c, "state", "State") - c.Data["Page"] = pager + pager.AddParam(ctx, "sort", "SortType") + pager.AddParam(ctx, "state", "State") + ctx.Data["Page"] = pager - c.HTML(http.StatusOK, tplNotificationSubscriptions) + ctx.HTML(http.StatusOK, tplNotificationSubscriptions) } // NotificationWatching returns the list of watching repos -func NotificationWatching(c *context.Context) { - page := c.FormInt("page") +func NotificationWatching(ctx *context.Context) { + page := ctx.FormInt("page") if page < 1 { page = 1 } var orderBy db.SearchOrderBy - c.Data["SortType"] = c.FormString("sort") - switch c.FormString("sort") { + ctx.Data["SortType"] = ctx.FormString("sort") + switch ctx.FormString("sort") { case "newest": orderBy = db.SearchOrderByNewest case "oldest": @@ -369,41 +369,41 @@ func NotificationWatching(c *context.Context) { case "fewestforks": orderBy = db.SearchOrderByForks default: - c.Data["SortType"] = "recentupdate" + ctx.Data["SortType"] = "recentupdate" orderBy = db.SearchOrderByRecentUpdated } - repos, count, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, }, - Actor: c.Doer, - Keyword: c.FormTrim("q"), + Actor: ctx.Doer, + Keyword: ctx.FormTrim("q"), OrderBy: orderBy, - Private: c.IsSigned, - WatchedByID: c.Doer.ID, + Private: ctx.IsSigned, + WatchedByID: ctx.Doer.ID, Collaborate: util.OptionalBoolFalse, - TopicOnly: c.FormBool("topic"), + TopicOnly: ctx.FormBool("topic"), IncludeDescription: setting.UI.SearchRepoDescription, }) if err != nil { - c.ServerError("ErrSearchRepository", err) + ctx.ServerError("SearchRepository", err) return } total := int(count) - c.Data["Total"] = total - c.Data["Repos"] = repos + ctx.Data["Total"] = total + ctx.Data["Repos"] = repos // redirect to last page if request page is more than total pages pager := context.NewPagination(total, setting.UI.User.RepoPagingNum, page, 5) - pager.SetDefaultParams(c) - c.Data["Page"] = pager + pager.SetDefaultParams(ctx) + ctx.Data["Page"] = pager - c.Data["Status"] = 2 - c.Data["Title"] = c.Tr("notification.watching") + ctx.Data["Status"] = 2 + ctx.Data["Title"] = ctx.Tr("notification.watching") - c.HTML(http.StatusOK, tplNotificationSubscriptions) + ctx.HTML(http.StatusOK, tplNotificationSubscriptions) } // NewAvailable returns the notification counts diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 6e16b377dbc3b..982290e0ab2e8 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -203,7 +203,7 @@ func Profile(ctx *context.Context) { } case "stars": ctx.Data["PageIsProfileStarList"] = true - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, @@ -235,7 +235,7 @@ func Profile(ctx *context.Context) { return } case "watching": - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, @@ -257,7 +257,7 @@ func Profile(ctx *context.Context) { total = int(count) default: - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, diff --git a/services/agit/agit.go b/services/agit/agit.go index a7e701d6c4f46..803ff696b0eb8 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -96,7 +96,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. headBranch = curentTopicBranch } - pr, err := issues_model.GetUnmergedPullRequest(repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit) + pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { return nil, fmt.Errorf("Failed to get unmerged agit flow pull request in repository: %s/%s Error: %w", ownerName, repoName, err) @@ -159,7 +159,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. } // update exist pull request - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return nil, fmt.Errorf("Unable to load base repository for PR[%d] Error: %w", pr.ID, err) } @@ -203,15 +203,15 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. if err != nil { return nil, fmt.Errorf("Failed to get user. Error: %w", err) } - err = pr.LoadIssue() + err = pr.LoadIssue(ctx) if err != nil { return nil, fmt.Errorf("Failed to load pull issue. Error: %w", err) } comment, err := issues_model.CreatePushPullComment(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i]) if err == nil && comment != nil { - notification.NotifyPullRequestPushCommits(pusher, pr, comment) + notification.NotifyPullRequestPushCommits(ctx, pusher, pr, comment) } - notification.NotifyPullRequestSynchronized(pusher, pr) + notification.NotifyPullRequestSynchronized(ctx, pusher, pr) isForcePush := comment != nil && comment.IsForcePush results = append(results, private.HookProcReceiveRefResult{ diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index edfd0f6cadf25..a9d1e179aedba 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -272,7 +272,7 @@ Loop: // SignMerge determines if we should sign a PR merge commit to the base repository func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, string, *git.Signature, error) { - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to get Base Repo for pull request") return false, "", nil, err } diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index 5c38367e3be52..3291ed31f0da1 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -188,8 +188,8 @@ func handlePull(pullID int64, sha string) { // We get the latest sha commit hash again to handle the case where the check of a previous push // did not succeed or was not finished yet. - if err = pr.LoadHeadRepoCtx(ctx); err != nil { - log.Error("pull[%d] LoadHeadRepoCtx: %v", pr.ID, err) + if err = pr.LoadHeadRepo(ctx); err != nil { + log.Error("pull[%d] LoadHeadRepo: %v", pr.ID, err) return } @@ -244,8 +244,8 @@ func handlePull(pullID int64, sha string) { if pr.BaseRepoID == pr.HeadRepoID { baseGitRepo = headGitRepo } else { - if err = pr.LoadBaseRepoCtx(ctx); err != nil { - log.Error("LoadBaseRepoCtx: %v", err) + if err = pr.LoadBaseRepo(ctx); err != nil { + log.Error("LoadBaseRepo: %v", err) return } diff --git a/services/comments/comments.go b/services/comments/comments.go index 7167219c20ce0..190b8a6725b0b 100644 --- a/services/comments/comments.go +++ b/services/comments/comments.go @@ -5,6 +5,8 @@ package comments import ( + "context" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" @@ -14,7 +16,7 @@ import ( ) // CreateIssueComment creates a plain issue comment. -func CreateIssueComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) { +func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) { comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{ Type: issues_model.CommentTypeComment, Doer: doer, @@ -27,27 +29,27 @@ func CreateIssueComment(doer *user_model.User, repo *repo_model.Repository, issu return nil, err } - mentions, err := issues_model.FindAndUpdateIssueMentions(db.DefaultContext, issue, doer, comment.Content) + mentions, err := issues_model.FindAndUpdateIssueMentions(ctx, issue, doer, comment.Content) if err != nil { return nil, err } - notification.NotifyCreateIssueComment(doer, repo, issue, comment, mentions) + notification.NotifyCreateIssueComment(ctx, doer, repo, issue, comment, mentions) return comment, nil } // UpdateComment updates information of comment. -func UpdateComment(c *issues_model.Comment, doer *user_model.User, oldContent string) error { +func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User, oldContent string) error { needsContentHistory := c.Content != oldContent && (c.Type == issues_model.CommentTypeComment || c.Type == issues_model.CommentTypeReview || c.Type == issues_model.CommentTypeCode) if needsContentHistory { - hasContentHistory, err := issues_model.HasIssueContentHistory(db.DefaultContext, c.IssueID, c.ID) + hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID) if err != nil { return err } if !hasContentHistory { - if err = issues_model.SaveIssueContentHistory(db.DefaultContext, c.PosterID, c.IssueID, c.ID, + if err = issues_model.SaveIssueContentHistory(ctx, c.PosterID, c.IssueID, c.ID, c.CreatedUnix, oldContent, true); err != nil { return err } @@ -59,33 +61,27 @@ func UpdateComment(c *issues_model.Comment, doer *user_model.User, oldContent st } if needsContentHistory { - err := issues_model.SaveIssueContentHistory(db.DefaultContext, doer.ID, c.IssueID, c.ID, timeutil.TimeStampNow(), c.Content, false) + err := issues_model.SaveIssueContentHistory(ctx, doer.ID, c.IssueID, c.ID, timeutil.TimeStampNow(), c.Content, false) if err != nil { return err } } - notification.NotifyUpdateComment(doer, c, oldContent) + notification.NotifyUpdateComment(ctx, doer, c, oldContent) return nil } // DeleteComment deletes the comment -func DeleteComment(doer *user_model.User, comment *issues_model.Comment) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) error { + err := db.AutoTx(ctx, func(ctx context.Context) error { + return issues_model.DeleteComment(ctx, comment) + }) if err != nil { return err } - defer committer.Close() - - if err := issues_model.DeleteComment(ctx, comment); err != nil { - return err - } - if err := committer.Commit(); err != nil { - return err - } - notification.NotifyDeleteComment(doer, comment) + notification.NotifyDeleteComment(ctx, doer, comment) return nil } diff --git a/services/issue/assignee.go b/services/issue/assignee.go index e24f8500c9ae2..291fc31637141 100644 --- a/services/issue/assignee.go +++ b/services/issue/assignee.go @@ -51,13 +51,13 @@ func ToggleAssignee(issue *issues_model.Issue, doer *user_model.User, assigneeID return } - assignee, err1 := user_model.GetUserByID(assigneeID) + assignee, err1 := user_model.GetUserByIDCtx(db.DefaultContext, assigneeID) if err1 != nil { err = err1 return } - notification.NotifyIssueChangeAssignee(doer, issue, assignee, removed, comment) + notification.NotifyIssueChangeAssignee(db.DefaultContext, doer, issue, assignee, removed, comment) return removed, comment, err } @@ -75,7 +75,7 @@ func ReviewRequest(issue *issues_model.Issue, doer, reviewer *user_model.User, i } if comment != nil { - notification.NotifyPullReviewRequest(doer, issue, reviewer, isAdd, comment) + notification.NotifyPullReviewRequest(db.DefaultContext, doer, issue, reviewer, isAdd, comment) } return comment, err @@ -246,7 +246,7 @@ func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewe } // notify all user in this team - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(db.DefaultContext); err != nil { return } @@ -262,7 +262,7 @@ func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewe continue } comment.AssigneeID = member.ID - notification.NotifyPullReviewRequest(doer, issue, member, isAdd, comment) + notification.NotifyPullReviewRequest(db.DefaultContext, doer, issue, member, isAdd, comment) } return comment, err diff --git a/services/issue/content.go b/services/issue/content.go index 6f493892f4cb5..851d986de3010 100644 --- a/services/issue/content.go +++ b/services/issue/content.go @@ -5,6 +5,7 @@ package issue import ( + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/notification" @@ -18,7 +19,7 @@ func ChangeContent(issue *issues_model.Issue, doer *user_model.User, content str return err } - notification.NotifyIssueChangeContent(doer, issue, oldContent) + notification.NotifyIssueChangeContent(db.DefaultContext, doer, issue, oldContent) return nil } diff --git a/services/issue/issue.go b/services/issue/issue.go index 8342d7f5d2de7..ba9b17a0c8ab1 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -38,12 +38,12 @@ func NewIssue(repo *repo_model.Repository, issue *issues_model.Issue, labelIDs [ return err } - notification.NotifyNewIssue(issue, mentions) + notification.NotifyNewIssue(db.DefaultContext, issue, mentions) if len(issue.Labels) > 0 { - notification.NotifyIssueChangeLabels(issue.Poster, issue, issue.Labels, nil) + notification.NotifyIssueChangeLabels(db.DefaultContext, issue.Poster, issue, issue.Labels, nil) } if issue.Milestone != nil { - notification.NotifyIssueChangeMilestone(issue.Poster, issue, 0) + notification.NotifyIssueChangeMilestone(db.DefaultContext, issue.Poster, issue, 0) } return nil @@ -58,7 +58,7 @@ func ChangeTitle(issue *issues_model.Issue, doer *user_model.User, title string) return } - notification.NotifyIssueChangeTitle(doer, issue, oldTitle) + notification.NotifyIssueChangeTitle(db.DefaultContext, doer, issue, oldTitle) return nil } @@ -72,7 +72,7 @@ func ChangeIssueRef(issue *issues_model.Issue, doer *user_model.User, ref string return err } - notification.NotifyIssueChangeRef(doer, issue, oldRef) + notification.NotifyIssueChangeRef(db.DefaultContext, doer, issue, oldRef) return nil } @@ -135,10 +135,10 @@ func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssi // DeleteIssue deletes an issue func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue) error { // load issue before deleting it - if err := issue.LoadAttributes(db.DefaultContext); err != nil { + if err := issue.LoadAttributes(gitRepo.Ctx); err != nil { return err } - if err := issue.LoadPullRequest(); err != nil { + if err := issue.LoadPullRequest(gitRepo.Ctx); err != nil { return err } @@ -154,7 +154,7 @@ func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_m } } - notification.NotifyDeleteIssue(doer, issue) + notification.NotifyDeleteIssue(gitRepo.Ctx, doer, issue) return nil } @@ -162,7 +162,7 @@ func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_m // AddAssigneeIfNotAssigned adds an assignee only if he isn't already assigned to the issue. // Also checks for access of assigned user func AddAssigneeIfNotAssigned(issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (err error) { - assignee, err := user_model.GetUserByID(assigneeID) + assignee, err := user_model.GetUserByIDCtx(db.DefaultContext, assigneeID) if err != nil { return err } diff --git a/services/issue/label.go b/services/issue/label.go index a9a0c20b01492..cd29fcebaebf4 100644 --- a/services/issue/label.go +++ b/services/issue/label.go @@ -18,7 +18,7 @@ func ClearLabels(issue *issues_model.Issue, doer *user_model.User) (err error) { return } - notification.NotifyIssueClearLabels(doer, issue) + notification.NotifyIssueClearLabels(db.DefaultContext, doer, issue) return nil } @@ -29,7 +29,7 @@ func AddLabel(issue *issues_model.Issue, doer *user_model.User, label *issues_mo return err } - notification.NotifyIssueChangeLabels(doer, issue, []*issues_model.Label{label}, nil) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, []*issues_model.Label{label}, nil) return nil } @@ -39,7 +39,7 @@ func AddLabels(issue *issues_model.Issue, doer *user_model.User, labels []*issue return err } - notification.NotifyIssueChangeLabels(doer, issue, labels, nil) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, labels, nil) return nil } @@ -74,7 +74,7 @@ func RemoveLabel(issue *issues_model.Issue, doer *user_model.User, label *issues return err } - notification.NotifyIssueChangeLabels(doer, issue, nil, []*issues_model.Label{label}) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, nil, []*issues_model.Label{label}) return nil } @@ -89,6 +89,6 @@ func ReplaceLabels(issue *issues_model.Issue, doer *user_model.User, labels []*i return err } - notification.NotifyIssueChangeLabels(doer, issue, labels, old) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, labels, old) return nil } diff --git a/services/issue/milestone.go b/services/issue/milestone.go index 965b07556d1e0..2be4a9e70a2e5 100644 --- a/services/issue/milestone.go +++ b/services/issue/milestone.go @@ -79,7 +79,7 @@ func ChangeMilestoneAssign(issue *issues_model.Issue, doer *user_model.User, old return fmt.Errorf("Commit: %w", err) } - notification.NotifyIssueChangeMilestone(doer, issue, oldMilestoneID) + notification.NotifyIssueChangeMilestone(db.DefaultContext, doer, issue, oldMilestoneID) return nil } diff --git a/services/issue/status.go b/services/issue/status.go index 0da5c88762c81..2d4622324ca9f 100644 --- a/services/issue/status.go +++ b/services/issue/status.go @@ -38,7 +38,7 @@ func changeStatusCtx(ctx context.Context, issue *issues_model.Issue, doer *user_ } } - notification.NotifyIssueChangeStatus(doer, issue, comment, closed) + notification.NotifyIssueChangeStatus(ctx, doer, issue, comment, closed) return nil } diff --git a/services/lfs/locks.go b/services/lfs/locks.go index e87589d124684..45ba8faacd238 100644 --- a/services/lfs/locks.go +++ b/services/lfs/locks.go @@ -57,7 +57,7 @@ func GetListLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, rv.Authorization, true, false) if !authenticated { @@ -144,7 +144,7 @@ func PostLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { @@ -211,7 +211,7 @@ func VerifyLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { @@ -277,7 +277,7 @@ func UnLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { diff --git a/services/mailer/mail.go b/services/mailer/mail.go index 85a7d107e5275..a9e36e10f89b8 100644 --- a/services/mailer/mail.go +++ b/services/mailer/mail.go @@ -18,7 +18,6 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -265,7 +264,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient "Issue": ctx.Issue, "Comment": ctx.Comment, "IsPull": ctx.Issue.IsPull, - "User": ctx.Issue.Repo.MustOwner(), + "User": ctx.Issue.Repo.MustOwner(ctx), "Repo": ctx.Issue.Repo.FullName(), "Doer": ctx.Doer, "IsMention": fromMention, @@ -395,13 +394,13 @@ func sanitizeSubject(subject string) string { } // SendIssueAssignedMail composes and sends issue assigned email -func SendIssueAssignedMail(issue *issues_model.Issue, doer *user_model.User, content string, comment *issues_model.Comment, recipients []*user_model.User) error { +func SendIssueAssignedMail(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, content string, comment *issues_model.Comment, recipients []*user_model.User) error { if setting.MailService == nil { // No mail service configured return nil } - if err := issue.LoadRepo(db.DefaultContext); err != nil { + if err := issue.LoadRepo(ctx); err != nil { log.Error("Unable to load repo [%d] for issue #%d [%d]. Error: %v", issue.RepoID, issue.Index, issue.ID, err) return err } @@ -417,7 +416,7 @@ func SendIssueAssignedMail(issue *issues_model.Issue, doer *user_model.User, con for lang, tos := range langMap { msgs, err := composeIssueCommentMessages(&mailCommentContext{ - Context: context.TODO(), // TODO: use a correct context + Context: ctx, Issue: issue, Doer: doer, ActionType: activities_model.ActionType(0), diff --git a/services/mailer/mail_issue.go b/services/mailer/mail_issue.go index 61e276805dbfb..e7ff1d59d6c05 100644 --- a/services/mailer/mail_issue.go +++ b/services/mailer/mail_issue.go @@ -45,13 +45,13 @@ const ( func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_model.User) error { // Required by the mail composer; make sure to load these before calling the async function if err := ctx.Issue.LoadRepo(ctx); err != nil { - return fmt.Errorf("LoadRepo(): %w", err) + return fmt.Errorf("LoadRepo: %w", err) } - if err := ctx.Issue.LoadPoster(); err != nil { - return fmt.Errorf("LoadPoster(): %w", err) + if err := ctx.Issue.LoadPoster(ctx); err != nil { + return fmt.Errorf("LoadPoster: %w", err) } - if err := ctx.Issue.LoadPullRequest(); err != nil { - return fmt.Errorf("LoadPullRequest(): %w", err) + if err := ctx.Issue.LoadPullRequest(ctx); err != nil { + return fmt.Errorf("LoadPullRequest: %w", err) } // Enough room to avoid reallocations @@ -61,14 +61,14 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_mo unfiltered[0] = ctx.Issue.PosterID // =========== Assignees =========== - ids, err := issues_model.GetAssigneeIDsByIssue(ctx.Issue.ID) + ids, err := issues_model.GetAssigneeIDsByIssue(ctx, ctx.Issue.ID) if err != nil { return fmt.Errorf("GetAssigneeIDsByIssue(%d): %w", ctx.Issue.ID, err) } unfiltered = append(unfiltered, ids...) // =========== Participants (i.e. commenters, reviewers) =========== - ids, err = issues_model.GetParticipantsIDsByIssueID(ctx.Issue.ID) + ids, err = issues_model.GetParticipantsIDsByIssueID(ctx, ctx.Issue.ID) if err != nil { return fmt.Errorf("GetParticipantsIDsByIssueID(%d): %w", ctx.Issue.ID, err) } @@ -110,7 +110,7 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_mo } visited.AddMultiple(ids...) - unfilteredUsers, err := user_model.GetMaileableUsersByIDs(unfiltered, false) + unfilteredUsers, err := user_model.GetMaileableUsersByIDs(ctx, unfiltered, false) if err != nil { return err } @@ -173,7 +173,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, users []*user_model.User, vi // MailParticipants sends new issue thread created emails to repository watchers // and mentioned people. -func MailParticipants(issue *issues_model.Issue, doer *user_model.User, opType activities_model.ActionType, mentions []*user_model.User) error { +func MailParticipants(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, opType activities_model.ActionType, mentions []*user_model.User) error { if setting.MailService == nil { // No mail service configured return nil @@ -188,7 +188,7 @@ func MailParticipants(issue *issues_model.Issue, doer *user_model.User, opType a forceDoerNotification := opType == activities_model.ActionAutoMergePullRequest if err := mailIssueCommentToParticipants( &mailCommentContext{ - Context: context.TODO(), // TODO: use a correct context + Context: ctx, Issue: issue, Doer: doer, ActionType: opType, diff --git a/services/mailer/mail_release.go b/services/mailer/mail_release.go index 6df3fbbf1d0d6..b15fc05ce92f4 100644 --- a/services/mailer/mail_release.go +++ b/services/mailer/mail_release.go @@ -36,7 +36,7 @@ func MailNewRelease(ctx context.Context, rel *repo_model.Release) { return } - recipients, err := user_model.GetMaileableUsersByIDs(watcherIDList, false) + recipients, err := user_model.GetMaileableUsersByIDs(ctx, watcherIDList, false) if err != nil { log.Error("user_model.GetMaileableUsersByIDs: %v", err) return diff --git a/services/mailer/mail_repo.go b/services/mailer/mail_repo.go index 6fe9df0926e88..d3f5120929d20 100644 --- a/services/mailer/mail_repo.go +++ b/services/mailer/mail_repo.go @@ -6,9 +6,9 @@ package mailer import ( "bytes" + "context" "fmt" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -18,14 +18,14 @@ import ( ) // SendRepoTransferNotifyMail triggers a notification e-mail when a pending repository transfer was created -func SendRepoTransferNotifyMail(doer, newOwner *user_model.User, repo *repo_model.Repository) error { +func SendRepoTransferNotifyMail(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { if setting.MailService == nil { // No mail service configured return nil } if newOwner.IsOrganization() { - users, err := organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, newOwner.ID) + users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID) if err != nil { return err } diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 68a7182b07e09..362492631fa87 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -84,7 +84,7 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, labels, 12) - releases, err := repo_model.GetReleasesByRepoID(repo.ID, repo_model.FindReleasesOptions{ + releases, err := repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ ListOptions: db.ListOptions{ PageSize: 10, Page: 0, @@ -94,7 +94,7 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, releases, 8) - releases, err = repo_model.GetReleasesByRepoID(repo.ID, repo_model.FindReleasesOptions{ + releases, err = repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ ListOptions: db.ListOptions{ PageSize: 10, Page: 0, @@ -104,14 +104,14 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, releases, 1) - issues, err := issues_model.Issues(&issues_model.IssuesOptions{ + issues, err := issues_model.Issues(db.DefaultContext, &issues_model.IssuesOptions{ RepoID: repo.ID, IsPull: util.OptionalBoolFalse, SortType: "oldest", }) assert.NoError(t, err) assert.Len(t, issues, 15) - assert.NoError(t, issues[0].LoadDiscussComments()) + assert.NoError(t, issues[0].LoadDiscussComments(db.DefaultContext)) assert.Empty(t, issues[0].Comments) pulls, _, err := issues_model.PullRequests(repo.ID, &issues_model.PullRequestsOptions{ @@ -119,8 +119,8 @@ func TestGiteaUploadRepo(t *testing.T) { }) assert.NoError(t, err) assert.Len(t, pulls, 30) - assert.NoError(t, pulls[0].LoadIssue()) - assert.NoError(t, pulls[0].Issue.LoadDiscussComments()) + assert.NoError(t, pulls[0].LoadIssue(db.DefaultContext)) + assert.NoError(t, pulls[0].Issue.LoadDiscussComments(db.DefaultContext)) assert.Len(t, pulls[0].Issue.Comments, 2) } diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 6002e6b8edb28..4a77569d869c1 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -459,18 +459,18 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { log.Error("SyncMirrors [repo: %-v]: unable to GetRefCommitID [ref_name: %s]: %v", m.Repo, result.refName, err) continue } - notification.NotifySyncPushCommits(m.Repo.MustOwner(), m.Repo, &repo_module.PushUpdateOptions{ + notification.NotifySyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{ RefFullName: result.refName, OldCommitID: git.EmptySHA, NewCommitID: commitID, }, repo_module.NewPushCommits()) - notification.NotifySyncCreateRef(m.Repo.MustOwner(), m.Repo, tp, result.refName, commitID) + notification.NotifySyncCreateRef(ctx, m.Repo.MustOwner(ctx), m.Repo, tp, result.refName, commitID) continue } // Delete reference if result.newCommitID == gitShortEmptySha { - notification.NotifySyncDeleteRef(m.Repo.MustOwner(), m.Repo, tp, result.refName) + notification.NotifySyncDeleteRef(ctx, m.Repo.MustOwner(ctx), m.Repo, tp, result.refName) continue } @@ -498,7 +498,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { theCommits.CompareURL = m.Repo.ComposeCompareURL(oldCommitID, newCommitID) - notification.NotifySyncPushCommits(m.Repo.MustOwner(), m.Repo, &repo_module.PushUpdateOptions{ + notification.NotifySyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{ RefFullName: result.refName, OldCommitID: oldCommitID, NewCommitID: newCommitID, diff --git a/services/packages/packages.go b/services/packages/packages.go index 4513215ae14d9..76fdd02bf265c 100644 --- a/services/packages/packages.go +++ b/services/packages/packages.go @@ -108,12 +108,12 @@ func createPackageAndAddFile(pvci *PackageCreationInfo, pfci *PackageFileCreatio } if created { - pd, err := packages_model.GetPackageDescriptor(ctx, pv) + pd, err := packages_model.GetPackageDescriptor(db.DefaultContext, pv) if err != nil { return nil, nil, err } - notification.NotifyPackageCreate(pvci.Creator, pd) + notification.NotifyPackageCreate(db.DefaultContext, pvci.Creator, pd) } return pv, pf, nil @@ -409,7 +409,7 @@ func RemovePackageVersion(doer *user_model.User, pv *packages_model.PackageVersi return err } - notification.NotifyPackageDelete(doer, pd) + notification.NotifyPackageDelete(db.DefaultContext, doer, pd) return nil } diff --git a/services/pull/check.go b/services/pull/check.go index 6e91c22f3ea63..faf3459f16f3b 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -48,7 +48,7 @@ var ( func AddToTaskQueue(pr *issues_model.PullRequest) { err := prPatchCheckerQueue.PushFunc(strconv.FormatInt(pr.ID, 10), func() error { pr.Status = issues_model.PullRequestStatusChecking - err := pr.UpdateColsIfNotMerged("status") + err := pr.UpdateColsIfNotMerged(db.DefaultContext, "status") if err != nil { log.Error("AddToTaskQueue.UpdateCols[%d].(add to queue): %v", pr.ID, err) } else { @@ -68,7 +68,7 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce return ErrHasMerged } - if err := pr.LoadIssueCtx(ctx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { return err } else if pr.Issue.IsClosed { return ErrIsClosed @@ -142,7 +142,7 @@ func isSignedIfRequired(ctx context.Context, pr *issues_model.PullRequest, doer // checkAndUpdateStatus checks if pull request is possible to leaving checking status, // and set to be either conflict or mergeable. -func checkAndUpdateStatus(pr *issues_model.PullRequest) { +func checkAndUpdateStatus(ctx context.Context, pr *issues_model.PullRequest) { // Status is not changed to conflict means mergeable. if pr.Status == issues_model.PullRequestStatusChecking { pr.Status = issues_model.PullRequestStatusMergeable @@ -155,7 +155,7 @@ func checkAndUpdateStatus(pr *issues_model.PullRequest) { } if !has { - if err := pr.UpdateColsIfNotMerged("merge_base", "status", "conflicted_files", "changed_protected_files"); err != nil { + if err := pr.UpdateColsIfNotMerged(ctx, "merge_base", "status", "conflicted_files", "changed_protected_files"); err != nil { log.Error("Update[%d]: %v", pr.ID, err) } } @@ -232,7 +232,7 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com // manuallyMerged checks if a pull request got manually merged // When a pull request got manually merged mark the pull request as merged func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool { - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("PullRequest[%d].LoadBaseRepo: %v", pr.ID, err) return false } @@ -278,7 +278,7 @@ func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool { return false } - notification.NotifyMergePullRequest(pr, merger) + notification.NotifyMergePullRequest(ctx, merger, pr) log.Info("manuallyMerged[%d]: Marked as manually merged into %s/%s by commit id: %s", pr.ID, pr.BaseRepo.Name, pr.BaseBranch, commit.ID.String()) return true @@ -346,7 +346,7 @@ func testPR(id int64) { } return } - checkAndUpdateStatus(pr) + checkAndUpdateStatus(ctx, pr) } // CheckPrsForBaseBranch check all pulls with bseBrannch diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go index 5d846129f6ce4..10692221a4100 100644 --- a/services/pull/commit_status.go +++ b/services/pull/commit_status.go @@ -101,7 +101,7 @@ func IsPullCommitStatusPass(ctx context.Context, pr *issues_model.PullRequest) ( // GetPullRequestCommitStatusState returns pull request merged commit status state func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullRequest) (structs.CommitStatusState, error) { // Ensure HeadRepo is loaded - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { return "", errors.Wrap(err, "LoadHeadRepo") } @@ -129,7 +129,7 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR return "", err } - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return "", errors.Wrap(err, "LoadBaseRepo") } diff --git a/services/pull/edits.go b/services/pull/edits.go index 2938f2b108b93..84f7c80da7b76 100644 --- a/services/pull/edits.go +++ b/services/pull/edits.go @@ -23,7 +23,7 @@ func SetAllowEdits(ctx context.Context, doer *user_model.User, pr *issues_model. return ErrUserHasNoPermissionForAction } - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { return err } diff --git a/services/pull/merge.go b/services/pull/merge.go index 6f37a887db438..b29c9bc859932 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -40,18 +40,18 @@ import ( ) // GetDefaultMergeMessage returns default message used when merging pull request -func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (string, error) { - if err := pr.LoadHeadRepo(); err != nil { +func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (string, error) { + if err := pr.LoadHeadRepo(ctx); err != nil { return "", err } - if err := pr.LoadBaseRepo(); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return "", err } if pr.BaseRepo == nil { return "", repo_model.ErrRepoNotExist{ID: pr.BaseRepoID} } - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { return "", err } @@ -90,7 +90,7 @@ func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRe vars["HeadRepoOwnerName"] = pr.HeadRepo.OwnerName vars["HeadRepoName"] = pr.HeadRepo.Name } - refs, err := pr.ResolveCrossReferences(baseGitRepo.Ctx) + refs, err := pr.ResolveCrossReferences(ctx) if err == nil { closeIssueIndexes := make([]string, 0, len(refs)) closeWord := "close" @@ -134,10 +134,10 @@ func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRe // Merge merges pull request to base repository. // Caller should check PR is ready to be merged (review and status checks) func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error { - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %w", err) - } else if err := pr.LoadBaseRepo(); err != nil { + } else if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) return fmt.Errorf("LoadBaseRepo: %w", err) } @@ -179,24 +179,24 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U pr.MergerID = doer.ID if _, err := pr.SetMerged(hammerCtx); err != nil { - log.Error("setMerged [%d]: %v", pr.ID, err) + log.Error("SetMerged [%d]: %v", pr.ID, err) } - if err := pr.LoadIssueCtx(hammerCtx); err != nil { - log.Error("loadIssue [%d]: %v", pr.ID, err) + if err := pr.LoadIssue(hammerCtx); err != nil { + log.Error("LoadIssue [%d]: %v", pr.ID, err) } if err := pr.Issue.LoadRepo(hammerCtx); err != nil { - log.Error("loadRepo for issue [%d]: %v", pr.ID, err) + log.Error("LoadRepo for issue [%d]: %v", pr.ID, err) } if err := pr.Issue.Repo.GetOwner(hammerCtx); err != nil { - log.Error("GetOwner for issue repo [%d]: %v", pr.ID, err) + log.Error("GetOwner for PR [%d]: %v", pr.ID, err) } if wasAutoMerged { - notification.NotifyAutoMergePullRequest(pr, doer) + notification.NotifyAutoMergePullRequest(hammerCtx, doer, pr) } else { - notification.NotifyMergePullRequest(pr, doer) + notification.NotifyMergePullRequest(hammerCtx, doer, pr) } // Reset cached commit count @@ -210,7 +210,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U } for _, ref := range refs { - if err = ref.LoadIssueCtx(hammerCtx); err != nil { + if err = ref.LoadIssue(hammerCtx); err != nil { return err } if err = ref.Issue.LoadRepo(hammerCtx); err != nil { @@ -511,7 +511,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode return "", err } - if err = pr.Issue.LoadPoster(); err != nil { + if err = pr.Issue.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return "", fmt.Errorf("LoadPoster: %w", err) } @@ -767,7 +767,7 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a // CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks) func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) { - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return fmt.Errorf("LoadBaseRepo: %w", err) } @@ -878,7 +878,7 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit return err } - notification.NotifyMergePullRequest(pr, doer) + notification.NotifyMergePullRequest(baseGitRepo.Ctx, doer, pr) log.Info("manuallyMerged[%d]: Marked as manually merged into %s/%s by commit id: %s", pr.ID, pr.BaseRepo.Name, pr.BaseBranch, commitID) return nil } diff --git a/services/pull/patch.go b/services/pull/patch.go index 9b87ac22e296c..1046095ff1103 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -30,7 +30,7 @@ import ( // DownloadDiffOrPatch will write the patch for the pr to the writer func DownloadDiffOrPatch(ctx context.Context, pr *issues_model.PullRequest, w io.Writer, patch, binary bool) error { - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to load base repository ID %d for pr #%d [%d]", pr.BaseRepoID, pr.Index, pr.ID) return err } diff --git a/services/pull/pull.go b/services/pull/pull.go index 5f8bd6b67120c..e0dcefe1410b8 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -82,12 +82,12 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *issu return err } - notification.NotifyNewPullRequest(pr, mentions) + notification.NotifyNewPullRequest(prCtx, pr, mentions) if len(pull.Labels) > 0 { - notification.NotifyIssueChangeLabels(pull.Poster, pull, pull.Labels, nil) + notification.NotifyIssueChangeLabels(prCtx, pull.Poster, pull, pull.Labels, nil) } if pull.Milestone != nil { - notification.NotifyIssueChangeMilestone(pull.Poster, pull, 0) + notification.NotifyIssueChangeMilestone(prCtx, pull.Poster, pull, 0) } // add first push codes comment @@ -172,7 +172,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer } // Check if pull request for the new target branch already exists - existingPr, err := issues_model.GetUnmergedPullRequest(pr.HeadRepoID, pr.BaseRepoID, pr.HeadBranch, targetBranch, issues_model.PullRequestFlowGithub) + existingPr, err := issues_model.GetUnmergedPullRequest(ctx, pr.HeadRepoID, pr.BaseRepoID, pr.HeadBranch, targetBranch, issues_model.PullRequestFlowGithub) if existingPr != nil { return issues_model.ErrPullRequestAlreadyExists{ ID: existingPr.ID, @@ -210,7 +210,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer pr.CommitsAhead = divergence.Ahead pr.CommitsBehind = divergence.Behind - if err := pr.UpdateColsIfNotMerged("merge_base", "status", "conflicted_files", "changed_protected_files", "base_branch", "commits_ahead", "commits_behind"); err != nil { + if err := pr.UpdateColsIfNotMerged(ctx, "merge_base", "status", "conflicted_files", "changed_protected_files", "base_branch", "commits_ahead", "commits_behind"); err != nil { return err } @@ -231,9 +231,9 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer } func checkForInvalidation(ctx context.Context, requests issues_model.PullRequestList, repoID int64, doer *user_model.User, branch string) error { - repo, err := repo_model.GetRepositoryByID(repoID) + repo, err := repo_model.GetRepositoryByIDCtx(ctx, repoID) if err != nil { - return fmt.Errorf("GetRepositoryByID: %w", err) + return fmt.Errorf("GetRepositoryByIDCtx: %w", err) } gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) if err != nil { @@ -301,7 +301,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, } pr.Issue.PullRequest = pr - notification.NotifyPullRequestSynchronized(doer, pr) + notification.NotifyPullRequestSynchronized(ctx, doer, pr) } } } @@ -320,7 +320,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, AddToTaskQueue(pr) comment, err := issues_model.CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID) if err == nil && comment != nil { - notification.NotifyPullRequestPushCommits(doer, pr, comment) + notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment) } } @@ -352,14 +352,14 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, // checkIfPRContentChanged checks if diff to target branch has changed by push // A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) { - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { return false, fmt.Errorf("LoadHeadRepo: %w", err) } else if pr.HeadRepo == nil { // corrupt data assumed changed return true, nil } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return false, fmt.Errorf("LoadBaseRepo: %w", err) } @@ -430,22 +430,22 @@ func PushToBaseRepo(ctx context.Context, pr *issues_model.PullRequest) (err erro func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, prefixHeadBranch string) (err error) { log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName()) - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("Unable to load head repository for PR[%d] Error: %v", pr.ID, err) return err } headRepoPath := pr.HeadRepo.RepoPath() - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) return err } baseRepoPath := pr.BaseRepo.RepoPath() - if err = pr.LoadIssue(); err != nil { + if err = pr.LoadIssue(ctx); err != nil { return fmt.Errorf("unable to load issue %d for pr %d: %w", pr.IssueID, pr.ID, err) } - if err = pr.Issue.LoadPoster(); err != nil { + if err = pr.Issue.LoadPoster(ctx); err != nil { return fmt.Errorf("unable to load poster %d for pr %d: %w", pr.Issue.PosterID, pr.ID, err) } @@ -485,7 +485,7 @@ func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, pre // UpdateRef update refs/pull/id/head directly for agit flow pull request func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) { log.Trace("UpdateRef[%d]: upgate pull request ref in base repo '%s'", pr.ID, pr.GetGitRefName()) - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) return err } @@ -583,21 +583,21 @@ var commitMessageTrailersPattern = regexp.MustCompile(`(?:^|\n\n)(?:[\w-]+[ \t]* // GetSquashMergeCommitMessages returns the commit messages between head and merge base (if there is one) func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequest) string { - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { log.Error("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err) return "" } - if err := pr.Issue.LoadPoster(); err != nil { + if err := pr.Issue.LoadPoster(ctx); err != nil { log.Error("Cannot load poster %d for pr id %d, index %d Error: %v", pr.Issue.PosterID, pr.ID, pr.Index, err) return "" } if pr.HeadRepo == nil { var err error - pr.HeadRepo, err = repo_model.GetRepositoryByID(pr.HeadRepoID) + pr.HeadRepo, err = repo_model.GetRepositoryByIDCtx(ctx, pr.HeadRepoID) if err != nil { - log.Error("GetRepositoryById[%d]: %v", pr.HeadRepoID, err) + log.Error("GetRepositoryByIdCtx[%d]: %v", pr.HeadRepoID, err) return "" } } @@ -743,10 +743,10 @@ func GetIssuesLastCommitStatus(ctx context.Context, issues issues_model.IssueLis // GetIssuesAllCommitStatus returns a map of issue ID to a list of all statuses for the most recent commit as well as a map of issue ID to only the commit's latest status func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64][]*git_model.CommitStatus, map[int64]*git_model.CommitStatus, error) { - if err := issues.LoadPullRequests(); err != nil { + if err := issues.LoadPullRequests(ctx); err != nil { return nil, nil, err } - if _, err := issues.LoadRepositories(); err != nil { + if _, err := issues.LoadRepositories(ctx); err != nil { return nil, nil, err } @@ -802,7 +802,7 @@ func getAllCommitStatus(gitRepo *git.Repository, pr *issues_model.PullRequest) ( // IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, branchName string) (bool, error) { var err error - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return false, err } baseGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) @@ -816,7 +816,7 @@ func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, br return false, err } - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { return false, err } var headGitRepo *git.Repository diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index 769e3c72e9d2b..22eefd1624a3d 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -8,6 +8,7 @@ package pull import ( "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -40,18 +41,18 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) gitRepo, err := git.OpenRepository(git.DefaultContext, pr.BaseRepo.RepoPath()) assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, err := GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", mergeMessage) pr.BaseRepoID = 1 pr.HeadRepoID = 2 - mergeMessage, err = GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo1:branch2 into master", mergeMessage) } @@ -70,12 +71,12 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2, BaseRepo: baseRepo}) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) gitRepo, err := git.OpenRepository(git.DefaultContext, pr.BaseRepo.RepoPath()) assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, err := GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (!3) from branch2 into master", mergeMessage) @@ -84,7 +85,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr.HeadRepoID = 2 pr.BaseRepo = nil pr.HeadRepo = nil - mergeMessage, err = GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo2:branch2 into master", mergeMessage) diff --git a/services/pull/review.go b/services/pull/review.go index 16c9e108ee741..2555e1b3b35e2 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -67,7 +67,7 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git. return nil, err } - notification.NotifyCreateIssueComment(doer, issue.Repo, issue, comment, mentions) + notification.NotifyCreateIssueComment(ctx, doer, issue.Repo, issue, comment, mentions) return comment, nil } @@ -119,12 +119,12 @@ var notEnoughLines = regexp.MustCompile(`exit status 128 - fatal: file .* has on // createCodeComment creates a plain code comment at the specified line / path func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, treePath string, line, reviewID int64) (*issues_model.Comment, error) { var commitID, patch string - if err := issue.LoadPullRequest(); err != nil { - return nil, fmt.Errorf("GetPullRequestByIssueID: %w", err) + if err := issue.LoadPullRequest(ctx); err != nil { + return nil, fmt.Errorf("LoadPullRequest: %w", err) } pr := issue.PullRequest - if err := pr.LoadBaseRepoCtx(ctx); err != nil { - return nil, fmt.Errorf("LoadHeadRepo: %w", err) + if err := pr.LoadBaseRepo(ctx); err != nil { + return nil, fmt.Errorf("LoadBaseRepo: %w", err) } gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) if err != nil { @@ -254,7 +254,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos return nil, nil, err } - notification.NotifyPullRequestReview(pr, review, comm, mentions) + notification.NotifyPullRequestReview(ctx, pr, review, comm, mentions) for _, lines := range review.CodeComments { for _, comments := range lines { @@ -263,7 +263,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos if err != nil { return nil, nil, err } - notification.NotifyPullRequestCodeComment(pr, codeComment, mentions) + notification.NotifyPullRequestCodeComment(ctx, pr, codeComment, mentions) } } } @@ -316,7 +316,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string, return nil, nil } - if err = review.Issue.LoadPullRequest(); err != nil { + if err = review.Issue.LoadPullRequest(ctx); err != nil { return } if err = review.Issue.LoadAttributes(ctx); err != nil { @@ -339,7 +339,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string, comment.Poster = doer comment.Issue = review.Issue - notification.NotifyPullRevieweDismiss(doer, review, comment) + notification.NotifyPullReviewDismiss(ctx, doer, review, comment) return comment, err } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 15e776c4b9ce4..9c04aa1c92fe6 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -23,7 +23,7 @@ import ( // createTemporaryRepo creates a temporary repo with "base" for pr.BaseBranch and "tracking" for pr.HeadBranch // it also create a second base branch called "original_base" func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (string, error) { - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) return "", fmt.Errorf("LoadHeadRepo: %w", err) } else if pr.HeadRepo == nil { @@ -31,7 +31,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str return "", &repo_model.ErrRepoNotExist{ ID: pr.HeadRepoID, } - } else if err := pr.LoadBaseRepoCtx(ctx); err != nil { + } else if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) return "", fmt.Errorf("LoadBaseRepo: %w", err) } else if pr.BaseRepo == nil { diff --git a/services/pull/update.go b/services/pull/update.go index bd4880a2fc7a0..36e66bb7a9d50 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -48,10 +48,10 @@ func Update(ctx context.Context, pull *issues_model.PullRequest, doer *user_mode return fmt.Errorf("Not support update agit flow pull request's head branch") } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %w", err) - } else if err = pr.LoadBaseRepoCtx(ctx); err != nil { + } else if err = pr.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) return fmt.Errorf("LoadBaseRepo: %w", err) } @@ -145,10 +145,10 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest, // GetDiverging determines how many commits a PR is ahead or behind the PR base branch func GetDiverging(ctx context.Context, pr *issues_model.PullRequest) (*git.DivergeObject, error) { log.Trace("GetDiverging[%d]: compare commits", pr.ID) - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return nil, err } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { return nil, err } diff --git a/services/release/release.go b/services/release/release.go index cf398debbb8eb..eb989381f0f57 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -24,24 +24,24 @@ import ( "code.gitea.io/gitea/modules/timeutil" ) -func createTag(gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) { +func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) { var created bool // Only actual create when publish. if !rel.IsDraft { if !gitRepo.IsTagExist(rel.TagName) { - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return false, err } - protectedTags, err := git_model.GetProtectedTags(rel.Repo.ID) + protectedTags, err := git_model.GetProtectedTags(ctx, rel.Repo.ID) if err != nil { return false, fmt.Errorf("GetProtectedTags: %w", err) } // Trim '--' prefix to prevent command line argument vulnerability. rel.TagName = strings.TrimPrefix(rel.TagName, "--") - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, rel.TagName, rel.PublisherID) + isAllowed, err := git_model.IsUserAllowedToControlTag(ctx, protectedTags, rel.TagName, rel.PublisherID) if err != nil { return false, err } @@ -81,13 +81,13 @@ func createTag(gitRepo *git.Repository, rel *repo_model.Release, msg string) (bo commits.CompareURL = rel.Repo.ComposeCompareURL(git.EmptySHA, commit.ID.String()) notification.NotifyPushCommits( - rel.Publisher, rel.Repo, + ctx, rel.Publisher, rel.Repo, &repository.PushUpdateOptions{ RefFullName: git.TagPrefix + rel.TagName, OldCommitID: git.EmptySHA, NewCommitID: commit.ID.String(), }, commits) - notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName, commit.ID.String()) + notification.NotifyCreateRef(ctx, rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName, commit.ID.String()) rel.CreatedUnix = timeutil.TimeStampNow() } commit, err := gitRepo.GetTagCommit(rel.TagName) @@ -102,7 +102,7 @@ func createTag(gitRepo *git.Repository, rel *repo_model.Release, msg string) (bo } if rel.PublisherID <= 0 { - u, err := user_model.GetUserByEmail(commit.Author.Email) + u, err := user_model.GetUserByEmailContext(ctx, commit.Author.Email) if err == nil { rel.PublisherID = u.ID } @@ -124,7 +124,7 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU } } - if _, err = createTag(gitRepo, rel, msg); err != nil { + if _, err = createTag(gitRepo.Ctx, gitRepo, rel, msg); err != nil { return err } @@ -138,7 +138,7 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU } if !rel.IsDraft { - notification.NotifyNewRelease(rel) + notification.NotifyNewRelease(gitRepo.Ctx, rel) } return nil @@ -173,7 +173,7 @@ func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.R IsTag: true, } - if _, err = createTag(gitRepo, rel, msg); err != nil { + if _, err = createTag(ctx, gitRepo, rel, msg); err != nil { return err } @@ -190,7 +190,7 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod if rel.ID == 0 { return errors.New("UpdateRelease only accepts an exist release") } - isCreated, err := createTag(gitRepo, rel, "") + isCreated, err := createTag(gitRepo.Ctx, gitRepo, rel, "") if err != nil { return err } @@ -272,12 +272,12 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod } if !isCreated { - notification.NotifyUpdateRelease(doer, rel) + notification.NotifyUpdateRelease(gitRepo.Ctx, doer, rel) return } if !rel.IsDraft { - notification.NotifyNewRelease(rel) + notification.NotifyNewRelease(gitRepo.Ctx, rel) } return err @@ -296,11 +296,11 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } if delTag { - protectedTags, err := git_model.GetProtectedTags(rel.RepoID) + protectedTags, err := git_model.GetProtectedTags(ctx, rel.RepoID) if err != nil { return fmt.Errorf("GetProtectedTags: %w", err) } - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, rel.TagName, rel.PublisherID) + isAllowed, err := git_model.IsUserAllowedToControlTag(ctx, protectedTags, rel.TagName, rel.PublisherID) if err != nil { return err } @@ -318,15 +318,15 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } notification.NotifyPushCommits( - doer, repo, + ctx, doer, repo, &repository.PushUpdateOptions{ RefFullName: git.TagPrefix + rel.TagName, OldCommitID: rel.Sha1, NewCommitID: git.EmptySHA, }, repository.NewPushCommits()) - notification.NotifyDeleteRef(doer, repo, "tag", git.TagPrefix+rel.TagName) + notification.NotifyDeleteRef(ctx, doer, repo, "tag", git.TagPrefix+rel.TagName) - if err := repo_model.DeleteReleaseByID(id); err != nil { + if err := repo_model.DeleteReleaseByID(ctx, id); err != nil { return fmt.Errorf("DeleteReleaseByID: %w", err) } } else { @@ -338,11 +338,11 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } rel.Repo = repo - if err = rel.LoadAttributes(); err != nil { + if err = rel.LoadAttributes(ctx); err != nil { return fmt.Errorf("LoadAttributes: %w", err) } - if err := repo_model.DeleteAttachmentsByRelease(rel.ID); err != nil { + if err := repo_model.DeleteAttachmentsByRelease(ctx, rel.ID); err != nil { return fmt.Errorf("DeleteAttachments: %w", err) } @@ -353,7 +353,7 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } } - notification.NotifyDeleteRelease(doer, rel) + notification.NotifyDeleteRelease(ctx, doer, rel) return nil } diff --git a/services/release/release_test.go b/services/release/release_test.go index c0cafb5fcc081..1ade9bed37afa 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -297,13 +297,13 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.NotEmpty(t, release.CreatedUnix) releaseCreatedUnix := release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Note = "Changed note" - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -321,12 +321,12 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -344,13 +344,13 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: true, IsTag: false, } - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" release.Note = "Changed note" - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) } diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 57a21f500cd56..3895c54c7b957 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -96,7 +96,7 @@ func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOption return nil, err } - notification.NotifyCreateRepository(doer, u, repo) + notification.NotifyCreateRepository(db.DefaultContext, doer, u, repo) return repo, nil } diff --git a/services/repository/branch.go b/services/repository/branch.go index 1328422582980..e1f26b89afc2e 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -11,6 +11,7 @@ import ( "strings" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -141,8 +142,8 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g return "", err } - notification.NotifyDeleteRef(doer, repo, "branch", git.BranchPrefix+from) - notification.NotifyCreateRef(doer, repo, "branch", git.BranchPrefix+to, refID) + notification.NotifyDeleteRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+from) + notification.NotifyCreateRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+to, refID) return "", nil } diff --git a/services/repository/fork.go b/services/repository/fork.go index e597bfa449d4a..a9a2b33ed8472 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -177,7 +177,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork } } - notification.NotifyForkRepository(doer, opts.BaseRepo, repo) + notification.NotifyForkRepository(ctx, doer, opts.BaseRepo, repo) return repo, nil } diff --git a/services/repository/push.go b/services/repository/push.go index 6776ff9f740f1..e2db18e1f7599 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -117,7 +117,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { tagName := opts.TagName() if opts.IsDelRef() { notification.NotifyPushCommits( - pusher, repo, + db.DefaultContext, pusher, repo, &repo_module.PushUpdateOptions{ RefFullName: git.TagPrefix + tagName, OldCommitID: opts.OldCommitID, @@ -125,7 +125,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { }, repo_module.NewPushCommits()) delTags = append(delTags, tagName) - notification.NotifyDeleteRef(pusher, repo, "tag", opts.RefFullName) + notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName) } else { // is new tag newCommit, err := gitRepo.GetCommit(opts.NewCommitID) if err != nil { @@ -137,7 +137,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { commits.CompareURL = repo.ComposeCompareURL(git.EmptySHA, opts.NewCommitID) notification.NotifyPushCommits( - pusher, repo, + db.DefaultContext, pusher, repo, &repo_module.PushUpdateOptions{ RefFullName: git.TagPrefix + tagName, OldCommitID: git.EmptySHA, @@ -145,7 +145,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { }, commits) addTags = append(addTags, tagName) - notification.NotifyCreateRef(pusher, repo, "tag", opts.RefFullName, opts.NewCommitID) + notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName, opts.NewCommitID) } } else if opts.IsBranch() { // If is branch reference if pusher == nil || pusher.ID != opts.PusherID { @@ -190,7 +190,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { if err != nil { return fmt.Errorf("newCommit.CommitsBeforeLimit: %w", err) } - notification.NotifyCreateRef(pusher, repo, "branch", opts.RefFullName, opts.NewCommitID) + notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName, opts.NewCommitID) } else { l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID) if err != nil { @@ -250,7 +250,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum] } - notification.NotifyPushCommits(pusher, repo, opts, commits) + notification.NotifyPushCommits(db.DefaultContext, pusher, repo, opts, commits) if err = git_model.RemoveDeletedBranchByName(repo.ID, branch); err != nil { log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, branch, err) @@ -261,7 +261,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err) } } else { - notification.NotifyDeleteRef(pusher, repo, "branch", opts.RefFullName) + notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName) if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil { // close all related pulls log.Error("close related pull request failed: %v", err) diff --git a/services/repository/repository.go b/services/repository/repository.go index 2f2c27ff20bf6..c369b98aae091 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -32,7 +32,7 @@ func CreateRepository(doer, owner *user_model.User, opts repo_module.CreateRepoO return nil, err } - notification.NotifyCreateRepository(doer, owner, repo) + notification.NotifyCreateRepository(db.DefaultContext, doer, owner, repo) return repo, nil } @@ -45,7 +45,7 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod if notify { // If the repo itself has webhooks, we need to trigger them before deleting it... - notification.NotifyDeleteRepository(doer, repo) + notification.NotifyDeleteRepository(ctx, doer, repo) } if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil { diff --git a/services/repository/template.go b/services/repository/template.go index bb5e3f46689cd..625bc305de7ad 100644 --- a/services/repository/template.go +++ b/services/repository/template.go @@ -101,7 +101,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R return nil, err } - notification.NotifyCreateRepository(doer, owner, generateRepo) + notification.NotifyCreateRepository(db.DefaultContext, doer, owner, generateRepo) return generateRepo, nil } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index a0f4a7685ccbd..2778f2e744234 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -55,7 +55,7 @@ func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Reposit } } - notification.NotifyTransferRepository(doer, repo, oldOwner.Name) + notification.NotifyTransferRepository(db.DefaultContext, doer, repo, oldOwner.Name) return nil } @@ -78,7 +78,7 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne repoWorkingPool.CheckOut(fmt.Sprint(repo.ID)) repo.Name = newRepoName - notification.NotifyRenameRepository(doer, repo, oldRepoName) + notification.NotifyRenameRepository(db.DefaultContext, doer, repo, oldRepoName) return nil } @@ -127,7 +127,7 @@ func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.R } // notify users who are able to accept / reject transfer - notification.NotifyRepoPendingTransfer(doer, newOwner, repo) + notification.NotifyRepoPendingTransfer(db.DefaultContext, doer, newOwner, repo) return nil } diff --git a/services/task/migrate.go b/services/task/migrate.go index faca6908a271b..307c60a09a337 100644 --- a/services/task/migrate.go +++ b/services/task/migrate.go @@ -51,7 +51,7 @@ func runMigrateTask(t *admin_model.Task) (err error) { if err == nil { err = admin_model.FinishMigrateTask(t) if err == nil { - notification.NotifyMigrateRepository(t.Doer, t.Owner, t.Repo) + notification.NotifyMigrateRepository(db.DefaultContext, t.Doer, t.Owner, t.Repo) return } diff --git a/services/user/user.go b/services/user/user.go index 4186efe68257a..9976bc7bd3464 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -78,7 +78,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { Actor: u, }) if err != nil { - return fmt.Errorf("SearchRepositoryByName: %w", err) + return fmt.Errorf("GetUserRepositories: %w", err) } if len(repos) == 0 { break diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 342e764f4da16..1780022eb4b2f 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -224,7 +224,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_mode } ws = append(ws, repoHooks...) - owner = source.Repository.MustOwner() + owner = source.Repository.MustOwner(ctx) } // check if owner is an org and append additional webhooks diff --git a/templates/user/notification/notification_div.tmpl b/templates/user/notification/notification_div.tmpl index 192652d06b2b3..18071549a0c59 100644 --- a/templates/user/notification/notification_div.tmpl +++ b/templates/user/notification/notification_div.tmpl @@ -34,7 +34,6 @@ {{range $notification := .Notifications}} {{$issue := .Issue}} {{$repo := .Repository}} - {{$repoOwner := $repo.MustOwner}} {{if eq .Status 3}} @@ -69,9 +68,7 @@ - - {{$repoOwner.Name}}/{{$repo.Name}} - + {{$repo.FullName}} {{if ne .Status 3}} diff --git a/tests/integration/api_comment_test.go b/tests/integration/api_comment_test.go index 126d886842e49..9cac32b9b9df4 100644 --- a/tests/integration/api_comment_test.go +++ b/tests/integration/api_comment_test.go @@ -10,6 +10,7 @@ import ( "net/url" "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -115,7 +116,7 @@ func TestAPIGetComment(t *testing.T) { defer tests.PrepareTestEnv(t)() comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2}) - assert.NoError(t, comment.LoadIssue()) + assert.NoError(t, comment.LoadIssue(db.DefaultContext)) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID}) repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) @@ -129,7 +130,7 @@ func TestAPIGetComment(t *testing.T) { var apiComment api.Comment DecodeJSON(t, resp, &apiComment) - assert.NoError(t, comment.LoadPoster()) + assert.NoError(t, comment.LoadPoster(db.DefaultContext)) expect := convert.ToComment(comment) assert.Equal(t, expect.ID, apiComment.ID) diff --git a/tests/integration/api_issue_reaction_test.go b/tests/integration/api_issue_reaction_test.go index a3cb9303fbcf9..9afc7475e2769 100644 --- a/tests/integration/api_issue_reaction_test.go +++ b/tests/integration/api_issue_reaction_test.go @@ -82,7 +82,7 @@ func TestAPICommentReactions(t *testing.T) { defer tests.PrepareTestEnv(t)() comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2}) - _ = comment.LoadIssue() + _ = comment.LoadIssue(db.DefaultContext) issue := comment.Issue _ = issue.LoadRepo(db.DefaultContext) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID}) diff --git a/tests/integration/api_notification_test.go b/tests/integration/api_notification_test.go index bf85520bb53b7..f14380222873e 100644 --- a/tests/integration/api_notification_test.go +++ b/tests/integration/api_notification_test.go @@ -10,6 +10,7 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -25,7 +26,7 @@ func TestAPINotification(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5}) - assert.NoError(t, thread5.LoadAttributes()) + assert.NoError(t, thread5.LoadAttributes(db.DefaultContext)) session := loginUser(t, user2.Name) token := getTokenForLoggedInUser(t, session) @@ -143,7 +144,7 @@ func TestAPINotificationPUT(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5}) - assert.NoError(t, thread5.LoadAttributes()) + assert.NoError(t, thread5.LoadAttributes(db.DefaultContext)) session := loginUser(t, user2.Name) token := getTokenForLoggedInUser(t, session) diff --git a/tests/integration/api_pull_commits_test.go b/tests/integration/api_pull_commits_test.go index aa58f44bbe510..6753ceaa97310 100644 --- a/tests/integration/api_pull_commits_test.go +++ b/tests/integration/api_pull_commits_test.go @@ -8,6 +8,7 @@ import ( "net/http" "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -19,12 +20,12 @@ import ( func TestAPIPullCommits(t *testing.T) { defer tests.PrepareTestEnv(t)() - pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - assert.NoError(t, pullIssue.LoadIssue()) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pullIssue.HeadRepoID}) + pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pr.HeadRepoID}) session := loginUser(t, "user2") - req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/%s/pulls/%d/commits", repo.OwnerName, repo.Name, pullIssue.Index) + req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/%s/pulls/%d/commits", repo.OwnerName, repo.Name, pr.Index) resp := session.MakeRequest(t, req, http.StatusOK) var commits []*api.Commit diff --git a/tests/integration/api_pull_test.go b/tests/integration/api_pull_test.go index 8ce92f3d4a622..81842b05fbb25 100644 --- a/tests/integration/api_pull_test.go +++ b/tests/integration/api_pull_test.go @@ -10,6 +10,7 @@ import ( "net/http" "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -65,11 +66,11 @@ func TestAPIMergePullWIP(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Status: issues_model.PullRequestStatusMergeable}, unittest.Cond("has_merged = ?", false)) - pr.LoadIssue() + pr.LoadIssue(db.DefaultContext) issue_service.ChangeTitle(pr.Issue, owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title) // force reload - pr.LoadAttributes() + pr.LoadAttributes(db.DefaultContext) assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0]) diff --git a/tests/integration/eventsource_test.go b/tests/integration/eventsource_test.go index cd496e01292bb..2f698659cb963 100644 --- a/tests/integration/eventsource_test.go +++ b/tests/integration/eventsource_test.go @@ -11,6 +11,7 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -57,7 +58,7 @@ func TestEventSourceManagerRun(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5}) - assert.NoError(t, thread5.LoadAttributes()) + assert.NoError(t, thread5.LoadAttributes(db.DefaultContext)) session := loginUser(t, user2.Name) token := getTokenForLoggedInUser(t, session) diff --git a/tests/integration/pull_update_test.go b/tests/integration/pull_update_test.go index c08faaaeb6f4e..1bfe5c7050ddd 100644 --- a/tests/integration/pull_update_test.go +++ b/tests/integration/pull_update_test.go @@ -35,8 +35,8 @@ func TestAPIPullUpdate(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) - assert.NoError(t, pr.LoadBaseRepo()) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) session := loginUser(t, "user2") token := getTokenForLoggedInUser(t, session) @@ -63,8 +63,8 @@ func TestAPIPullUpdateByRebase(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) - assert.NoError(t, pr.LoadBaseRepo()) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) session := loginUser(t, "user2") token := getTokenForLoggedInUser(t, session) diff --git a/tests/integration/repo_tag_test.go b/tests/integration/repo_tag_test.go index fb08895e212f3..e20c725915560 100644 --- a/tests/integration/repo_tag_test.go +++ b/tests/integration/repo_tag_test.go @@ -9,6 +9,7 @@ import ( "testing" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -74,22 +75,22 @@ func TestCreateNewTagProtected(t *testing.T) { }) // Cleanup - releases, err := repo_model.GetReleasesByRepoID(repo.ID, repo_model.FindReleasesOptions{ + releases, err := repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ IncludeTags: true, TagNames: []string{"v-1", "v-1.1"}, }) assert.NoError(t, err) for _, release := range releases { - err = repo_model.DeleteReleaseByID(release.ID) + err = repo_model.DeleteReleaseByID(db.DefaultContext, release.ID) assert.NoError(t, err) } - protectedTags, err := git_model.GetProtectedTags(repo.ID) + protectedTags, err := git_model.GetProtectedTags(db.DefaultContext, repo.ID) assert.NoError(t, err) for _, protectedTag := range protectedTags { - err = git_model.DeleteProtectedTag(protectedTag) + err = git_model.DeleteProtectedTag(db.DefaultContext, protectedTag) assert.NoError(t, err) } } From eec1c718806797b21ba5f6c1ceddf711e9d4801a Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 19 Nov 2022 12:08:06 +0100 Subject: [PATCH 10/14] Show syntax lexer name in file view/blame (#21814) Show which Chroma Lexer is used to highlight the file in the file header. It's useful for development to see what was detected, and I think it's not bad info to have for the user: Screenshot 2022-11-14 at 22 31 16 Screenshot 2022-11-14 at 22 36 06 Screenshot 2022-11-14 at 22 36 26 Also, I improved the way this header overflows on small screens: Screenshot 2022-11-14 at 22 44 36 Co-authored-by: delvh Co-authored-by: Lauris BH Co-authored-by: Lunny Xiao Co-authored-by: John Olheiser --- modules/highlight/highlight.go | 36 ++++++++++++------ modules/highlight/highlight_test.go | 59 +++++++++++++++++++---------- modules/indexer/code/search.go | 5 ++- modules/util/util.go | 10 ++++- routers/web/repo/blame.go | 13 ++++++- routers/web/repo/view.go | 3 +- services/gitdiff/gitdiff.go | 3 +- services/gitdiff/highlightdiff.go | 4 +- templates/repo/blame.tmpl | 13 ++----- templates/repo/file_info.tmpl | 28 ++++++++++++++ templates/repo/view_file.tmpl | 30 ++------------- 11 files changed, 132 insertions(+), 72 deletions(-) create mode 100644 templates/repo/file_info.tmpl diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go index 65ed74b019950..3836c05880884 100644 --- a/modules/highlight/highlight.go +++ b/modules/highlight/highlight.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/analyze" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "github.com/alecthomas/chroma/v2" "github.com/alecthomas/chroma/v2/formatters/html" @@ -56,18 +57,18 @@ func NewContext() { }) } -// Code returns a HTML version of code string with chroma syntax highlighting classes -func Code(fileName, language, code string) string { +// Code returns a HTML version of code string with chroma syntax highlighting classes and the matched lexer name +func Code(fileName, language, code string) (string, string) { NewContext() // diff view newline will be passed as empty, change to literal '\n' so it can be copied // preserve literal newline in blame view if code == "" || code == "\n" { - return "\n" + return "\n", "" } if len(code) > sizeLimit { - return code + return code, "" } var lexer chroma.Lexer @@ -103,7 +104,10 @@ func Code(fileName, language, code string) string { } cache.Add(fileName, lexer) } - return CodeFromLexer(lexer, code) + + lexerName := formatLexerName(lexer.Config().Name) + + return CodeFromLexer(lexer, code), lexerName } // CodeFromLexer returns a HTML version of code string with chroma syntax highlighting classes @@ -134,12 +138,12 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string { return strings.TrimSuffix(htmlbuf.String(), "\n") } -// File returns a slice of chroma syntax highlighted HTML lines of code -func File(fileName, language string, code []byte) ([]string, error) { +// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name +func File(fileName, language string, code []byte) ([]string, string, error) { NewContext() if len(code) > sizeLimit { - return PlainText(code), nil + return PlainText(code), "", nil } formatter := html.New(html.WithClasses(true), @@ -172,9 +176,11 @@ func File(fileName, language string, code []byte) ([]string, error) { } } + lexerName := formatLexerName(lexer.Config().Name) + iterator, err := lexer.Tokenise(nil, string(code)) if err != nil { - return nil, fmt.Errorf("can't tokenize code: %w", err) + return nil, "", fmt.Errorf("can't tokenize code: %w", err) } tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens()) @@ -185,13 +191,13 @@ func File(fileName, language string, code []byte) ([]string, error) { iterator = chroma.Literator(tokens...) err = formatter.Format(htmlBuf, styles.GitHub, iterator) if err != nil { - return nil, fmt.Errorf("can't format code: %w", err) + return nil, "", fmt.Errorf("can't format code: %w", err) } lines = append(lines, htmlBuf.String()) htmlBuf.Reset() } - return lines, nil + return lines, lexerName, nil } // PlainText returns non-highlighted HTML for code @@ -212,3 +218,11 @@ func PlainText(code []byte) []string { } return m } + +func formatLexerName(name string) string { + if name == "fallback" { + return "Plaintext" + } + + return util.ToTitleCaseNoLower(name) +} diff --git a/modules/highlight/highlight_test.go b/modules/highlight/highlight_test.go index 8f83f4a2f6128..189975374614a 100644 --- a/modules/highlight/highlight_test.go +++ b/modules/highlight/highlight_test.go @@ -17,34 +17,52 @@ func lines(s string) []string { func TestFile(t *testing.T) { tests := []struct { - name string - code string - want []string + name string + code string + want []string + lexerName string }{ { - name: "empty.py", - code: "", - want: lines(""), + name: "empty.py", + code: "", + want: lines(""), + lexerName: "Python", }, { - name: "tags.txt", - code: "<>", - want: lines("<>"), + name: "empty.js", + code: "", + want: lines(""), + lexerName: "JavaScript", }, { - name: "tags.py", - code: "<>", - want: lines(`<>`), + name: "empty.yaml", + code: "", + want: lines(""), + lexerName: "YAML", }, { - name: "eol-no.py", - code: "a=1", - want: lines(`a=1`), + name: "tags.txt", + code: "<>", + want: lines("<>"), + lexerName: "Plaintext", }, { - name: "eol-newline1.py", - code: "a=1\n", - want: lines(`a=1\n`), + name: "tags.py", + code: "<>", + want: lines(`<>`), + lexerName: "Python", + }, + { + name: "eol-no.py", + code: "a=1", + want: lines(`a=1`), + lexerName: "Python", + }, + { + name: "eol-newline1.py", + code: "a=1\n", + want: lines(`a=1\n`), + lexerName: "Python", }, { name: "eol-newline2.py", @@ -54,6 +72,7 @@ func TestFile(t *testing.T) { \n `, ), + lexerName: "Python", }, { name: "empty-line-with-space.py", @@ -73,17 +92,19 @@ c=2 \n c=2`, ), + lexerName: "Python", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - out, err := File(tt.name, "", []byte(tt.code)) + out, lexerName, err := File(tt.name, "", []byte(tt.code)) assert.NoError(t, err) expected := strings.Join(tt.want, "\n") actual := strings.Join(out, "\n") assert.Equal(t, strings.Count(actual, "")) assert.EqualValues(t, expected, actual) + assert.Equal(t, tt.lexerName, lexerName) }) } } diff --git a/modules/indexer/code/search.go b/modules/indexer/code/search.go index bb7715bafcdc6..df255fa8758f8 100644 --- a/modules/indexer/code/search.go +++ b/modules/indexer/code/search.go @@ -94,6 +94,9 @@ func searchResult(result *SearchResult, startIndex, endIndex int) (*Result, erro lineNumbers[i] = startLineNum + i index += len(line) } + + highlighted, _ := highlight.Code(result.Filename, "", formattedLinesBuffer.String()) + return &Result{ RepoID: result.RepoID, Filename: result.Filename, @@ -102,7 +105,7 @@ func searchResult(result *SearchResult, startIndex, endIndex int) (*Result, erro Language: result.Language, Color: result.Color, LineNumbers: lineNumbers, - FormattedLines: highlight.Code(result.Filename, "", formattedLinesBuffer.String()), + FormattedLines: highlighted, }, nil } diff --git a/modules/util/util.go b/modules/util/util.go index be60fe4b4bbdf..6df47ca56821f 100644 --- a/modules/util/util.go +++ b/modules/util/util.go @@ -186,13 +186,21 @@ func ToUpperASCII(s string) string { return string(b) } -var titleCaser = cases.Title(language.English) +var ( + titleCaser = cases.Title(language.English) + titleCaserNoLower = cases.Title(language.English, cases.NoLower) +) // ToTitleCase returns s with all english words capitalized func ToTitleCase(s string) string { return titleCaser.String(s) } +// ToTitleCaseNoLower returns s with all english words capitalized without lowercasing +func ToTitleCaseNoLower(s string) string { + return titleCaserNoLower.String(s) +} + var ( whitespaceOnly = regexp.MustCompile("(?m)^[ \t]+$") leadingWhitespace = regexp.MustCompile("(?m)(^[ \t]*)(?:[^ \t\n])") diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index 64a6f0ec53850..52d5c3c6e628f 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -100,6 +100,8 @@ func RefBlame(ctx *context.Context) { ctx.Data["FileName"] = blob.Name() ctx.Data["NumLines"], err = blob.GetBlobLineCount() + ctx.Data["NumLinesSet"] = true + if err != nil { ctx.NotFound("GetBlobLineCount", err) return @@ -237,6 +239,8 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m rows := make([]*blameRow, 0) escapeStatus := &charset.EscapeStatus{} + var lexerName string + i := 0 commitCnt := 0 for _, part := range blameParts { @@ -278,7 +282,13 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m line += "\n" } fileName := fmt.Sprintf("%v", ctx.Data["FileName"]) - line = highlight.Code(fileName, language, line) + line, lexerNameForLine := highlight.Code(fileName, language, line) + + // set lexer name to the first detected lexer. this is certainly suboptimal and + // we should instead highlight the whole file at once + if lexerName == "" { + lexerName = lexerNameForLine + } br.EscapeStatus, line = charset.EscapeControlHTML(line, ctx.Locale) br.Code = gotemplate.HTML(line) @@ -290,4 +300,5 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m ctx.Data["EscapeStatus"] = escapeStatus ctx.Data["BlameRows"] = rows ctx.Data["CommitCnt"] = commitCnt + ctx.Data["LexerName"] = lexerName } diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index e7aca04819296..7500dbb34bb35 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -568,7 +568,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st language = "" } } - fileContent, err := highlight.File(blob.Name(), language, buf) + fileContent, lexerName, err := highlight.File(blob.Name(), language, buf) + ctx.Data["LexerName"] = lexerName if err != nil { log.Error("highlight.File failed, fallback to plain text: %v", err) fileContent = highlight.PlainText(buf) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 3c8c5c81a5694..d24c0ac082698 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -280,7 +280,8 @@ func DiffInlineWithUnicodeEscape(s template.HTML, locale translation.Locale) Dif // DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped func DiffInlineWithHighlightCode(fileName, language, code string, locale translation.Locale) DiffInline { - status, content := charset.EscapeControlHTML(highlight.Code(fileName, language, code), locale) + highlighted, _ := highlight.Code(fileName, language, code) + status, content := charset.EscapeControlHTML(highlighted, locale) return DiffInline{EscapeStatus: status, Content: template.HTML(content)} } diff --git a/services/gitdiff/highlightdiff.go b/services/gitdiff/highlightdiff.go index 4ceada4d7ec95..727827232d618 100644 --- a/services/gitdiff/highlightdiff.go +++ b/services/gitdiff/highlightdiff.go @@ -91,8 +91,8 @@ func (hcd *highlightCodeDiff) diffWithHighlight(filename, language, codeA, codeB hcd.collectUsedRunes(codeA) hcd.collectUsedRunes(codeB) - highlightCodeA := highlight.Code(filename, language, codeA) - highlightCodeB := highlight.Code(filename, language, codeB) + highlightCodeA, _ := highlight.Code(filename, language, codeA) + highlightCodeB, _ := highlight.Code(filename, language, codeB) highlightCodeA = hcd.convertToPlaceholders(highlightCodeA) highlightCodeB = hcd.convertToPlaceholders(highlightCodeB) diff --git a/templates/repo/blame.tmpl b/templates/repo/blame.tmpl index b697573d24eaa..e4a10ee57dd56 100644 --- a/templates/repo/blame.tmpl +++ b/templates/repo/blame.tmpl @@ -1,14 +1,9 @@
-

-
-
-
- {{.NumLines}} {{.locale.TrN .NumLines "repo.line" "repo.lines"}} -
-
{{FileSize .FileSize}}
-
+

+
+ {{template "repo/file_info" .}}
-
+
{{.locale.Tr "repo.file_raw"}} {{if not .IsViewCommit}} diff --git a/templates/repo/file_info.tmpl b/templates/repo/file_info.tmpl new file mode 100644 index 0000000000000..90a831fb8e897 --- /dev/null +++ b/templates/repo/file_info.tmpl @@ -0,0 +1,28 @@ +
+ {{if .FileIsSymlink}} +
+ {{.locale.Tr "repo.symbolic_link"}} +
+ {{end}} + {{if .NumLinesSet}}{{/* Explicit attribute needed to show 0 line changes */}} +
+ {{.NumLines}} {{.locale.TrN .NumLines "repo.line" "repo.lines"}} +
+ {{end}} + {{if .FileSize}} +
+ {{FileSize .FileSize}}{{if .IsLFSFile}} ({{.locale.Tr "repo.stored_lfs"}}){{end}} +
+ {{end}} + {{if .LFSLock}} +
+ {{svg "octicon-lock" 16 "mr-2"}} + {{.LFSLockOwner}} +
+ {{end}} + {{if .LexerName}} +
+ {{.LexerName}} +
+ {{end}} +
diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index 60d2a812defd0..321600a9975fe 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -6,38 +6,16 @@
{{end}} -

-
+

+
{{if .ReadmeInList}} {{svg "octicon-book" 16 "mr-3"}} {{.FileName}} {{else}} -
- {{if .FileIsSymlink}} -
- {{.locale.Tr "repo.symbolic_link"}} -
- {{end}} - {{if .NumLinesSet}} -
- {{.NumLines}} {{.locale.TrN .NumLines "repo.line" "repo.lines"}} -
- {{end}} - {{if .FileSize}} -
- {{FileSize .FileSize}}{{if .IsLFSFile}} ({{.locale.Tr "repo.stored_lfs"}}){{end}} -
- {{end}} - {{if .LFSLock}} -
- {{svg "octicon-lock" 16 "mr-2"}} - {{.LFSLockOwner}} -
- {{end}} -
+ {{template "repo/file_info" .}} {{end}}
-
+
{{if .HasSourceRenderedToggle}}
{{svg "octicon-code" 15}} From c8f3eb6acbf16b9f2e74fa2bfabb384359fbadd8 Mon Sep 17 00:00:00 2001 From: Jim Kirisame Date: Sat, 19 Nov 2022 23:19:14 +0800 Subject: [PATCH 11/14] Fix wechatwork webhook sends empty content in PR review (#21762) Wechatwork webhook is sending the following string for pull request reviews: ``` markdown # > ``` This commit fixes this problem. --- services/webhook/wechatwork.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/webhook/wechatwork.go b/services/webhook/wechatwork.go index 5344ccaa22db7..acaa12253bc80 100644 --- a/services/webhook/wechatwork.go +++ b/services/webhook/wechatwork.go @@ -139,7 +139,7 @@ func (f *WechatworkPayload) PullRequest(p *api.PullRequestPayload) (api.Payloade func (f *WechatworkPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { var text, title string switch p.Action { - case api.HookIssueSynchronized: + case api.HookIssueReviewed: action, err := parseHookPullRequestEventType(event) if err != nil { return nil, err From d3f850cc0e791fa5ee5b25d824c475505fc12444 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Sat, 19 Nov 2022 23:22:15 +0800 Subject: [PATCH 12/14] Support comma-delimited string as labels in issue template (#21831) The [labels in issue YAML templates](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax) can be a string array or a comma-delimited string, so a single string should be valid labels. The old codes committed in #20987 ignore this, that's why the warning is displayed: image Fixes #17877. --- modules/issue/template/template.go | 4 +- modules/issue/template/template_test.go | 312 ++++++++++++++++-------- modules/issue/template/unmarshal.go | 2 +- modules/markup/markdown/meta_test.go | 48 ++-- modules/structs/issue.go | 53 +++- modules/structs/issue_test.go | 63 +++++ templates/swagger/v1_json.tmpl | 13 +- 7 files changed, 362 insertions(+), 133 deletions(-) diff --git a/modules/issue/template/template.go b/modules/issue/template/template.go index 3b33852cb58d5..0bdf5a198746d 100644 --- a/modules/issue/template/template.go +++ b/modules/issue/template/template.go @@ -165,7 +165,7 @@ func validateOptions(field *api.IssueFormField, idx int) error { return position.Errorf("should be a string") } case api.IssueFormFieldTypeCheckboxes: - opt, ok := option.(map[interface{}]interface{}) + opt, ok := option.(map[string]interface{}) if !ok { return position.Errorf("should be a dictionary") } @@ -351,7 +351,7 @@ func (o *valuedOption) Label() string { return label } case api.IssueFormFieldTypeCheckboxes: - if vs, ok := o.data.(map[interface{}]interface{}); ok { + if vs, ok := o.data.(map[string]interface{}); ok { if v, ok := vs["label"].(string); ok { return v } diff --git a/modules/issue/template/template_test.go b/modules/issue/template/template_test.go index 883e1e0780510..c3863a64a6e16 100644 --- a/modules/issue/template/template_test.go +++ b/modules/issue/template/template_test.go @@ -6,18 +6,21 @@ package template import ( "net/url" - "reflect" "testing" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" + + "github.com/stretchr/testify/require" ) func TestValidate(t *testing.T) { tests := []struct { - name string - content string - wantErr string + name string + filename string + content string + want *api.IssueTemplate + wantErr string }{ { name: "miss name", @@ -316,21 +319,9 @@ body: `, wantErr: "body[0](checkboxes), option[0]: 'required' should be a bool", }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tmpl, err := unmarshal("test.yaml", []byte(tt.content)) - if err != nil { - t.Fatal(err) - } - if err := Validate(tmpl); (err == nil) != (tt.wantErr == "") || err != nil && err.Error() != tt.wantErr { - t.Errorf("Validate() error = %v, wantErr %q", err, tt.wantErr) - } - }) - } - - t.Run("valid", func(t *testing.T) { - content := ` + { + name: "valid", + content: ` name: Name title: Title about: About @@ -386,96 +377,227 @@ body: required: false - label: Option 3 of checkboxes required: true -` - want := &api.IssueTemplate{ - Name: "Name", - Title: "Title", - About: "About", - Labels: []string{"label1", "label2"}, - Ref: "Ref", - Fields: []*api.IssueFormField{ - { - Type: "markdown", - ID: "id1", - Attributes: map[string]interface{}{ - "value": "Value of the markdown", +`, + want: &api.IssueTemplate{ + Name: "Name", + Title: "Title", + About: "About", + Labels: []string{"label1", "label2"}, + Ref: "Ref", + Fields: []*api.IssueFormField{ + { + Type: "markdown", + ID: "id1", + Attributes: map[string]interface{}{ + "value": "Value of the markdown", + }, }, - }, - { - Type: "textarea", - ID: "id2", - Attributes: map[string]interface{}{ - "label": "Label of textarea", - "description": "Description of textarea", - "placeholder": "Placeholder of textarea", - "value": "Value of textarea", - "render": "bash", + { + Type: "textarea", + ID: "id2", + Attributes: map[string]interface{}{ + "label": "Label of textarea", + "description": "Description of textarea", + "placeholder": "Placeholder of textarea", + "value": "Value of textarea", + "render": "bash", + }, + Validations: map[string]interface{}{ + "required": true, + }, }, - Validations: map[string]interface{}{ - "required": true, + { + Type: "input", + ID: "id3", + Attributes: map[string]interface{}{ + "label": "Label of input", + "description": "Description of input", + "placeholder": "Placeholder of input", + "value": "Value of input", + }, + Validations: map[string]interface{}{ + "required": true, + "is_number": true, + "regex": "[a-zA-Z0-9]+", + }, }, - }, - { - Type: "input", - ID: "id3", - Attributes: map[string]interface{}{ - "label": "Label of input", - "description": "Description of input", - "placeholder": "Placeholder of input", - "value": "Value of input", + { + Type: "dropdown", + ID: "id4", + Attributes: map[string]interface{}{ + "label": "Label of dropdown", + "description": "Description of dropdown", + "multiple": true, + "options": []interface{}{ + "Option 1 of dropdown", + "Option 2 of dropdown", + "Option 3 of dropdown", + }, + }, + Validations: map[string]interface{}{ + "required": true, + }, }, - Validations: map[string]interface{}{ - "required": true, - "is_number": true, - "regex": "[a-zA-Z0-9]+", + { + Type: "checkboxes", + ID: "id5", + Attributes: map[string]interface{}{ + "label": "Label of checkboxes", + "description": "Description of checkboxes", + "options": []interface{}{ + map[string]interface{}{"label": "Option 1 of checkboxes", "required": true}, + map[string]interface{}{"label": "Option 2 of checkboxes", "required": false}, + map[string]interface{}{"label": "Option 3 of checkboxes", "required": true}, + }, + }, }, }, - { - Type: "dropdown", - ID: "id4", - Attributes: map[string]interface{}{ - "label": "Label of dropdown", - "description": "Description of dropdown", - "multiple": true, - "options": []interface{}{ - "Option 1 of dropdown", - "Option 2 of dropdown", - "Option 3 of dropdown", + FileName: "test.yaml", + }, + wantErr: "", + }, + { + name: "single label", + content: ` +name: Name +title: Title +about: About +labels: label1 +ref: Ref +body: + - type: markdown + id: id1 + attributes: + value: Value of the markdown +`, + want: &api.IssueTemplate{ + Name: "Name", + Title: "Title", + About: "About", + Labels: []string{"label1"}, + Ref: "Ref", + Fields: []*api.IssueFormField{ + { + Type: "markdown", + ID: "id1", + Attributes: map[string]interface{}{ + "value": "Value of the markdown", }, }, - Validations: map[string]interface{}{ - "required": true, + }, + FileName: "test.yaml", + }, + wantErr: "", + }, + { + name: "comma-delimited labels", + content: ` +name: Name +title: Title +about: About +labels: label1,label2,,label3 ,, +ref: Ref +body: + - type: markdown + id: id1 + attributes: + value: Value of the markdown +`, + want: &api.IssueTemplate{ + Name: "Name", + Title: "Title", + About: "About", + Labels: []string{"label1", "label2", "label3"}, + Ref: "Ref", + Fields: []*api.IssueFormField{ + { + Type: "markdown", + ID: "id1", + Attributes: map[string]interface{}{ + "value": "Value of the markdown", + }, }, }, - { - Type: "checkboxes", - ID: "id5", - Attributes: map[string]interface{}{ - "label": "Label of checkboxes", - "description": "Description of checkboxes", - "options": []interface{}{ - map[interface{}]interface{}{"label": "Option 1 of checkboxes", "required": true}, - map[interface{}]interface{}{"label": "Option 2 of checkboxes", "required": false}, - map[interface{}]interface{}{"label": "Option 3 of checkboxes", "required": true}, + FileName: "test.yaml", + }, + wantErr: "", + }, + { + name: "empty string as labels", + content: ` +name: Name +title: Title +about: About +labels: '' +ref: Ref +body: + - type: markdown + id: id1 + attributes: + value: Value of the markdown +`, + want: &api.IssueTemplate{ + Name: "Name", + Title: "Title", + About: "About", + Labels: nil, + Ref: "Ref", + Fields: []*api.IssueFormField{ + { + Type: "markdown", + ID: "id1", + Attributes: map[string]interface{}{ + "value": "Value of the markdown", }, }, }, + FileName: "test.yaml", }, - FileName: "test.yaml", - } - got, err := unmarshal("test.yaml", []byte(content)) - if err != nil { - t.Fatal(err) - } - if err := Validate(got); err != nil { - t.Errorf("Validate() error = %v", err) - } - if !reflect.DeepEqual(want, got) { - jsonWant, _ := json.Marshal(want) - jsonGot, _ := json.Marshal(got) - t.Errorf("want:\n%s\ngot:\n%s", jsonWant, jsonGot) - } - }) + wantErr: "", + }, + { + name: "comma delimited labels in markdown", + filename: "test.md", + content: `--- +name: Name +title: Title +about: About +labels: label1,label2,,label3 ,, +ref: Ref +--- +Content +`, + want: &api.IssueTemplate{ + Name: "Name", + Title: "Title", + About: "About", + Labels: []string{"label1", "label2", "label3"}, + Ref: "Ref", + Fields: nil, + Content: "Content\n", + FileName: "test.md", + }, + wantErr: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + filename := "test.yaml" + if tt.filename != "" { + filename = tt.filename + } + tmpl, err := unmarshal(filename, []byte(tt.content)) + require.NoError(t, err) + if tt.wantErr != "" { + require.EqualError(t, Validate(tmpl), tt.wantErr) + } else { + require.NoError(t, Validate(tmpl)) + want, _ := json.Marshal(tt.want) + got, _ := json.Marshal(tmpl) + require.JSONEq(t, string(want), string(got)) + } + }) + } } func TestRenderToMarkdown(t *testing.T) { diff --git a/modules/issue/template/unmarshal.go b/modules/issue/template/unmarshal.go index 24587b0fed2b1..3398719cf687e 100644 --- a/modules/issue/template/unmarshal.go +++ b/modules/issue/template/unmarshal.go @@ -16,7 +16,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) // CouldBe indicates a file with the filename could be a template, diff --git a/modules/markup/markdown/meta_test.go b/modules/markup/markdown/meta_test.go index 720d0066f4f0b..1e9768e618694 100644 --- a/modules/markup/markdown/meta_test.go +++ b/modules/markup/markdown/meta_test.go @@ -9,82 +9,86 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/structs" - "github.com/stretchr/testify/assert" ) -func validateMetadata(it structs.IssueTemplate) bool { - /* - A legacy to keep the unit tests working. - Copied from the method "func (it IssueTemplate) Valid() bool", the original method has been removed. - Because it becomes quite complicated to validate an issue template which is support yaml form now. - The new way to validate an issue template is to call the Validate in modules/issue/template, - */ +/* +IssueTemplate is a legacy to keep the unit tests working. +Copied from structs.IssueTemplate, the original type has been changed a lot to support yaml template. +*/ +type IssueTemplate struct { + Name string `json:"name" yaml:"name"` + Title string `json:"title" yaml:"title"` + About string `json:"about" yaml:"about"` + Labels []string `json:"labels" yaml:"labels"` + Ref string `json:"ref" yaml:"ref"` +} + +func (it *IssueTemplate) Valid() bool { return strings.TrimSpace(it.Name) != "" && strings.TrimSpace(it.About) != "" } func TestExtractMetadata(t *testing.T) { t.Run("ValidFrontAndBody", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate body, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s\n%s", sepTest, frontTest, sepTest, bodyTest), &meta) assert.NoError(t, err) assert.Equal(t, bodyTest, body) assert.Equal(t, metaTest, meta) - assert.True(t, validateMetadata(meta)) + assert.True(t, meta.Valid()) }) t.Run("NoFirstSeparator", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate _, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s", frontTest, sepTest, bodyTest), &meta) assert.Error(t, err) }) t.Run("NoLastSeparator", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate _, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s", sepTest, frontTest, bodyTest), &meta) assert.Error(t, err) }) t.Run("NoBody", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate body, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s", sepTest, frontTest, sepTest), &meta) assert.NoError(t, err) assert.Equal(t, "", body) assert.Equal(t, metaTest, meta) - assert.True(t, validateMetadata(meta)) + assert.True(t, meta.Valid()) }) } func TestExtractMetadataBytes(t *testing.T) { t.Run("ValidFrontAndBody", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate body, err := ExtractMetadataBytes([]byte(fmt.Sprintf("%s\n%s\n%s\n%s", sepTest, frontTest, sepTest, bodyTest)), &meta) assert.NoError(t, err) assert.Equal(t, bodyTest, string(body)) assert.Equal(t, metaTest, meta) - assert.True(t, validateMetadata(meta)) + assert.True(t, meta.Valid()) }) t.Run("NoFirstSeparator", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate _, err := ExtractMetadataBytes([]byte(fmt.Sprintf("%s\n%s\n%s", frontTest, sepTest, bodyTest)), &meta) assert.Error(t, err) }) t.Run("NoLastSeparator", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate _, err := ExtractMetadataBytes([]byte(fmt.Sprintf("%s\n%s\n%s", sepTest, frontTest, bodyTest)), &meta) assert.Error(t, err) }) t.Run("NoBody", func(t *testing.T) { - var meta structs.IssueTemplate + var meta IssueTemplate body, err := ExtractMetadataBytes([]byte(fmt.Sprintf("%s\n%s\n%s", sepTest, frontTest, sepTest)), &meta) assert.NoError(t, err) assert.Equal(t, "", string(body)) assert.Equal(t, metaTest, meta) - assert.True(t, validateMetadata(meta)) + assert.True(t, meta.Valid()) }) } @@ -97,7 +101,7 @@ labels: - bug - "test label"` bodyTest = "This is the body" - metaTest = structs.IssueTemplate{ + metaTest = IssueTemplate{ Name: "Test", About: "A Test", Title: "Test Title", diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 25c6251fbf2d3..45c3f6294ab59 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -5,8 +5,12 @@ package structs import ( + "fmt" "path" + "strings" "time" + + "gopkg.in/yaml.v3" ) // StateType issue state type @@ -143,14 +147,47 @@ type IssueFormField struct { // IssueTemplate represents an issue template for a repository // swagger:model type IssueTemplate struct { - Name string `json:"name" yaml:"name"` - Title string `json:"title" yaml:"title"` - About string `json:"about" yaml:"about"` // Using "description" in a template file is compatible - Labels []string `json:"labels" yaml:"labels"` - Ref string `json:"ref" yaml:"ref"` - Content string `json:"content" yaml:"-"` - Fields []*IssueFormField `json:"body" yaml:"body"` - FileName string `json:"file_name" yaml:"-"` + Name string `json:"name" yaml:"name"` + Title string `json:"title" yaml:"title"` + About string `json:"about" yaml:"about"` // Using "description" in a template file is compatible + Labels IssueTemplateLabels `json:"labels" yaml:"labels"` + Ref string `json:"ref" yaml:"ref"` + Content string `json:"content" yaml:"-"` + Fields []*IssueFormField `json:"body" yaml:"body"` + FileName string `json:"file_name" yaml:"-"` +} + +type IssueTemplateLabels []string + +func (l *IssueTemplateLabels) UnmarshalYAML(value *yaml.Node) error { + var labels []string + if value.IsZero() { + *l = labels + return nil + } + switch value.Kind { + case yaml.ScalarNode: + str := "" + err := value.Decode(&str) + if err != nil { + return err + } + for _, v := range strings.Split(str, ",") { + if v = strings.TrimSpace(v); v == "" { + continue + } + labels = append(labels, v) + } + *l = labels + return nil + case yaml.SequenceNode: + if err := value.Decode(&labels); err != nil { + return err + } + *l = labels + return nil + } + return fmt.Errorf("line %d: cannot unmarshal %s into IssueTemplateLabels", value.Line, value.ShortTag()) } // IssueTemplateType defines issue template type diff --git a/modules/structs/issue_test.go b/modules/structs/issue_test.go index 5312585d0f0f4..72b40f7cf24c3 100644 --- a/modules/structs/issue_test.go +++ b/modules/structs/issue_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" ) func TestIssueTemplate_Type(t *testing.T) { @@ -41,3 +42,65 @@ func TestIssueTemplate_Type(t *testing.T) { }) } } + +func TestIssueTemplateLabels_UnmarshalYAML(t *testing.T) { + tests := []struct { + name string + content string + tmpl *IssueTemplate + want *IssueTemplate + wantErr string + }{ + { + name: "array", + content: `labels: ["a", "b", "c"]`, + tmpl: &IssueTemplate{ + Labels: []string{"should_be_overwrote"}, + }, + want: &IssueTemplate{ + Labels: []string{"a", "b", "c"}, + }, + }, + { + name: "string", + content: `labels: "a,b,c"`, + tmpl: &IssueTemplate{ + Labels: []string{"should_be_overwrote"}, + }, + want: &IssueTemplate{ + Labels: []string{"a", "b", "c"}, + }, + }, + { + name: "empty", + content: `labels:`, + tmpl: &IssueTemplate{ + Labels: []string{"should_be_overwrote"}, + }, + want: &IssueTemplate{ + Labels: nil, + }, + }, + { + name: "error", + content: ` +labels: + a: aa + b: bb +`, + tmpl: &IssueTemplate{}, + wantErr: "line 3: cannot unmarshal !!map into IssueTemplateLabels", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := yaml.Unmarshal([]byte(tt.content), tt.tmpl) + if tt.wantErr != "" { + assert.EqualError(t, err, tt.wantErr) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.want, tt.tmpl) + } + }) + } +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index fe3185ea77ea4..ddafc146a159c 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -16818,11 +16818,7 @@ "x-go-name": "FileName" }, "labels": { - "type": "array", - "items": { - "type": "string" - }, - "x-go-name": "Labels" + "$ref": "#/definitions/IssueTemplateLabels" }, "name": { "type": "string", @@ -16839,6 +16835,13 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "IssueTemplateLabels": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "Label": { "description": "Label a label to an issue or a pr", "type": "object", From 32db62515f2e2109dd4f2d7136e4005d20d0def4 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Sun, 20 Nov 2022 15:08:38 +0100 Subject: [PATCH 13/14] Add package registry cleanup rules (#21658) Fixes #20514 Fixes #20766 Fixes #20631 This PR adds Cleanup Rules for the package registry. This allows to delete unneeded packages automatically. Cleanup rules can be set up from the user or org settings. Please have a look at the documentation because I'm not a native english speaker. Rule Form ![grafik](https://user-images.githubusercontent.com/1666336/199330792-c13918a6-e196-4e71-9f53-18554515edca.png) Rule List ![grafik](https://user-images.githubusercontent.com/1666336/199331261-5f6878e8-a80c-4985-800d-ebb3524b1a8d.png) Rule Preview ![grafik](https://user-images.githubusercontent.com/1666336/199330917-c95e4017-cf64-4142-a3e4-af18c4f127c3.png) Co-authored-by: Lunny Xiao --- docs/content/doc/packages/storage.en-us.md | 84 +++++++ models/migrations/migrations.go | 2 + models/migrations/v1_19/v234.go | 29 +++ models/packages/package.go | 15 ++ models/packages/package_cleanup_rule.go | 110 +++++++++ models/packages/package_version.go | 9 + options/locale/locale_en-US.ini | 23 ++ routers/web/org/setting_packages.go | 87 +++++++ routers/web/shared/packages/packages.go | 226 ++++++++++++++++++ routers/web/user/setting/packages.go | 80 +++++++ routers/web/web.go | 48 +++- services/forms/package_form.go | 31 +++ services/packages/container/cleanup.go | 35 +-- services/packages/container/common.go | 36 +++ services/packages/packages.go | 71 +++++- templates/org/settings/navbar.tmpl | 5 + templates/org/settings/packages.tmpl | 14 ++ .../settings/packages_cleanup_rules_edit.tmpl | 14 ++ .../packages_cleanup_rules_preview.tmpl | 13 + .../package/shared/cleanup_rules/edit.tmpl | 73 ++++++ .../package/shared/cleanup_rules/list.tmpl | 34 +++ .../package/shared/cleanup_rules/preview.tmpl | 34 +++ templates/user/settings/navbar.tmpl | 5 + templates/user/settings/packages.tmpl | 9 + .../settings/packages_cleanup_rules_edit.tmpl | 9 + .../packages_cleanup_rules_preview.tmpl | 8 + tests/integration/api_packages_test.go | 175 +++++++++++++- 27 files changed, 1243 insertions(+), 36 deletions(-) create mode 100644 docs/content/doc/packages/storage.en-us.md create mode 100644 models/migrations/v1_19/v234.go create mode 100644 models/packages/package_cleanup_rule.go create mode 100644 routers/web/org/setting_packages.go create mode 100644 routers/web/shared/packages/packages.go create mode 100644 routers/web/user/setting/packages.go create mode 100644 services/forms/package_form.go create mode 100644 services/packages/container/common.go create mode 100644 templates/org/settings/packages.tmpl create mode 100644 templates/org/settings/packages_cleanup_rules_edit.tmpl create mode 100644 templates/org/settings/packages_cleanup_rules_preview.tmpl create mode 100644 templates/package/shared/cleanup_rules/edit.tmpl create mode 100644 templates/package/shared/cleanup_rules/list.tmpl create mode 100644 templates/package/shared/cleanup_rules/preview.tmpl create mode 100644 templates/user/settings/packages.tmpl create mode 100644 templates/user/settings/packages_cleanup_rules_edit.tmpl create mode 100644 templates/user/settings/packages_cleanup_rules_preview.tmpl diff --git a/docs/content/doc/packages/storage.en-us.md b/docs/content/doc/packages/storage.en-us.md new file mode 100644 index 0000000000000..c922496a9902a --- /dev/null +++ b/docs/content/doc/packages/storage.en-us.md @@ -0,0 +1,84 @@ +--- +date: "2022-11-01T00:00:00+00:00" +title: "Storage" +slug: "packages/storage" +draft: false +toc: false +menu: + sidebar: + parent: "packages" + name: "storage" + weight: 5 + identifier: "storage" +--- + +# Storage + +This document describes the storage of the package registry and how it can be managed. + +**Table of Contents** + +{{< toc >}} + +## Deduplication + +The package registry has a build-in deduplication of uploaded blobs. +If two identical files are uploaded only one blob is saved on the filesystem. +This ensures no space is wasted for duplicated files. + +If two packages are uploaded with identical files, both packages will display the same size but on the filesystem they require only half of the size. +Whenever a package gets deleted only the references to the underlaying blobs are removed. +The blobs get not removed at this moment, so they still require space on the filesystem. +When a new package gets uploaded the existing blobs may get referenced again. + +These unreferenced blobs get deleted by a [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}). +The config setting `OLDER_THAN` configures how long unreferenced blobs are kept before they get deleted. + +## Cleanup Rules + +Package registries can become large over time without cleanup. +It's recommended to delete unnecessary packages and set up cleanup rules to automatically manage the package registry usage. +Every package owner (user or organization) manages the cleanup rules which are applied to their packages. + +|Setting|Description| +|-|-| +|Enabled|Turn the cleanup rule on or off.| +|Type|Every rule manages a specific package type.| +|Apply pattern to full package name|If enabled, the patterns below are applied to the full package name (`package/version`). Otherwise only the version (`version`) is used.| +|Keep the most recent|How many versions to *always* keep for each package.| +|Keep versions matching|The regex pattern that determines which versions to keep. An empty pattern keeps no version while `.+` keeps all versions. The container registry will always keep the `latest` version even if not configured.| +|Remove versions older than|Remove only versions older than the selected days.| +|Remove versions matching|The regex pattern that determines which versions to remove. An empty pattern or `.+` leads to the removal of every package if no other setting tells otherwise.| + +Every cleanup rule can show a preview of the affected packages. +This can be used to check if the cleanup rules is proper configured. + +### Regex examples + +Regex patterns are automatically surrounded with `\A` and `\z` anchors. +Do not include any `\A`, `\z`, `^` or `$` token in the regex patterns as they are not necessary. +The patterns are case-insensitive which matches the behaviour of the package registry in Gitea. + +|Pattern|Description| +|-|-| +|`.*`|Match every possible version.| +|`v.+`|Match versions that start with `v`.| +|`release`|Match only the version `release`.| +|`release.*`|Match versions that are either named or start with `release`.| +|`.+-temp-.+`|Match versions that contain `-temp-`.| +|`v.+\|release`|Match versions that either start with `v` or are named `release`.| +|`package/v.+\|other/release`|Match versions of the package `package` that start with `v` or the version `release` of the package `other`. This needs the setting *Apply pattern to full package name* enabled.| + +### How the cleanup rules work + +The cleanup rules are part of the [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}) and run periodicly. + +The cleanup rule: + +1. Collects all packages of the package type for the owners registry. +1. For every package it collects all versions. +1. Excludes from the list the # versions based on the *Keep the most recent* value. +1. Excludes from the list any versions matching the *Keep versions matching* value. +1. Excludes from the list the versions more recent than the *Remove versions older than* value. +1. Excludes from the list any versions not matching the *Remove versions matching* value. +1. Deletes the remaining versions. diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 6ef4ef561794a..c48fc8d9a8a99 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -439,6 +439,8 @@ var migrations = []Migration{ NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText), // v233 -> v234 NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook), + // v234 -> v235 + NewMigration("Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_19/v234.go b/models/migrations/v1_19/v234.go new file mode 100644 index 0000000000000..9d609c58d3d2d --- /dev/null +++ b/models/migrations/v1_19/v234.go @@ -0,0 +1,29 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package v1_19 //nolint + +import ( + "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/xorm" +) + +func CreatePackageCleanupRuleTable(x *xorm.Engine) error { + type PackageCleanupRule struct { + ID int64 `xorm:"pk autoincr"` + Enabled bool `xorm:"INDEX NOT NULL DEFAULT false"` + OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL DEFAULT 0"` + Type string `xorm:"UNIQUE(s) INDEX NOT NULL"` + KeepCount int `xorm:"NOT NULL DEFAULT 0"` + KeepPattern string `xorm:"NOT NULL DEFAULT ''"` + RemoveDays int `xorm:"NOT NULL DEFAULT 0"` + RemovePattern string `xorm:"NOT NULL DEFAULT ''"` + MatchFullName bool `xorm:"NOT NULL DEFAULT false"` + CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL DEFAULT 0"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"` + } + + return x.Sync2(new(PackageCleanupRule)) +} diff --git a/models/packages/package.go b/models/packages/package.go index e39a7c4e411d4..cea04a0957955 100644 --- a/models/packages/package.go +++ b/models/packages/package.go @@ -45,6 +45,21 @@ const ( TypeVagrant Type = "vagrant" ) +var TypeList = []Type{ + TypeComposer, + TypeConan, + TypeContainer, + TypeGeneric, + TypeHelm, + TypeMaven, + TypeNpm, + TypeNuGet, + TypePub, + TypePyPI, + TypeRubyGems, + TypeVagrant, +} + // Name gets the name of the package type func (pt Type) Name() string { switch pt { diff --git a/models/packages/package_cleanup_rule.go b/models/packages/package_cleanup_rule.go new file mode 100644 index 0000000000000..ab45226cf1503 --- /dev/null +++ b/models/packages/package_cleanup_rule.go @@ -0,0 +1,110 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package packages + +import ( + "context" + "errors" + "fmt" + "regexp" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/builder" +) + +var ErrPackageCleanupRuleNotExist = errors.New("Package blob does not exist") + +func init() { + db.RegisterModel(new(PackageCleanupRule)) +} + +// PackageCleanupRule represents a rule which describes when to clean up package versions +type PackageCleanupRule struct { + ID int64 `xorm:"pk autoincr"` + Enabled bool `xorm:"INDEX NOT NULL DEFAULT false"` + OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL DEFAULT 0"` + Type Type `xorm:"UNIQUE(s) INDEX NOT NULL"` + KeepCount int `xorm:"NOT NULL DEFAULT 0"` + KeepPattern string `xorm:"NOT NULL DEFAULT ''"` + KeepPatternMatcher *regexp.Regexp `xorm:"-"` + RemoveDays int `xorm:"NOT NULL DEFAULT 0"` + RemovePattern string `xorm:"NOT NULL DEFAULT ''"` + RemovePatternMatcher *regexp.Regexp `xorm:"-"` + MatchFullName bool `xorm:"NOT NULL DEFAULT false"` + CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL DEFAULT 0"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"` +} + +func (pcr *PackageCleanupRule) CompiledPattern() error { + if pcr.KeepPatternMatcher != nil || pcr.RemovePatternMatcher != nil { + return nil + } + + if pcr.KeepPattern != "" { + var err error + pcr.KeepPatternMatcher, err = regexp.Compile(fmt.Sprintf(`(?i)\A%s\z`, pcr.KeepPattern)) + if err != nil { + return err + } + } + + if pcr.RemovePattern != "" { + var err error + pcr.RemovePatternMatcher, err = regexp.Compile(fmt.Sprintf(`(?i)\A%s\z`, pcr.RemovePattern)) + if err != nil { + return err + } + } + + return nil +} + +func InsertCleanupRule(ctx context.Context, pcr *PackageCleanupRule) (*PackageCleanupRule, error) { + return pcr, db.Insert(ctx, pcr) +} + +func GetCleanupRuleByID(ctx context.Context, id int64) (*PackageCleanupRule, error) { + pcr := &PackageCleanupRule{} + + has, err := db.GetEngine(ctx).ID(id).Get(pcr) + if err != nil { + return nil, err + } + if !has { + return nil, ErrPackageCleanupRuleNotExist + } + return pcr, nil +} + +func UpdateCleanupRule(ctx context.Context, pcr *PackageCleanupRule) error { + _, err := db.GetEngine(ctx).ID(pcr.ID).AllCols().Update(pcr) + return err +} + +func GetCleanupRulesByOwner(ctx context.Context, ownerID int64) ([]*PackageCleanupRule, error) { + pcrs := make([]*PackageCleanupRule, 0, 10) + return pcrs, db.GetEngine(ctx).Where("owner_id = ?", ownerID).Find(&pcrs) +} + +func DeleteCleanupRuleByID(ctx context.Context, ruleID int64) error { + _, err := db.GetEngine(ctx).ID(ruleID).Delete(&PackageCleanupRule{}) + return err +} + +func HasOwnerCleanupRuleForPackageType(ctx context.Context, ownerID int64, packageType Type) (bool, error) { + return db.GetEngine(ctx). + Where("owner_id = ? AND type = ?", ownerID, packageType). + Exist(&PackageCleanupRule{}) +} + +func IterateEnabledCleanupRules(ctx context.Context, callback func(context.Context, *PackageCleanupRule) error) error { + return db.Iterate( + ctx, + builder.Eq{"enabled": true}, + callback, + ) +} diff --git a/models/packages/package_version.go b/models/packages/package_version.go index 48c6aa7d607fa..6ee362502f69b 100644 --- a/models/packages/package_version.go +++ b/models/packages/package_version.go @@ -320,6 +320,15 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P return pvs, count, err } +// ExistVersion checks if a version matching the search options exist +func ExistVersion(ctx context.Context, opts *PackageSearchOptions) (bool, error) { + return db.GetEngine(ctx). + Where(opts.toConds()). + Table("package_version"). + Join("INNER", "package", "package.id = package_version.package_id"). + Exist(new(PackageVersion)) +} + // CountVersions counts all versions of packages matching the search options func CountVersions(ctx context.Context, opts *PackageSearchOptions) (int64, error) { return db.GetEngine(ctx). diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index eb2a1c86dbbf1..ce93e92d34550 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -86,6 +86,9 @@ remove = Remove remove_all = Remove All edit = Edit +enabled = Enabled +disabled = Disabled + copy = Copy copy_url = Copy URL copy_content = Copy content @@ -3186,3 +3189,23 @@ settings.delete.description = Deleting a package is permanent and cannot be undo settings.delete.notice = You are about to delete %s (%s). This operation is irreversible, are you sure? settings.delete.success = The package has been deleted. settings.delete.error = Failed to delete the package. +owner.settings.cleanuprules.title = Manage Cleanup Rules +owner.settings.cleanuprules.add = Add Cleanup Rule +owner.settings.cleanuprules.edit = Edit Cleanup Rule +owner.settings.cleanuprules.none = No cleanup rules available. Read the docs to learn more. +owner.settings.cleanuprules.preview = Cleanup Rule Preview +owner.settings.cleanuprules.preview.overview = %d packages are scheduled to be removed. +owner.settings.cleanuprules.preview.none = Cleanup rule does not match any packages. +owner.settings.cleanuprules.enabled = Enabled +owner.settings.cleanuprules.pattern_full_match = Apply pattern to full package name +owner.settings.cleanuprules.keep.title = Versions that match these rules are kept, even if they match a removal rule below. +owner.settings.cleanuprules.keep.count = Keep the most recent +owner.settings.cleanuprules.keep.count.1 = 1 version per package +owner.settings.cleanuprules.keep.count.n = %d versions per package +owner.settings.cleanuprules.keep.pattern = Keep versions matching +owner.settings.cleanuprules.keep.pattern.container = The latest version is always kept for Container packages. +owner.settings.cleanuprules.remove.title = Versions that match these rules are removed, unless a rule above says to keep them. +owner.settings.cleanuprules.remove.days = Remove versions older than +owner.settings.cleanuprules.remove.pattern = Remove versions matching +owner.settings.cleanuprules.success.update = Cleanup rule has been updated. +owner.settings.cleanuprules.success.delete = Cleanup rule has been deleted. diff --git a/routers/web/org/setting_packages.go b/routers/web/org/setting_packages.go new file mode 100644 index 0000000000000..c7edf4a18531c --- /dev/null +++ b/routers/web/org/setting_packages.go @@ -0,0 +1,87 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package org + +import ( + "fmt" + "net/http" + + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + shared "code.gitea.io/gitea/routers/web/shared/packages" +) + +const ( + tplSettingsPackages base.TplName = "org/settings/packages" + tplSettingsPackagesRuleEdit base.TplName = "org/settings/packages_cleanup_rules_edit" + tplSettingsPackagesRulePreview base.TplName = "org/settings/packages_cleanup_rules_preview" +) + +func Packages(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetPackagesContext(ctx, ctx.ContextUser) + + ctx.HTML(http.StatusOK, tplSettingsPackages) +} + +func PackagesRuleAdd(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetRuleAddContext(ctx) + + ctx.HTML(http.StatusOK, tplSettingsPackagesRuleEdit) +} + +func PackagesRuleEdit(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetRuleEditContext(ctx, ctx.ContextUser) + + ctx.HTML(http.StatusOK, tplSettingsPackagesRuleEdit) +} + +func PackagesRuleAddPost(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsSettingsPackages"] = true + + shared.PerformRuleAddPost( + ctx, + ctx.ContextUser, + fmt.Sprintf("%s/org/%s/settings/packages", setting.AppSubURL, ctx.ContextUser.Name), + tplSettingsPackagesRuleEdit, + ) +} + +func PackagesRuleEditPost(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsSettingsPackages"] = true + + shared.PerformRuleEditPost( + ctx, + ctx.ContextUser, + fmt.Sprintf("%s/org/%s/settings/packages", setting.AppSubURL, ctx.ContextUser.Name), + tplSettingsPackagesRuleEdit, + ) +} + +func PackagesRulePreview(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetRulePreviewContext(ctx, ctx.ContextUser) + + ctx.HTML(http.StatusOK, tplSettingsPackagesRulePreview) +} diff --git a/routers/web/shared/packages/packages.go b/routers/web/shared/packages/packages.go new file mode 100644 index 0000000000000..5e934d707ee41 --- /dev/null +++ b/routers/web/shared/packages/packages.go @@ -0,0 +1,226 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package packages + +import ( + "fmt" + "net/http" + "time" + + "code.gitea.io/gitea/models/db" + packages_model "code.gitea.io/gitea/models/packages" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/services/forms" + container_service "code.gitea.io/gitea/services/packages/container" +) + +func SetPackagesContext(ctx *context.Context, owner *user_model.User) { + pcrs, err := packages_model.GetCleanupRulesByOwner(ctx, owner.ID) + if err != nil { + ctx.ServerError("GetCleanupRulesByOwner", err) + return + } + + ctx.Data["CleanupRules"] = pcrs +} + +func SetRuleAddContext(ctx *context.Context) { + setRuleEditContext(ctx, nil) +} + +func SetRuleEditContext(ctx *context.Context, owner *user_model.User) { + pcr := getCleanupRuleByContext(ctx, owner) + if pcr == nil { + return + } + + setRuleEditContext(ctx, pcr) +} + +func setRuleEditContext(ctx *context.Context, pcr *packages_model.PackageCleanupRule) { + ctx.Data["IsEditRule"] = pcr != nil + + if pcr == nil { + pcr = &packages_model.PackageCleanupRule{} + } + ctx.Data["CleanupRule"] = pcr + ctx.Data["AvailableTypes"] = packages_model.TypeList +} + +func PerformRuleAddPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.TplName) { + performRuleEditPost(ctx, owner, nil, redirectURL, template) +} + +func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.TplName) { + pcr := getCleanupRuleByContext(ctx, owner) + if pcr == nil { + return + } + + form := web.GetForm(ctx).(*forms.PackageCleanupRuleForm) + + if form.Action == "remove" { + if err := packages_model.DeleteCleanupRuleByID(ctx, pcr.ID); err != nil { + ctx.ServerError("DeleteCleanupRuleByID", err) + return + } + + ctx.Flash.Success(ctx.Tr("packages.owner.settings.cleanuprules.success.delete")) + ctx.Redirect(redirectURL) + } else { + performRuleEditPost(ctx, owner, pcr, redirectURL, template) + } +} + +func performRuleEditPost(ctx *context.Context, owner *user_model.User, pcr *packages_model.PackageCleanupRule, redirectURL string, template base.TplName) { + isEditRule := pcr != nil + + if pcr == nil { + pcr = &packages_model.PackageCleanupRule{} + } + + form := web.GetForm(ctx).(*forms.PackageCleanupRuleForm) + + pcr.Enabled = form.Enabled + pcr.OwnerID = owner.ID + pcr.KeepCount = form.KeepCount + pcr.KeepPattern = form.KeepPattern + pcr.RemoveDays = form.RemoveDays + pcr.RemovePattern = form.RemovePattern + pcr.MatchFullName = form.MatchFullName + + ctx.Data["IsEditRule"] = isEditRule + ctx.Data["CleanupRule"] = pcr + ctx.Data["AvailableTypes"] = packages_model.TypeList + + if ctx.HasError() { + ctx.HTML(http.StatusOK, template) + return + } + + if isEditRule { + if err := packages_model.UpdateCleanupRule(ctx, pcr); err != nil { + ctx.ServerError("UpdateCleanupRule", err) + return + } + } else { + pcr.Type = packages_model.Type(form.Type) + + if has, err := packages_model.HasOwnerCleanupRuleForPackageType(ctx, owner.ID, pcr.Type); err != nil { + ctx.ServerError("HasOwnerCleanupRuleForPackageType", err) + return + } else if has { + ctx.Data["Err_Type"] = true + ctx.HTML(http.StatusOK, template) + return + } + + var err error + if pcr, err = packages_model.InsertCleanupRule(ctx, pcr); err != nil { + ctx.ServerError("InsertCleanupRule", err) + return + } + } + + ctx.Flash.Success(ctx.Tr("packages.owner.settings.cleanuprules.success.update")) + ctx.Redirect(fmt.Sprintf("%s/rules/%d", redirectURL, pcr.ID)) +} + +func SetRulePreviewContext(ctx *context.Context, owner *user_model.User) { + pcr := getCleanupRuleByContext(ctx, owner) + if pcr == nil { + return + } + + if err := pcr.CompiledPattern(); err != nil { + ctx.ServerError("CompiledPattern", err) + return + } + + olderThan := time.Now().AddDate(0, 0, -pcr.RemoveDays) + + packages, err := packages_model.GetPackagesByType(ctx, pcr.OwnerID, pcr.Type) + if err != nil { + ctx.ServerError("GetPackagesByType", err) + return + } + + versionsToRemove := make([]*packages_model.PackageDescriptor, 0, 10) + + for _, p := range packages { + pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ + PackageID: p.ID, + IsInternal: util.OptionalBoolFalse, + Sort: packages_model.SortCreatedDesc, + Paginator: db.NewAbsoluteListOptions(pcr.KeepCount, 200), + }) + if err != nil { + ctx.ServerError("SearchVersions", err) + return + } + for _, pv := range pvs { + if skip, err := container_service.ShouldBeSkipped(ctx, pcr, p, pv); err != nil { + ctx.ServerError("ShouldBeSkipped", err) + return + } else if skip { + continue + } + + toMatch := pv.LowerVersion + if pcr.MatchFullName { + toMatch = p.LowerName + "/" + pv.LowerVersion + } + + if pcr.KeepPatternMatcher != nil && pcr.KeepPatternMatcher.MatchString(toMatch) { + continue + } + if pv.CreatedUnix.AsLocalTime().After(olderThan) { + continue + } + if pcr.RemovePatternMatcher != nil && !pcr.RemovePatternMatcher.MatchString(toMatch) { + continue + } + + pd, err := packages_model.GetPackageDescriptor(ctx, pv) + if err != nil { + ctx.ServerError("GetPackageDescriptor", err) + return + } + versionsToRemove = append(versionsToRemove, pd) + } + } + + ctx.Data["CleanupRule"] = pcr + ctx.Data["VersionsToRemove"] = versionsToRemove +} + +func getCleanupRuleByContext(ctx *context.Context, owner *user_model.User) *packages_model.PackageCleanupRule { + id := ctx.FormInt64("id") + if id == 0 { + id = ctx.ParamsInt64("id") + } + + pcr, err := packages_model.GetCleanupRuleByID(ctx, id) + if err != nil { + if err == packages_model.ErrPackageCleanupRuleNotExist { + ctx.NotFound("", err) + } else { + ctx.ServerError("GetCleanupRuleByID", err) + } + return nil + } + + if pcr != nil && pcr.OwnerID == owner.ID { + return pcr + } + + ctx.NotFound("", fmt.Errorf("PackageCleanupRule[%v] not associated to owner %v", id, owner)) + + return nil +} diff --git a/routers/web/user/setting/packages.go b/routers/web/user/setting/packages.go new file mode 100644 index 0000000000000..d44e904556d2b --- /dev/null +++ b/routers/web/user/setting/packages.go @@ -0,0 +1,80 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package setting + +import ( + "net/http" + + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + shared "code.gitea.io/gitea/routers/web/shared/packages" +) + +const ( + tplSettingsPackages base.TplName = "user/settings/packages" + tplSettingsPackagesRuleEdit base.TplName = "user/settings/packages_cleanup_rules_edit" + tplSettingsPackagesRulePreview base.TplName = "user/settings/packages_cleanup_rules_preview" +) + +func Packages(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetPackagesContext(ctx, ctx.Doer) + + ctx.HTML(http.StatusOK, tplSettingsPackages) +} + +func PackagesRuleAdd(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetRuleAddContext(ctx) + + ctx.HTML(http.StatusOK, tplSettingsPackagesRuleEdit) +} + +func PackagesRuleEdit(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetRuleEditContext(ctx, ctx.Doer) + + ctx.HTML(http.StatusOK, tplSettingsPackagesRuleEdit) +} + +func PackagesRuleAddPost(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("settings") + ctx.Data["PageIsSettingsPackages"] = true + + shared.PerformRuleAddPost( + ctx, + ctx.Doer, + setting.AppSubURL+"/user/settings/packages", + tplSettingsPackagesRuleEdit, + ) +} + +func PackagesRuleEditPost(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsSettingsPackages"] = true + + shared.PerformRuleEditPost( + ctx, + ctx.Doer, + setting.AppSubURL+"/user/settings/packages", + tplSettingsPackagesRuleEdit, + ) +} + +func PackagesRulePreview(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("packages.title") + ctx.Data["PageIsSettingsPackages"] = true + + shared.SetRulePreviewContext(ctx, ctx.Doer) + + ctx.HTML(http.StatusOK, tplSettingsPackagesRulePreview) +} diff --git a/routers/web/web.go b/routers/web/web.go index 5fefbad88a4f3..142f2384eb3c4 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -303,6 +303,13 @@ func RegisterRoutes(m *web.Route) { } } + packagesEnabled := func(ctx *context.Context) { + if !setting.Packages.Enabled { + ctx.Error(http.StatusForbidden) + return + } + } + // FIXME: not all routes need go through same middleware. // Especially some AJAX requests, we can reduce middleware number to improve performance. // Routers. @@ -443,12 +450,27 @@ func RegisterRoutes(m *web.Route) { m.Combo("/keys").Get(user_setting.Keys). Post(bindIgnErr(forms.AddKeyForm{}), user_setting.KeysPost) m.Post("/keys/delete", user_setting.DeleteKey) + m.Group("/packages", func() { + m.Get("", user_setting.Packages) + m.Group("/rules", func() { + m.Group("/add", func() { + m.Get("", user_setting.PackagesRuleAdd) + m.Post("", bindIgnErr(forms.PackageCleanupRuleForm{}), user_setting.PackagesRuleAddPost) + }) + m.Group("/{id}", func() { + m.Get("", user_setting.PackagesRuleEdit) + m.Post("", bindIgnErr(forms.PackageCleanupRuleForm{}), user_setting.PackagesRuleEditPost) + m.Get("/preview", user_setting.PackagesRulePreview) + }) + }) + }, packagesEnabled) m.Get("/organization", user_setting.Organization) m.Get("/repos", user_setting.Repos) m.Post("/repos/unadopted", user_setting.AdoptOrDeleteRepository) }, reqSignIn, func(ctx *context.Context) { ctx.Data["PageIsUserSettings"] = true ctx.Data["AllThemes"] = setting.UI.Themes + ctx.Data["EnablePackages"] = setting.Packages.Enabled }) m.Group("/user", func() { @@ -526,12 +548,10 @@ func RegisterRoutes(m *web.Route) { m.Post("/delete", admin.DeleteRepo) }) - if setting.Packages.Enabled { - m.Group("/packages", func() { - m.Get("", admin.Packages) - m.Post("/delete", admin.DeletePackageVersion) - }) - } + m.Group("/packages", func() { + m.Get("", admin.Packages) + m.Post("/delete", admin.DeletePackageVersion) + }, packagesEnabled) m.Group("/hooks", func() { m.Get("", admin.DefaultOrSystemWebhooks) @@ -750,8 +770,24 @@ func RegisterRoutes(m *web.Route) { }) m.Route("/delete", "GET,POST", org.SettingsDelete) + + m.Group("/packages", func() { + m.Get("", org.Packages) + m.Group("/rules", func() { + m.Group("/add", func() { + m.Get("", org.PackagesRuleAdd) + m.Post("", bindIgnErr(forms.PackageCleanupRuleForm{}), org.PackagesRuleAddPost) + }) + m.Group("/{id}", func() { + m.Get("", org.PackagesRuleEdit) + m.Post("", bindIgnErr(forms.PackageCleanupRuleForm{}), org.PackagesRuleEditPost) + m.Get("/preview", org.PackagesRulePreview) + }) + }) + }, packagesEnabled) }, func(ctx *context.Context) { ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable + ctx.Data["EnablePackages"] = setting.Packages.Enabled }) }, context.OrgAssignment(true, true)) }, reqSignIn) diff --git a/services/forms/package_form.go b/services/forms/package_form.go new file mode 100644 index 0000000000000..6c3ff52a9c01b --- /dev/null +++ b/services/forms/package_form.go @@ -0,0 +1,31 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package forms + +import ( + "net/http" + + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/web/middleware" + + "gitea.com/go-chi/binding" +) + +type PackageCleanupRuleForm struct { + ID int64 + Enabled bool + Type string `binding:"Required;In(composer,conan,container,generic,helm,maven,npm,nuget,pub,pypi,rubygems,vagrant)"` + KeepCount int `binding:"In(0,1,5,10,25,50,100)"` + KeepPattern string `binding:"RegexPattern"` + RemoveDays int `binding:"In(0,7,14,30,60,90,180)"` + RemovePattern string `binding:"RegexPattern"` + MatchFullName bool + Action string `binding:"Required;In(save,remove)"` +} + +func (f *PackageCleanupRuleForm) Validate(req *http.Request, errs binding.Errors) binding.Errors { + ctx := context.GetContext(req) + return middleware.Validate(errs, ctx.Data, f, ctx.Locale) +} diff --git a/services/packages/container/cleanup.go b/services/packages/container/cleanup.go index d23a481f279e4..e3d414d45c4e9 100644 --- a/services/packages/container/cleanup.go +++ b/services/packages/container/cleanup.go @@ -6,13 +6,12 @@ package container import ( "context" - "strings" "time" packages_model "code.gitea.io/gitea/models/packages" container_model "code.gitea.io/gitea/models/packages/container" - user_model "code.gitea.io/gitea/models/user" container_module "code.gitea.io/gitea/modules/packages/container" + "code.gitea.io/gitea/modules/packages/container/oci" "code.gitea.io/gitea/modules/util" ) @@ -82,24 +81,30 @@ func cleanupExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) e return nil } -// UpdateRepositoryNames updates the repository name property for all packages of the specific owner -func UpdateRepositoryNames(ctx context.Context, owner *user_model.User, newOwnerName string) error { - ps, err := packages_model.GetPackagesByType(ctx, owner.ID, packages_model.TypeContainer) - if err != nil { - return err +func ShouldBeSkipped(ctx context.Context, pcr *packages_model.PackageCleanupRule, p *packages_model.Package, pv *packages_model.PackageVersion) (bool, error) { + // Always skip the "latest" tag + if pv.LowerVersion == "latest" { + return true, nil } - newOwnerName = strings.ToLower(newOwnerName) - - for _, p := range ps { - if err := packages_model.DeletePropertyByName(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository); err != nil { - return err + // Check if the version is a digest (or untagged) + if oci.Digest(pv.LowerVersion).Validate() { + // Check if there is another manifest referencing this version + has, err := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{ + PackageID: p.ID, + Properties: map[string]string{ + container_module.PropertyManifestReference: pv.LowerVersion, + }, + }) + if err != nil { + return false, err } - if _, err := packages_model.InsertProperty(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository, newOwnerName+"/"+p.LowerName); err != nil { - return err + // Skip it if the version is referenced + if has { + return true, nil } } - return nil + return false, nil } diff --git a/services/packages/container/common.go b/services/packages/container/common.go new file mode 100644 index 0000000000000..40d8914a01635 --- /dev/null +++ b/services/packages/container/common.go @@ -0,0 +1,36 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package container + +import ( + "context" + "strings" + + packages_model "code.gitea.io/gitea/models/packages" + user_model "code.gitea.io/gitea/models/user" + container_module "code.gitea.io/gitea/modules/packages/container" +) + +// UpdateRepositoryNames updates the repository name property for all packages of the specific owner +func UpdateRepositoryNames(ctx context.Context, owner *user_model.User, newOwnerName string) error { + ps, err := packages_model.GetPackagesByType(ctx, owner.ID, packages_model.TypeContainer) + if err != nil { + return err + } + + newOwnerName = strings.ToLower(newOwnerName) + + for _, p := range ps { + if err := packages_model.DeletePropertyByName(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository); err != nil { + return err + } + + if _, err := packages_model.InsertProperty(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository, newOwnerName+"/"+p.LowerName); err != nil { + return err + } + } + + return nil +} diff --git a/services/packages/packages.go b/services/packages/packages.go index 76fdd02bf265c..7343ffc530d55 100644 --- a/services/packages/packages.go +++ b/services/packages/packages.go @@ -443,13 +443,80 @@ func DeletePackageFile(ctx context.Context, pf *packages_model.PackageFile) erro } // Cleanup removes expired package data -func Cleanup(unused context.Context, olderThan time.Duration) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func Cleanup(taskCtx context.Context, olderThan time.Duration) error { + ctx, committer, err := db.TxContext(taskCtx) if err != nil { return err } defer committer.Close() + err = packages_model.IterateEnabledCleanupRules(ctx, func(ctx context.Context, pcr *packages_model.PackageCleanupRule) error { + select { + case <-taskCtx.Done(): + return db.ErrCancelledf("While processing package cleanup rules") + default: + } + + if err := pcr.CompiledPattern(); err != nil { + return fmt.Errorf("CleanupRule [%d]: CompilePattern failed: %w", pcr.ID, err) + } + + olderThan := time.Now().AddDate(0, 0, -pcr.RemoveDays) + + packages, err := packages_model.GetPackagesByType(ctx, pcr.OwnerID, pcr.Type) + if err != nil { + return fmt.Errorf("CleanupRule [%d]: GetPackagesByType failed: %w", pcr.ID, err) + } + + for _, p := range packages { + pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ + PackageID: p.ID, + IsInternal: util.OptionalBoolFalse, + Sort: packages_model.SortCreatedDesc, + Paginator: db.NewAbsoluteListOptions(pcr.KeepCount, 200), + }) + if err != nil { + return fmt.Errorf("CleanupRule [%d]: SearchVersions failed: %w", pcr.ID, err) + } + for _, pv := range pvs { + if skip, err := container_service.ShouldBeSkipped(ctx, pcr, p, pv); err != nil { + return fmt.Errorf("CleanupRule [%d]: container.ShouldBeSkipped failed: %w", pcr.ID, err) + } else if skip { + log.Debug("Rule[%d]: keep '%s/%s' (container)", pcr.ID, p.Name, pv.Version) + continue + } + + toMatch := pv.LowerVersion + if pcr.MatchFullName { + toMatch = p.LowerName + "/" + pv.LowerVersion + } + + if pcr.KeepPatternMatcher != nil && pcr.KeepPatternMatcher.MatchString(toMatch) { + log.Debug("Rule[%d]: keep '%s/%s' (keep pattern)", pcr.ID, p.Name, pv.Version) + continue + } + if pv.CreatedUnix.AsLocalTime().After(olderThan) { + log.Debug("Rule[%d]: keep '%s/%s' (remove days)", pcr.ID, p.Name, pv.Version) + continue + } + if pcr.RemovePatternMatcher != nil && !pcr.RemovePatternMatcher.MatchString(toMatch) { + log.Debug("Rule[%d]: keep '%s/%s' (remove pattern)", pcr.ID, p.Name, pv.Version) + continue + } + + log.Debug("Rule[%d]: remove '%s/%s'", pcr.ID, p.Name, pv.Version) + + if err := DeletePackageVersionAndReferences(ctx, pv); err != nil { + return fmt.Errorf("CleanupRule [%d]: DeletePackageVersionAndReferences failed: %w", pcr.ID, err) + } + } + } + return nil + }) + if err != nil { + return err + } + if err := container_service.Cleanup(ctx, olderThan); err != nil { return err } diff --git a/templates/org/settings/navbar.tmpl b/templates/org/settings/navbar.tmpl index e7cbb87344d1b..7df1c85903c9c 100644 --- a/templates/org/settings/navbar.tmpl +++ b/templates/org/settings/navbar.tmpl @@ -17,6 +17,11 @@ {{.locale.Tr "settings.applications"}} {{end}} + {{if .EnablePackages}} + + {{.locale.Tr "packages.title"}} + + {{end}} {{.locale.Tr "org.settings.delete"}} diff --git a/templates/org/settings/packages.tmpl b/templates/org/settings/packages.tmpl new file mode 100644 index 0000000000000..bb5d95e1072a2 --- /dev/null +++ b/templates/org/settings/packages.tmpl @@ -0,0 +1,14 @@ +{{template "base/head" .}} +
+ {{template "org/header" .}} +
+
+ {{template "org/settings/navbar" .}} +
+ {{template "base/alert" .}} + {{template "package/shared/cleanup_rules/list" .}} +
+
+
+
+{{template "base/footer" .}} diff --git a/templates/org/settings/packages_cleanup_rules_edit.tmpl b/templates/org/settings/packages_cleanup_rules_edit.tmpl new file mode 100644 index 0000000000000..8c3725f4d7e9e --- /dev/null +++ b/templates/org/settings/packages_cleanup_rules_edit.tmpl @@ -0,0 +1,14 @@ +{{template "base/head" .}} +
+ {{template "org/header" .}} +
+
+ {{template "org/settings/navbar" .}} +
+ {{template "base/alert" .}} + {{template "package/shared/cleanup_rules/edit" .}} +
+
+
+
+{{template "base/footer" .}} diff --git a/templates/org/settings/packages_cleanup_rules_preview.tmpl b/templates/org/settings/packages_cleanup_rules_preview.tmpl new file mode 100644 index 0000000000000..e0e4652c367eb --- /dev/null +++ b/templates/org/settings/packages_cleanup_rules_preview.tmpl @@ -0,0 +1,13 @@ +{{template "base/head" .}} +
+ {{template "org/header" .}} +
+
+ {{template "org/settings/navbar" .}} +
+ {{template "package/shared/cleanup_rules/preview" .}} +
+
+
+
+{{template "base/footer" .}} diff --git a/templates/package/shared/cleanup_rules/edit.tmpl b/templates/package/shared/cleanup_rules/edit.tmpl new file mode 100644 index 0000000000000..f8525afb70b45 --- /dev/null +++ b/templates/package/shared/cleanup_rules/edit.tmpl @@ -0,0 +1,73 @@ +

{{if .IsEditRule}}{{.locale.Tr "packages.owner.settings.cleanuprules.edit"}}{{else}}{{.locale.Tr "packages.owner.settings.cleanuprules.add"}}{{end}}

+
+
+ {{.CsrfTokenHtml}} + +
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+

{{.locale.Tr "packages.owner.settings.cleanuprules.keep.title"}}

+
+ + +
+
+ + +

{{.locale.Tr "packages.owner.settings.cleanuprules.keep.pattern.container" | Safe}}

+
+
+

{{.locale.Tr "packages.owner.settings.cleanuprules.remove.title"}}

+
+ + +
+
+ + +
+
+ {{if .IsEditRule}} + + + {{.locale.Tr "packages.owner.settings.cleanuprules.preview"}} + {{else}} + + {{end}} +
+
+
diff --git a/templates/package/shared/cleanup_rules/list.tmpl b/templates/package/shared/cleanup_rules/list.tmpl new file mode 100644 index 0000000000000..09f95e4f4a4bd --- /dev/null +++ b/templates/package/shared/cleanup_rules/list.tmpl @@ -0,0 +1,34 @@ +

+ {{.locale.Tr "packages.owner.settings.cleanuprules.title"}} + +

+
+
+ {{range .CleanupRules}} +
+ + {{svg .Type.SVGName 36}} +
+ {{.Type.Name}} +
{{if .Enabled}}{{$.locale.Tr "enabled"}}{{else}}{{$.locale.Tr "disabled"}}{{end}}
+ {{if .KeepCount}}
{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count"}}: {{if eq .KeepCount 1}}{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count.1"}}{{else}}{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.count.n" .KeepCount}}{{end}}
{{end}} + {{if .KeepPattern}}
{{$.locale.Tr "packages.owner.settings.cleanuprules.keep.pattern"}}: {{EllipsisString .KeepPattern 100}}
{{end}} + {{if .RemoveDays}}
{{$.locale.Tr "packages.owner.settings.cleanuprules.remove.days"}}: {{$.locale.Tr "tool.days" .RemoveDays}}
{{end}} + {{if .RemovePattern}}
{{$.locale.Tr "packages.owner.settings.cleanuprules.remove.pattern"}}: {{EllipsisString .RemovePattern 100}}
{{end}} +
+
+ {{else}} +
{{.locale.Tr "packages.owner.settings.cleanuprules.none"}}
+ {{end}} +
+
diff --git a/templates/package/shared/cleanup_rules/preview.tmpl b/templates/package/shared/cleanup_rules/preview.tmpl new file mode 100644 index 0000000000000..c59ad67f7749c --- /dev/null +++ b/templates/package/shared/cleanup_rules/preview.tmpl @@ -0,0 +1,34 @@ +

{{.locale.Tr "packages.owner.settings.cleanuprules.preview"}}

+
+

{{.locale.Tr "packages.owner.settings.cleanuprules.preview.overview" (len .VersionsToRemove)}}

+
+
+ + + + + + + + + + + + + {{range .VersionsToRemove}} + + + + + + + + + {{else}} + + + + {{end}} + +
{{.locale.Tr "admin.packages.type"}}{{.locale.Tr "admin.packages.name"}}{{.locale.Tr "admin.packages.version"}}{{.locale.Tr "admin.packages.creator"}}{{.locale.Tr "admin.packages.size"}}{{.locale.Tr "admin.packages.published"}}
{{.Package.Type.Name}}{{.Package.Name}}{{.Version.Version}}{{.Creator.Name}}{{FileSize .CalculateBlobSize}}
{{.locale.Tr "packages.owner.settings.cleanuprules.preview.none"}}
+
diff --git a/templates/user/settings/navbar.tmpl b/templates/user/settings/navbar.tmpl index 01ae055d79097..d17494fc04856 100644 --- a/templates/user/settings/navbar.tmpl +++ b/templates/user/settings/navbar.tmpl @@ -18,6 +18,11 @@ {{.locale.Tr "settings.ssh_gpg_keys"}} + {{if .EnablePackages}} + + {{.locale.Tr "packages.title"}} + + {{end}} {{.locale.Tr "settings.organization"}} diff --git a/templates/user/settings/packages.tmpl b/templates/user/settings/packages.tmpl new file mode 100644 index 0000000000000..2612313454e88 --- /dev/null +++ b/templates/user/settings/packages.tmpl @@ -0,0 +1,9 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "base/alert" .}} + {{template "package/shared/cleanup_rules/list" .}} +
+
+{{template "base/footer" .}} diff --git a/templates/user/settings/packages_cleanup_rules_edit.tmpl b/templates/user/settings/packages_cleanup_rules_edit.tmpl new file mode 100644 index 0000000000000..4cf642b7e166a --- /dev/null +++ b/templates/user/settings/packages_cleanup_rules_edit.tmpl @@ -0,0 +1,9 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "base/alert" .}} + {{template "package/shared/cleanup_rules/edit" .}} +
+
+{{template "base/footer" .}} diff --git a/templates/user/settings/packages_cleanup_rules_preview.tmpl b/templates/user/settings/packages_cleanup_rules_preview.tmpl new file mode 100644 index 0000000000000..20041f9a42fdc --- /dev/null +++ b/templates/user/settings/packages_cleanup_rules_preview.tmpl @@ -0,0 +1,8 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "package/shared/cleanup_rules/preview" .}} +
+
+{{template "base/footer" .}} diff --git a/tests/integration/api_packages_test.go b/tests/integration/api_packages_test.go index 815685ea79960..8efb70848bf6b 100644 --- a/tests/integration/api_packages_test.go +++ b/tests/integration/api_packages_test.go @@ -203,22 +203,171 @@ func TestPackageQuota(t *testing.T) { func TestPackageCleanup(t *testing.T) { defer tests.PrepareTestEnv(t)() - time.Sleep(time.Second) + duration, _ := time.ParseDuration("-1h") - pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0)) - assert.NoError(t, err) - assert.NotEmpty(t, pbs) + t.Run("Common", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration) + assert.NoError(t, err) + assert.NotEmpty(t, pbs) - _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) - assert.NoError(t, err) + _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) + assert.NoError(t, err) - err = packages_service.Cleanup(nil, time.Duration(0)) - assert.NoError(t, err) + err = packages_service.Cleanup(db.DefaultContext, duration) + assert.NoError(t, err) - pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0)) - assert.NoError(t, err) - assert.Empty(t, pbs) + pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration) + assert.NoError(t, err) + assert.Empty(t, pbs) + + _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) + assert.ErrorIs(t, err, packages_model.ErrPackageNotExist) + }) - _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) - assert.ErrorIs(t, err, packages_model.ErrPackageNotExist) + t.Run("CleanupRules", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + + type version struct { + Version string + ShouldExist bool + Created int64 + } + + cases := []struct { + Name string + Versions []version + Rule *packages_model.PackageCleanupRule + }{ + { + Name: "Disabled", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: false, + }, + }, + { + Name: "KeepCount", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "v1.0", ShouldExist: true}, + {Version: "test-3", ShouldExist: false, Created: 1}, + {Version: "test-4", ShouldExist: false, Created: 1}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + KeepCount: 2, + }, + }, + { + Name: "KeepPattern", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "v1.0", ShouldExist: false}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + KeepPattern: "k.+p", + }, + }, + { + Name: "RemoveDays", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "v1.0", ShouldExist: false, Created: 1}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + RemoveDays: 60, + }, + }, + { + Name: "RemovePattern", + Versions: []version{ + {Version: "test", ShouldExist: true}, + {Version: "test-3", ShouldExist: false}, + {Version: "test-4", ShouldExist: false}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + RemovePattern: `t[e]+st-\d+`, + }, + }, + { + Name: "MatchFullName", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "test", ShouldExist: false}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + RemovePattern: `package/test|different/keep`, + MatchFullName: true, + }, + }, + { + Name: "Mixed", + Versions: []version{ + {Version: "keep", ShouldExist: true, Created: time.Now().Add(time.Duration(10000)).Unix()}, + {Version: "dummy", ShouldExist: true, Created: 1}, + {Version: "test-3", ShouldExist: true}, + {Version: "test-4", ShouldExist: false, Created: 1}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + KeepCount: 1, + KeepPattern: `dummy`, + RemoveDays: 7, + RemovePattern: `t[e]+st-\d+`, + }, + }, + } + + for _, c := range cases { + t.Run(c.Name, func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + for _, v := range c.Versions { + url := fmt.Sprintf("/api/packages/%s/generic/package/%s/file.bin", user.Name, v.Version) + req := NewRequestWithBody(t, "PUT", url, bytes.NewReader([]byte{1})) + AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusCreated) + + if v.Created != 0 { + pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeGeneric, "package", v.Version) + assert.NoError(t, err) + _, err = db.GetEngine(db.DefaultContext).Exec("UPDATE package_version SET created_unix = ? WHERE id = ?", v.Created, pv.ID) + assert.NoError(t, err) + } + } + + c.Rule.OwnerID = user.ID + c.Rule.Type = packages_model.TypeGeneric + + pcr, err := packages_model.InsertCleanupRule(db.DefaultContext, c.Rule) + assert.NoError(t, err) + + err = packages_service.Cleanup(db.DefaultContext, duration) + assert.NoError(t, err) + + for _, v := range c.Versions { + pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeGeneric, "package", v.Version) + if v.ShouldExist { + assert.NoError(t, err) + err = packages_service.DeletePackageVersionAndReferences(db.DefaultContext, pv) + assert.NoError(t, err) + } else { + assert.ErrorIs(t, err, packages_model.ErrPackageNotExist) + } + } + + assert.NoError(t, packages_model.DeleteCleanupRuleByID(db.DefaultContext, pcr.ID)) + }) + } + }) } From 43aafc5ba189efe9750326b21ee5a7c827929b75 Mon Sep 17 00:00:00 2001 From: Andrew Buettner <82419291+KB3HNS@users.noreply.github.com> Date: Sun, 20 Nov 2022 14:14:03 -0600 Subject: [PATCH 14/14] Improve documentation for PAM and static deployment (#21866) ## Changes proposed in [referenced issue 21845][1] - Expand PAM configuration description with working examples. - Clarify `STATIC_URL_PREFIX` use (include "assets" and only works after database has been initialized) - Add note for HTTPS proxy support VIA Apache. [1]: https://github.com/go-gitea/gitea/issues/21845 --- .../doc/advanced/config-cheat-sheet.en-us.md | 7 ++- .../doc/features/authentication.en-us.md | 46 +++++++++++++++++-- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index aece6afc08020..92758c61e402e 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -289,8 +289,13 @@ The following configuration set `Content-Type: application/vnd.android.package-a This includes CSS files, images, JS files and web fonts. Avatar images are dynamic resources and still served by Gitea. The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`. - Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective. + Requests are then made as `%(ROOT_URL)s/static/assets/css/index.css` or `https://cdn.example.com/assets/css/index.css` respectively. The static files are located in the `public/` directory of the Gitea source repository. + You can proxy the STATIC_URL_PREFIX requests to Gitea server to serve the static + assets, or copy the manually built Gitea assets from `$GITEA_BUILD/public` to + the assets location, eg: `/var/www/assets`, make sure `$STATIC_URL_PREFIX/assets/css/index.css` + points to `/var/www/assets/css/index.css`. + - `HTTP_ADDR`: **0.0.0.0**: HTTP listen address. - If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings. diff --git a/docs/content/doc/features/authentication.en-us.md b/docs/content/doc/features/authentication.en-us.md index 7d555d1dcc4b0..f25065d9c48db 100644 --- a/docs/content/doc/features/authentication.en-us.md +++ b/docs/content/doc/features/authentication.en-us.md @@ -166,11 +166,47 @@ Uses the following fields: ## PAM (Pluggable Authentication Module) -To configure PAM, set the 'PAM Service Name' to a filename in `/etc/pam.d/`. To -work with normal Linux passwords, the user running Gitea must have read access -to `/etc/shadow`. - -**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build), and the official binaries provided do not have this enabled. +This procedure enables PAM authentication. Users may still be added to the +system manually using the user administration. PAM provides a mechanism to +automatically add users to the current database by testing them against PAM +authentication. To work with normal Linux passwords, the user running Gitea +must also have read access to `/etc/shadow` in order to check the validity of +the account when logging in using a public key. + +**Note**: If a user has added SSH public keys into Gitea, the use of these +keys _may_ bypass the login check system. Therefore, if you wish to disable a user who +authenticates with PAM, you _should_ also manually disable the account in Gitea using the +built-in user manager. + +1. Configure and prepare the installation. + - It is recommended that you create an administrative user. + - Deselecting automatic sign-up may also be desired. +1. Once the database has been initialized, log in as the newly created +administrative user. +1. Navigate to the user setting (icon in top-right corner), and select +`Site Administration` -> `Authentication Sources`, and select +`Add Authentication Source`. +1. Fill out the field as follows: + - `Authentication Type` : `PAM` + - `Name` : Any value should be valid here, use "System Authentication" if + you'd like. + - `PAM Service Name` : Select the appropriate file listed under `/etc/pam.d/` + that performs the authentication desired.[^1] + - `PAM Email Domain` : The e-mail suffix to append to user authentication. + For example, if the login system expects a user called `gituser`, and this + field is set to `mail.com`, then Gitea will expect the `user email` field + for an authenticated GIT instance to be `gituser@mail.com`.[^2] + +**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build), +and the official binaries provided do not have this enabled. PAM requires that +the necessary libpam dynamic library be available and the necessary PAM +development headers be accessible to the compiler. + +[^1]: For example, using standard Linux log-in on Debian "Bullseye" use +`common-session-noninteractive` - this value may be valid for other flavors of +Debian including Ubuntu and Mint, consult your distribution's documentation. +[^2]: **This is a required field for PAM**. Be aware: In the above example, the +user will log into the Gitea web interface as `gituser` and not `gituser@mail.com` ## SMTP (Simple Mail Transfer Protocol)