From 48cd82b759bbd1f60bd7a39026fb80159813448d Mon Sep 17 00:00:00 2001 From: Peter Verraedt Date: Fri, 21 Jul 2023 21:41:38 +0200 Subject: [PATCH 01/23] Fix version in rpm repodata/primary.xml.gz (#26009) The version listed in rpm repodata should only contain the rpm version (1.0.0) and not the combination of version and release (1.0.0-2). We correct this behaviour in primary.xml.gz, filelists.xml.gz and others.xml.gz. Signed-off-by: Peter Verraedt --- services/packages/rpm/repository.go | 6 +++--- tests/integration/api_packages_rpm_test.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/services/packages/rpm/repository.go b/services/packages/rpm/repository.go index fb78e2b1135a..774613509e7e 100644 --- a/services/packages/rpm/repository.go +++ b/services/packages/rpm/repository.go @@ -378,7 +378,7 @@ func buildPrimary(pv *packages_model.PackageVersion, pfs []*packages_model.Packa Architecture: pd.FileMetadata.Architecture, Version: Version{ Epoch: pd.FileMetadata.Epoch, - Version: pd.Version.Version, + Version: pd.FileMetadata.Version, Release: pd.FileMetadata.Release, }, Checksum: Checksum{ @@ -466,7 +466,7 @@ func buildFilelists(pv *packages_model.PackageVersion, pfs []*packages_model.Pac Architecture: pd.FileMetadata.Architecture, Version: Version{ Epoch: pd.FileMetadata.Epoch, - Version: pd.Version.Version, + Version: pd.FileMetadata.Version, Release: pd.FileMetadata.Release, }, Files: pd.FileMetadata.Files, @@ -513,7 +513,7 @@ func buildOther(pv *packages_model.PackageVersion, pfs []*packages_model.Package Architecture: pd.FileMetadata.Architecture, Version: Version{ Epoch: pd.FileMetadata.Epoch, - Version: pd.Version.Version, + Version: pd.FileMetadata.Version, Release: pd.FileMetadata.Release, }, Changelogs: pd.FileMetadata.Changelogs, diff --git a/tests/integration/api_packages_rpm_test.go b/tests/integration/api_packages_rpm_test.go index e66460899f60..fc4c4d1c4b66 100644 --- a/tests/integration/api_packages_rpm_test.go +++ b/tests/integration/api_packages_rpm_test.go @@ -196,15 +196,15 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN switch d.Type { case "primary": assert.EqualValues(t, 718, d.Size) - assert.EqualValues(t, 1731, d.OpenSize) + assert.EqualValues(t, 1729, d.OpenSize) assert.Equal(t, "repodata/primary.xml.gz", d.Location.Href) case "filelists": - assert.EqualValues(t, 258, d.Size) - assert.EqualValues(t, 328, d.OpenSize) + assert.EqualValues(t, 257, d.Size) + assert.EqualValues(t, 326, d.OpenSize) assert.Equal(t, "repodata/filelists.xml.gz", d.Location.Href) case "other": - assert.EqualValues(t, 308, d.Size) - assert.EqualValues(t, 396, d.OpenSize) + assert.EqualValues(t, 306, d.Size) + assert.EqualValues(t, 394, d.OpenSize) assert.Equal(t, "repodata/other.xml.gz", d.Location.Href) } } From d6d39ccd33f7514f21eca2d89e16379201e291b9 Mon Sep 17 00:00:00 2001 From: delvh Date: Sat, 22 Jul 2023 11:01:38 +0200 Subject: [PATCH 02/23] Add changelog for 1.20.1 (#26015) --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d22f02e069f1..c08834645cb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,34 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log; to see the highlights of what has been added to each release, please refer to the [blog](https://blog.gitea.io). +## [1.20.1](https://github.com/go-gitea/gitea/releases/tag/1.20.1) - 2023-07-22 + +* SECURITY + * Disallow dangerous URL schemes (#25960) (#25964) +* ENHANCEMENTS + * Show the mismatched ROOT_URL warning on the sign-in page if OAuth2 is enabled (#25947) (#25972) + * Make pending commit status yellow again (#25935) (#25968) +* BUGFIXES + * Fix version in rpm repodata/primary.xml.gz (#26009) (#26048) + * Fix env config parsing for "GITEA____APP_NAME" (#26001) (#26013) + * ParseScope with owner/repo always sets owner to zero (#25987) (#25989) + * Fix SSPI auth panic (#25955) (#25969) + * Avoid creating directories when loading config (#25944) (#25957) + * Make environment-to-ini work with INSTALL_LOCK=true (#25926) (#25937) + * Ignore `runs-on` with expressions when warning no matched runners (#25917) (#25933) + * Avoid opening/closing PRs which are already merged (#25883) (#25903) +* DOCS + * RPM Registry: Show zypper commands for SUSE based distros as well (#25981) (#26020) + * Correctly refer to dev tags as nightly in the docker docs (#26004) (#26019) + * Update path related documents (#25417) (#25982) +* MISC + * Adding remaining enum for migration repo model type. (#26021) (#26034) + * Fix the route for pull-request's authors (#26016) (#26018) + * Fix commit status color on dashboard repolist (#25993) (#25998) + * Avoid hard-coding height in language dropdown menu (#25986) (#25997) + * Add shutting down notice (#25920) (#25922) + * Fix incorrect milestone count when provide a keyword (#25880) (#25904) + ## [1.20.0](https://github.com/go-gitea/gitea/releases/tag/v1.20.0) - 2023-07-16 * BREAKING From 73033b1ad895a351e5276ba82ee0c4215600133f Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 22 Jul 2023 11:32:50 +0200 Subject: [PATCH 03/23] Improve text for empty issue/pr description (#26047) The previous text implied that content was going to be added later, but I don't think we should make such assumptions. image --- options/locale/locale_en-US.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 5f671676b585..94ae49098157 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1448,7 +1448,7 @@ issues.context.quote_reply = Quote Reply issues.context.reference_issue = Reference in New Issue issues.context.edit = Edit issues.context.delete = Delete -issues.no_content = There is no content yet. +issues.no_content = No description provided. issues.close = Close Issue issues.comment_pull_merged_at = merged commit %[1]s into %[2]s %[3]s issues.comment_manually_pull_merged_at = manually merged commit %[1]s into %[2]s %[3]s From acc74c2fc6e67ca72293da1540226c3931700566 Mon Sep 17 00:00:00 2001 From: JonRB <4564448+eeyrjmr@users.noreply.github.com> Date: Sat, 22 Jul 2023 10:34:01 +0100 Subject: [PATCH 04/23] Update secrets.en-us.md (#26057) Present documentation does not capture that secrets are only visible if ACTIONS are enabled for a repository. This PR adds a short note --- docs/content/doc/usage/secrets.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/usage/secrets.en-us.md b/docs/content/doc/usage/secrets.en-us.md index c193a54a6c09..fe7677fc316f 100644 --- a/docs/content/doc/usage/secrets.en-us.md +++ b/docs/content/doc/usage/secrets.en-us.md @@ -18,7 +18,7 @@ menu: # Secrets Secrets allow you to store sensitive information in your user, organization or repository. -Secrets are available on Gitea 1.19+. +Secrets are available on Gitea 1.19+ and are only visible in 1.20+ when ACTIONS are enabled # Naming your secrets From a7e82735742096fabd97eb6faa0389d2dc49464d Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sat, 22 Jul 2023 18:54:48 +0800 Subject: [PATCH 05/23] Fix the truncate and alignment problem for some admin tables (#26042) Some "text truncate email" code were just copied&pasted, they are not suitable for most admin tables. For the table layouts, some "max-width" helpers could be very helpful. At least, we can get rid of the confusing "email" CSS class. ![image](https://github.com/go-gitea/gitea/assets/2114189/0b0bd068-56fc-41cf-b4a3-ed45eb797401) ![image](https://github.com/go-gitea/gitea/assets/2114189/e7f843a3-5f46-4205-b383-4c7ef647ce83) ![image](https://github.com/go-gitea/gitea/assets/2114189/ce8d65e1-7e03-466e-a03b-9bd33815da91) --- templates/admin/emails/list.tmpl | 4 +-- templates/admin/packages/list.tmpl | 4 +-- templates/admin/user/list.tmpl | 2 +- tests/integration/auth_ldap_test.go | 45 +++++++---------------------- web_src/css/admin.css | 4 --- web_src/css/helpers.css | 1 + 6 files changed, 16 insertions(+), 44 deletions(-) diff --git a/templates/admin/emails/list.tmpl b/templates/admin/emails/list.tmpl index 67e9cb05e896..153877174bf4 100644 --- a/templates/admin/emails/list.tmpl +++ b/templates/admin/emails/list.tmpl @@ -47,8 +47,8 @@ {{range .Emails}} {{.Name}} - {{.FullName}} - + {{.FullName}} + {{.Email}} {{if .IsPrimary}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} {{if .CanChange}} diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl index a0b6fd9bb055..9aa1d933f6a3 100644 --- a/templates/admin/packages/list.tmpl +++ b/templates/admin/packages/list.tmpl @@ -56,8 +56,8 @@ {{end}} {{.Package.Type.Name}} - {{.Package.Name}} - + {{.Package.Name}} + {{.Version.Version}} {{.Creator.Name}} {{if .Repository}} diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl index 3742b4ae8517..45fed87a4001 100644 --- a/templates/admin/user/list.tmpl +++ b/templates/admin/user/list.tmpl @@ -85,7 +85,7 @@ {{.ID}} {{.Name}} - + {{.Email}} {{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} {{if .IsAdmin}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} {{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go index d2160a3dbea2..25395f572102 100644 --- a/tests/integration/auth_ldap_test.go +++ b/tests/integration/auth_ldap_test.go @@ -226,45 +226,20 @@ func TestLDAPUserSync(t *testing.T) { addAuthSourceLDAP(t, "", "") auth.SyncExternalUsers(context.Background(), true) - session := loginUser(t, "user1") // Check if users exists - for _, u := range gitLDAPUsers { - req := NewRequest(t, "GET", "/admin/users?q="+u.UserName) - resp := session.MakeRequest(t, req, http.StatusOK) - - htmlDoc := NewHTMLParser(t, resp.Body) - - tr := htmlDoc.doc.Find("table.table tbody tr") - if !assert.True(t, tr.Length() == 1) { - continue - } - tds := tr.Find("td") - if !assert.True(t, tds.Length() > 0) { - continue - } - assert.Equal(t, u.UserName, strings.TrimSpace(tds.Find("td:nth-child(2) a").Text())) - assert.Equal(t, u.Email, strings.TrimSpace(tds.Find("td:nth-child(3) span").Text())) - if u.IsAdmin { - assert.True(t, tds.Find("td:nth-child(5) svg").HasClass("octicon-check")) - } else { - assert.True(t, tds.Find("td:nth-child(5) svg").HasClass("octicon-x")) - } - if u.IsRestricted { - assert.True(t, tds.Find("td:nth-child(6) svg").HasClass("octicon-check")) - } else { - assert.True(t, tds.Find("td:nth-child(6) svg").HasClass("octicon-x")) - } + for _, gitLDAPUser := range gitLDAPUsers { + dbUser, err := user_model.GetUserByName(db.DefaultContext, gitLDAPUser.UserName) + assert.NoError(t, err) + assert.Equal(t, gitLDAPUser.UserName, dbUser.Name) + assert.Equal(t, gitLDAPUser.Email, dbUser.Email) + assert.Equal(t, gitLDAPUser.IsAdmin, dbUser.IsAdmin) + assert.Equal(t, gitLDAPUser.IsRestricted, dbUser.IsRestricted) } // Check if no users exist - for _, u := range otherLDAPUsers { - req := NewRequest(t, "GET", "/admin/users?q="+u.UserName) - resp := session.MakeRequest(t, req, http.StatusOK) - - htmlDoc := NewHTMLParser(t, resp.Body) - - tr := htmlDoc.doc.Find("table.table tbody tr") - assert.True(t, tr.Length() == 0) + for _, otherLDAPUser := range otherLDAPUsers { + _, err := user_model.GetUserByName(db.DefaultContext, otherLDAPUser.UserName) + assert.True(t, user_model.IsErrUserNotExist(err)) } } diff --git a/web_src/css/admin.css b/web_src/css/admin.css index 8c9d1e201c2a..ec3cfbf22a3d 100644 --- a/web_src/css/admin.css +++ b/web_src/css/admin.css @@ -26,10 +26,6 @@ margin: 12px -1rem -1rem; } -.admin.user table.table .email { - max-width: 200px; -} - .admin dl.admin-dl-horizontal { padding: 1em; margin: 0; diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css index 73f2ebe79bd4..8a6c2c653907 100644 --- a/web_src/css/helpers.css +++ b/web_src/css/helpers.css @@ -52,6 +52,7 @@ Gitea's private styles use `g-` prefix. text-overflow: ellipsis; } +.gt-max-width-12rem { max-width: 12rem !important; } .gt-max-width-24rem { max-width: 24rem !important; } /* below class names match Tailwind CSS */ From c42b71877edb4830b9573101d20853222d66fb3c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 22 Jul 2023 19:47:06 +0800 Subject: [PATCH 06/23] Fix branch list auth (#26041) The public repositories' branch list dropdown will return wrong because it requires login wrongly. Caused by #25719 --- routers/web/web.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/web.go b/routers/web/web.go index 455791ad802d..6d5ccad484fa 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1091,7 +1091,6 @@ func registerRoutes(m *web.Route) { }, context.RepoRef(), canEnableEditor, context.RepoMustNotBeArchived()) m.Group("/branches", func() { - m.Get("/list", repo.GetBranchesList) m.Group("/_new", func() { m.Post("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.CreateBranch) m.Post("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.CreateBranch) @@ -1248,6 +1247,7 @@ func registerRoutes(m *web.Route) { }, repo.MustBeNotEmpty, dlSourceEnabled, reqRepoCodeReader) m.Group("/branches", func() { + m.Get("/list", repo.GetBranchesList) m.Get("", repo.Branches) }, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) From b167f35113e643ccdb17a2dde55bdec5960b284b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 22 Jul 2023 22:14:27 +0800 Subject: [PATCH 07/23] Add context parameter to some database functions (#26055) To avoid deadlock problem, almost database related functions should be have ctx as the first parameter. This PR do a refactor for some of these functions. --- models/activities/action.go | 8 +-- models/activities/repo_activity.go | 54 ++++++++++---------- models/issues/comment_list.go | 11 ++-- models/issues/issue.go | 14 ++--- models/issues/issue_list.go | 8 +-- models/issues/issue_list_test.go | 2 +- models/issues/issue_search.go | 2 +- models/issues/pull_list.go | 23 ++++----- models/issues/pull_test.go | 8 +-- models/issues/tracked_time.go | 20 +++----- models/issues/tracked_time_test.go | 2 +- models/migrate.go | 4 +- models/migrate_test.go | 2 +- modules/context/permission.go | 2 +- modules/context/repo.go | 12 ++--- routers/api/v1/api.go | 2 +- routers/api/v1/repo/branch.go | 8 +-- routers/api/v1/repo/file.go | 2 +- routers/api/v1/repo/issue.go | 10 ++-- routers/api/v1/repo/issue_attachment.go | 2 +- routers/api/v1/repo/issue_comment.go | 6 +-- routers/api/v1/repo/issue_dependency.go | 6 +-- routers/api/v1/repo/issue_label.go | 8 +-- routers/api/v1/repo/issue_pin.go | 6 +-- routers/api/v1/repo/issue_reaction.go | 4 +- routers/api/v1/repo/issue_stopwatch.go | 2 +- routers/api/v1/repo/issue_subscription.go | 6 +-- routers/api/v1/repo/issue_tracked_time.go | 26 +++++----- routers/private/hook_pre_receive.go | 2 +- routers/web/feed/convert.go | 2 +- routers/web/repo/issue.go | 14 ++--- routers/web/repo/issue_dependency.go | 4 +- routers/web/repo/issue_pin.go | 2 +- routers/web/repo/issue_timetrack.go | 2 +- routers/web/repo/pull.go | 2 +- routers/web/repo/setting/protected_branch.go | 2 +- routers/web/repo/view.go | 8 +-- services/agit/agit.go | 2 +- services/convert/convert.go | 12 ++--- services/convert/issue_comment.go | 2 +- services/issue/comments.go | 6 +-- services/issue/commit.go | 24 ++++----- services/issue/commit_test.go | 17 +++--- services/issue/status.go | 9 +--- services/migrations/gitea_uploader.go | 5 +- services/pull/check.go | 10 ++-- services/pull/check_test.go | 3 +- services/pull/merge.go | 26 ++++------ services/pull/pull.go | 26 +++++----- services/repository/push.go | 6 +-- 50 files changed, 209 insertions(+), 237 deletions(-) diff --git a/models/activities/action.go b/models/activities/action.go index 57f579372f80..7f22605d0d15 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -391,10 +391,10 @@ func (a *Action) GetIssueInfos() []string { } // GetIssueTitle returns the title of first issue associated -// with the action. +// with the action. This function will be invoked in template so keep db.DefaultContext here func (a *Action) GetIssueTitle() string { index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) - issue, err := issues_model.GetIssueByIndex(a.RepoID, index) + issue, err := issues_model.GetIssueByIndex(db.DefaultContext, a.RepoID, index) if err != nil { log.Error("GetIssueByIndex: %v", err) return "500 when get issue" @@ -404,9 +404,9 @@ func (a *Action) GetIssueTitle() string { // GetIssueContent returns the content of first issue associated with // this action. -func (a *Action) GetIssueContent() string { +func (a *Action) GetIssueContent(ctx context.Context) string { index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) - issue, err := issues_model.GetIssueByIndex(a.RepoID, index) + issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) if err != nil { log.Error("GetIssueByIndex: %v", err) return "500 when get issue" diff --git a/models/activities/repo_activity.go b/models/activities/repo_activity.go index 72b6be312260..509f9caaf3e4 100644 --- a/models/activities/repo_activity.go +++ b/models/activities/repo_activity.go @@ -47,21 +47,21 @@ type ActivityStats struct { func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, releases, issues, prs, code bool) (*ActivityStats, error) { stats := &ActivityStats{Code: &git.CodeActivityStats{}} if releases { - if err := stats.FillReleases(repo.ID, timeFrom); err != nil { + if err := stats.FillReleases(ctx, repo.ID, timeFrom); err != nil { return nil, fmt.Errorf("FillReleases: %w", err) } } if prs { - if err := stats.FillPullRequests(repo.ID, timeFrom); err != nil { + if err := stats.FillPullRequests(ctx, repo.ID, timeFrom); err != nil { return nil, fmt.Errorf("FillPullRequests: %w", err) } } if issues { - if err := stats.FillIssues(repo.ID, timeFrom); err != nil { + if err := stats.FillIssues(ctx, repo.ID, timeFrom); err != nil { return nil, fmt.Errorf("FillIssues: %w", err) } } - if err := stats.FillUnresolvedIssues(repo.ID, timeFrom, issues, prs); err != nil { + if err := stats.FillUnresolvedIssues(ctx, repo.ID, timeFrom, issues, prs); err != nil { return nil, fmt.Errorf("FillUnresolvedIssues: %w", err) } if code { @@ -205,41 +205,41 @@ func (stats *ActivityStats) PublishedReleaseCount() int { } // FillPullRequests returns pull request information for activity page -func (stats *ActivityStats) FillPullRequests(repoID int64, fromTime time.Time) error { +func (stats *ActivityStats) FillPullRequests(ctx context.Context, repoID int64, fromTime time.Time) error { var err error var count int64 // Merged pull requests - sess := pullRequestsForActivityStatement(repoID, fromTime, true) + sess := pullRequestsForActivityStatement(ctx, repoID, fromTime, true) sess.OrderBy("pull_request.merged_unix DESC") stats.MergedPRs = make(issues_model.PullRequestList, 0) if err = sess.Find(&stats.MergedPRs); err != nil { return err } - if err = stats.MergedPRs.LoadAttributes(); err != nil { + if err = stats.MergedPRs.LoadAttributes(ctx); err != nil { return err } // Merged pull request authors - sess = pullRequestsForActivityStatement(repoID, fromTime, true) + sess = pullRequestsForActivityStatement(ctx, repoID, fromTime, true) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("pull_request").Get(&count); err != nil { return err } stats.MergedPRAuthorCount = count // Opened pull requests - sess = pullRequestsForActivityStatement(repoID, fromTime, false) + sess = pullRequestsForActivityStatement(ctx, repoID, fromTime, false) sess.OrderBy("issue.created_unix ASC") stats.OpenedPRs = make(issues_model.PullRequestList, 0) if err = sess.Find(&stats.OpenedPRs); err != nil { return err } - if err = stats.OpenedPRs.LoadAttributes(); err != nil { + if err = stats.OpenedPRs.LoadAttributes(ctx); err != nil { return err } // Opened pull request authors - sess = pullRequestsForActivityStatement(repoID, fromTime, false) + sess = pullRequestsForActivityStatement(ctx, repoID, fromTime, false) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("pull_request").Get(&count); err != nil { return err } @@ -248,8 +248,8 @@ func (stats *ActivityStats) FillPullRequests(repoID int64, fromTime time.Time) e return nil } -func pullRequestsForActivityStatement(repoID int64, fromTime time.Time, merged bool) *xorm.Session { - sess := db.GetEngine(db.DefaultContext).Where("pull_request.base_repo_id=?", repoID). +func pullRequestsForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, merged bool) *xorm.Session { + sess := db.GetEngine(ctx).Where("pull_request.base_repo_id=?", repoID). Join("INNER", "issue", "pull_request.issue_id = issue.id") if merged { @@ -264,12 +264,12 @@ func pullRequestsForActivityStatement(repoID int64, fromTime time.Time, merged b } // FillIssues returns issue information for activity page -func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error { +func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTime time.Time) error { var err error var count int64 // Closed issues - sess := issuesForActivityStatement(repoID, fromTime, true, false) + sess := issuesForActivityStatement(ctx, repoID, fromTime, true, false) sess.OrderBy("issue.closed_unix DESC") stats.ClosedIssues = make(issues_model.IssueList, 0) if err = sess.Find(&stats.ClosedIssues); err != nil { @@ -277,14 +277,14 @@ func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error { } // Closed issue authors - sess = issuesForActivityStatement(repoID, fromTime, true, false) + sess = issuesForActivityStatement(ctx, repoID, fromTime, true, false) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil { return err } stats.ClosedIssueAuthorCount = count // New issues - sess = issuesForActivityStatement(repoID, fromTime, false, false) + sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false) sess.OrderBy("issue.created_unix ASC") stats.OpenedIssues = make(issues_model.IssueList, 0) if err = sess.Find(&stats.OpenedIssues); err != nil { @@ -292,7 +292,7 @@ func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error { } // Opened issue authors - sess = issuesForActivityStatement(repoID, fromTime, false, false) + sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil { return err } @@ -302,12 +302,12 @@ func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error { } // FillUnresolvedIssues returns unresolved issue and pull request information for activity page -func (stats *ActivityStats) FillUnresolvedIssues(repoID int64, fromTime time.Time, issues, prs bool) error { +func (stats *ActivityStats) FillUnresolvedIssues(ctx context.Context, repoID int64, fromTime time.Time, issues, prs bool) error { // Check if we need to select anything if !issues && !prs { return nil } - sess := issuesForActivityStatement(repoID, fromTime, false, true) + sess := issuesForActivityStatement(ctx, repoID, fromTime, false, true) if !issues || !prs { sess.And("issue.is_pull = ?", prs) } @@ -316,8 +316,8 @@ func (stats *ActivityStats) FillUnresolvedIssues(repoID int64, fromTime time.Tim return sess.Find(&stats.UnresolvedIssues) } -func issuesForActivityStatement(repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session { - sess := db.GetEngine(db.DefaultContext).Where("issue.repo_id = ?", repoID). +func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session { + sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID). And("issue.is_closed = ?", closed) if !unresolved { @@ -336,12 +336,12 @@ func issuesForActivityStatement(repoID int64, fromTime time.Time, closed, unreso } // FillReleases returns release information for activity page -func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error { +func (stats *ActivityStats) FillReleases(ctx context.Context, repoID int64, fromTime time.Time) error { var err error var count int64 // Published releases list - sess := releasesForActivityStatement(repoID, fromTime) + sess := releasesForActivityStatement(ctx, repoID, fromTime) sess.OrderBy("release.created_unix DESC") stats.PublishedReleases = make([]*repo_model.Release, 0) if err = sess.Find(&stats.PublishedReleases); err != nil { @@ -349,7 +349,7 @@ func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error } // Published releases authors - sess = releasesForActivityStatement(repoID, fromTime) + sess = releasesForActivityStatement(ctx, repoID, fromTime) if _, err = sess.Select("count(distinct release.publisher_id) as `count`").Table("release").Get(&count); err != nil { return err } @@ -358,8 +358,8 @@ func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error return nil } -func releasesForActivityStatement(repoID int64, fromTime time.Time) *xorm.Session { - return db.GetEngine(db.DefaultContext).Where("release.repo_id = ?", repoID). +func releasesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session { + return db.GetEngine(ctx).Where("release.repo_id = ?", repoID). And("release.is_draft = ?", false). And("release.created_unix >= ?", fromTime.Unix()) } diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index e9c8406c3a51..6f1d350eb42f 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -465,8 +465,9 @@ func (comments CommentList) loadReviews(ctx context.Context) error { return nil } -// loadAttributes loads all attributes -func (comments CommentList) loadAttributes(ctx context.Context) (err error) { +// LoadAttributes loads attributes of the comments, except for attachments and +// comments +func (comments CommentList) LoadAttributes(ctx context.Context) (err error) { if err = comments.LoadPosters(ctx); err != nil { return err } @@ -501,9 +502,3 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { return comments.loadDependentIssues(ctx) } - -// LoadAttributes loads attributes of the comments, except for attachments and -// comments -func (comments CommentList) LoadAttributes() error { - return comments.loadAttributes(db.DefaultContext) -} diff --git a/models/issues/issue.go b/models/issues/issue.go index c1a802c792a0..9d60d011ed7a 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -354,7 +354,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return err } - if err = issue.Comments.loadAttributes(ctx); err != nil { + if err = issue.Comments.LoadAttributes(ctx); err != nil { return err } if issue.IsTimetrackerEnabled(ctx) { @@ -502,7 +502,7 @@ func (issue *Issue) GetLastEventLabelFake() string { } // GetIssueByIndex returns raw issue without loading attributes by index in a repository. -func GetIssueByIndex(repoID, index int64) (*Issue, error) { +func GetIssueByIndex(ctx context.Context, repoID, index int64) (*Issue, error) { if index < 1 { return nil, ErrIssueNotExist{} } @@ -510,7 +510,7 @@ func GetIssueByIndex(repoID, index int64) (*Issue, error) { RepoID: repoID, Index: index, } - has, err := db.GetEngine(db.DefaultContext).Get(issue) + has, err := db.GetEngine(ctx).Get(issue) if err != nil { return nil, err } else if !has { @@ -520,12 +520,12 @@ func GetIssueByIndex(repoID, index int64) (*Issue, error) { } // GetIssueWithAttrsByIndex returns issue by index in a repository. -func GetIssueWithAttrsByIndex(repoID, index int64) (*Issue, error) { - issue, err := GetIssueByIndex(repoID, index) +func GetIssueWithAttrsByIndex(ctx context.Context, repoID, index int64) (*Issue, error) { + issue, err := GetIssueByIndex(ctx, repoID, index) if err != nil { return nil, err } - return issue, issue.LoadAttributes(db.DefaultContext) + return issue, issue.LoadAttributes(ctx) } // GetIssueByID returns an issue by given ID. @@ -846,7 +846,7 @@ func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) ([]*Issue, return nil, err } - err = IssueList(issues).LoadAttributes() + err = IssueList(issues).LoadAttributes(ctx) if err != nil { return nil, err } diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index 9cc41ec6ab37..a932ac255436 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -526,7 +526,7 @@ 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 { +func (issues IssueList) LoadAttributes(ctx context.Context) error { if _, err := issues.LoadRepositories(ctx); err != nil { return fmt.Errorf("issue.loadAttributes: LoadRepositories: %w", err) } @@ -562,12 +562,6 @@ func (issues IssueList) loadAttributes(ctx context.Context) error { return nil } -// LoadAttributes loads attributes of the issues, except for attachments and -// comments -func (issues IssueList) LoadAttributes() error { - return issues.loadAttributes(db.DefaultContext) -} - // LoadComments loads comments func (issues IssueList) LoadComments(ctx context.Context) error { return issues.loadComments(ctx, builder.NewCond()) diff --git a/models/issues/issue_list_test.go b/models/issues/issue_list_test.go index 696c3b765d3d..9069e1012da5 100644 --- a/models/issues/issue_list_test.go +++ b/models/issues/issue_list_test.go @@ -39,7 +39,7 @@ func TestIssueList_LoadAttributes(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}), } - assert.NoError(t, issueList.LoadAttributes()) + assert.NoError(t, issueList.LoadAttributes(db.DefaultContext)) for _, issue := range issueList { assert.EqualValues(t, issue.RepoID, issue.Repo.ID) for _, label := range issue.Labels { diff --git a/models/issues/issue_search.go b/models/issues/issue_search.go index 9fd13f09956a..6540ce02c0c5 100644 --- a/models/issues/issue_search.go +++ b/models/issues/issue_search.go @@ -440,7 +440,7 @@ func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) { return nil, fmt.Errorf("unable to query Issues: %w", err) } - if err := issues.LoadAttributes(); err != nil { + if err := issues.LoadAttributes(ctx); err != nil { return nil, fmt.Errorf("unable to LoadAttributes for Issues: %w", err) } diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index c443928344d1..3b2416900b5d 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -51,16 +51,16 @@ func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xor } // GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged -func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) { +func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) { prs := make([]*PullRequest, 0, 2) - sess := db.GetEngine(db.DefaultContext). + sess := db.GetEngine(ctx). Join("INNER", "issue", "issue.id = pull_request.issue_id"). Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?", repoID, branch, false, false, PullRequestFlowGithub) return prs, sess.Find(&prs) } // CanMaintainerWriteToBranch check whether user is a maintainer and could write to the branch -func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *user_model.User) bool { +func CanMaintainerWriteToBranch(ctx context.Context, p access_model.Permission, branch string, user *user_model.User) bool { if p.CanWrite(unit.TypeCode) { return true } @@ -69,18 +69,18 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user * return false } - prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch) + prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, p.Units[0].RepoID, branch) if err != nil { return false } for _, pr := range prs { if pr.AllowMaintainerEdit { - err = pr.LoadBaseRepo(db.DefaultContext) + err = pr.LoadBaseRepo(ctx) if err != nil { continue } - prPerm, err := access_model.GetUserRepoPermission(db.DefaultContext, pr.BaseRepo, user) + prPerm, err := access_model.GetUserRepoPermission(ctx, pr.BaseRepo, user) if err != nil { continue } @@ -104,9 +104,9 @@ func HasUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch // GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged // by given base information (repo and branch). -func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) { +func GetUnmergedPullRequestsByBaseInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) { prs := make([]*PullRequest, 0, 2) - return prs, db.GetEngine(db.DefaultContext). + return prs, db.GetEngine(ctx). Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?", repoID, branch, false, false). OrderBy("issue.updated_unix DESC"). @@ -154,7 +154,7 @@ func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, // PullRequestList defines a list of pull requests type PullRequestList []*PullRequest -func (prs PullRequestList) loadAttributes(ctx context.Context) error { +func (prs PullRequestList) LoadAttributes(ctx context.Context) error { if len(prs) == 0 { return nil } @@ -199,8 +199,3 @@ func (prs PullRequestList) GetIssueIDs() []int64 { } return issueIDs } - -// LoadAttributes load all the prs attributes -func (prs PullRequestList) LoadAttributes() error { - return prs.loadAttributes(db.DefaultContext) -} diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go index 5856b5dc5863..0990a3b87067 100644 --- a/models/issues/pull_test.go +++ b/models/issues/pull_test.go @@ -148,7 +148,7 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) { func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2") + prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "branch2") assert.NoError(t, err) assert.Len(t, prs, 1) for _, pr := range prs { @@ -159,7 +159,7 @@ func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) { func TestGetUnmergedPullRequestsByBaseInfo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(1, "master") + prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(db.DefaultContext, 1, "master") assert.NoError(t, err) assert.Len(t, prs, 1) pr := prs[0] @@ -242,13 +242,13 @@ func TestPullRequestList_LoadAttributes(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}), unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}), } - assert.NoError(t, issues_model.PullRequestList(prs).LoadAttributes()) + assert.NoError(t, issues_model.PullRequestList(prs).LoadAttributes(db.DefaultContext)) for _, pr := range prs { assert.NotNil(t, pr.Issue) assert.Equal(t, pr.IssueID, pr.Issue.ID) } - assert.NoError(t, issues_model.PullRequestList([]*issues_model.PullRequest{}).LoadAttributes()) + assert.NoError(t, issues_model.PullRequestList([]*issues_model.PullRequest{}).LoadAttributes(db.DefaultContext)) } // TODO TestAddTestPullRequestTask diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go index d117b74bc037..58c6b775f077 100644 --- a/models/issues/tracked_time.go +++ b/models/issues/tracked_time.go @@ -43,11 +43,7 @@ func (t *TrackedTime) AfterLoad() { } // LoadAttributes load Issue, User -func (t *TrackedTime) LoadAttributes() (err error) { - return t.loadAttributes(db.DefaultContext) -} - -func (t *TrackedTime) loadAttributes(ctx context.Context) (err error) { +func (t *TrackedTime) LoadAttributes(ctx context.Context) (err error) { // Load the issue if t.Issue == nil { t.Issue, err = GetIssueByID(ctx, t.IssueID) @@ -76,9 +72,9 @@ func (t *TrackedTime) loadAttributes(ctx context.Context) (err error) { } // LoadAttributes load Issue, User -func (tl TrackedTimeList) LoadAttributes() error { +func (tl TrackedTimeList) LoadAttributes(ctx context.Context) error { for _, t := range tl { - if err := t.LoadAttributes(); err != nil { + if err := t.LoadAttributes(ctx); err != nil { return err } } @@ -143,8 +139,8 @@ func GetTrackedTimes(ctx context.Context, options *FindTrackedTimesOptions) (tra } // CountTrackedTimes returns count of tracked times that fit to the given options. -func CountTrackedTimes(opts *FindTrackedTimesOptions) (int64, error) { - sess := db.GetEngine(db.DefaultContext).Where(opts.toCond()) +func CountTrackedTimes(ctx context.Context, opts *FindTrackedTimesOptions) (int64, error) { + sess := db.GetEngine(ctx).Where(opts.toCond()) if opts.RepositoryID > 0 || opts.MilestoneID > 0 { sess = sess.Join("INNER", "issue", "issue.id = tracked_time.issue_id") } @@ -157,8 +153,8 @@ func GetTrackedSeconds(ctx context.Context, opts FindTrackedTimesOptions) (track } // AddTime will add the given time (in seconds) to the issue -func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func AddTime(ctx context.Context, user *user_model.User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return nil, err } @@ -276,7 +272,7 @@ func DeleteTime(t *TrackedTime) error { } defer committer.Close() - if err := t.loadAttributes(ctx); err != nil { + if err := t.LoadAttributes(ctx); err != nil { return err } diff --git a/models/issues/tracked_time_test.go b/models/issues/tracked_time_test.go index 37ba1cfdc490..1d881091839b 100644 --- a/models/issues/tracked_time_test.go +++ b/models/issues/tracked_time_test.go @@ -25,7 +25,7 @@ func TestAddTime(t *testing.T) { assert.NoError(t, err) // 3661 = 1h 1min 1s - trackedTime, err := issues_model.AddTime(user3, issue1, 3661, time.Now()) + trackedTime, err := issues_model.AddTime(db.DefaultContext, user3, issue1, 3661, time.Now()) assert.NoError(t, err) assert.Equal(t, int64(3), trackedTime.UserID) assert.Equal(t, int64(1), trackedTime.IssueID) diff --git a/models/migrate.go b/models/migrate.go index 82cacd4a75b2..9705d0ad04c4 100644 --- a/models/migrate.go +++ b/models/migrate.go @@ -128,8 +128,8 @@ func InsertIssueComments(comments []*issues_model.Comment) error { } // InsertPullRequests inserted pull requests -func InsertPullRequests(prs ...*issues_model.PullRequest) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func InsertPullRequests(ctx context.Context, prs ...*issues_model.PullRequest) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/migrate_test.go b/models/migrate_test.go index 42102f9a7d22..74736a28492c 100644 --- a/models/migrate_test.go +++ b/models/migrate_test.go @@ -122,7 +122,7 @@ func TestMigrate_InsertPullRequests(t *testing.T) { Issue: i, } - err := InsertPullRequests(p) + err := InsertPullRequests(db.DefaultContext, p) assert.NoError(t, err) _ = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{IssueID: i.ID}) diff --git a/modules/context/permission.go b/modules/context/permission.go index 09343b8b50bc..14a9801dccba 100644 --- a/modules/context/permission.go +++ b/modules/context/permission.go @@ -35,7 +35,7 @@ func RequireRepoWriter(unitType unit.Type) func(ctx *Context) { // CanEnableEditor checks if the user is allowed to write to the branch of the repo func CanEnableEditor() func(ctx *Context) { return func(ctx *Context) { - if !ctx.Repo.CanWriteToBranch(ctx.Doer, ctx.Repo.BranchName) { + if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { ctx.NotFound("CanWriteToBranch denies permission", nil) return } diff --git a/modules/context/repo.go b/modules/context/repo.go index 2c67735c934c..f5c56cf83323 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -66,13 +66,13 @@ type Repository struct { } // CanWriteToBranch checks if the branch is writable by the user -func (r *Repository) CanWriteToBranch(user *user_model.User, branch string) bool { - return issues_model.CanMaintainerWriteToBranch(r.Permission, branch, user) +func (r *Repository) CanWriteToBranch(ctx context.Context, user *user_model.User, branch string) bool { + return issues_model.CanMaintainerWriteToBranch(ctx, r.Permission, branch, user) } // CanEnableEditor returns true if repository is editable and user has proper access level. -func (r *Repository) CanEnableEditor(user *user_model.User) bool { - return r.IsViewBranch && r.CanWriteToBranch(user, r.BranchName) && r.Repository.CanEnableEditor() && !r.Repository.IsArchived +func (r *Repository) CanEnableEditor(ctx context.Context, user *user_model.User) bool { + return r.IsViewBranch && r.CanWriteToBranch(ctx, user, r.BranchName) && r.Repository.CanEnableEditor() && !r.Repository.IsArchived } // CanCreateBranch returns true if repository is editable and user has proper access level. @@ -118,7 +118,7 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use sign, keyID, _, err := asymkey_service.SignCRUDAction(ctx, r.Repository.RepoPath(), doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName) - canCommit := r.CanEnableEditor(doer) && userCanPush + canCommit := r.CanEnableEditor(ctx, doer) && userCanPush if requireSigned { canCommit = canCommit && sign } @@ -134,7 +134,7 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use return CanCommitToBranchResults{ CanCommitToBranch: canCommit, - EditorEnabled: r.CanEnableEditor(doer), + EditorEnabled: r.CanEnableEditor(ctx, doer), UserCanPush: userCanPush, RequireSigned: requireSigned, WillSign: sign, diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index eee97cbc2093..91483f0e388f 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -386,7 +386,7 @@ func reqRepoWriter(unitTypes ...unit.Type) func(ctx *context.APIContext) { // reqRepoBranchWriter user should have a permission to write to a branch, or be a site admin func reqRepoBranchWriter(ctx *context.APIContext) { options, ok := web.GetForm(ctx).(api.FileOptionInterface) - if !ok || (!ctx.Repo.CanWriteToBranch(ctx.Doer, options.Branch()) && !ctx.IsUserSiteAdmin()) { + if !ok || (!ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, options.Branch()) && !ctx.IsUserSiteAdmin()) { ctx.Error(http.StatusForbidden, "reqRepoBranchWriter", "user should have a permission to write to this branch") return } diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 5e2c9878f088..577776dadd36 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -644,7 +644,7 @@ func CreateBranchProtection(ctx *context.APIContext) { } if isBranchExist { - if err = pull_service.CheckPRsForBaseBranch(ctx.Repo.Repository, ruleName); err != nil { + if err = pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, ruleName); err != nil { ctx.Error(http.StatusInternalServerError, "CheckPRsForBaseBranch", err) return } @@ -669,7 +669,7 @@ func CreateBranchProtection(ctx *context.APIContext) { } for _, branchName := range matchedBranches { - if err = pull_service.CheckPRsForBaseBranch(ctx.Repo.Repository, branchName); err != nil { + if err = pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, branchName); err != nil { ctx.Error(http.StatusInternalServerError, "CheckPRsForBaseBranch", err) return } @@ -914,7 +914,7 @@ func EditBranchProtection(ctx *context.APIContext) { } if isBranchExist { - if err = pull_service.CheckPRsForBaseBranch(ctx.Repo.Repository, bpName); err != nil { + if err = pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, bpName); err != nil { ctx.Error(http.StatusInternalServerError, "CheckPrsForBaseBranch", err) return } @@ -940,7 +940,7 @@ func EditBranchProtection(ctx *context.APIContext) { } for _, branchName := range matchedBranches { - if err = pull_service.CheckPRsForBaseBranch(ctx.Repo.Repository, branchName); err != nil { + if err = pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, branchName); err != nil { ctx.Error(http.StatusInternalServerError, "CheckPrsForBaseBranch", err) return } diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index ffde5855ba15..ea311c320292 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -398,7 +398,7 @@ func GetEditorconfig(ctx *context.APIContext) { // canWriteFiles returns true if repository is editable and user has proper access level. func canWriteFiles(ctx *context.APIContext, branch string) bool { - return ctx.Repo.CanWriteToBranch(ctx.Doer, branch) && + return ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, branch) && !ctx.Repo.Repository.IsMirror && !ctx.Repo.Repository.IsArchived } diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index e76775ae8222..8a61fc983451 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -552,7 +552,7 @@ func GetIssue(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -661,7 +661,7 @@ func CreateIssue(ctx *context.APIContext) { } if form.Closed { - if err := issue_service.ChangeStatus(issue, ctx.Doer, "", true); err != nil { + if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", true); err != nil { if issues_model.IsErrDependenciesLeft(err) { ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") return @@ -721,7 +721,7 @@ func EditIssue(ctx *context.APIContext) { // "$ref": "#/responses/error" form := web.GetForm(ctx).(*api.EditIssueOption) - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -877,7 +877,7 @@ func DeleteIssue(ctx *context.APIContext) { // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound(err) @@ -933,7 +933,7 @@ func UpdateIssueDeadline(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" form := web.GetForm(ctx).(*api.EditDeadlineOption) - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go index 779da9fd7f80..ad83c206d9c6 100644 --- a/routers/api/v1/repo/issue_attachment.go +++ b/routers/api/v1/repo/issue_attachment.go @@ -307,7 +307,7 @@ func DeleteIssueAttachment(ctx *context.APIContext) { } func getIssueFromContext(ctx *context.APIContext) *issues_model.Issue { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64("index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64("index")) if err != nil { ctx.NotFoundOrServerError("GetIssueByIndex", issues_model.IsErrIssueNotExist, err) return nil diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index c2392126db90..1f8e16147ffa 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -64,7 +64,7 @@ func ListIssueComments(ctx *context.APIContext) { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { ctx.Error(http.StatusInternalServerError, "GetRawIssueByIndex", err) return @@ -161,7 +161,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { ctx.Error(http.StatusInternalServerError, "GetRawIssueByIndex", err) return @@ -351,7 +351,7 @@ func CreateIssueComment(ctx *context.APIContext) { // "403": // "$ref": "#/responses/forbidden" form := web.GetForm(ctx).(*api.CreateIssueCommentOption) - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) return diff --git a/routers/api/v1/repo/issue_dependency.go b/routers/api/v1/repo/issue_dependency.go index 8a57ad581e28..b0eb208a32ed 100644 --- a/routers/api/v1/repo/issue_dependency.go +++ b/routers/api/v1/repo/issue_dependency.go @@ -59,7 +59,7 @@ func GetIssueDependencies(ctx *context.APIContext) { return } - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound("IsErrIssueNotExist", err) @@ -484,7 +484,7 @@ func RemoveIssueBlocking(ctx *context.APIContext) { } func getParamsIssue(ctx *context.APIContext) *issues_model.Issue { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound("IsErrIssueNotExist", err) @@ -518,7 +518,7 @@ func getFormIssue(ctx *context.APIContext, form *api.IssueMeta) *issues_model.Is repo = ctx.Repo.Repository } - issue, err := issues_model.GetIssueByIndex(repo.ID, form.Index) + issue, err := issues_model.GetIssueByIndex(ctx, repo.ID, form.Index) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound("IsErrIssueNotExist", err) diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go index 9d43c66d8c99..fc83b6f14c94 100644 --- a/routers/api/v1/repo/issue_label.go +++ b/routers/api/v1/repo/issue_label.go @@ -45,7 +45,7 @@ func ListIssueLabels(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -157,7 +157,7 @@ func DeleteIssueLabel(ctx *context.APIContext) { // "422": // "$ref": "#/responses/validationError" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -275,7 +275,7 @@ func ClearIssueLabels(ctx *context.APIContext) { // "403": // "$ref": "#/responses/forbidden" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -299,7 +299,7 @@ func ClearIssueLabels(ctx *context.APIContext) { } func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) (*issues_model.Issue, []*issues_model.Label, error) { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() diff --git a/routers/api/v1/repo/issue_pin.go b/routers/api/v1/repo/issue_pin.go index 1e774d4afa07..687673908399 100644 --- a/routers/api/v1/repo/issue_pin.go +++ b/routers/api/v1/repo/issue_pin.go @@ -41,7 +41,7 @@ func PinIssue(ctx *context.APIContext) { // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -98,7 +98,7 @@ func UnpinIssue(ctx *context.APIContext) { // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -159,7 +159,7 @@ func MoveIssuePin(ctx *context.APIContext) { // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index 921f6e53f9c0..49e5a74aa3b1 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -269,7 +269,7 @@ func GetIssueReactions(ctx *context.APIContext) { // "403": // "$ref": "#/responses/forbidden" - issue, err := issues_model.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -389,7 +389,7 @@ func DeleteIssueReaction(ctx *context.APIContext) { } func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) { - issue, err := issues_model.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() diff --git a/routers/api/v1/repo/issue_stopwatch.go b/routers/api/v1/repo/issue_stopwatch.go index 9ab3c61deb4f..75fa86313857 100644 --- a/routers/api/v1/repo/issue_stopwatch.go +++ b/routers/api/v1/repo/issue_stopwatch.go @@ -161,7 +161,7 @@ func DeleteIssueStopwatch(ctx *context.APIContext) { } func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*issues_model.Issue, error) { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go index 107119eb08f5..5a0547126465 100644 --- a/routers/api/v1/repo/issue_subscription.go +++ b/routers/api/v1/repo/issue_subscription.go @@ -104,7 +104,7 @@ func DelIssueSubscription(ctx *context.APIContext) { } func setIssueSubscription(ctx *context.APIContext, watch bool) { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -185,7 +185,7 @@ func CheckIssueSubscription(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() @@ -251,7 +251,7 @@ func GetIssueSubscribers(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound() diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index 1ff934950c04..3286a7c82e4e 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -75,7 +75,7 @@ func ListTrackedTimes(ctx *context.APIContext) { ctx.NotFound("Timetracker is disabled") return } - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound(err) @@ -121,7 +121,7 @@ func ListTrackedTimes(ctx *context.APIContext) { } } - count, err := issues_model.CountTrackedTimes(opts) + count, err := issues_model.CountTrackedTimes(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -132,7 +132,7 @@ func ListTrackedTimes(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err) return } - if err = trackedTimes.LoadAttributes(); err != nil { + if err = trackedTimes.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -179,7 +179,7 @@ func AddTime(ctx *context.APIContext) { // "403": // "$ref": "#/responses/forbidden" form := web.GetForm(ctx).(*api.AddTimeOption) - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound(err) @@ -214,12 +214,12 @@ func AddTime(ctx *context.APIContext) { created = form.Created } - trackedTime, err := issues_model.AddTime(user, issue, form.Time, created) + trackedTime, err := issues_model.AddTime(ctx, user, issue, form.Time, created) if err != nil { ctx.Error(http.StatusInternalServerError, "AddTime", err) return } - if err = trackedTime.LoadAttributes(); err != nil { + if err = trackedTime.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -260,7 +260,7 @@ func ResetIssueTime(ctx *context.APIContext) { // "403": // "$ref": "#/responses/forbidden" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound(err) @@ -331,7 +331,7 @@ func DeleteTime(ctx *context.APIContext) { // "403": // "$ref": "#/responses/forbidden" - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound(err) @@ -443,7 +443,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err) return } - if err = trackedTimes.LoadAttributes(); err != nil { + if err = trackedTimes.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -540,7 +540,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { } } - count, err := issues_model.CountTrackedTimes(opts) + count, err := issues_model.CountTrackedTimes(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -551,7 +551,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err) return } - if err = trackedTimes.LoadAttributes(); err != nil { + if err = trackedTimes.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -601,7 +601,7 @@ func ListMyTrackedTimes(ctx *context.APIContext) { return } - count, err := issues_model.CountTrackedTimes(opts) + count, err := issues_model.CountTrackedTimes(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -613,7 +613,7 @@ func ListMyTrackedTimes(ctx *context.APIContext) { return } - if err = trackedTimes.LoadAttributes(); err != nil { + if err = trackedTimes.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index 7f37d73795a0..4399e4985187 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -55,7 +55,7 @@ func (ctx *preReceiveContext) CanWriteCode() bool { if !ctx.loadPusherAndPermission() { return false } - ctx.canWriteCode = issues_model.CanMaintainerWriteToBranch(ctx.userPerm, ctx.branchName, ctx.user) || ctx.deployKeyAccessMode >= perm_model.AccessModeWrite + ctx.canWriteCode = issues_model.CanMaintainerWriteToBranch(ctx, ctx.userPerm, ctx.branchName, ctx.user) || ctx.deployKeyAccessMode >= perm_model.AccessModeWrite ctx.checkedCanWriteCode = true } return ctx.canWriteCode diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 76dc769c65f5..3775ba495a0d 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -220,7 +220,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio case activities_model.ActionCreateIssue, activities_model.ActionCreatePullRequest: desc = strings.Join(act.GetIssueInfos(), "#") - content = renderMarkdown(ctx, act, act.GetIssueContent()) + content = renderMarkdown(ctx, act, act.GetIssueContent(ctx)) case activities_model.ActionCommentIssue, activities_model.ActionApprovePullRequest, activities_model.ActionRejectPullRequest, activities_model.ActionCommentPull: desc = act.GetIssueTitle() comment := act.GetIssueInfos()[1] diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index f85551404849..b7d159d15808 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1278,7 +1278,7 @@ func ViewIssue(ctx *context.Context) { } } - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound("GetIssueByIndex", err) @@ -1981,7 +1981,7 @@ func sortDependencyInfo(blockers []*issues_model.DependencyInfo) { // GetActionIssue will return the issue which is used in the context. func GetActionIssue(ctx *context.Context) *issues_model.Issue { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { ctx.NotFoundOrServerError("GetIssueByIndex", issues_model.IsErrIssueNotExist, err) return nil @@ -2046,7 +2046,7 @@ func getActionIssues(ctx *context.Context) issues_model.IssueList { // GetIssueInfo get an issue of a repository func GetIssueInfo(ctx *context.Context) { - issue, err := issues_model.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.Error(http.StatusNotFound) @@ -2170,7 +2170,7 @@ func UpdateIssueContent(ctx *context.Context) { // UpdateIssueDeadline updates an issue deadline func UpdateIssueDeadline(ctx *context.Context) { form := web.GetForm(ctx).(*api.EditDeadlineOption) - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound("GetIssueByIndex", err) @@ -2784,7 +2784,7 @@ func UpdateIssueStatus(ctx *context.Context) { continue } if issue.IsClosed != isClosed { - if err := issue_service.ChangeStatus(issue, ctx.Doer, "", isClosed); err != nil { + if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", isClosed); err != nil { if issues_model.IsErrDependenciesLeft(err) { ctx.JSON(http.StatusPreconditionFailed, map[string]any{ "error": ctx.Tr("repo.issues.dependency.issue_batch_close_blocked", issue.Index), @@ -2869,7 +2869,7 @@ func NewComment(ctx *context.Context) { // Regenerate patch and test conflict. if pr == nil { issue.PullRequest.HeadCommitID = "" - pull_service.AddToTaskQueue(issue.PullRequest) + pull_service.AddToTaskQueue(ctx, issue.PullRequest) } // check whether the ref of PR in base repo is consistent with the head commit of head branch in the head repo @@ -2927,7 +2927,7 @@ func NewComment(ctx *context.Context) { ctx.Flash.Info(ctx.Tr("repo.pulls.open_unmerged_pull_exists", pr.Index)) } else { isClosed := form.Status == "close" - if err := issue_service.ChangeStatus(issue, ctx.Doer, "", isClosed); err != nil { + if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", isClosed); err != nil { log.Error("ChangeStatus: %v", err) if issues_model.IsErrDependenciesLeft(err) { diff --git a/routers/web/repo/issue_dependency.go b/routers/web/repo/issue_dependency.go index d3af319c711a..5b9c570b74f9 100644 --- a/routers/web/repo/issue_dependency.go +++ b/routers/web/repo/issue_dependency.go @@ -15,7 +15,7 @@ import ( // AddDependency adds new dependencies func AddDependency(ctx *context.Context) { issueIndex := ctx.ParamsInt64("index") - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, issueIndex) if err != nil { ctx.ServerError("GetIssueByIndex", err) return @@ -90,7 +90,7 @@ func AddDependency(ctx *context.Context) { // RemoveDependency removes the dependency func RemoveDependency(ctx *context.Context) { issueIndex := ctx.ParamsInt64("index") - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, issueIndex) if err != nil { ctx.ServerError("GetIssueByIndex", err) return diff --git a/routers/web/repo/issue_pin.go b/routers/web/repo/issue_pin.go index 871ca3b333ae..f853f72335e6 100644 --- a/routers/web/repo/issue_pin.go +++ b/routers/web/repo/issue_pin.go @@ -39,7 +39,7 @@ func IssuePinOrUnpin(ctx *context.Context) { // IssueUnpin unpins a Issue func IssueUnpin(ctx *context.Context) { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { ctx.Status(http.StatusInternalServerError) log.Error(err.Error()) diff --git a/routers/web/repo/issue_timetrack.go b/routers/web/repo/issue_timetrack.go index 7dc7d0797dc0..04ca65dd9a1e 100644 --- a/routers/web/repo/issue_timetrack.go +++ b/routers/web/repo/issue_timetrack.go @@ -42,7 +42,7 @@ func AddTimeManually(c *context.Context) { return } - if _, err := issues_model.AddTime(c.Doer, issue, int64(total.Seconds()), time.Now()); err != nil { + if _, err := issues_model.AddTime(c, c.Doer, issue, int64(total.Seconds()), time.Now()); err != nil { c.ServerError("AddTime", err) return } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index adfc01c2517f..5290e25d463f 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -300,7 +300,7 @@ func ForkPost(ctx *context.Context) { } func checkPullInfo(ctx *context.Context) *issues_model.Issue { - issue, err := issues_model.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { ctx.NotFound("GetIssueByIndex", err) diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index b8775cca2d3c..cf59e747d84f 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -303,7 +303,7 @@ func SettingsProtectedBranchPost(ctx *context.Context) { return } for _, branchName := range matchedBranches { - if err = pull_service.CheckPRsForBaseBranch(ctx.Repo.Repository, branchName); err != nil { + if err = pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, branchName); err != nil { ctx.ServerError("CheckPRsForBaseBranch", err) return } diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index ece2ec5416a5..a1c82f5395d7 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -530,7 +530,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["LineEscapeStatus"] = statuses } if !fInfo.isLFSFile { - if ctx.Repo.CanEnableEditor(ctx.Doer) { + if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) { if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { ctx.Data["CanEditFile"] = false ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") @@ -540,7 +540,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st } } else if !ctx.Repo.IsViewBranch { ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") - } else if !ctx.Repo.CanWriteToBranch(ctx.Doer, ctx.Repo.BranchName) { + } else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit") } } @@ -578,7 +578,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st } } - if ctx.Repo.CanEnableEditor(ctx.Doer) { + if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) { if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { ctx.Data["CanDeleteFile"] = false ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") @@ -588,7 +588,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st } } else if !ctx.Repo.IsViewBranch { ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") - } else if !ctx.Repo.CanWriteToBranch(ctx.Doer, ctx.Repo.BranchName) { + } else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_have_write_access") } } diff --git a/services/agit/agit.go b/services/agit/agit.go index 208ea109f4c7..ac8c52d19c9f 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -197,7 +197,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. return nil, fmt.Errorf("Failed to update pull ref. Error: %w", err) } - pull_service.AddToTaskQueue(pr) + pull_service.AddToTaskQueue(ctx, pr) pusher, err := user_model.GetUserByID(ctx, opts.UserID) if err != nil { return nil, fmt.Errorf("Failed to get user. Error: %w", err) diff --git a/services/convert/convert.go b/services/convert/convert.go index 25c89747e304..cb246a8b4b79 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -56,16 +56,16 @@ func ToBranch(ctx context.Context, repo *repo_model.Repository, branchName strin var canPush bool var err error if user != nil { - hasPerm, err = access_model.HasAccessUnit(db.DefaultContext, user, repo, unit.TypeCode, perm.AccessModeWrite) + hasPerm, err = access_model.HasAccessUnit(ctx, user, repo, unit.TypeCode, perm.AccessModeWrite) if err != nil { return nil, err } - perms, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + perms, err := access_model.GetUserRepoPermission(ctx, repo, user) if err != nil { return nil, err } - canPush = issues_model.CanMaintainerWriteToBranch(perms, branchName, user) + canPush = issues_model.CanMaintainerWriteToBranch(ctx, perms, branchName, user) } return &api.Branch{ @@ -94,13 +94,13 @@ func ToBranch(ctx context.Context, repo *repo_model.Repository, branchName strin } if user != nil { - permission, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + permission, err := access_model.GetUserRepoPermission(ctx, repo, user) if err != nil { return nil, err } bp.Repo = repo - branch.UserCanPush = bp.CanUserPush(db.DefaultContext, user) - branch.UserCanMerge = git_model.IsUserMergeWhitelisted(db.DefaultContext, bp, user.ID, permission) + branch.UserCanPush = bp.CanUserPush(ctx, user) + branch.UserCanMerge = git_model.IsUserMergeWhitelisted(ctx, bp, user.ID, permission) } return branch, nil diff --git a/services/convert/issue_comment.go b/services/convert/issue_comment.go index b0145c38e639..1308051e7c10 100644 --- a/services/convert/issue_comment.go +++ b/services/convert/issue_comment.go @@ -114,7 +114,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu } if c.Time != nil { - err = c.Time.LoadAttributes() + err = c.Time.LoadAttributes(ctx) if err != nil { log.Error("Time.LoadAttributes: %v", err) return nil diff --git a/services/issue/comments.go b/services/issue/comments.go index 4a181499bcd8..ed05f725ff60 100644 --- a/services/issue/comments.go +++ b/services/issue/comments.go @@ -36,13 +36,13 @@ func CreateComment(ctx context.Context, opts *issues_model.CreateCommentOptions) } // CreateRefComment creates a commit reference comment to issue. -func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error { +func CreateRefComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error { if len(commitSHA) == 0 { return fmt.Errorf("cannot create reference with empty commit SHA") } // Check if same reference from same commit has already existed. - has, err := db.GetEngine(db.DefaultContext).Get(&issues_model.Comment{ + has, err := db.GetEngine(ctx).Get(&issues_model.Comment{ Type: issues_model.CommentTypeCommitRef, IssueID: issue.ID, CommitSHA: commitSHA, @@ -53,7 +53,7 @@ func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue return nil } - _, err = CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{ + _, err = CreateComment(ctx, &issues_model.CreateCommentOptions{ Type: issues_model.CommentTypeCommitRef, Doer: doer, Repo: repo, diff --git a/services/issue/commit.go b/services/issue/commit.go index 7a8c71e609c4..e493a032114a 100644 --- a/services/issue/commit.go +++ b/services/issue/commit.go @@ -4,6 +4,7 @@ package issue import ( + "context" "fmt" "html" "net/url" @@ -12,7 +13,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" @@ -78,20 +78,20 @@ func timeLogToAmount(str string) int64 { return a } -func issueAddTime(issue *issues_model.Issue, doer *user_model.User, time time.Time, timeLog string) error { +func issueAddTime(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, time time.Time, timeLog string) error { amount := timeLogToAmount(timeLog) if amount == 0 { return nil } - _, err := issues_model.AddTime(doer, issue, amount, time) + _, err := issues_model.AddTime(ctx, doer, issue, amount, time) return err } // getIssueFromRef returns the issue referenced by a ref. Returns a nil *Issue // if the provided ref references a non-existent issue. -func getIssueFromRef(repo *repo_model.Repository, index int64) (*issues_model.Issue, error) { - issue, err := issues_model.GetIssueByIndex(repo.ID, index) +func getIssueFromRef(ctx context.Context, repo *repo_model.Repository, index int64) (*issues_model.Issue, error) { + issue, err := issues_model.GetIssueByIndex(ctx, repo.ID, index) if err != nil { if issues_model.IsErrIssueNotExist(err) { return nil, nil @@ -102,7 +102,7 @@ func getIssueFromRef(repo *repo_model.Repository, index int64) (*issues_model.Is } // UpdateIssuesCommit checks if issues are manipulated by commit message. -func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, commits []*repository.PushCommit, branchName string) error { +func UpdateIssuesCommit(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commits []*repository.PushCommit, branchName string) error { // Commits are appended in the reverse order. for i := len(commits) - 1; i >= 0; i-- { c := commits[i] @@ -120,7 +120,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm // issue is from another repo if len(ref.Owner) > 0 && len(ref.Name) > 0 { - refRepo, err = repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, ref.Owner, ref.Name) + refRepo, err = repo_model.GetRepositoryByOwnerAndName(ctx, ref.Owner, ref.Name) if err != nil { if repo_model.IsErrRepoNotExist(err) { log.Warn("Repository referenced in commit but does not exist: %v", err) @@ -132,14 +132,14 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm } else { refRepo = repo } - if refIssue, err = getIssueFromRef(refRepo, ref.Index); err != nil { + if refIssue, err = getIssueFromRef(ctx, refRepo, ref.Index); err != nil { return err } if refIssue == nil { continue } - perm, err := access_model.GetUserRepoPermission(db.DefaultContext, refRepo, doer) + perm, err := access_model.GetUserRepoPermission(ctx, refRepo, doer) if err != nil { return err } @@ -159,7 +159,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm } message := fmt.Sprintf(`%s`, html.EscapeString(repo.Link()), html.EscapeString(url.PathEscape(c.Sha1)), html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0])) - if err = CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil { + if err = CreateRefComment(ctx, doer, refRepo, refIssue, message, c.Sha1); err != nil { return err } @@ -187,13 +187,13 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm } close := ref.Action == references.XRefActionCloses if close && len(ref.TimeLog) > 0 { - if err := issueAddTime(refIssue, doer, c.Timestamp, ref.TimeLog); err != nil { + if err := issueAddTime(ctx, refIssue, doer, c.Timestamp, ref.TimeLog); err != nil { return err } } if close != refIssue.IsClosed { refIssue.Repo = refRepo - if err := ChangeStatus(refIssue, doer, c.Sha1, close); err != nil { + if err := ChangeStatus(ctx, refIssue, doer, c.Sha1, close); err != nil { return err } } diff --git a/services/issue/commit_test.go b/services/issue/commit_test.go index 590e7adce99f..1bc9f6f951c6 100644 --- a/services/issue/commit_test.go +++ b/services/issue/commit_test.go @@ -7,6 +7,7 @@ import ( "testing" 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" "code.gitea.io/gitea/models/unittest" @@ -60,7 +61,7 @@ func TestUpdateIssuesCommit(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 2}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -87,7 +88,7 @@ func TestUpdateIssuesCommit(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch")) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, "non-existing-branch")) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -113,7 +114,7 @@ func TestUpdateIssuesCommit(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -139,7 +140,7 @@ func TestUpdateIssuesCommit_Colon(t *testing.T) { issueBean := &issues_model.Issue{RepoID: repo.ID, Index: 4} unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 2}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) } @@ -172,7 +173,7 @@ func TestUpdateIssuesCommit_Issue5957(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch")) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, "non-existing-branch")) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -207,7 +208,7 @@ func TestUpdateIssuesCommit_AnotherRepo(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -242,7 +243,7 @@ func TestUpdateIssuesCommit_AnotherRepo_FullAddress(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -292,7 +293,7 @@ func TestUpdateIssuesCommit_AnotherRepoNoPermission(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, commentBean2) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, commentBean2) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") diff --git a/services/issue/status.go b/services/issue/status.go index d4a0fce3e586..3718a5048f93 100644 --- a/services/issue/status.go +++ b/services/issue/status.go @@ -6,7 +6,6 @@ package issue import ( "context" - "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/log" @@ -14,13 +13,7 @@ import ( ) // ChangeStatus changes issue status to open or closed. -func ChangeStatus(issue *issues_model.Issue, doer *user_model.User, commitID string, closed bool) error { - return changeStatusCtx(db.DefaultContext, issue, doer, commitID, closed) -} - -// changeStatusCtx changes issue status to open or closed. -// TODO: if context is not db.DefaultContext we get a deadlock!!! -func changeStatusCtx(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, commitID string, closed bool) error { +func ChangeStatus(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, commitID string, closed bool) error { comment, err := issues_model.ChangeIssueStatus(ctx, issue, doer, closed) if err != nil { if issues_model.IsErrDependenciesLeft(err) && closed { diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index ad4293184e71..ee7fc578514f 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -515,6 +515,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error { // CreatePullRequests creates pull requests func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error { gprs := make([]*issues_model.PullRequest, 0, len(prs)) + ctx := db.DefaultContext for _, pr := range prs { gpr, err := g.newPullRequest(pr) if err != nil { @@ -527,12 +528,12 @@ func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error gprs = append(gprs, gpr) } - if err := models.InsertPullRequests(gprs...); err != nil { + if err := models.InsertPullRequests(ctx, gprs...); err != nil { return err } for _, pr := range gprs { g.issues[pr.Issue.Index] = pr.Issue - pull.AddToTaskQueue(pr) + pull.AddToTaskQueue(ctx, pr) } return nil } diff --git a/services/pull/check.go b/services/pull/check.go index b5150ad9a804..ec898201bb66 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -43,9 +43,9 @@ var ( ) // AddToTaskQueue adds itself to pull request test task queue. -func AddToTaskQueue(pr *issues_model.PullRequest) { +func AddToTaskQueue(ctx context.Context, pr *issues_model.PullRequest) { pr.Status = issues_model.PullRequestStatusChecking - err := pr.UpdateColsIfNotMerged(db.DefaultContext, "status") + err := pr.UpdateColsIfNotMerged(ctx, "status") if err != nil { log.Error("AddToTaskQueue(%-v).UpdateCols.(add to queue): %v", pr, err) return @@ -369,14 +369,14 @@ func testPR(id int64) { } // CheckPRsForBaseBranch check all pulls with baseBrannch -func CheckPRsForBaseBranch(baseRepo *repo_model.Repository, baseBranchName string) error { - prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(baseRepo.ID, baseBranchName) +func CheckPRsForBaseBranch(ctx context.Context, baseRepo *repo_model.Repository, baseBranchName string) error { + prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, baseRepo.ID, baseBranchName) if err != nil { return err } for _, pr := range prs { - AddToTaskQueue(pr) + AddToTaskQueue(ctx, pr) } return nil diff --git a/services/pull/check_test.go b/services/pull/check_test.go index 57ccb2003366..4a99859f5a37 100644 --- a/services/pull/check_test.go +++ b/services/pull/check_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "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/queue" @@ -36,7 +37,7 @@ func TestPullRequest_AddToTaskQueue(t *testing.T) { assert.NoError(t, err) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - AddToTaskQueue(pr) + AddToTaskQueue(db.DefaultContext, pr) assert.Eventually(t, func() bool { pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) diff --git a/services/pull/merge.go b/services/pull/merge.go index 416c74446351..7051fd9eda24 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -24,7 +24,6 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/references" @@ -182,10 +181,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "") }() - // Run the merge in the hammer context to prevent cancellation - hammerCtx := graceful.GetManager().HammerContext() - - pr.MergedCommitID, err = doMergeAndPush(hammerCtx, pr, doer, mergeStyle, expectedHeadCommitID, message) + pr.MergedCommitID, err = doMergeAndPush(ctx, pr, doer, mergeStyle, expectedHeadCommitID, message) if err != nil { return err } @@ -194,47 +190,47 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U pr.Merger = doer pr.MergerID = doer.ID - if _, err := pr.SetMerged(hammerCtx); err != nil { + if _, err := pr.SetMerged(ctx); err != nil { log.Error("SetMerged %-v: %v", pr, err) } - if err := pr.LoadIssue(hammerCtx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { log.Error("LoadIssue %-v: %v", pr, err) } - if err := pr.Issue.LoadRepo(hammerCtx); err != nil { + if err := pr.Issue.LoadRepo(ctx); err != nil { log.Error("pr.Issue.LoadRepo %-v: %v", pr, err) } - if err := pr.Issue.Repo.LoadOwner(hammerCtx); err != nil { + if err := pr.Issue.Repo.LoadOwner(ctx); err != nil { log.Error("LoadOwner for %-v: %v", pr, err) } if wasAutoMerged { - notification.NotifyAutoMergePullRequest(hammerCtx, doer, pr) + notification.NotifyAutoMergePullRequest(ctx, doer, pr) } else { - notification.NotifyMergePullRequest(hammerCtx, doer, pr) + notification.NotifyMergePullRequest(ctx, doer, pr) } // Reset cached commit count cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true)) // Resolve cross references - refs, err := pr.ResolveCrossReferences(hammerCtx) + refs, err := pr.ResolveCrossReferences(ctx) if err != nil { log.Error("ResolveCrossReferences: %v", err) return nil } for _, ref := range refs { - if err = ref.LoadIssue(hammerCtx); err != nil { + if err = ref.LoadIssue(ctx); err != nil { return err } - if err = ref.Issue.LoadRepo(hammerCtx); err != nil { + if err = ref.Issue.LoadRepo(ctx); err != nil { return err } close := ref.RefAction == references.XRefActionCloses if close != ref.Issue.IsClosed { - if err = issue_service.ChangeStatus(ref.Issue, doer, pr.MergedCommitID, close); err != nil { + if err = issue_service.ChangeStatus(ctx, ref.Issue, doer, pr.MergedCommitID, close); err != nil { // Allow ErrDependenciesLeft if !issues_model.IsErrDependenciesLeft(err) { return err diff --git a/services/pull/pull.go b/services/pull/pull.go index 5f55a36f333e..3c6caec8825a 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -265,7 +265,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, // TODO: graceful: AddTestPullRequestTask needs to become a queue! // GetUnmergedPullRequestsByHeadInfo() only return open and unmerged PR. - prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch) + prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repoID, branch) if err != nil { log.Error("Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err) return @@ -282,7 +282,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, continue } - AddToTaskQueue(pr) + AddToTaskQueue(ctx, pr) comment, err := CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID) if err == nil && comment != nil { notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment) @@ -291,7 +291,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, if isSync { requests := issues_model.PullRequestList(prs) - if err = requests.LoadAttributes(); err != nil { + if err = requests.LoadAttributes(ctx); err != nil { log.Error("PullRequestList.LoadAttributes: %v", err) } if invalidationErr := checkForInvalidation(ctx, requests, repoID, doer, branch); invalidationErr != nil { @@ -341,7 +341,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, } log.Trace("AddTestPullRequestTask [base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch) - prs, err = issues_model.GetUnmergedPullRequestsByBaseInfo(repoID, branch) + prs, err = issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch) if err != nil { log.Error("Find pull requests [base_repo_id: %d, base_branch: %s]: %v", repoID, branch, err) return @@ -360,7 +360,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, log.Error("UpdateCommitDivergence: %v", err) } } - AddToTaskQueue(pr) + AddToTaskQueue(ctx, pr) } }) } @@ -514,25 +514,25 @@ func (errs errlist) Error() string { } // CloseBranchPulls close all the pull requests who's head branch is the branch -func CloseBranchPulls(doer *user_model.User, repoID int64, branch string) error { - prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch) +func CloseBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch string) error { + prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repoID, branch) if err != nil { return err } - prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(repoID, branch) + prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch) if err != nil { return err } prs = append(prs, prs2...) - if err := issues_model.PullRequestList(prs).LoadAttributes(); err != nil { + if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil { return err } var errs errlist for _, pr := range prs { - if err = issue_service.ChangeStatus(pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) && !issues_model.IsErrDependenciesLeft(err) { + if err = issue_service.ChangeStatus(ctx, pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) && !issues_model.IsErrDependenciesLeft(err) { errs = append(errs, err) } } @@ -551,12 +551,12 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re var errs errlist for _, branch := range branches { - prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repo.ID, branch.Name) + prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repo.ID, branch.Name) if err != nil { return err } - if err = issues_model.PullRequestList(prs).LoadAttributes(); err != nil { + if err = issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil { return err } @@ -566,7 +566,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re if pr.BaseRepoID == repo.ID { continue } - if err = issue_service.ChangeStatus(pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) { + if err = issue_service.ChangeStatus(ctx, pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) { errs = append(errs, err) } } diff --git a/services/repository/push.go b/services/repository/push.go index 8cff5f66b6aa..68ff172ea3f3 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -222,7 +222,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { commits := repo_module.GitToPushCommits(l) commits.HeadCommit = repo_module.CommitToPushCommit(newCommit) - if err := issue_service.UpdateIssuesCommit(pusher, repo, commits.Commits, refName); err != nil { + if err := issue_service.UpdateIssuesCommit(ctx, pusher, repo, commits.Commits, refName); err != nil { log.Error("updateIssuesCommit: %v", err) } @@ -269,12 +269,12 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { } } else { notification.NotifyDeleteRef(ctx, pusher, repo, opts.RefFullName) - if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil { + if err = pull_service.CloseBranchPulls(ctx, pusher, repo.ID, branch); err != nil { // close all related pulls log.Error("close related pull request failed: %v", err) } - if err := git_model.AddDeletedBranch(db.DefaultContext, repo.ID, branch, pusher.ID); err != nil { + if err := git_model.AddDeletedBranch(ctx, repo.ID, branch, pusher.ID); err != nil { return fmt.Errorf("AddDeletedBranch %s:%s failed: %v", repo.FullName(), branch, err) } } From a12a5f3652c339b17b187ff424a480631a3c1e1e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 23 Jul 2023 17:56:43 +0800 Subject: [PATCH 08/23] Fix duplicated url prefix on issue context menu (#26066) Fix #26060 --- templates/repo/issue/view_content/context_menu.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/issue/view_content/context_menu.tmpl b/templates/repo/issue/view_content/context_menu.tmpl index 296668c9e04b..ed22bc878b38 100644 --- a/templates/repo/issue/view_content/context_menu.tmpl +++ b/templates/repo/issue/view_content/context_menu.tmpl @@ -10,7 +10,7 @@ {{else}} {{$referenceUrl = printf "%s/files#%s" .ctxData.Issue.Link .item.HashTag}} {{end}} -
{{.ctxData.locale.Tr "repo.issues.context.copy_link"}}
+
{{.ctxData.locale.Tr "repo.issues.context.copy_link"}}
{{.ctxData.locale.Tr "repo.issues.context.quote_reply"}}
{{if not .ctxData.UnitIssuesGlobalDisabled}}
{{.ctxData.locale.Tr "repo.issues.context.reference_issue"}}
From 4e4a71f3a089451a72ff3f8fd65d3d66060ce03d Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 24 Jul 2023 00:27:48 +0000 Subject: [PATCH 09/23] [skip ci] Updated translations via Crowdin --- options/locale/locale_pt-PT.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 34e6488db9b9..20ef4cde6981 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -1673,7 +1673,7 @@ pulls.is_empty=As modificações feitas neste ramo já existem no ramo de destin pulls.required_status_check_failed=Algumas das verificações obrigatórias não foram bem sucedidas. pulls.required_status_check_missing=Estão faltando algumas verificações necessárias. pulls.required_status_check_administrator=Uma vez que é administrador, ainda pode realizar a integração deste pedido. -pulls.blocked_by_approvals=Este pedido de integração ainda não tem aprovações suficientes. Já foram concedidas %d de um total de%d aprovações. +pulls.blocked_by_approvals=Este pedido de integração ainda não tem aprovações suficientes. Já foram concedidas %d de um total de %d aprovações. pulls.blocked_by_rejection=Este pedido de integração tem modificações solicitadas por um revisor oficial. pulls.blocked_by_official_review_requests=Este pedido de integração tem pedidos de revisão oficiais. pulls.blocked_by_outdated_branch=Este pedido de integração foi bloqueado por ser obsoleto. From 24c3bb95acfd906dc752f867615dafd170176502 Mon Sep 17 00:00:00 2001 From: HesterG Date: Mon, 24 Jul 2023 09:05:16 +0800 Subject: [PATCH 10/23] Categorize admin settings sidebar panel (#26030) This PR reorganize and categorize the admin settings sidebar panel into groups: - User Accounts, User Emails, Organizations, Authentication Sources -> Identity & Access - Repositories, Packages -> Code Assets - Webhooks, Applications -> Integrations Before: Screen Shot 2023-07-21 at 10 30 28 After: all configurable settings enabled (package, oauth, webhook) Screen Shot 2023-07-21 at 10 27 30 all configurable settings disabled (package, oauth, webhook) Screen Shot 2023-07-21 at 10 25 19 only oauth enabled Screen Shot 2023-07-21 at 10 26 23 only webhook enabled Screen Shot 2023-07-21 at 10 26 55 --- options/locale/locale_en-US.ini | 3 ++ templates/admin/navbar.tmpl | 77 ++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 94ae49098157..24be7e0fc30f 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2627,10 +2627,13 @@ teams.invite.description = Please click the button below to join the team. [admin] dashboard = Dashboard +identity_access = Identity & Access users = User Accounts organizations = Organizations +assets = Code Assets repositories = Repositories hooks = Webhooks +integrations = Integrations authentication = Authentication Sources emails = User Emails config = Configuration diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index a96e5c93677a..4cfdbac73f38 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -4,35 +4,60 @@ {{.locale.Tr "admin.dashboard"}} - - {{.locale.Tr "admin.users"}} - - - {{.locale.Tr "admin.organizations"}} - - - {{.locale.Tr "admin.repositories"}} - - {{if .EnablePackages}} - - {{.locale.Tr "packages.title"}} - - {{end}} - {{if not DisableWebhooks}} +
+ {{.locale.Tr "admin.identity_access"}} + +
+
+ {{.locale.Tr "admin.assets"}} + +
+ + {{if and (not DisableWebhooks) .EnableOAuth2}} +
+ {{.locale.Tr "admin.integrations"}} + +
+ {{else}} + {{if not DisableWebhooks}} {{.locale.Tr "admin.hooks"}} - {{end}} - - {{.locale.Tr "admin.authentication"}} - - - {{.locale.Tr "admin.emails"}} - - {{if .EnableOAuth2}} - - {{.locale.Tr "settings.applications"}} - + {{end}} + {{if .EnableOAuth2}} + + {{.locale.Tr "settings.applications"}} + + {{end}} {{end}} {{if .EnableActions}}
From f3d41c61eb0e66aacc269508d27716425673509b Mon Sep 17 00:00:00 2001 From: delvh Date: Mon, 24 Jul 2023 05:47:27 +0200 Subject: [PATCH 11/23] Remove `db.DefaultContext` in `routers/` and `cmd/` (#26076) Now, the only remaining usages of `models.db.DefaultContext` are in - `modules` - `models` - `services` --- cmd/admin.go | 9 +- routers/api/packages/composer/composer.go | 2 +- routers/api/packages/conan/conan.go | 96 ++++++++++----------- routers/api/packages/container/blob.go | 20 ++--- routers/api/packages/container/container.go | 10 +-- routers/api/packages/container/manifest.go | 24 +++--- routers/api/packages/npm/npm.go | 68 +++++++-------- routers/api/v1/user/key.go | 3 +- routers/web/admin/packages.go | 2 +- routers/web/healthcheck/check.go | 7 +- routers/web/repo/view.go | 8 +- 11 files changed, 121 insertions(+), 128 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index add3d67d74cc..ea62075093c2 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -5,6 +5,7 @@ package cmd import ( + "context" "errors" "fmt" "net/url" @@ -373,7 +374,7 @@ func runRepoSyncReleases(_ *cli.Context) error { continue } - oldnum, err := getReleaseCount(repo.ID) + oldnum, err := getReleaseCount(ctx, repo.ID) if err != nil { log.Warn(" GetReleaseCountByRepoID: %v", err) } @@ -385,7 +386,7 @@ func runRepoSyncReleases(_ *cli.Context) error { continue } - count, err = getReleaseCount(repo.ID) + count, err = getReleaseCount(ctx, repo.ID) if err != nil { log.Warn(" GetReleaseCountByRepoID: %v", err) gitRepo.Close() @@ -401,9 +402,9 @@ func runRepoSyncReleases(_ *cli.Context) error { return nil } -func getReleaseCount(id int64) (int64, error) { +func getReleaseCount(ctx context.Context, id int64) (int64, error) { return repo_model.GetReleaseCountByRepoID( - db.DefaultContext, + ctx, id, repo_model.FindReleasesOptions{ IncludeTags: true, diff --git a/routers/api/packages/composer/composer.go b/routers/api/packages/composer/composer.go index bf5bda743f56..75bbfdf4d3bd 100644 --- a/routers/api/packages/composer/composer.go +++ b/routers/api/packages/composer/composer.go @@ -114,7 +114,7 @@ func SearchPackages(ctx *context.Context) { // EnumeratePackages lists all package names // https://packagist.org/apidoc#list-packages func EnumeratePackages(ctx *context.Context) { - ps, err := packages_model.GetPackagesByType(db.DefaultContext, ctx.Package.Owner.ID, packages_model.TypeComposer) + ps, err := packages_model.GetPackagesByType(ctx, ctx.Package.Owner.ID, packages_model.TypeComposer) if err != nil { apiError(ctx, http.StatusInternalServerError, err) return diff --git a/routers/api/packages/conan/conan.go b/routers/api/packages/conan/conan.go index 6e1727fd7647..d7349a84b260 100644 --- a/routers/api/packages/conan/conan.go +++ b/routers/api/packages/conan/conan.go @@ -4,6 +4,7 @@ package conan import ( + std_ctx "context" "fmt" "io" "net/http" @@ -602,67 +603,62 @@ func DeletePackageV2(ctx *context.Context) { } func deleteRecipeOrPackage(apictx *context.Context, rref *conan_module.RecipeReference, ignoreRecipeRevision bool, pref *conan_module.PackageReference, ignorePackageRevision bool) error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - pv, err := packages_model.GetVersionByNameAndVersion(ctx, apictx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version) - if err != nil { - return err - } + var pd *packages_model.PackageDescriptor + versionDeleted := false - pd, err := packages_model.GetPackageDescriptor(ctx, pv) - if err != nil { - return err - } + err := db.WithTx(apictx, func(ctx std_ctx.Context) error { + pv, err := packages_model.GetVersionByNameAndVersion(ctx, apictx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version) + if err != nil { + return err + } - filter := map[string]string{ - conan_module.PropertyRecipeUser: rref.User, - conan_module.PropertyRecipeChannel: rref.Channel, - } - if !ignoreRecipeRevision { - filter[conan_module.PropertyRecipeRevision] = rref.RevisionOrDefault() - } - if pref != nil { - filter[conan_module.PropertyPackageReference] = pref.Reference - if !ignorePackageRevision { - filter[conan_module.PropertyPackageRevision] = pref.RevisionOrDefault() + pd, err = packages_model.GetPackageDescriptor(ctx, pv) + if err != nil { + return err } - } - pfs, _, err := packages_model.SearchFiles(ctx, &packages_model.PackageFileSearchOptions{ - VersionID: pv.ID, - Properties: filter, - }) - if err != nil { - return err - } - if len(pfs) == 0 { - return conan_model.ErrPackageReferenceNotExist - } + filter := map[string]string{ + conan_module.PropertyRecipeUser: rref.User, + conan_module.PropertyRecipeChannel: rref.Channel, + } + if !ignoreRecipeRevision { + filter[conan_module.PropertyRecipeRevision] = rref.RevisionOrDefault() + } + if pref != nil { + filter[conan_module.PropertyPackageReference] = pref.Reference + if !ignorePackageRevision { + filter[conan_module.PropertyPackageRevision] = pref.RevisionOrDefault() + } + } - for _, pf := range pfs { - if err := packages_service.DeletePackageFile(ctx, pf); err != nil { + pfs, _, err := packages_model.SearchFiles(ctx, &packages_model.PackageFileSearchOptions{ + VersionID: pv.ID, + Properties: filter, + }) + if err != nil { return err } - } - - versionDeleted := false - has, err := packages_model.HasVersionFileReferences(ctx, pv.ID) - if err != nil { - return err - } - if !has { - versionDeleted = true + if len(pfs) == 0 { + return conan_model.ErrPackageReferenceNotExist + } - if err := packages_service.DeletePackageVersionAndReferences(ctx, pv); err != nil { + for _, pf := range pfs { + if err := packages_service.DeletePackageFile(ctx, pf); err != nil { + return err + } + } + has, err := packages_model.HasVersionFileReferences(ctx, pv.ID) + if err != nil { return err } - } + if !has { + versionDeleted = true - if err := committer.Commit(); err != nil { + return packages_service.DeletePackageVersionAndReferences(ctx, pv) + } + return nil + }) + if err != nil { return err } diff --git a/routers/api/packages/container/blob.go b/routers/api/packages/container/blob.go index c8e8dd054529..f2d63297c141 100644 --- a/routers/api/packages/container/blob.go +++ b/routers/api/packages/container/blob.go @@ -26,19 +26,19 @@ var uploadVersionMutex sync.Mutex // saveAsPackageBlob creates a package blob from an upload // The uploaded blob gets stored in a special upload version to link them to the package/image -func saveAsPackageBlob(hsr packages_module.HashedSizeReader, pci *packages_service.PackageCreationInfo) (*packages_model.PackageBlob, error) { +func saveAsPackageBlob(ctx context.Context, hsr packages_module.HashedSizeReader, pci *packages_service.PackageCreationInfo) (*packages_model.PackageBlob, error) { pb := packages_service.NewPackageBlob(hsr) exists := false contentStore := packages_module.NewContentStore() - uploadVersion, err := getOrCreateUploadVersion(&pci.PackageInfo) + uploadVersion, err := getOrCreateUploadVersion(ctx, &pci.PackageInfo) if err != nil { return nil, err } - err = db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err = db.WithTx(ctx, func(ctx context.Context) error { if err := packages_service.CheckSizeQuotaExceeded(ctx, pci.Creator, pci.Owner, packages_model.TypeContainer, hsr.Size()); err != nil { return err } @@ -79,24 +79,24 @@ func saveAsPackageBlob(hsr packages_module.HashedSizeReader, pci *packages_servi } // mountBlob mounts the specific blob to a different package -func mountBlob(pi *packages_service.PackageInfo, pb *packages_model.PackageBlob) error { - uploadVersion, err := getOrCreateUploadVersion(pi) +func mountBlob(ctx context.Context, pi *packages_service.PackageInfo, pb *packages_model.PackageBlob) error { + uploadVersion, err := getOrCreateUploadVersion(ctx, pi) if err != nil { return err } - return db.WithTx(db.DefaultContext, func(ctx context.Context) error { + return db.WithTx(ctx, func(ctx context.Context) error { return createFileForBlob(ctx, uploadVersion, pb) }) } -func getOrCreateUploadVersion(pi *packages_service.PackageInfo) (*packages_model.PackageVersion, error) { +func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageInfo) (*packages_model.PackageVersion, error) { var uploadVersion *packages_model.PackageVersion // FIXME: Replace usage of mutex with database transaction // https://github.com/go-gitea/gitea/pull/21862 uploadVersionMutex.Lock() - err := db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err := db.WithTx(ctx, func(ctx context.Context) error { created := true p := &packages_model.Package{ OwnerID: pi.Owner.ID, @@ -172,8 +172,8 @@ func createFileForBlob(ctx context.Context, pv *packages_model.PackageVersion, p return nil } -func deleteBlob(ownerID int64, image, digest string) error { - return db.WithTx(db.DefaultContext, func(ctx context.Context) error { +func deleteBlob(ctx context.Context, ownerID int64, image, digest string) error { + return db.WithTx(ctx, func(ctx context.Context) error { pfds, err := container_model.GetContainerBlobs(ctx, &container_model.BlobSearchOptions{ OwnerID: ownerID, Image: image, diff --git a/routers/api/packages/container/container.go b/routers/api/packages/container/container.go index 8f79805cc8b3..7bd5cadaaf66 100644 --- a/routers/api/packages/container/container.go +++ b/routers/api/packages/container/container.go @@ -210,7 +210,7 @@ func InitiateUploadBlob(ctx *context.Context) { } if accessible { - if err := mountBlob(&packages_service.PackageInfo{Owner: ctx.Package.Owner, Name: image}, blob.Blob); err != nil { + if err := mountBlob(ctx, &packages_service.PackageInfo{Owner: ctx.Package.Owner, Name: image}, blob.Blob); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } @@ -239,7 +239,7 @@ func InitiateUploadBlob(ctx *context.Context) { return } - if _, err := saveAsPackageBlob( + if _, err := saveAsPackageBlob(ctx, buf, &packages_service.PackageCreationInfo{ PackageInfo: packages_service.PackageInfo{ @@ -384,7 +384,7 @@ func EndUploadBlob(ctx *context.Context) { return } - if _, err := saveAsPackageBlob( + if _, err := saveAsPackageBlob(ctx, uploader, &packages_service.PackageCreationInfo{ PackageInfo: packages_service.PackageInfo{ @@ -502,7 +502,7 @@ func DeleteBlob(ctx *context.Context) { return } - if err := deleteBlob(ctx.Package.Owner.ID, ctx.Params("image"), d); err != nil { + if err := deleteBlob(ctx, ctx.Package.Owner.ID, ctx.Params("image"), d); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } @@ -543,7 +543,7 @@ func UploadManifest(ctx *context.Context) { return } - digest, err := processManifest(mci, buf) + digest, err := processManifest(ctx, mci, buf) if err != nil { var namedError *namedError if errors.As(err, &namedError) { diff --git a/routers/api/packages/container/manifest.go b/routers/api/packages/container/manifest.go index 1dbd058d6b11..6678ed20bc4b 100644 --- a/routers/api/packages/container/manifest.go +++ b/routers/api/packages/container/manifest.go @@ -50,7 +50,7 @@ type manifestCreationInfo struct { Properties map[string]string } -func processManifest(mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) { +func processManifest(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) { var index oci.Index if err := json.NewDecoder(buf).Decode(&index); err != nil { return "", err @@ -72,14 +72,14 @@ func processManifest(mci *manifestCreationInfo, buf *packages_module.HashedBuffe } if isImageManifestMediaType(mci.MediaType) { - return processImageManifest(mci, buf) + return processImageManifest(ctx, mci, buf) } else if isImageIndexMediaType(mci.MediaType) { - return processImageManifestIndex(mci, buf) + return processImageManifestIndex(ctx, mci, buf) } return "", errManifestInvalid } -func processImageManifest(mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) { +func processImageManifest(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) { manifestDigest := "" err := func() error { @@ -92,7 +92,7 @@ func processImageManifest(mci *manifestCreationInfo, buf *packages_module.Hashed return err } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -181,7 +181,7 @@ func processImageManifest(mci *manifestCreationInfo, buf *packages_module.Hashed return err } - if err := notifyPackageCreate(mci.Creator, pv); err != nil { + if err := notifyPackageCreate(ctx, mci.Creator, pv); err != nil { return err } @@ -196,7 +196,7 @@ func processImageManifest(mci *manifestCreationInfo, buf *packages_module.Hashed return manifestDigest, nil } -func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) { +func processImageManifestIndex(ctx context.Context, mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) { manifestDigest := "" err := func() error { @@ -209,7 +209,7 @@ func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.H return err } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -285,7 +285,7 @@ func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.H return err } - if err := notifyPackageCreate(mci.Creator, pv); err != nil { + if err := notifyPackageCreate(ctx, mci.Creator, pv); err != nil { return err } @@ -300,13 +300,13 @@ func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.H return manifestDigest, nil } -func notifyPackageCreate(doer *user_model.User, pv *packages_model.PackageVersion) error { - pd, err := packages_model.GetPackageDescriptor(db.DefaultContext, pv) +func notifyPackageCreate(ctx context.Context, doer *user_model.User, pv *packages_model.PackageVersion) error { + pd, err := packages_model.GetPackageDescriptor(ctx, pv) if err != nil { return err } - notification.NotifyPackageCreate(db.DefaultContext, doer, pd) + notification.NotifyPackageCreate(ctx, doer, pd) return nil } diff --git a/routers/api/packages/npm/npm.go b/routers/api/packages/npm/npm.go index 3616211d6184..d1e271f23ff3 100644 --- a/routers/api/packages/npm/npm.go +++ b/routers/api/packages/npm/npm.go @@ -5,6 +5,7 @@ package npm import ( "bytes" + std_ctx "context" "errors" "fmt" "io" @@ -222,7 +223,7 @@ func UploadPackage(ctx *context.Context) { } for _, tag := range npmPackage.DistTags { - if err := setPackageTag(tag, pv, false); err != nil { + if err := setPackageTag(ctx, tag, pv, false); err != nil { if err == errInvalidTagName { apiError(ctx, http.StatusBadRequest, err) return @@ -345,7 +346,7 @@ func AddPackageTag(ctx *context.Context) { return } - if err := setPackageTag(ctx.Params("tag"), pv, false); err != nil { + if err := setPackageTag(ctx, ctx.Params("tag"), pv, false); err != nil { if err == errInvalidTagName { apiError(ctx, http.StatusBadRequest, err) return @@ -366,7 +367,7 @@ func DeletePackageTag(ctx *context.Context) { } if len(pvs) != 0 { - if err := setPackageTag(ctx.Params("tag"), pvs[0], true); err != nil { + if err := setPackageTag(ctx, ctx.Params("tag"), pvs[0], true); err != nil { if err == errInvalidTagName { apiError(ctx, http.StatusBadRequest, err) return @@ -377,7 +378,7 @@ func DeletePackageTag(ctx *context.Context) { } } -func setPackageTag(tag string, pv *packages_model.PackageVersion, deleteOnly bool) error { +func setPackageTag(ctx std_ctx.Context, tag string, pv *packages_model.PackageVersion, deleteOnly bool) error { if tag == "" { return errInvalidTagName } @@ -386,47 +387,42 @@ func setPackageTag(tag string, pv *packages_model.PackageVersion, deleteOnly boo return errInvalidTagName } - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ - PackageID: pv.PackageID, - Properties: map[string]string{ - npm_module.TagProperty: tag, - }, - IsInternal: util.OptionalBoolFalse, - }) - if err != nil { - return err - } - - if len(pvs) == 1 { - pvps, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeVersion, pvs[0].ID, npm_module.TagProperty) + return db.WithTx(ctx, func(ctx std_ctx.Context) error { + pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ + PackageID: pv.PackageID, + Properties: map[string]string{ + npm_module.TagProperty: tag, + }, + IsInternal: util.OptionalBoolFalse, + }) if err != nil { return err } - for _, pvp := range pvps { - if pvp.Value == tag { - if err := packages_model.DeletePropertyByID(ctx, pvp.ID); err != nil { - return err + if len(pvs) == 1 { + pvps, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeVersion, pvs[0].ID, npm_module.TagProperty) + if err != nil { + return err + } + + for _, pvp := range pvps { + if pvp.Value == tag { + if err := packages_model.DeletePropertyByID(ctx, pvp.ID); err != nil { + return err + } + break } - break } } - } - if !deleteOnly { - _, err = packages_model.InsertProperty(ctx, packages_model.PropertyTypeVersion, pv.ID, npm_module.TagProperty, tag) - if err != nil { - return err + if !deleteOnly { + _, err = packages_model.InsertProperty(ctx, packages_model.PropertyTypeVersion, pv.ID, npm_module.TagProperty, tag) + if err != nil { + return err + } } - } - - return committer.Commit() + return nil + }) } func PackageSearch(ctx *context.Context) { diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index f90c65817d28..6c04d0943a7d 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -8,7 +8,6 @@ import ( "net/http" asymkey_model "code.gitea.io/gitea/models/asymkey" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" @@ -31,7 +30,7 @@ func appendPrivateInformation(ctx std_ctx.Context, apiKey *api.PublicKey, key *a if defaultUser.ID == key.OwnerID { apiKey.Owner = convert.ToUser(ctx, defaultUser, defaultUser) } else { - user, err := user_model.GetUserByID(db.DefaultContext, key.OwnerID) + user, err := user_model.GetUserByID(ctx, key.OwnerID) if err != nil { return apiKey, err } diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go index ace54fc0d80e..731a1d6ac2f2 100644 --- a/routers/web/admin/packages.go +++ b/routers/web/admin/packages.go @@ -85,7 +85,7 @@ func Packages(ctx *context.Context) { // DeletePackageVersion deletes a package version func DeletePackageVersion(ctx *context.Context) { - pv, err := packages_model.GetVersionByID(db.DefaultContext, ctx.FormInt64("id")) + pv, err := packages_model.GetVersionByID(ctx, ctx.FormInt64("id")) if err != nil { ctx.ServerError("GetRepositoryByID", err) return diff --git a/routers/web/healthcheck/check.go b/routers/web/healthcheck/check.go index e11dd2aca2e8..ecb73a928fd6 100644 --- a/routers/web/healthcheck/check.go +++ b/routers/web/healthcheck/check.go @@ -4,6 +4,7 @@ package healthcheck import ( + "context" "net/http" "os" "time" @@ -72,7 +73,7 @@ func Check(w http.ResponseWriter, r *http.Request) { statuses := make([]status, 0) if setting.InstallLock { - statuses = append(statuses, checkDatabase(rsp.Checks)) + statuses = append(statuses, checkDatabase(r.Context(), rsp.Checks)) statuses = append(statuses, checkCache(rsp.Checks)) } for _, s := range statuses { @@ -89,9 +90,9 @@ func Check(w http.ResponseWriter, r *http.Request) { } // database checks gitea database status -func checkDatabase(checks checks) status { +func checkDatabase(ctx context.Context, checks checks) status { st := componentStatus{} - if err := db.GetEngine(db.DefaultContext).Ping(); err != nil { + if err := db.GetEngine(ctx).Ping(); err != nil { st.Status = fail st.Time = getCheckTime() log.Error("database ping failed with error: %v", err) diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index a1c82f5395d7..221c1f4c4f62 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -198,7 +198,7 @@ type fileInfo struct { st typesniffer.SniffedType } -func getFileReader(repoID int64, blob *git.Blob) ([]byte, io.ReadCloser, *fileInfo, error) { +func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) ([]byte, io.ReadCloser, *fileInfo, error) { dataRc, err := blob.DataAsync() if err != nil { return nil, nil, nil, err @@ -221,7 +221,7 @@ func getFileReader(repoID int64, blob *git.Blob) ([]byte, io.ReadCloser, *fileIn return buf, dataRc, &fileInfo{isTextFile, false, blob.Size(), nil, st}, nil } - meta, err := git_model.GetLFSMetaObjectByOid(db.DefaultContext, repoID, pointer.Oid) + meta, err := git_model.GetLFSMetaObjectByOid(ctx, repoID, pointer.Oid) if err != nil && err != git_model.ErrLFSObjectNotExist { // fallback to plain file return buf, dataRc, &fileInfo{isTextFile, false, blob.Size(), nil, st}, nil } @@ -265,7 +265,7 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr ctx.Data["ReadmeExist"] = true ctx.Data["FileIsSymlink"] = readmeFile.IsLink() - buf, dataRc, fInfo, err := getFileReader(ctx.Repo.Repository.ID, target.Blob()) + buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, target.Blob()) if err != nil { ctx.ServerError("getFileReader", err) return @@ -328,7 +328,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["IsViewFile"] = true ctx.Data["HideRepoInfo"] = true blob := entry.Blob() - buf, dataRc, fInfo, err := getFileReader(ctx.Repo.Repository.ID, blob) + buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, blob) if err != nil { ctx.ServerError("getFileReader", err) return From f2138d6968a96721f58655196ab4f132c20f9425 Mon Sep 17 00:00:00 2001 From: Chongyi Zheng Date: Sun, 23 Jul 2023 23:13:41 -0500 Subject: [PATCH 12/23] Replace gogs/cron with go-co-op/gocron (#25977) Replace `github.com/gogs/cron` with `github.com/go-co-op/gocron` as the former package is not maintained for many years. --------- Co-authored-by: delvh --- assets/go-licenses.json | 15 ++++++--- go.mod | 3 +- go.sum | 10 ++++-- services/cron/cron.go | 34 +++++++++++++-------- services/cron/tasks.go | 22 +++++++++++-- services/cron/tasks_test.go | 61 +++++++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 22 deletions(-) create mode 100644 services/cron/tasks_test.go diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 384a57cf47f4..3a0da33a0a38 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -409,6 +409,11 @@ "path": "github.com/go-chi/cors/LICENSE", "licenseText": "Copyright (c) 2014 Olivier Poitrey \u003crs@dailymotion.com\u003e\nCopyright (c) 2016-Present https://github.com/go-chi authors\n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" }, + { + "name": "github.com/go-co-op/gocron", + "path": "github.com/go-co-op/gocron/LICENSE", + "licenseText": "MIT License\n\nCopyright (c) 2014, 辣椒面\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" + }, { "name": "github.com/go-enry/go-enry/v2", "path": "github.com/go-enry/go-enry/v2/LICENSE", @@ -484,11 +489,6 @@ "path": "github.com/gogs/chardet/LICENSE", "licenseText": "Copyright (c) 2012 chardet Authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nPartial of the Software is derived from ICU project. See icu-license.html for\nlicense of the derivative portions.\n" }, - { - "name": "github.com/gogs/cron", - "path": "github.com/gogs/cron/LICENSE", - "licenseText": "Copyright (C) 2012 Rob Figueiredo\nAll Rights Reserved.\n\nMIT LICENSE\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" - }, { "name": "github.com/gogs/go-gogs-client", "path": "github.com/gogs/go-gogs-client/LICENSE", @@ -909,6 +909,11 @@ "path": "github.com/robfig/cron/LICENSE", "licenseText": "Copyright (C) 2012 Rob Figueiredo\nAll Rights Reserved.\n\nMIT LICENSE\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" }, + { + "name": "github.com/robfig/cron/v3", + "path": "github.com/robfig/cron/v3/LICENSE", + "licenseText": "Copyright (C) 2012 Rob Figueiredo\nAll Rights Reserved.\n\nMIT LICENSE\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" + }, { "name": "github.com/rs/xid", "path": "github.com/rs/xid/LICENSE", diff --git a/go.mod b/go.mod index 29a17b16abf5..9038bdd689f2 100644 --- a/go.mod +++ b/go.mod @@ -41,6 +41,7 @@ require ( github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/cors v1.2.1 + github.com/go-co-op/gocron v1.30.1 github.com/go-enry/go-enry/v2 v2.8.4 github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e github.com/go-git/go-billy/v5 v5.4.1 @@ -52,7 +53,6 @@ require ( github.com/go-webauthn/webauthn v0.8.6 github.com/gobwas/glob v0.2.3 github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f - github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang-jwt/jwt/v5 v5.0.0 github.com/google/go-github/v53 v53.2.0 @@ -253,6 +253,7 @@ require ( github.com/rhysd/actionlint v1.6.25 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron v1.2.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/xid v1.5.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 9c6250c1016c..976c0ead3835 100644 --- a/go.sum +++ b/go.sum @@ -371,6 +371,8 @@ github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= +github.com/go-co-op/gocron v1.30.1 h1:tjWUvJl5KrcwpkEkSXFSQFr4F9h5SfV/m4+RX0cV2fs= +github.com/go-co-op/gocron v1.30.1/go.mod h1:39f6KNSGVOU1LO/ZOoZfcSxwlsJDQOKSu8erN0SH48Y= github.com/go-enry/go-enry/v2 v2.8.4 h1:QrY3hx/RiqCJJRbdU0MOcjfTM1a586J0WSooqdlJIhs= github.com/go-enry/go-enry/v2 v2.8.4/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo= @@ -496,8 +498,6 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= -github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 h1:yXtpJr/LV6PFu4nTLgfjQdcMdzjbqqXMEnHfq0Or6p8= -github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3G5amEoiNbhVrmM+ZQEcnQvNQ2KaZk= github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0= github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= @@ -787,6 +787,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -1038,10 +1039,14 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= @@ -1250,6 +1255,7 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= diff --git a/services/cron/cron.go b/services/cron/cron.go index 72deb94cebe1..e3f31d08f0c9 100644 --- a/services/cron/cron.go +++ b/services/cron/cron.go @@ -14,10 +14,10 @@ import ( "code.gitea.io/gitea/modules/sync" "code.gitea.io/gitea/modules/translation" - "github.com/gogs/cron" + "github.com/go-co-op/gocron" ) -var c = cron.New() +var scheduler = gocron.NewScheduler(time.Local) // Prevent duplicate running tasks. var taskStatusTable = sync.NewStatusTable() @@ -39,11 +39,11 @@ func NewContext(original context.Context) { } } - c.Start() + scheduler.StartAsync() started = true lock.Unlock() graceful.GetManager().RunAtShutdown(context.Background(), func() { - c.Stop() + scheduler.Stop() lock.Lock() started = false lock.Unlock() @@ -77,13 +77,20 @@ type TaskTable []*TaskTableRow // ListTasks returns all running cron tasks. func ListTasks() TaskTable { - entries := c.Entries() - eMap := map[string]*cron.Entry{} - for _, e := range entries { - eMap[e.Description] = e + jobs := scheduler.Jobs() + jobMap := map[string]*gocron.Job{} + for _, job := range jobs { + // the first tag is the task name + tags := job.Tags() + if len(tags) == 0 { // should never happen + continue + } + jobMap[job.Tags()[0]] = job } + lock.Lock() defer lock.Unlock() + tTable := make([]*TaskTableRow, 0, len(tasks)) for _, task := range tasks { spec := "-" @@ -91,10 +98,13 @@ func ListTasks() TaskTable { next time.Time prev time.Time ) - if e, ok := eMap[task.Name]; ok { - spec = e.Spec - next = e.Next - prev = e.Prev + if e, ok := jobMap[task.Name]; ok { + tags := e.Tags() + if len(tags) > 1 { + spec = tags[1] // the second tag is the task spec + } + next = e.NextRun() + prev = e.PreviousRun() } task.lock.Lock() tTable = append(tTable, &TaskTableRow{ diff --git a/services/cron/tasks.go b/services/cron/tasks.go index 1c5493c8983d..ea1925c26c73 100644 --- a/services/cron/tasks.go +++ b/services/cron/tasks.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "reflect" + "strings" "sync" "code.gitea.io/gitea/models/db" @@ -176,8 +177,7 @@ func RegisterTask(name string, config Config, fun func(context.Context, *user_mo if config.IsEnabled() { // We cannot use the entry return as there is no way to lock it - if _, err = c.AddJob(name, config.GetSchedule(), task); err != nil { - log.Error("Unable to register cron task with name: %s Error: %v", name, err) + if err := addTaskToScheduler(task); err != nil { return err } } @@ -199,3 +199,21 @@ func RegisterTaskFatal(name string, config Config, fun func(context.Context, *us log.Fatal("Unable to register cron task %s Error: %v", name, err) } } + +func addTaskToScheduler(task *Task) error { + tags := []string{task.Name, task.config.GetSchedule()} // name and schedule can't be get from job, so we add them as tag + if scheduleHasSeconds(task.config.GetSchedule()) { + scheduler = scheduler.CronWithSeconds(task.config.GetSchedule()) + } else { + scheduler = scheduler.Cron(task.config.GetSchedule()) + } + if _, err := scheduler.Tag(tags...).Do(task.Run); err != nil { + log.Error("Unable to register cron task with name: %s Error: %v", task.Name, err) + return err + } + return nil +} + +func scheduleHasSeconds(schedule string) bool { + return len(strings.Fields(schedule)) >= 6 +} diff --git a/services/cron/tasks_test.go b/services/cron/tasks_test.go new file mode 100644 index 000000000000..69052d739c4c --- /dev/null +++ b/services/cron/tasks_test.go @@ -0,0 +1,61 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cron + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddTaskToScheduler(t *testing.T) { + assert.Len(t, scheduler.Jobs(), 0) + defer scheduler.Clear() + + // no seconds + err := addTaskToScheduler(&Task{ + Name: "task 1", + config: &BaseConfig{ + Schedule: "5 4 * * *", + }, + }) + assert.NoError(t, err) + assert.Len(t, scheduler.Jobs(), 1) + assert.Equal(t, "task 1", scheduler.Jobs()[0].Tags()[0]) + assert.Equal(t, "5 4 * * *", scheduler.Jobs()[0].Tags()[1]) + + // with seconds + err = addTaskToScheduler(&Task{ + Name: "task 2", + config: &BaseConfig{ + Schedule: "30 5 4 * * *", + }, + }) + assert.NoError(t, err) + assert.Len(t, scheduler.Jobs(), 2) + assert.Equal(t, "task 2", scheduler.Jobs()[1].Tags()[0]) + assert.Equal(t, "30 5 4 * * *", scheduler.Jobs()[1].Tags()[1]) +} + +func TestScheduleHasSeconds(t *testing.T) { + tests := []struct { + schedule string + hasSecond bool + }{ + {"* * * * * *", true}, + {"* * * * *", false}, + {"5 4 * * *", false}, + {"5 4 * * *", false}, + {"5,8 4 * * *", false}, + {"* * * * * *", true}, + {"5,8 4 * * *", false}, + } + + for i, test := range tests { + t.Run(strconv.Itoa(i), func(t *testing.T) { + assert.Equal(t, test.hasSecond, scheduleHasSeconds(test.schedule)) + }) + } +} From 4b6764bbb36f616035477480fc14959687d9d65b Mon Sep 17 00:00:00 2001 From: "Panagiotis \"Ivory\" Vasilopoulos" Date: Mon, 24 Jul 2023 04:17:32 +0000 Subject: [PATCH 13/23] Make organization redirect warning more clear (#26077) --- options/locale/locale_en-US.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 24be7e0fc30f..8784ab6878fe 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -640,7 +640,7 @@ update_language_success = Language has been updated. update_profile_success = Your profile has been updated. change_username = Your username has been changed. change_username_prompt = Note: username changes also change your account URL. -change_username_redirect_prompt = The old username will redirect until it is claimed. +change_username_redirect_prompt = The old username will redirect until someone claims it. continue = Continue cancel = Cancel language = Language @@ -2545,7 +2545,7 @@ settings.visibility.private_shortname = Private settings.update_settings = Update Settings settings.update_setting_success = Organization settings have been updated. -settings.change_orgname_prompt = Note: changing the organization name also changes the organization's URL. +settings.change_orgname_prompt = Note: Changing the organization name will also change your organization's URL and free the old name. settings.change_orgname_redirect_prompt = The old name will redirect until it is claimed. settings.update_avatar_success = The organization's avatar has been updated. settings.delete = Delete Organization From 674df05b16f396bf6f2a952923b9c2dfe371415b Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Mon, 24 Jul 2023 12:57:21 +0800 Subject: [PATCH 14/23] Use stderr as fallback if the log file can't be opened (#26074) If the log file can't be opened, what should it do? panic/exit? ignore logs? fallback to stderr? It seems that "fallback to stderr" is slightly better than others .... --- modules/log/event_writer_file.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/log/event_writer_file.go b/modules/log/event_writer_file.go index 4f41b96453a0..fd73d7d30a04 100644 --- a/modules/log/event_writer_file.go +++ b/modules/log/event_writer_file.go @@ -4,6 +4,8 @@ package log import ( + "io" + "code.gitea.io/gitea/modules/util/rotatingfilewriter" ) @@ -19,7 +21,7 @@ type WriterFileOption struct { type eventWriterFile struct { *EventWriterBaseImpl - fileWriter *rotatingfilewriter.RotatingFileWriter + fileWriter io.WriteCloser } var _ EventWriter = (*eventWriterFile)(nil) @@ -37,7 +39,10 @@ func NewEventWriterFile(name string, mode WriterMode) EventWriter { CompressionLevel: opt.CompressionLevel, }) if err != nil { + // if the log file can't be opened, what should it do? panic/exit? ignore logs? fallback to stderr? + // it seems that "fallback to stderr" is slightly better than others .... FallbackErrorf("unable to open log file %q: %v", opt.FileName, err) + w.fileWriter = nopCloser{Writer: LoggerToWriter(FallbackErrorf)} } w.OutputWriteCloser = w.fileWriter return w From f5c7d4cfddfe7fc615199a7438749ed79c40361f Mon Sep 17 00:00:00 2001 From: sillyguodong <33891828+sillyguodong@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:11:27 +0800 Subject: [PATCH 15/23] Reduce unnecessary DB queries for Actions tasks (#25199) Close #24544 Changes: - Create `action_tasks_version` table to store the latest version of each scope (global, org and repo). - When a job with the status of `waiting` is created, the tasks version of the scopes it belongs to will increase. - When the status of a job already in the database is updated to `waiting`, the tasks version of the scopes it belongs to will increase. - On Gitea side, in `FeatchTask()`, will try to query the `action_tasks_version` record of the scope of the runner that call `FetchTask()`. If the record does not exist, will insert a row. Then, Gitea will compare the version passed from runner to Gitea with the version in database, if inconsistent, try pick task. Gitea always returns the latest version from database to the runner. Related: - Protocol: https://gitea.com/gitea/actions-proto-def/pulls/10 - Runner: https://gitea.com/gitea/act_runner/pulls/219 --- models/actions/run.go | 10 +++ models/actions/run_job.go | 7 ++ models/actions/task.go | 3 +- models/actions/tasks_version.go | 105 +++++++++++++++++++++++++++ models/migrations/migrations.go | 2 + models/migrations/v1_21/v267.go | 23 ++++++ routers/api/actions/runner/runner.go | 33 +++++++-- 7 files changed, 174 insertions(+), 9 deletions(-) create mode 100644 models/actions/tasks_version.go create mode 100644 models/migrations/v1_21/v267.go diff --git a/models/actions/run.go b/models/actions/run.go index 7b62ff884f4c..5396c612f6e3 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -195,6 +195,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork } runJobs := make([]*ActionRunJob, 0, len(jobs)) + var hasWaiting bool for _, v := range jobs { id, job := v.Job() needs := job.Needs() @@ -205,6 +206,8 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork status := StatusWaiting if len(needs) > 0 || run.NeedApproval { status = StatusBlocked + } else { + hasWaiting = true } job.Name, _ = util.SplitStringAtByteN(job.Name, 255) runJobs = append(runJobs, &ActionRunJob{ @@ -225,6 +228,13 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork return err } + // if there is a job in the waiting status, increase tasks version. + if hasWaiting { + if err := IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil { + return err + } + } + return commiter.Commit() } diff --git a/models/actions/run_job.go b/models/actions/run_job.go index 0002e507704d..c7620cd8bca2 100644 --- a/models/actions/run_job.go +++ b/models/actions/run_job.go @@ -111,6 +111,13 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col return affected, nil } + if affected != 0 && util.SliceContains(cols, "status") && job.Status.IsWaiting() { + // if the status of job changes to waiting again, increase tasks version. + if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil { + return affected, err + } + } + if job.RunID == 0 { var err error if job, err = GetRunJobByID(ctx, job.ID); err != nil { diff --git a/models/actions/task.go b/models/actions/task.go index 55044ec82d10..9cc0fd0df83d 100644 --- a/models/actions/task.go +++ b/models/actions/task.go @@ -215,12 +215,11 @@ func GetRunningTaskByToken(ctx context.Context, token string) (*ActionTask, erro } func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask, bool, error) { - dbCtx, commiter, err := db.TxContext(ctx) + ctx, commiter, err := db.TxContext(ctx) if err != nil { return nil, false, err } defer commiter.Close() - ctx = dbCtx.WithContext(ctx) e := db.GetEngine(ctx) diff --git a/models/actions/tasks_version.go b/models/actions/tasks_version.go new file mode 100644 index 000000000000..5c0a86538d57 --- /dev/null +++ b/models/actions/tasks_version.go @@ -0,0 +1,105 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package actions + +import ( + "context" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" +) + +// ActionTasksVersion +// If both ownerID and repoID is zero, its scope is global. +// If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currrently). +// If ownerID is zero and repoID is not zero, its scope is repo. +type ActionTasksVersion struct { + ID int64 `xorm:"pk autoincr"` + OwnerID int64 `xorm:"UNIQUE(owner_repo)"` + RepoID int64 `xorm:"INDEX UNIQUE(owner_repo)"` + Version int64 + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` +} + +func init() { + db.RegisterModel(new(ActionTasksVersion)) +} + +func GetTasksVersionByScope(ctx context.Context, ownerID, repoID int64) (int64, error) { + var tasksVersion ActionTasksVersion + has, err := db.GetEngine(ctx).Where("owner_id = ? AND repo_id = ?", ownerID, repoID).Get(&tasksVersion) + if err != nil { + return 0, err + } else if !has { + return 0, nil + } + return tasksVersion.Version, err +} + +func insertTasksVersion(ctx context.Context, ownerID, repoID int64) (*ActionTasksVersion, error) { + tasksVersion := &ActionTasksVersion{ + OwnerID: ownerID, + RepoID: repoID, + Version: 1, + } + if _, err := db.GetEngine(ctx).Insert(tasksVersion); err != nil { + return nil, err + } + return tasksVersion, nil +} + +func increaseTasksVersionByScope(ctx context.Context, ownerID, repoID int64) error { + result, err := db.GetEngine(ctx).Exec("UPDATE action_tasks_version SET version = version + 1 WHERE owner_id = ? AND repo_id = ?", ownerID, repoID) + if err != nil { + return err + } + affected, err := result.RowsAffected() + if err != nil { + return err + } + + if affected == 0 { + // if update sql does not affect any rows, the database may be broken, + // so re-insert the row of version data here. + if _, err := insertTasksVersion(ctx, ownerID, repoID); err != nil { + return err + } + } + + return nil +} + +func IncreaseTaskVersion(ctx context.Context, ownerID, repoID int64) error { + ctx, commiter, err := db.TxContext(ctx) + if err != nil { + return err + } + defer commiter.Close() + + // 1. increase global + if err := increaseTasksVersionByScope(ctx, 0, 0); err != nil { + log.Error("IncreaseTasksVersionByScope(Global): %v", err) + return err + } + + // 2. increase owner + if ownerID > 0 { + if err := increaseTasksVersionByScope(ctx, ownerID, 0); err != nil { + log.Error("IncreaseTasksVersionByScope(Owner): %v", err) + return err + } + } + + // 3. increase repo + if repoID > 0 { + if err := increaseTasksVersionByScope(ctx, 0, repoID); err != nil { + log.Error("IncreaseTasksVersionByScope(Repo): %v", err) + return err + } + } + + return commiter.Commit() +} diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 6599cb9cda3e..bfe4b56cd1ce 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -515,6 +515,8 @@ var migrations = []Migration{ NewMigration("Alter Actions Artifact table", v1_21.AlterActionArtifactTable), // v266 -> v267 NewMigration("Reduce commit status", v1_21.ReduceCommitStatus), + // v267 -> v268 + NewMigration("Add action_tasks_version table", v1_21.CreateActionTasksVersionTable), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_21/v267.go b/models/migrations/v1_21/v267.go new file mode 100644 index 000000000000..bc0e954bdcc9 --- /dev/null +++ b/models/migrations/v1_21/v267.go @@ -0,0 +1,23 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_21 //nolint + +import ( + "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/xorm" +) + +func CreateActionTasksVersionTable(x *xorm.Engine) error { + type ActionTasksVersion struct { + ID int64 `xorm:"pk autoincr"` + OwnerID int64 `xorm:"UNIQUE(owner_repo)"` + RepoID int64 `xorm:"INDEX UNIQUE(owner_repo)"` + Version int64 + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` + } + + return x.Sync(new(ActionTasksVersion)) +} diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index 17801cb32202..6de5964cb77b 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -127,20 +127,39 @@ func (s *Service) Declare( // FetchTask assigns a task to the runner func (s *Service) FetchTask( ctx context.Context, - _ *connect.Request[runnerv1.FetchTaskRequest], + req *connect.Request[runnerv1.FetchTaskRequest], ) (*connect.Response[runnerv1.FetchTaskResponse], error) { runner := GetRunner(ctx) var task *runnerv1.Task - if t, ok, err := pickTask(ctx, runner); err != nil { - log.Error("pick task failed: %v", err) - return nil, status.Errorf(codes.Internal, "pick task: %v", err) - } else if ok { - task = t + tasksVersion := req.Msg.TasksVersion // task version from runner + latestVersion, err := actions_model.GetTasksVersionByScope(ctx, runner.OwnerID, runner.RepoID) + if err != nil { + return nil, status.Errorf(codes.Internal, "query tasks version failed: %v", err) + } else if latestVersion == 0 { + if err := actions_model.IncreaseTaskVersion(ctx, runner.OwnerID, runner.RepoID); err != nil { + return nil, status.Errorf(codes.Internal, "fail to increase task version: %v", err) + } + // if we don't increase the value of `latestVersion` here, + // the response of FetchTask will return tasksVersion as zero. + // and the runner will treat it as an old version of Gitea. + latestVersion++ } + if tasksVersion != latestVersion { + // if the task version in request is not equal to the version in db, + // it means there may still be some tasks not be assgined. + // try to pick a task for the runner that send the request. + if t, ok, err := pickTask(ctx, runner); err != nil { + log.Error("pick task failed: %v", err) + return nil, status.Errorf(codes.Internal, "pick task: %v", err) + } else if ok { + task = t + } + } res := connect.NewResponse(&runnerv1.FetchTaskResponse{ - Task: task, + Task: task, + TasksVersion: latestVersion, }) return res, nil } From 478f36a53891bac457fa3f9baebae8a6232be1f6 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Mon, 24 Jul 2023 14:49:18 +0800 Subject: [PATCH 16/23] Add missing default value for some Bool cli flags (#26082) In #25959 I forgot to add default values to some Bool flags (which were BoolT in cli/v1, BoolT means default to be true) This PR adds the default "Value" for them. ``` ./cmd/manager_logging.go: }, cli.BoolTFlag{ ./cmd/manager_logging.go- Name: "rotate, r", ./cmd/manager_logging.go- Usage: "Rotate logs", -- ./cmd/manager_logging.go: }, cli.BoolTFlag{ ./cmd/manager_logging.go- Name: "daily, d", ./cmd/manager_logging.go- Usage: "Rotate logs daily", -- ./cmd/manager_logging.go: }, cli.BoolTFlag{ ./cmd/manager_logging.go- Name: "compress, z", ./cmd/manager_logging.go- Usage: "Compress rotated logs", -- ./cmd/admin.go: cli.BoolTFlag{ ./cmd/admin.go- Name: "force-smtps", ./cmd/admin.go- Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.", -- ./cmd/admin.go: cli.BoolTFlag{ ./cmd/admin.go- Name: "skip-verify", ./cmd/admin.go- Usage: "Skip TLS verify.", -- ./cmd/admin.go: cli.BoolTFlag{ ./cmd/admin.go- Name: "disable-helo", ./cmd/admin.go- Usage: "Disable SMTP helo.", -- ./cmd/admin.go: cli.BoolTFlag{ ./cmd/admin.go- Name: "skip-local-2fa", ./cmd/admin.go- Usage: "Skip 2FA to log on.", -- ./cmd/admin.go: cli.BoolTFlag{ ./cmd/admin.go- Name: "active", ./cmd/admin.go- Usage: "This Authentication Source is Activated.", ``` --- cmd/admin.go | 5 +++++ cmd/manager_logging.go | 3 +++ 2 files changed, 8 insertions(+) diff --git a/cmd/admin.go b/cmd/admin.go index ea62075093c2..745427ca2425 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -298,10 +298,12 @@ var ( &cli.BoolFlag{ Name: "force-smtps", Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.", + Value: true, }, &cli.BoolFlag{ Name: "skip-verify", Usage: "Skip TLS verify.", + Value: true, }, &cli.StringFlag{ Name: "helo-hostname", @@ -311,6 +313,7 @@ var ( &cli.BoolFlag{ Name: "disable-helo", Usage: "Disable SMTP helo.", + Value: true, }, &cli.StringFlag{ Name: "allowed-domains", @@ -320,10 +323,12 @@ var ( &cli.BoolFlag{ Name: "skip-local-2fa", Usage: "Skip 2FA to log on.", + Value: true, }, &cli.BoolFlag{ Name: "active", Usage: "This Authentication Source is Activated.", + Value: true, }, } diff --git a/cmd/manager_logging.go b/cmd/manager_logging.go index 84c962561e1a..7d34fc9ac21b 100644 --- a/cmd/manager_logging.go +++ b/cmd/manager_logging.go @@ -117,6 +117,7 @@ var ( Name: "rotate", Aliases: []string{"r"}, Usage: "Rotate logs", + Value: true, }, &cli.Int64Flag{ Name: "max-size", @@ -127,6 +128,7 @@ var ( Name: "daily", Aliases: []string{"d"}, Usage: "Rotate logs daily", + Value: true, }, &cli.IntFlag{ Name: "max-days", @@ -137,6 +139,7 @@ var ( Name: "compress", Aliases: []string{"z"}, Usage: "Compress rotated logs", + Value: true, }, &cli.IntFlag{ Name: "compression-level", From cdd3d4b8d8814137e16116002e5bf6aad38b794f Mon Sep 17 00:00:00 2001 From: idk Date: Mon, 24 Jul 2023 03:18:17 -0400 Subject: [PATCH 17/23] Allow the use of alternative net.Listener implementations by downstreams (#25855) This is a simple PR which moves the `GetListener` function to a `DefaultGetListener` function, and changes `GetListener` to be a variable which by default points to the `DefaultGetListener` function. This allows people who may exist quasi-downstream of Gitea to create alternate "GetListener" functions, with identical signatures, which return different implementations of the `net.Listener` interface. This approach is expressly intended to be non-invasive and have the least possible impact on the gitea codebase. A previous version of this idea was rejected before: https://github.com/go-gitea/gitea/issues/15544 but because of issues like: https://github.com/go-gitea/gitea/issues/22335 I **really** think that recommending people configure proxies by hand is exactly the wrong way to do things(This is why there is a Tor Browser.). This tiny change lets me put proper hidden service configuration into single `i2p.go` file which lives in `modules/graceful/` and which never has to be checked in to your codebase or affect your dependencies or bloat your project in any way, it can live on a branch in my fork and I'll fast-forward every release and never the twain shall meet. The main use-case for this is to listen on Peer-to-Peer networks and Hidden Services directly without error-prone and cumbersome port-forwarding configuration. For instance, I might implement an "I2PGetListener" as follows: ```Go // adapted from i2p.go which is unchecked-in in my modules/graceful/ directory import "github.com/eyedeekay/onramp" var garlic = &onramp.Garlic{} func I2PGetListener(network, address string) (net.Listener, error) { // Add a deferral to say that we've tried to grab a listener defer GetManager().InformCleanup() switch network { case "tcp", "tcp4", "tcp6", "i2p", "i2pt": return garlic.Listen() case "unix", "unixpacket": // I2P isn't really a replacement for the stuff you use Unix sockets for and it's also not an anonymity risk, so treat them normally unixAddr, err := net.ResolveUnixAddr(network, address) if err != nil { return nil, err } return GetListenerUnix(network, unixAddr) default: return nil, net.UnknownNetworkError(network) } } ``` I could then substitute that GetListener function and be 50% of the way to having a fully-functioning gitea-over-hidden-services instance without any additional configuration(The other 50% doesn't require any code-changes on gitea's part). There are 2 advantages here, one being convenience, first this turns hidden services into a zero-configuration option for self-hosting gitea, and second safety, these Go libraries are passing around hidden-service-only versions of the net.Addr struct, they're using hidden-service-only versions of the sockets, which are both expressly designed to never require access to any information outside the hidden service network, manipulating the application so it reveals information about the host becomes much more difficult, and some attacks become nearly impossible. It also opens up TLS-over-Hidden Services support which is niche right now, of course, but in a future where gitea instances federate if hidden services want to be part of the federation they're probably going to need TLS certificates. They don't need to be painful to set up. This doesn't fix an open issue, but it might affect: - https://github.com/go-gitea/gitea/issues/22335 - my `i2p.go` file actually has a mod that fixes this but it requires adding a handful of new dependencies to gitea and isn't compatible with the normal way you guys recommend using a proxy so I don't think it's ready to send to you as a PR, but if I can find a non-invasive way to fix it I will. - https://github.com/go-gitea/gitea/issues/18240 I hereby agree to the Code of Conduct published here: https://github.com/go-gitea/gitea/blob/8b89563bf1031089a218e6d05dc61047281b35ee/CODE_OF_CONDUCT.md I have read and understood the recommendations published here: https://github.com/go-gitea/gitea/blob/8b89563bf1031089a218e6d05dc61047281b35ee/CONTRIBUTING.md Thank you for your consideration. --------- Co-authored-by: eyedeekay Co-authored-by: wxiaoguang --- modules/graceful/net_unix.go | 8 +++++--- modules/graceful/net_windows.go | 8 +++++--- modules/graceful/server.go | 8 ++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/graceful/net_unix.go b/modules/graceful/net_unix.go index e9c128512308..f5af1e39378a 100644 --- a/modules/graceful/net_unix.go +++ b/modules/graceful/net_unix.go @@ -150,11 +150,13 @@ func CloseProvidedListeners() error { return returnableError } -// GetListener obtains a listener for the local network address. The network must be +// DefaultGetListener obtains a listener for the local network address. The network must be // a stream-oriented network: "tcp", "tcp4", "tcp6", "unix" or "unixpacket". It // returns an provided net.Listener for the matching network and address, or -// creates a new one using net.Listen. -func GetListener(network, address string) (net.Listener, error) { +// creates a new one using net.Listen. This function can be replaced by changing the +// GetListener variable at the top of this file, for example to listen on an onion service using +// github.com/cretz/bine +func DefaultGetListener(network, address string) (net.Listener, error) { // Add a deferral to say that we've tried to grab a listener defer GetManager().InformCleanup() switch network { diff --git a/modules/graceful/net_windows.go b/modules/graceful/net_windows.go index a2f58e224a94..15d228d6b654 100644 --- a/modules/graceful/net_windows.go +++ b/modules/graceful/net_windows.go @@ -9,9 +9,11 @@ package graceful import "net" -// GetListener obtains a listener for the local network address. -// On windows this is basically just a shim around net.Listen. -func GetListener(network, address string) (net.Listener, error) { +// DefaultGetListener obtains a listener for the local network address. +// On windows this is basically just a shim around net.Listen. This function +// can be replaced by changing the GetListener variable at the top of this file, +// for example to listen on an onion service using github.com/cretz/bine +func DefaultGetListener(network, address string) (net.Listener, error) { // Add a deferral to say that we've tried to grab a listener defer GetManager().InformCleanup() diff --git a/modules/graceful/server.go b/modules/graceful/server.go index e42d35cd49b8..bd917828bc86 100644 --- a/modules/graceful/server.go +++ b/modules/graceful/server.go @@ -33,6 +33,14 @@ var ( PerWriteWriteTimeoutKbTime = 10 * time.Second ) +// GetListener returns a listener from a GetListener function, which must have the +// signature: `func FunctioName(network, address string) (net.Listener, error)`. +// This determines the implementation of net.Listener which the server will use.` +// It is implemented in this way so that downstreams may specify the type of listener +// they want to provide Gitea on by default, such as with a hidden service or a p2p network +// No need to worry about "breaking" if there would be a refactoring for the Listeners. No compatibility-guarantee for this mechanism +var GetListener = DefaultGetListener + func init() { DefaultMaxHeaderBytes = 0 // use http.DefaultMaxHeaderBytes - which currently is 1 << 20 (1MB) } From 4211efe8b7a0b38420da5c5d4f287a8d466aedc2 Mon Sep 17 00:00:00 2001 From: caicandong <50507092+CaiCandong@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:48:44 +0800 Subject: [PATCH 18/23] fix Missing 404 swagger response docs for /admin/users/{username} (#26086) close #26079 --- routers/api/v1/admin/user.go | 2 ++ templates/swagger/v1_json.tmpl | 3 +++ 2 files changed, 5 insertions(+) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index c3af5dc90a75..4f1e9a3f5373 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -312,6 +312,8 @@ func DeleteUser(ctx *context.APIContext) { // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" // "422": // "$ref": "#/responses/validationError" diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 7b3a616740ca..69874bdc75f0 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -620,6 +620,9 @@ "403": { "$ref": "#/responses/forbidden" }, + "404": { + "$ref": "#/responses/notFound" + }, "422": { "$ref": "#/responses/validationError" } From 6aa30af724b73c698b87c24fd5bb7d71b3c37abe Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Mon, 24 Jul 2023 16:19:44 +0200 Subject: [PATCH 19/23] Fix handling of Debian files with trailing slash (#26087) Fixes #26022 - Fix handling of files with trailing slash - Fix handling of duplicate package file errors - Added test for both --- modules/packages/debian/metadata.go | 4 +- modules/packages/debian/metadata_test.go | 110 ++++++++++-------- routers/api/packages/debian/debian.go | 2 +- tests/integration/api_packages_debian_test.go | 4 + 4 files changed, 70 insertions(+), 50 deletions(-) diff --git a/modules/packages/debian/metadata.go b/modules/packages/debian/metadata.go index dee524c8ff8b..bb77f7524bf6 100644 --- a/modules/packages/debian/metadata.go +++ b/modules/packages/debian/metadata.go @@ -80,7 +80,9 @@ func ParsePackage(r io.Reader) (*Package, error) { if strings.HasPrefix(hd.Name, controlTar) { var inner io.Reader - switch hd.Name[len(controlTar):] { + // https://man7.org/linux/man-pages/man5/deb-split.5.html#FORMAT + // The file names might contain a trailing slash (since dpkg 1.15.6). + switch strings.TrimSuffix(hd.Name[len(controlTar):], "/") { case "": inner = arr case ".gz": diff --git a/modules/packages/debian/metadata_test.go b/modules/packages/debian/metadata_test.go index 69fd51ea7900..26c2a6fc6880 100644 --- a/modules/packages/debian/metadata_test.go +++ b/modules/packages/debian/metadata_test.go @@ -69,57 +69,71 @@ func TestParsePackage(t *testing.T) { tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n")) tw.Close() - t.Run("None", func(t *testing.T) { - data := createArchive(map[string][]byte{"control.tar": buf.Bytes()}) - - p, err := ParsePackage(data) - assert.NotNil(t, p) - assert.NoError(t, err) - assert.Equal(t, "gitea", p.Name) - }) - - t.Run("gz", func(t *testing.T) { - var zbuf bytes.Buffer - zw := gzip.NewWriter(&zbuf) - zw.Write(buf.Bytes()) - zw.Close() - - data := createArchive(map[string][]byte{"control.tar.gz": zbuf.Bytes()}) - - p, err := ParsePackage(data) - assert.NotNil(t, p) - assert.NoError(t, err) - assert.Equal(t, "gitea", p.Name) - }) - - t.Run("xz", func(t *testing.T) { - var xbuf bytes.Buffer - xw, _ := xz.NewWriter(&xbuf) - xw.Write(buf.Bytes()) - xw.Close() - - data := createArchive(map[string][]byte{"control.tar.xz": xbuf.Bytes()}) - - p, err := ParsePackage(data) - assert.NotNil(t, p) - assert.NoError(t, err) - assert.Equal(t, "gitea", p.Name) - }) + cases := []struct { + Extension string + WriterFactory func(io.Writer) io.WriteCloser + }{ + { + Extension: "", + WriterFactory: func(w io.Writer) io.WriteCloser { + return nopCloser{w} + }, + }, + { + Extension: ".gz", + WriterFactory: func(w io.Writer) io.WriteCloser { + return gzip.NewWriter(w) + }, + }, + { + Extension: ".xz", + WriterFactory: func(w io.Writer) io.WriteCloser { + xw, _ := xz.NewWriter(w) + return xw + }, + }, + { + Extension: ".zst", + WriterFactory: func(w io.Writer) io.WriteCloser { + zw, _ := zstd.NewWriter(w) + return zw + }, + }, + } - t.Run("zst", func(t *testing.T) { - var zbuf bytes.Buffer - zw, _ := zstd.NewWriter(&zbuf) - zw.Write(buf.Bytes()) - zw.Close() + for _, c := range cases { + t.Run(c.Extension, func(t *testing.T) { + var cbuf bytes.Buffer + w := c.WriterFactory(&cbuf) + w.Write(buf.Bytes()) + w.Close() + + data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()}) + + p, err := ParsePackage(data) + assert.NotNil(t, p) + assert.NoError(t, err) + assert.Equal(t, "gitea", p.Name) + + t.Run("TrailingSlash", func(t *testing.T) { + data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()}) + + p, err := ParsePackage(data) + assert.NotNil(t, p) + assert.NoError(t, err) + assert.Equal(t, "gitea", p.Name) + }) + }) + } + }) +} - data := createArchive(map[string][]byte{"control.tar.zst": zbuf.Bytes()}) +type nopCloser struct { + io.Writer +} - p, err := ParsePackage(data) - assert.NotNil(t, p) - assert.NoError(t, err) - assert.Equal(t, "gitea", p.Name) - }) - }) +func (nopCloser) Close() error { + return nil } func TestParseControlFile(t *testing.T) { diff --git a/routers/api/packages/debian/debian.go b/routers/api/packages/debian/debian.go index f7270e0ae0ea..a6da1a11a8ab 100644 --- a/routers/api/packages/debian/debian.go +++ b/routers/api/packages/debian/debian.go @@ -187,7 +187,7 @@ func UploadPackageFile(ctx *context.Context) { ) if err != nil { switch err { - case packages_model.ErrDuplicatePackageVersion: + case packages_model.ErrDuplicatePackageVersion, packages_model.ErrDuplicatePackageFile: apiError(ctx, http.StatusBadRequest, err) case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize: apiError(ctx, http.StatusForbidden, err) diff --git a/tests/integration/api_packages_debian_test.go b/tests/integration/api_packages_debian_test.go index 3e25acd8cff2..2d92b9315994 100644 --- a/tests/integration/api_packages_debian_test.go +++ b/tests/integration/api_packages_debian_test.go @@ -144,6 +144,10 @@ func TestPackageDebian(t *testing.T) { } return seen }) + + req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture)) + AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusBadRequest) }) t.Run("Download", func(t *testing.T) { From ebb98d72462d3661caf8f5e2ca22c1ece5425409 Mon Sep 17 00:00:00 2001 From: caicandong <50507092+CaiCandong@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:39:10 +0800 Subject: [PATCH 20/23] doc guide the user to create the appropriate level runner (#26091) close #26045 --- docs/content/doc/usage/actions/act-runner.en-us.md | 6 +++--- docs/content/doc/usage/actions/act-runner.zh-cn.md | 6 +++--- docs/content/doc/usage/actions/quickstart.en-us.md | 6 +++++- docs/content/doc/usage/actions/quickstart.zh-cn.md | 6 +++++- docs/content/doc/usage/secrets.en-us.md | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/content/doc/usage/actions/act-runner.en-us.md b/docs/content/doc/usage/actions/act-runner.en-us.md index ddab43530e2e..1f4475508f9c 100644 --- a/docs/content/doc/usage/actions/act-runner.en-us.md +++ b/docs/content/doc/usage/actions/act-runner.en-us.md @@ -110,9 +110,9 @@ Note that the repository may still use instance-level or organization-level runn The level of the runner determines where to obtain the registration token. -- Instance level: The admin settings page, like `/admin/runners`. -- Organization level: The organization settings page, like `//settings/runners`. -- Repository level: The repository settings page, like `///settings/runners`. +- Instance level: The admin settings page, like `/admin/actions/runners`. +- Organization level: The organization settings page, like `//settings/actions/runners`. +- Repository level: The repository settings page, like `///settings/actions/runners`. If you cannot see the settings page, please make sure that you have the right permissions and that Actions have been enabled. diff --git a/docs/content/doc/usage/actions/act-runner.zh-cn.md b/docs/content/doc/usage/actions/act-runner.zh-cn.md index fb202e307821..cc5728290073 100644 --- a/docs/content/doc/usage/actions/act-runner.zh-cn.md +++ b/docs/content/doc/usage/actions/act-runner.zh-cn.md @@ -109,9 +109,9 @@ docker run -v $(pwd)/config.yaml:/config.yaml -e CONFIG_FILE=/config.yaml ... Runner级别决定了从哪里获取注册令牌。 -- 实例级别:管理员设置页面,例如 `/admin/runners`。 -- 组织级别:组织设置页面,例如 `//settings/runners`。 -- 存储库级别:存储库设置页面,例如 `///settings/runners`。 +- 实例级别:管理员设置页面,例如 `/admin/actions/runners`。 +- 组织级别:组织设置页面,例如 `//settings/actions/runners`。 +- 存储库级别:存储库设置页面,例如 `///settings/actions/runners`。 如果您无法看到设置页面,请确保您具有正确的权限并且已启用 Actions。 diff --git a/docs/content/doc/usage/actions/quickstart.en-us.md b/docs/content/doc/usage/actions/quickstart.en-us.md index 132d11f13f58..829f1a62c0b1 100644 --- a/docs/content/doc/usage/actions/quickstart.en-us.md +++ b/docs/content/doc/usage/actions/quickstart.en-us.md @@ -66,7 +66,11 @@ If you are unsure which address to use, the LAN address is usually the right cho `token` is used for authentication and identification, such as `P2U1U0oB4XaRCi8azcngmPCLbRpUGapalhmddh23`. It is one-time use only and cannot be used to register multiple runners. -You can obtain tokens from `/admin/runners`. +You can obtain different levels of 'tokens' from the following places to create the corresponding level of' runners': + +- Instance level: The admin settings page, like `/admin/actions/runners`. +- Organization level: The organization settings page, like `//settings/actions/runners`. +- Repository level: The repository settings page, like `///settings/actions/runners`. ![register runner](/images/usage/actions/register-runner.png) diff --git a/docs/content/doc/usage/actions/quickstart.zh-cn.md b/docs/content/doc/usage/actions/quickstart.zh-cn.md index 7a06b6edbd63..1893300b618f 100644 --- a/docs/content/doc/usage/actions/quickstart.zh-cn.md +++ b/docs/content/doc/usage/actions/quickstart.zh-cn.md @@ -66,7 +66,11 @@ Runner和Job容器(由Runner启动以执行Job)将连接到此地址。 `token` 用于身份验证和标识,例如 `P2U1U0oB4XaRCi8azcngmPCLbRpUGapalhmddh23`。 它只能使用一次,并且不能用于注册多个Runner。 -您可以从 `/admin/runners` 获取令牌。 +您可以从以下位置获取不同级别的`token`,从而创建出相应级别的`runner` + +- 实例级别:管理员设置页面,例如 `/admin/actions/runners`。 +- 组织级别:组织设置页面,例如 `//settings/actions/runners`。 +- 存储库级别:存储库设置页面,例如 `///settings/actions/runners`。 ![register runner](/images/usage/actions/register-runner.png) diff --git a/docs/content/doc/usage/secrets.en-us.md b/docs/content/doc/usage/secrets.en-us.md index fe7677fc316f..c82628f50cf8 100644 --- a/docs/content/doc/usage/secrets.en-us.md +++ b/docs/content/doc/usage/secrets.en-us.md @@ -18,7 +18,7 @@ menu: # Secrets Secrets allow you to store sensitive information in your user, organization or repository. -Secrets are available on Gitea 1.19+ and are only visible in 1.20+ when ACTIONS are enabled +Secrets are available on Gitea 1.19+ and are only visible in 1.20+ when ACTIONS are enabled. # Naming your secrets From 5db640abcd8608b065a1b390404bba2233220c95 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Tue, 25 Jul 2023 00:27:42 +0000 Subject: [PATCH 21/23] [skip ci] Updated translations via Crowdin --- options/locale/locale_tr-TR.ini | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index d28ed95fd1d4..c070e5fbc139 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -640,6 +640,7 @@ language=Dil ui=Tema hidden_comment_types=Gizli yorum türleri hidden_comment_types_description=Burada işaretlenen yorum türleri konu sayfalarında görüntülenmeyecektir. Örneğin "Etiket" seçildiğinde tüm ",