From 7df8d5f36d74a431a301f9f7a9f620ca0318d183 Mon Sep 17 00:00:00 2001 From: fsologureng Date: Tue, 8 Nov 2022 17:38:14 -0300 Subject: [PATCH 01/49] Fixes a11y behaviour for reactions and options in issue comments view --- options/locale/locale_en-US.ini | 1 + .../repo/issue/view_content/add_reaction.tmpl | 10 ++--- .../repo/issue/view_content/context_menu.tmpl | 16 +++---- web_src/js/features/aria.js | 43 ++++++++++++++++++- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index e610bc6b28121..7c857f9014ec7 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1333,6 +1333,7 @@ issues.draft_title = Draft issues.num_comments = %d comments issues.commented_at = `commented %s` issues.delete_comment_confirm = Are you sure you want to delete this comment? +issues.context.options_button = Comment Options issues.context.copy_link = Copy Link issues.context.quote_reply = Quote Reply issues.context.reference_issue = Reference in new issue diff --git a/templates/repo/issue/view_content/add_reaction.tmpl b/templates/repo/issue/view_content/add_reaction.tmpl index 9bd9022d28abf..fdaa8f2761c9f 100644 --- a/templates/repo/issue/view_content/add_reaction.tmpl +++ b/templates/repo/issue/view_content/add_reaction.tmpl @@ -1,13 +1,13 @@ {{if .ctx.IsSigned}} - @@ -60,7 +60,7 @@ {{$reactions := .Reactions.GroupByType}} {{if $reactions}}
- {{template "repo/issue/view_content/reactions" Dict "ctx" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions}} + {{template "repo/issue/view_content/reactions" Dict "ctx" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions "IdPrefix" .HashTag}}
{{end}} diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index de11846af7e94..b63640af46ca1 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -64,7 +64,7 @@ {{end}} {{end}} {{if not $.Repository.IsArchived}} - {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}} + {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "IdPrefix" .Issue.HashTag}} {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}} {{end}} @@ -86,7 +86,7 @@ {{$reactions := .Issue.Reactions.GroupByType}} {{if $reactions}}
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions}} + {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions "IdPrefix" .Issue.HashTag}}
{{end}} diff --git a/templates/repo/issue/view_content/add_reaction.tmpl b/templates/repo/issue/view_content/add_reaction.tmpl index fdaa8f2761c9f..a6e51b57f26c9 100644 --- a/templates/repo/issue/view_content/add_reaction.tmpl +++ b/templates/repo/issue/view_content/add_reaction.tmpl @@ -6,8 +6,8 @@ diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 7ed8cf3bde5e5..938ec7e2bbef7 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -66,7 +66,7 @@ {{end}} {{if not $.Repository.IsArchived}} - {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}} + {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "IdPrefix" .HashTag}} {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}} {{end}} @@ -88,7 +88,7 @@ {{$reactions := .Reactions.GroupByType}} {{if $reactions}}
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}} + {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions "IdPrefix" .HashTag}}
{{end}} @@ -438,8 +438,8 @@ {{end}} {{if not $.Repository.IsArchived}} - {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}} - {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}} + {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "IdPrefix" .HashTag}} + {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}} {{end}} @@ -460,7 +460,7 @@ {{$reactions := .Reactions.GroupByType}} {{if $reactions}}
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}} + {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions "IdPrefix" .HashTag}}
{{end}} @@ -565,7 +565,7 @@ {{end}} {{if not $.Repository.IsArchived}} - {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}} + {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "IdPrefix" .HashTag}} {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}} {{end}} @@ -584,7 +584,7 @@ {{$reactions := .Reactions.GroupByType}} {{if $reactions}}
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}} + {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions "IdPrefix" .HashTag}}
{{end}} diff --git a/templates/repo/issue/view_content/context_menu.tmpl b/templates/repo/issue/view_content/context_menu.tmpl index 1b9b775ae844d..24bec44e673d8 100644 --- a/templates/repo/issue/view_content/context_menu.tmpl +++ b/templates/repo/issue/view_content/context_menu.tmpl @@ -10,16 +10,16 @@ {{else}} {{$referenceUrl = Printf "%s/files#%s" .ctx.Issue.HTMLURL .item.HashTag}} {{end}} - - + + {{if not .ctx.UnitIssuesGlobalDisabled}} - + {{end}} {{if or .ctx.Permission.IsAdmin .IsCommentPoster .ctx.HasIssuesOrPullsWritePermission}}
- + {{if .delete}} - + {{end}} {{end}} diff --git a/templates/repo/issue/view_content/reactions.tmpl b/templates/repo/issue/view_content/reactions.tmpl index c0a925d18bf4c..d2362d49bfc60 100644 --- a/templates/repo/issue/view_content/reactions.tmpl +++ b/templates/repo/issue/view_content/reactions.tmpl @@ -5,5 +5,5 @@ {{end}} {{if AllowedReactions}} - {{template "repo/issue/view_content/add_reaction" Dict "ctx" $.ctx "ActionURL" .ActionURL}} + {{template "repo/issue/view_content/add_reaction" Dict "ctx" $.ctx "ActionURL" .ActionURL "IdPrefix" (Printf "%s-inline" .IdPrefix)}} {{end}} diff --git a/web_src/js/features/aria.js b/web_src/js/features/aria.js index a7534e7b32322..76076d378080f 100644 --- a/web_src/js/features/aria.js +++ b/web_src/js/features/aria.js @@ -33,87 +33,54 @@ function attachOneDropdownAria($dropdown) { const $focusable = $textSearch.length ? $textSearch : $dropdown; // see comment below if (!$focusable.length) return; - // prepare menu list const $menu = $dropdown.find('> .menu'); - if (!$menu.attr('id')) $menu.attr('id', generateAriaId()); - - // dropdown has 2 different focusing behaviors - // * with search input: the input is focused, and it works perfectly with aria-activedescendant pointing another sibling element. - // * without search input (but the readonly text), the dropdown itself is focused. then the aria-activedescendant points to the element inside dropdown - - // expected user interactions for dropdown with aria support: - // * user can use Tab to focus in the dropdown, then the dropdown menu (list) will be shown - // * user presses Tab on the focused dropdown to move focus to next sibling focusable element (but not the menu item) - // * user can use arrow key Up/Down to navigate between menu items - // * when user presses Enter: - // - if the menu item is clickable (eg: ), then trigger the click event - // - otherwise, the dropdown control (low-level code) handles the Enter event, hides the dropdown menu - - // TODO: multiple selection is not supported yet. - - $focusable.attr({ - 'role': 'menu', - 'aria-haspopup': 'menu', - 'aria-controls': $menu.attr('id'), - 'aria-expanded': 'false', - }); - - if ($dropdown.attr('data-content') && !$dropdown.attr('aria-label')) { - $dropdown.attr('aria-label', $dropdown.attr('data-content')); - } - - $menu.find('> .item').each((_, item) => { - prepareMenuItem($(item)); - }); - - // update aria attributes according to current active/selected item - const refreshAria = () => { - const isMenuVisible = !$menu.is('.hidden') && !$menu.is('.animating.out'); - $focusable.attr('aria-expanded', isMenuVisible ? 'true' : 'false'); - - let $active = $menu.find('> .item.active'); - if (!$active.length) $active = $menu.find('> .item.selected'); // it's strange that we need this fallback at the moment - - // if there is an active item, use its id. if no active item, then the empty string is set - $focusable.attr('aria-activedescendant', $active.attr('id')); - }; - - $dropdown.on('keydown', (e) => { - // here it must use keydown event before dropdown's keyup handler, otherwise there is no Enter event in our keyup handler - if (e.key === 'Enter') { - const $item = $dropdown.dropdown('get item', $dropdown.dropdown('get value')); - // if the selected item is clickable, then trigger the click event. in the future there could be a special CSS class for it. - if ($item && $item.is('a')) $item[0].click(); + if (!$dropdown.attr('data-aria-templated')) { + // prepare menu list + if (!$menu.attr('id')) $menu.attr('id', generateAriaId()); + + // dropdown has 2 different focusing behaviors + // * with search input: the input is focused, and it works perfectly with aria-activedescendant pointing another sibling element. + // * without search input (but the readonly text), the dropdown itself is focused. then the aria-activedescendant points to the element inside dropdown + + // expected user interactions for dropdown with aria support: + // * user can use Tab to focus in the dropdown, then the dropdown menu (list) will be shown + // * user presses Tab on the focused dropdown to move focus to next sibling focusable element (but not the menu item) + // * user can use arrow key Up/Down to navigate between menu items + // * when user presses Enter: + // - if the menu item is clickable (eg: ), then trigger the click event + // - otherwise, the dropdown control (low-level code) handles the Enter event, hides the dropdown menu + + // TODO: multiple selection is not supported yet. + + $focusable.attr({ + 'role': 'menu', + 'aria-haspopup': 'menu', + 'aria-controls': $menu.attr('id'), + 'aria-expanded': 'false', + }); + + if ($dropdown.attr('data-content') && !$dropdown.attr('aria-label')) { + $dropdown.attr('aria-label', $dropdown.attr('data-content')); } - }); - - // use setTimeout to run the refreshAria in next tick (to make sure the Fomantic UI code has finished its work) - const deferredRefreshAria = () => { setTimeout(refreshAria, 0) }; // do not return any value, jQuery has return-value related behaviors. - $focusable.on('focus', deferredRefreshAria); - $focusable.on('mouseup', deferredRefreshAria); - $focusable.on('blur', deferredRefreshAria); - $dropdown.on('keyup', (e) => { if (e.key.startsWith('Arrow')) deferredRefreshAria(); }); -} -function attachOneDropdownAriaTemplated($dropdown) { - if ($dropdown.attr('data-aria-attached')) return; - $dropdown.attr('data-aria-attached', 1); - - const $menu = $dropdown.find('> .menu'); + $menu.find('> .item').each((_, item) => { + prepareMenuItem($(item)); + }); + } // update aria attributes according to current active/selected item const refreshAria = () => { const isMenuVisible = !$menu.is('.hidden') && !$menu.is('.animating.out'); if (isMenuVisible) { - $dropdown.attr('aria-expanded', 'true'); + $focusable.attr('aria-expanded', 'true'); } else { - $dropdown.removeAttr('aria-expanded'); + $focusable.removeAttr('aria-expanded'); } let $active = $menu.find('> .item.active'); if (!$active.length) $active = $menu.find('> .item.selected'); // it's strange that we need this fallback at the moment // if there is an active item, use its id. if no active item, then the empty string is set - $dropdown.attr('aria-activedescendant', $active.attr('id')); + $focusable.attr('aria-activedescendant', $active.attr('id')); }; $dropdown.on('keydown', (e) => { @@ -130,13 +97,12 @@ function attachOneDropdownAriaTemplated($dropdown) { // use setTimeout to run the refreshAria in next tick (to make sure the Fomantic UI code has finished its work) const deferredRefreshAria = () => { setTimeout(refreshAria, 0) }; // do not return any value, jQuery has return-value related behaviors. - $dropdown.on('focus', deferredRefreshAria); - $dropdown.on('mouseup', deferredRefreshAria); - $dropdown.on('blur', deferredRefreshAria); + $focusable.on('focus', deferredRefreshAria); + $focusable.on('mouseup', deferredRefreshAria); + $focusable.on('blur', deferredRefreshAria); $dropdown.on('keyup', (e) => { if (e.key.startsWith('Arrow')) deferredRefreshAria(); }); } export function attachDropdownAria($dropdowns) { - $dropdowns.filter(':not([data-aria-templated])').each((_, e) => attachOneDropdownAria($(e))); - $dropdowns.filter('[data-aria-templated]').each((_, e) => attachOneDropdownAriaTemplated($(e))); + $dropdowns.each((_, e) => attachOneDropdownAria($(e))); } From f96187fca60d42922459d444ec40f3d955bf9e30 Mon Sep 17 00:00:00 2001 From: Gusted Date: Sun, 13 Nov 2022 05:14:35 +0100 Subject: [PATCH 09/49] Upgrade golang.org/x/crypto (#21792) - Update the crypto dependency to include https://github.com/golang/crypto/commit/6fad3dfc18918c2ac9c112e46b32473bd2e5e2f9 - Resolves #17798 Executed: `go get golang.org/x/crypto@6fad3dfc18918c2ac9c112e46b32473bd2e5e2f9 && rm go.sum && go mod tidy` --- go.mod | 8 ++++---- go.sum | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 408249880c752..cf1397c468884 100644 --- a/go.mod +++ b/go.mod @@ -94,11 +94,11 @@ require ( github.com/yuin/goldmark-meta v1.1.0 go.jolheiser.com/hcaptcha v0.0.4 go.jolheiser.com/pwn v0.0.3 - golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be - golang.org/x/net v0.0.0-20220927171203-f486391704dc + golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891 + golang.org/x/net v0.2.0 golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 - golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec - golang.org/x/text v0.3.8 + golang.org/x/sys v0.2.0 + golang.org/x/text v0.4.0 golang.org/x/tools v0.1.12 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/ini.v1 v1.67.0 diff --git a/go.sum b/go.sum index 65841b8ec334a..d6748eae34de6 100644 --- a/go.sum +++ b/go.sum @@ -1608,8 +1608,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A= -golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891 h1:WhEPFM1Ck5gaKybeSWvzI7Y/cd8K9K5tJGRxXMACOBA= +golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1721,8 +1721,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ= -golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1876,13 +1876,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI= -golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1892,8 +1892,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 62f360fb451f9e9ca5dc6b1e674a0d70b0a7b5d4 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Sun, 13 Nov 2022 07:55:19 +0200 Subject: [PATCH 10/49] Render number of commits in repo page in a user friendly way (#21786) Use `JsPrettyNumber` to render the number of commits * Closes #12637 ### Before ![1094](https://user-images.githubusercontent.com/20454870/201484428-eaa80d27-eeed-444e-9dc5-ae046424de2f.png) ### After ![1,094](https://user-images.githubusercontent.com/20454870/201484385-b5bdc290-86fd-493b-a87c-c987012b18ad.png) Signed-off-by: Yarden Shoham Co-authored-by: 6543 <6543@obermui.de> --- templates/repo/sub_menu.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/sub_menu.tmpl b/templates/repo/sub_menu.tmpl index fac8e5ac99ddc..e74823e36dea8 100644 --- a/templates/repo/sub_menu.tmpl +++ b/templates/repo/sub_menu.tmpl @@ -4,7 +4,7 @@
- {{.locale.Tr "repo.topic.done"}}
From 959e64e1301aef3614f2ad55188a4f782bd0e863 Mon Sep 17 00:00:00 2001 From: zeripath Date: Tue, 15 Nov 2022 08:08:59 +0000 Subject: [PATCH 17/49] Adjust gitea doctor --run storages to check all storage types (#21785) The doctor check `storages` currently only checks the attachment storage. This PR adds some basic garbage collection functionality for the other types of storage. Signed-off-by: Andrew Thornton Co-authored-by: Lunny Xiao --- models/git/lfs.go | 6 +- models/packages/package_blob.go | 7 + models/repo/archiver.go | 36 +++++ models/repo/attachment.go | 6 +- models/repo/avatar.go | 7 + models/user/avatar.go | 7 + modules/doctor/storage.go | 232 ++++++++++++++++++++++++++---- modules/git/repo_archive.go | 12 ++ modules/packages/content_store.go | 12 ++ routers/web/repo/lfs.go | 2 +- 10 files changed, 296 insertions(+), 31 deletions(-) diff --git a/models/git/lfs.go b/models/git/lfs.go index 74721dabb1b2c..87e07d7a5e0c1 100644 --- a/models/git/lfs.go +++ b/models/git/lfs.go @@ -235,9 +235,9 @@ func LFSObjectAccessible(user *user_model.User, oid string) (bool, error) { return count > 0, err } -// LFSObjectIsAssociated checks if a provided Oid is associated -func LFSObjectIsAssociated(oid string) (bool, error) { - return db.GetEngine(db.DefaultContext).Exist(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) +// ExistsLFSObject checks if a provided Oid exists within the DB +func ExistsLFSObject(ctx context.Context, oid string) (bool, error) { + return db.GetEngine(ctx).Exist(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) } // LFSAutoAssociate auto associates accessible LFSMetaObjects diff --git a/models/packages/package_blob.go b/models/packages/package_blob.go index 8c701d4285d09..fcb71a96ec677 100644 --- a/models/packages/package_blob.go +++ b/models/packages/package_blob.go @@ -62,6 +62,13 @@ func GetBlobByID(ctx context.Context, blobID int64) (*PackageBlob, error) { return pb, nil } +// ExistPackageBlobWithSHA returns if a package blob exists with the provided sha +func ExistPackageBlobWithSHA(ctx context.Context, blobSha256 string) (bool, error) { + return db.GetEngine(ctx).Exist(&PackageBlob{ + HashSHA256: blobSha256, + }) +} + // FindExpiredUnreferencedBlobs gets all blobs without associated files older than the specific duration func FindExpiredUnreferencedBlobs(ctx context.Context, olderThan time.Duration) ([]*PackageBlob, error) { pbs := make([]*PackageBlob, 0, 10) diff --git a/models/repo/archiver.go b/models/repo/archiver.go index 003911943f52a..84358ce0dc690 100644 --- a/models/repo/archiver.go +++ b/models/repo/archiver.go @@ -7,11 +7,14 @@ package repo import ( "context" "fmt" + "strconv" + "strings" "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) @@ -44,6 +47,28 @@ func (archiver *RepoArchiver) RelativePath() string { return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String()) } +// repoArchiverForRelativePath takes a relativePath created from (archiver *RepoArchiver) RelativePath() and creates a shell repoArchiver struct representing it +func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) { + parts := strings.SplitN(relativePath, "/", 3) + if len(parts) != 3 { + return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument} + } + repoID, err := strconv.ParseInt(parts[0], 10, 64) + if err != nil { + return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument} + } + nameExts := strings.SplitN(parts[2], ".", 2) + if len(nameExts) != 2 { + return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument} + } + + return &RepoArchiver{ + RepoID: repoID, + CommitID: parts[1] + nameExts[0], + Type: git.ToArchiveType(nameExts[1]), + }, nil +} + var delRepoArchiver = new(RepoArchiver) // DeleteRepoArchiver delete archiver @@ -65,6 +90,17 @@ func GetRepoArchiver(ctx context.Context, repoID int64, tp git.ArchiveType, comm return nil, nil } +// ExistsRepoArchiverWithStoragePath checks if there is a RepoArchiver for a given storage path +func ExistsRepoArchiverWithStoragePath(ctx context.Context, storagePath string) (bool, error) { + // We need to invert the path provided func (archiver *RepoArchiver) RelativePath() above + archiver, err := repoArchiverForRelativePath(storagePath) + if err != nil { + return false, err + } + + return db.GetEngine(ctx).Exist(archiver) +} + // AddRepoArchiver adds an archiver func AddRepoArchiver(ctx context.Context, archiver *RepoArchiver) error { _, err := db.GetEngine(ctx).Insert(archiver) diff --git a/models/repo/attachment.go b/models/repo/attachment.go index 180d7730ba715..df7528df09c9c 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -122,9 +122,9 @@ func GetAttachmentsByUUIDs(ctx context.Context, uuids []string) ([]*Attachment, return attachments, db.GetEngine(ctx).In("uuid", uuids).Find(&attachments) } -// ExistAttachmentsByUUID returns true if attachment is exist by given UUID -func ExistAttachmentsByUUID(uuid string) (bool, error) { - return db.GetEngine(db.DefaultContext).Where("`uuid`=?", uuid).Exist(new(Attachment)) +// ExistAttachmentsByUUID returns true if attachment exists with the given UUID +func ExistAttachmentsByUUID(ctx context.Context, uuid string) (bool, error) { + return db.GetEngine(ctx).Where("`uuid`=?", uuid).Exist(new(Attachment)) } // GetAttachmentsByIssueID returns all attachments of an issue. diff --git a/models/repo/avatar.go b/models/repo/avatar.go index 1bc37598feef9..84b9f5ac21eb6 100644 --- a/models/repo/avatar.go +++ b/models/repo/avatar.go @@ -24,6 +24,13 @@ func (repo *Repository) CustomAvatarRelativePath() string { return repo.Avatar } +// ExistsWithAvatarAtStoragePath returns true if there is a user with this Avatar +func ExistsWithAvatarAtStoragePath(ctx context.Context, storagePath string) (bool, error) { + // See func (repo *Repository) CustomAvatarRelativePath() + // repo.Avatar is used directly as the storage path - therefore we can check for existence directly using the path + return db.GetEngine(ctx).Where("`avatar`=?", storagePath).Exist(new(Repository)) +} + // RelAvatarLink returns a relative link to the repository's avatar. func (repo *Repository) RelAvatarLink() string { return repo.relAvatarLink(db.DefaultContext) diff --git a/models/user/avatar.go b/models/user/avatar.go index 102206f3a208e..f5237667464d4 100644 --- a/models/user/avatar.go +++ b/models/user/avatar.go @@ -111,3 +111,10 @@ func (u *User) IsUploadAvatarChanged(data []byte) bool { avatarID := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", u.ID, md5.Sum(data))))) return u.Avatar != avatarID } + +// ExistsWithAvatarAtStoragePath returns true if there is a user with this Avatar +func ExistsWithAvatarAtStoragePath(ctx context.Context, storagePath string) (bool, error) { + // See func (u *User) CustomAvatarRelativePath() + // u.Avatar is used directly as the storage path - therefore we can check for existence directly using the path + return db.GetEngine(ctx).Where("`avatar`=?", storagePath).Exist(new(User)) +} diff --git a/modules/doctor/storage.go b/modules/doctor/storage.go index dafd989cf03b9..8ae9168ea6e52 100644 --- a/modules/doctor/storage.go +++ b/modules/doctor/storage.go @@ -6,71 +6,255 @@ package doctor import ( "context" + "errors" + "io/fs" + "strings" - repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/git" + "code.gitea.io/gitea/models/packages" + "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/log" + packages_module "code.gitea.io/gitea/modules/packages" "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/modules/util" ) -func checkAttachmentStorageFiles(logger log.Logger, autofix bool) error { - var total, garbageNum int - var deletePaths []string - if err := storage.Attachments.IterateObjects(func(p string, obj storage.Object) error { +type commonStorageCheckOptions struct { + storer storage.ObjectStorage + isOrphaned func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) + name string +} + +func commonCheckStorage(ctx context.Context, logger log.Logger, autofix bool, opts *commonStorageCheckOptions) error { + totalCount, orphanedCount := 0, 0 + totalSize, orphanedSize := int64(0), int64(0) + + var pathsToDelete []string + if err := opts.storer.IterateObjects(func(p string, obj storage.Object) error { defer obj.Close() - total++ + totalCount++ stat, err := obj.Stat() if err != nil { return err } - exist, err := repo_model.ExistAttachmentsByUUID(stat.Name()) + totalSize += stat.Size() + + orphaned, err := opts.isOrphaned(p, obj, stat) if err != nil { return err } - if !exist { - garbageNum++ + if orphaned { + orphanedCount++ + orphanedSize += stat.Size() if autofix { - deletePaths = append(deletePaths, p) + pathsToDelete = append(pathsToDelete, p) } } return nil }); err != nil { - logger.Error("storage.Attachments.IterateObjects failed: %v", err) + logger.Error("Error whilst iterating %s storage: %v", opts.name, err) return err } - if garbageNum > 0 { + if orphanedCount > 0 { if autofix { var deletedNum int - for _, p := range deletePaths { - if err := storage.Attachments.Delete(p); err != nil { - log.Error("Delete attachment %s failed: %v", p, err) + for _, p := range pathsToDelete { + if err := opts.storer.Delete(p); err != nil { + log.Error("Error whilst deleting %s from %s storage: %v", p, opts.name, err) } else { deletedNum++ } } - logger.Info("%d missed information attachment detected, %d deleted.", garbageNum, deletedNum) + logger.Info("Deleted %d/%d orphaned %s(s)", deletedNum, orphanedCount, opts.name) } else { - logger.Warn("Checked %d attachment, %d missed information.", total, garbageNum) + logger.Warn("Found %d/%d (%s/%s) orphaned %s(s)", orphanedCount, totalCount, base.FileSize(orphanedSize), base.FileSize(totalSize), opts.name) } + } else { + logger.Info("Found %d (%s) %s(s)", totalCount, base.FileSize(totalSize), opts.name) } return nil } -func checkStorageFiles(ctx context.Context, logger log.Logger, autofix bool) error { - if err := storage.Init(); err != nil { - logger.Error("storage.Init failed: %v", err) - return err +type checkStorageOptions struct { + All bool + Attachments bool + LFS bool + Avatars bool + RepoAvatars bool + RepoArchives bool + Packages bool +} + +// checkStorage will return a doctor check function to check the requested storage types for "orphaned" stored object/files and optionally delete them +func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger log.Logger, autofix bool) error { + return func(ctx context.Context, logger log.Logger, autofix bool) error { + if err := storage.Init(); err != nil { + logger.Error("storage.Init failed: %v", err) + return err + } + + if opts.Attachments || opts.All { + if err := commonCheckStorage(ctx, logger, autofix, + &commonStorageCheckOptions{ + storer: storage.Attachments, + isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { + exists, err := repo.ExistAttachmentsByUUID(ctx, stat.Name()) + return !exists, err + }, + name: "attachment", + }); err != nil { + return err + } + } + + if opts.LFS || opts.All { + if err := commonCheckStorage(ctx, logger, autofix, + &commonStorageCheckOptions{ + storer: storage.LFS, + isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { + // The oid of an LFS stored object is the name but with all the path.Separators removed + oid := strings.ReplaceAll(path, "/", "") + exists, err := git.ExistsLFSObject(ctx, oid) + return !exists, err + }, + name: "LFS file", + }); err != nil { + return err + } + } + + if opts.Avatars || opts.All { + if err := commonCheckStorage(ctx, logger, autofix, + &commonStorageCheckOptions{ + storer: storage.Avatars, + isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { + exists, err := user.ExistsWithAvatarAtStoragePath(ctx, path) + return !exists, err + }, + name: "avatar", + }); err != nil { + return err + } + } + + if opts.RepoAvatars || opts.All { + if err := commonCheckStorage(ctx, logger, autofix, + &commonStorageCheckOptions{ + storer: storage.RepoAvatars, + isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { + exists, err := repo.ExistsWithAvatarAtStoragePath(ctx, path) + return !exists, err + }, + name: "repo avatar", + }); err != nil { + return err + } + } + + if opts.RepoArchives || opts.All { + if err := commonCheckStorage(ctx, logger, autofix, + &commonStorageCheckOptions{ + storer: storage.RepoAvatars, + isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { + exists, err := repo.ExistsRepoArchiverWithStoragePath(ctx, path) + if err == nil || errors.Is(err, util.ErrInvalidArgument) { + // invalid arguments mean that the object is not a valid repo archiver and it should be removed + return !exists, nil + } + return !exists, err + }, + name: "repo archive", + }); err != nil { + return err + } + } + + if opts.Packages || opts.All { + if err := commonCheckStorage(ctx, logger, autofix, + &commonStorageCheckOptions{ + storer: storage.Packages, + isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { + key, err := packages_module.RelativePathToKey(path) + if err != nil { + // If there is an error here then the relative path does not match a valid package + // Therefore it is orphaned by default + return true, nil + } + + exists, err := packages.ExistPackageBlobWithSHA(ctx, string(key)) + + return !exists, err + }, + name: "package blob", + }); err != nil { + return err + } + } + + return nil } - return checkAttachmentStorageFiles(logger, autofix) } func init() { Register(&Check{ - Title: "Check if there is garbage storage files", + Title: "Check if there are orphaned storage files", Name: "storages", IsDefault: false, - Run: checkStorageFiles, + Run: checkStorage(&checkStorageOptions{All: true}), + AbortIfFailed: false, + SkipDatabaseInitialization: false, + Priority: 1, + }) + + Register(&Check{ + Title: "Check if there are orphaned attachments in storage", + Name: "storage-attachments", + IsDefault: false, + Run: checkStorage(&checkStorageOptions{Attachments: true}), + AbortIfFailed: false, + SkipDatabaseInitialization: false, + Priority: 1, + }) + + Register(&Check{ + Title: "Check if there are orphaned lfs files in storage", + Name: "storage-lfs", + IsDefault: false, + Run: checkStorage(&checkStorageOptions{LFS: true}), + AbortIfFailed: false, + SkipDatabaseInitialization: false, + Priority: 1, + }) + + Register(&Check{ + Title: "Check if there are orphaned avatars in storage", + Name: "storage-avatars", + IsDefault: false, + Run: checkStorage(&checkStorageOptions{Avatars: true, RepoAvatars: true}), + AbortIfFailed: false, + SkipDatabaseInitialization: false, + Priority: 1, + }) + + Register(&Check{ + Title: "Check if there are orphaned archives in storage", + Name: "storage-archives", + IsDefault: false, + Run: checkStorage(&checkStorageOptions{RepoArchives: true}), + AbortIfFailed: false, + SkipDatabaseInitialization: false, + Priority: 1, + }) + + Register(&Check{ + Title: "Check if there are orphaned package blobs in storage", + Name: "storage-packages", + IsDefault: false, + Run: checkStorage(&checkStorageOptions{Packages: true}), AbortIfFailed: false, SkipDatabaseInitialization: false, Priority: 1, diff --git a/modules/git/repo_archive.go b/modules/git/repo_archive.go index a0cbfba5d965d..13be2004ca2f4 100644 --- a/modules/git/repo_archive.go +++ b/modules/git/repo_archive.go @@ -38,6 +38,18 @@ func (a ArchiveType) String() string { return "unknown" } +func ToArchiveType(s string) ArchiveType { + switch s { + case "zip": + return ZIP + case "tar.gz": + return TARGZ + case "bundle": + return BUNDLE + } + return 0 +} + // CreateArchive create archive content to the target path func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, target io.Writer, usePrefix bool, commitID string) error { if format.String() == "unknown" { diff --git a/modules/packages/content_store.go b/modules/packages/content_store.go index a3a5d1a6663c8..be416ac269350 100644 --- a/modules/packages/content_store.go +++ b/modules/packages/content_store.go @@ -7,8 +7,10 @@ package packages import ( "io" "path" + "strings" "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/modules/util" ) // BlobHash256Key is the key to address a blob content @@ -45,3 +47,13 @@ func (s *ContentStore) Delete(key BlobHash256Key) error { func KeyToRelativePath(key BlobHash256Key) string { return path.Join(string(key)[0:2], string(key)[2:4], string(key)) } + +// RelativePathToKey converts a relative path aa/bb/aabb000000... to the sha256 key aabb000000... +func RelativePathToKey(relativePath string) (BlobHash256Key, error) { + parts := strings.SplitN(relativePath, "/", 3) + if len(parts) != 3 || len(parts[0]) != 2 || len(parts[1]) != 2 || len(parts[2]) < 4 || parts[0]+parts[1] != parts[2][0:4] { + return "", util.ErrInvalidArgument + } + + return BlobHash256Key(parts[2]), nil +} diff --git a/routers/web/repo/lfs.go b/routers/web/repo/lfs.go index 67cb6837a56a6..9bf4307bfe092 100644 --- a/routers/web/repo/lfs.go +++ b/routers/web/repo/lfs.go @@ -478,7 +478,7 @@ func LFSPointerFiles(ctx *context.Context) { return err } if !result.Associatable { - associated, err := git_model.LFSObjectIsAssociated(pointerBlob.Oid) + associated, err := git_model.ExistsLFSObject(ctx, pointerBlob.Oid) if err != nil { return err } From 4cf8c4c8e56ff0c41b323a30dc195df07809a995 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 15 Nov 2022 11:33:52 +0200 Subject: [PATCH 18/49] Add `updated_at` field to PullReview API object (#21812) * Closes #19997 Adds an `updated_at` time field to the `PullReview` API object to specify when the pull request review's state changed. Signed-off-by: Yarden Shoham Co-authored-by: Lunny Xiao --- modules/convert/pull_review.go | 1 + modules/structs/pull_review.go | 2 ++ templates/swagger/v1_json.tmpl | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/modules/convert/pull_review.go b/modules/convert/pull_review.go index 93ce208224f8f..e8a543fea955a 100644 --- a/modules/convert/pull_review.go +++ b/modules/convert/pull_review.go @@ -39,6 +39,7 @@ func ToPullReview(ctx context.Context, r *issues_model.Review, doer *user_model. Dismissed: r.Dismissed, CodeCommentsCount: r.GetCodeCommentsCount(), Submitted: r.CreatedUnix.AsTime(), + Updated: r.UpdatedUnix.AsTime(), HTMLURL: r.HTMLURL(), HTMLPullURL: r.Issue.HTMLURL(), } diff --git a/modules/structs/pull_review.go b/modules/structs/pull_review.go index 7c9360a0c2200..ca2af48657365 100644 --- a/modules/structs/pull_review.go +++ b/modules/structs/pull_review.go @@ -40,6 +40,8 @@ type PullReview struct { CodeCommentsCount int `json:"comments_count"` // swagger:strfmt date-time Submitted time.Time `json:"submitted_at"` + // swagger:strfmt date-time + Updated time.Time `json:"updated_at"` HTMLURL string `json:"html_url"` HTMLPullURL string `json:"pull_request_url"` diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 229e219064192..fe3185ea77ea4 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -17891,6 +17891,11 @@ "team": { "$ref": "#/definitions/Team" }, + "updated_at": { + "type": "string", + "format": "date-time", + "x-go-name": "Updated" + }, "user": { "$ref": "#/definitions/User" } From a42675cd6642f085c0c72cf974e7775f6578358c Mon Sep 17 00:00:00 2001 From: Gary Moon Date: Tue, 15 Nov 2022 15:22:16 -0500 Subject: [PATCH 19/49] Skip GitHub migration tests if the API token is undefined (#21824) GitHub migration tests will be skipped if the secret for the GitHub API token hasn't been set. This change should make all tests pass (or skip in the case of this one) for anyone running the pipeline on their own infrastructure without further action on their part. Resolves https://github.com/go-gitea/gitea/issues/21739 Signed-off-by: Gary Moon --- services/migrations/github_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/migrations/github_test.go b/services/migrations/github_test.go index 90c1fcaef5b6b..7bbbbb616881f 100644 --- a/services/migrations/github_test.go +++ b/services/migrations/github_test.go @@ -18,7 +18,11 @@ import ( func TestGitHubDownloadRepo(t *testing.T) { GithubLimitRateRemaining = 3 // Wait at 3 remaining since we could have 3 CI in // - downloader := NewGithubDownloaderV3(context.Background(), "https://github.com", "", "", os.Getenv("GITHUB_READ_TOKEN"), "go-gitea", "test_repo") + token := os.Getenv("GITHUB_READ_TOKEN") + if token == "" { + t.Skip("Skipping GitHub migration test because GITHUB_READ_TOKEN is empty") + } + downloader := NewGithubDownloaderV3(context.Background(), "https://github.com", "", "", token, "go-gitea", "test_repo") err := downloader.RefreshRate() assert.NoError(t, err) From 3aa1484067db0d7dab265b6063483ac67e9c5c8f Mon Sep 17 00:00:00 2001 From: May Date: Tue, 15 Nov 2022 22:36:53 +0100 Subject: [PATCH 20/49] Added space between avatar and username (#21825) Added space between avatar and username which is missing on verified commit message and avatar is too close to username which is don't look nice. Current state ![image](https://user-images.githubusercontent.com/3164256/202007728-d7d6ecac-f754-454c-a67f-e422f4aac5a5.png) This is how it looks after change ![image](https://user-images.githubusercontent.com/3164256/202007984-d4a38a1c-7c24-4278-aa0f-9aa51c10f772.png) Co-authored-by: zeripath Co-authored-by: silverwind Co-authored-by: techknowlogick --- templates/repo/commit_page.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index 8ece768832fb7..2dcd02ad98dfd 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -200,7 +200,7 @@ {{else}} {{.locale.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}} - {{avatar .Verification.SigningUser 28}} + {{avatar .Verification.SigningUser 28 "mr-3"}} {{.Verification.SigningUser.GetDisplayName}} {{else}} {{svg "gitea-lock-cog" 16 "mr-3"}} From af4a07091774cf0002e57c89d881af289796bb63 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 16 Nov 2022 19:14:58 +0800 Subject: [PATCH 21/49] Ignore issue template with a special name (#21830) A file in `ISSUE_TEMPLATE` with the name `config.yml` shouldn't be treated as a YAML template, it's for [configuring the template chooser](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser). The old code tried to ignore the file, but it didn't work, caused by #20987. That's why the warning is displayed: image Note that this PR is not an implementation of `config.yml`, there will be another one to do it. --- modules/structs/issue.go | 6 ++--- modules/structs/issue_test.go | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 modules/structs/issue_test.go diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 70f5e1ba8eaa1..25c6251fbf2d3 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -5,7 +5,7 @@ package structs import ( - "path/filepath" + "path" "time" ) @@ -163,11 +163,11 @@ const ( // Type returns the type of IssueTemplate, can be "md", "yaml" or empty for known func (it IssueTemplate) Type() IssueTemplateType { - if it.Name == "config.yaml" || it.Name == "config.yml" { + if base := path.Base(it.FileName); base == "config.yaml" || base == "config.yml" { // ignore config.yaml which is a special configuration file return "" } - if ext := filepath.Ext(it.FileName); ext == ".md" { + if ext := path.Ext(it.FileName); ext == ".md" { return IssueTemplateTypeMarkdown } else if ext == ".yaml" || ext == ".yml" { return IssueTemplateTypeYaml diff --git a/modules/structs/issue_test.go b/modules/structs/issue_test.go new file mode 100644 index 0000000000000..5312585d0f0f4 --- /dev/null +++ b/modules/structs/issue_test.go @@ -0,0 +1,43 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package structs + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIssueTemplate_Type(t *testing.T) { + tests := []struct { + fileName string + want IssueTemplateType + }{ + { + fileName: ".gitea/ISSUE_TEMPLATE/bug_report.yaml", + want: IssueTemplateTypeYaml, + }, + { + fileName: ".gitea/ISSUE_TEMPLATE/bug_report.md", + want: IssueTemplateTypeMarkdown, + }, + { + fileName: ".gitea/ISSUE_TEMPLATE/bug_report.txt", + want: "", + }, + { + fileName: ".gitea/ISSUE_TEMPLATE/config.yaml", + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.fileName, func(t *testing.T) { + it := IssueTemplate{ + FileName: tt.fileName, + } + assert.Equal(t, tt.want, it.Type()) + }) + } +} From d936168b3fc8c524d0f708ba820b225f9a1f0690 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 17 Nov 2022 02:04:09 +0100 Subject: [PATCH 22/49] Tweak katex options (#21828) - Render directly into DOM, skipping string conversion - Add limiting options to prevent excessive size/macros - Remove invalid `display` option previously passed Ref: https://katex.org/docs/options.html Co-authored-by: John Olheiser --- web_src/js/markup/math.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web_src/js/markup/math.js b/web_src/js/markup/math.js index 5790a327a51f6..d4e40d5be2e34 100644 --- a/web_src/js/markup/math.js +++ b/web_src/js/markup/math.js @@ -23,12 +23,14 @@ export async function renderMath() { for (const el of els) { const source = el.textContent; - const options = {display: el.classList.contains('display')}; + const nodeName = el.classList.contains('display') ? 'p' : 'span'; try { - const markup = katex.renderToString(source, options); - const tempEl = document.createElement(options.display ? 'p' : 'span'); - tempEl.innerHTML = markup; + const tempEl = document.createElement(nodeName); + katex.render(source, tempEl, { + maxSize: 25, + maxExpand: 50, + }); targetElement(el).replaceWith(tempEl); } catch (error) { displayError(el, error); From 296e4ce4089267ac961780d10a0d8869ce209488 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Thu, 17 Nov 2022 18:55:15 +0100 Subject: [PATCH 23/49] Fix setting HTTP headers after write (#21833) The headers can't be modified after it was send to the client. --- modules/context/context.go | 66 +++++++++++++++-------- routers/api/packages/rubygems/rubygems.go | 8 ++- routers/common/repo.go | 41 ++++++-------- routers/web/feed/profile.go | 2 - routers/web/web.go | 5 +- 5 files changed, 68 insertions(+), 54 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index 4b6a21b217c3b..697eb769045a1 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -34,6 +34,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/translation" + "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web/middleware" "code.gitea.io/gitea/services/auth" @@ -322,9 +323,9 @@ func (ctx *Context) plainTextInternal(skip, status int, bs []byte) { if statusPrefix == 4 || statusPrefix == 5 { log.Log(skip, log.TRACE, "plainTextInternal (status=%d): %s", status, string(bs)) } - ctx.Resp.WriteHeader(status) ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff") + ctx.Resp.WriteHeader(status) if _, err := ctx.Resp.Write(bs); err != nil { log.ErrorWithSkip(skip, "plainTextInternal (status=%d): write bytes failed: %v", status, err) } @@ -345,36 +346,55 @@ func (ctx *Context) RespHeader() http.Header { return ctx.Resp.Header() } +type ServeHeaderOptions struct { + ContentType string // defaults to "application/octet-stream" + ContentTypeCharset string + Disposition string // defaults to "attachment" + Filename string + CacheDuration time.Duration // defaults to 5 minutes +} + // SetServeHeaders sets necessary content serve headers -func (ctx *Context) SetServeHeaders(filename string) { - ctx.Resp.Header().Set("Content-Description", "File Transfer") - ctx.Resp.Header().Set("Content-Type", "application/octet-stream") - ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+filename) - ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary") - ctx.Resp.Header().Set("Expires", "0") - ctx.Resp.Header().Set("Cache-Control", "must-revalidate") - ctx.Resp.Header().Set("Pragma", "public") - ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition") +func (ctx *Context) SetServeHeaders(opts *ServeHeaderOptions) { + header := ctx.Resp.Header() + + contentType := typesniffer.ApplicationOctetStream + if opts.ContentType != "" { + if opts.ContentTypeCharset != "" { + contentType = opts.ContentType + "; charset=" + strings.ToLower(opts.ContentTypeCharset) + } else { + contentType = opts.ContentType + } + } + header.Set("Content-Type", contentType) + header.Set("X-Content-Type-Options", "nosniff") + + if opts.Filename != "" { + disposition := opts.Disposition + if disposition == "" { + disposition = "attachment" + } + + backslashEscapedName := strings.ReplaceAll(strings.ReplaceAll(opts.Filename, `\`, `\\`), `"`, `\"`) // \ -> \\, " -> \" + header.Set("Content-Disposition", fmt.Sprintf(`%s; filename="%s"; filename*=UTF-8''%s`, disposition, backslashEscapedName, url.PathEscape(opts.Filename))) + header.Set("Access-Control-Expose-Headers", "Content-Disposition") + } + + duration := opts.CacheDuration + if duration == 0 { + duration = 5 * time.Minute + } + httpcache.AddCacheControlToHeader(header, duration) } // ServeContent serves content to http request func (ctx *Context) ServeContent(name string, r io.ReadSeeker, modTime time.Time) { - ctx.SetServeHeaders(name) + ctx.SetServeHeaders(&ServeHeaderOptions{ + Filename: name, + }) http.ServeContent(ctx.Resp, ctx.Req, name, modTime, r) } -// ServeFile serves given file to response. -func (ctx *Context) ServeFile(file string, names ...string) { - var name string - if len(names) > 0 { - name = names[0] - } else { - name = path.Base(file) - } - ctx.SetServeHeaders(name) - http.ServeFile(ctx.Resp, ctx.Req, file) -} - // UploadStream returns the request body or the first form file // Only form files need to get closed. func (ctx *Context) UploadStream() (rd io.ReadCloser, needToClose bool, err error) { diff --git a/routers/api/packages/rubygems/rubygems.go b/routers/api/packages/rubygems/rubygems.go index eeae21146cbe8..4adfb15731bac 100644 --- a/routers/api/packages/rubygems/rubygems.go +++ b/routers/api/packages/rubygems/rubygems.go @@ -77,7 +77,9 @@ func enumeratePackages(ctx *context.Context, filename string, pvs []*packages_mo }) } - ctx.SetServeHeaders(filename + ".gz") + ctx.SetServeHeaders(&context.ServeHeaderOptions{ + Filename: filename + ".gz", + }) zw := gzip.NewWriter(ctx.Resp) defer zw.Close() @@ -115,7 +117,9 @@ func ServePackageSpecification(ctx *context.Context) { return } - ctx.SetServeHeaders(filename) + ctx.SetServeHeaders(&context.ServeHeaderOptions{ + Filename: filename, + }) zw := zlib.NewWriter(ctx.Resp) defer zw.Close() diff --git a/routers/common/repo.go b/routers/common/repo.go index a9e80fad48c8d..f4b813d6b490b 100644 --- a/routers/common/repo.go +++ b/routers/common/repo.go @@ -7,7 +7,6 @@ package common import ( "fmt" "io" - "net/url" "path" "path/filepath" "strings" @@ -53,50 +52,44 @@ func ServeData(ctx *context.Context, filePath string, size int64, reader io.Read buf = buf[:n] } - httpcache.AddCacheControlToHeader(ctx.Resp.Header(), 5*time.Minute) - if size >= 0 { ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", size)) } else { log.Error("ServeData called to serve data: %s with size < 0: %d", filePath, size) } - fileName := path.Base(filePath) + opts := &context.ServeHeaderOptions{ + Filename: path.Base(filePath), + } + sniffedType := typesniffer.DetectContentType(buf) isPlain := sniffedType.IsText() || ctx.FormBool("render") - mimeType := "" - charset := "" if setting.MimeTypeMap.Enabled { - fileExtension := strings.ToLower(filepath.Ext(fileName)) - mimeType = setting.MimeTypeMap.Map[fileExtension] + fileExtension := strings.ToLower(filepath.Ext(filePath)) + opts.ContentType = setting.MimeTypeMap.Map[fileExtension] } - if mimeType == "" { + if opts.ContentType == "" { if sniffedType.IsBrowsableBinaryType() { - mimeType = sniffedType.GetMimeType() + opts.ContentType = sniffedType.GetMimeType() } else if isPlain { - mimeType = "text/plain" + opts.ContentType = "text/plain" } else { - mimeType = typesniffer.ApplicationOctetStream + opts.ContentType = typesniffer.ApplicationOctetStream } } if isPlain { + var charset string charset, err = charsetModule.DetectEncoding(buf) if err != nil { log.Error("Detect raw file %s charset failed: %v, using by default utf-8", filePath, err) charset = "utf-8" } + opts.ContentTypeCharset = strings.ToLower(charset) } - if charset != "" { - ctx.Resp.Header().Set("Content-Type", mimeType+"; charset="+strings.ToLower(charset)) - } else { - ctx.Resp.Header().Set("Content-Type", mimeType) - } - ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff") - isSVG := sniffedType.IsSvgImage() // serve types that can present a security risk with CSP @@ -109,16 +102,12 @@ func ServeData(ctx *context.Context, filePath string, size int64, reader io.Read ctx.Resp.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'") } - disposition := "inline" + opts.Disposition = "inline" if isSVG && !setting.UI.SVG.Enabled { - disposition = "attachment" + opts.Disposition = "attachment" } - // encode filename per https://datatracker.ietf.org/doc/html/rfc5987 - encodedFileName := `filename*=UTF-8''` + url.PathEscape(fileName) - - ctx.Resp.Header().Set("Content-Disposition", disposition+"; "+encodedFileName) - ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition") + ctx.SetServeHeaders(opts) _, err = ctx.Resp.Write(buf) if err != nil { diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go index 0e11f210cefe9..ffa34572bced7 100644 --- a/routers/web/feed/profile.go +++ b/routers/web/feed/profile.go @@ -5,7 +5,6 @@ package feed import ( - "net/http" "time" activities_model "code.gitea.io/gitea/models/activities" @@ -59,7 +58,6 @@ func showUserFeed(ctx *context.Context, formatType string) { // writeFeed write a feeds.Feed as atom or rss to ctx.Resp func writeFeed(ctx *context.Context, feed *feeds.Feed, formatType string) { - ctx.Resp.WriteHeader(http.StatusOK) if formatType == "atom" { ctx.Resp.Header().Set("Content-Type", "application/atom+xml;charset=utf-8") if err := feed.WriteAtom(ctx.Resp); err != nil { diff --git a/routers/web/web.go b/routers/web/web.go index d0ee9c5eac0ca..5fefbad88a4f3 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -604,7 +604,10 @@ func RegisterRoutes(m *web.Route) { m.Group("", func() { m.Get("/favicon.ico", func(ctx *context.Context) { - ctx.ServeFile(path.Join(setting.StaticRootPath, "public/img/favicon.png")) + ctx.SetServeHeaders(&context.ServeHeaderOptions{ + Filename: "favicon.png", + }) + http.ServeFile(ctx.Resp, ctx.Req, path.Join(setting.StaticRootPath, "public/img/favicon.png")) }) m.Group("/{username}", func() { m.Get(".png", func(ctx *context.Context) { ctx.Error(http.StatusNotFound) }) From d459d0adca0d693378381edbd5347f89a768da10 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Thu, 17 Nov 2022 20:29:33 +0100 Subject: [PATCH 24/49] Do not allow Ghost access to limited visible user/org (#21849) The Ghost user should not be allowed to have access to a limited visible user/org. Co-authored-by: Lauris BH --- models/organization/org.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/models/organization/org.go b/models/organization/org.go index af9c1f307c012..6bb982b2814f3 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -458,8 +458,9 @@ func CountOrgs(opts FindOrgOptions) (int64, error) { // HasOrgOrUserVisible tells if the given user can see the given org or user func HasOrgOrUserVisible(ctx context.Context, orgOrUser, user *user_model.User) bool { - // Not SignedUser - if user == nil { + // If user is nil, it's an anonymous user/request. + // The Ghost user is handled like an anonymous user. + if user == nil || user.IsGhost() { return orgOrUser.Visibility == structs.VisibleTypePublic } From d8ef6ce6308c375f3f7679bed9fb1f3ffe525a43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Nov 2022 21:32:59 -0500 Subject: [PATCH 25/49] Bump loader-utils from 2.0.3 to 2.0.4 (#21852) Bumps [loader-utils](https://github.com/webpack/loader-utils) from 2.0.3 to 2.0.4.
Release notes

Sourced from loader-utils's releases.

v2.0.4

2.0.4 (2022-11-11)

Bug Fixes

Changelog

Sourced from loader-utils's changelog.

2.0.4 (2022-11-11)

Bug Fixes

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=loader-utils&package-manager=npm_and_yarn&previous-version=2.0.3&new-version=2.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/go-gitea/gitea/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf8d4b05e2fc0..d46d3a15cae58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6182,9 +6182,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz", - "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -14465,9 +14465,9 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" }, "loader-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz", - "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", From 8def28314abc3bfe839132de4234e91e1b3449b5 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 18 Nov 2022 14:34:39 +0800 Subject: [PATCH 26/49] Fix "build from source" document to clarify the `bindata` tag is required. (#21853) --- docs/content/doc/installation/from-source.en-us.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md index a6493598be235..01a5e1eaee8dc 100644 --- a/docs/content/doc/installation/from-source.en-us.md +++ b/docs/content/doc/installation/from-source.en-us.md @@ -94,7 +94,7 @@ are provided to keep the build process as simple as possible. Depending on requirements, the following build tags can be included. -- `bindata`: Build a single monolithic binary, with all assets included. +- `bindata`: Build a single monolithic binary, with all assets included. Required for production build. - `sqlite sqlite_unlock_notify`: Enable support for a [SQLite3](https://sqlite.org/) database. Suggested only for tiny installations. @@ -103,11 +103,10 @@ Depending on requirements, the following build tags can be included. available to PAM. - `gogit`: (EXPERIMENTAL) Use go-git variants of Git commands. -Bundling assets into the binary using the `bindata` build tag is recommended for -production deployments. It is possible to serve the static assets directly via a reverse proxy, -but in most cases it is not necessary, and assets should still be bundled in the binary. -You may want to exclude bindata while developing/testing Gitea. -To include assets, add the `bindata` tag: +Bundling all assets (JS/CSS/templates, etc) into the binary. Using the `bindata` build tag is required for +production deployments. You could exclude `bindata` when you are developing/testing Gitea or able to separate the assets correctly. + +To include all assets, use the `bindata` tag: ```bash TAGS="bindata" make build From 003ad304ee945e3b3c884cf49e8433491bf0412b Mon Sep 17 00:00:00 2001 From: Gusted Date: Fri, 18 Nov 2022 15:23:34 +0100 Subject: [PATCH 27/49] Prevent dangling user redirects (#21856) - It's possible that the `user_redirect` table contains a user id that no longer exists. - Delete a user redirect upon deleting the user. - Add a check for these dangling user redirects to check-db-consistency. --- models/user.go | 1 + modules/doctor/dbconsistency.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/models/user.go b/models/user.go index 85f465127aebd..0fc28ff055a7a 100644 --- a/models/user.go +++ b/models/user.go @@ -89,6 +89,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) &user_model.UserBadge{UserID: u.ID}, &pull_model.AutoMerge{DoerID: u.ID}, &pull_model.ReviewState{UserID: u.ID}, + &user_model.Redirect{RedirectUserID: u.ID}, ); err != nil { return fmt.Errorf("deleteBeans: %w", err) } diff --git a/modules/doctor/dbconsistency.go b/modules/doctor/dbconsistency.go index 7ae349908efb4..89d974a35002d 100644 --- a/modules/doctor/dbconsistency.go +++ b/modules/doctor/dbconsistency.go @@ -205,6 +205,9 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er // find stopwatches without existing issue genericOrphanCheck("Orphaned Stopwatches without existing Issue", "stopwatch", "issue", "stopwatch.issue_id=`issue`.id"), + // find redirects without existing user. + genericOrphanCheck("Orphaned Redirects without existing redirect user", + "user_redirect", "user", "user_redirect.redirect_user_id=`user`.id"), ) for _, c := range consistencyChecks { From 92697c8272122a6797e472f3489f4c92b8e65bb2 Mon Sep 17 00:00:00 2001 From: Percy Ma Date: Sat, 19 Nov 2022 01:01:06 +0800 Subject: [PATCH 28/49] chore: add webpack export type check (#21857) add webpack export type check Co-authored-by: techknowlogick --- webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.js b/webpack.config.js index 26632429929b9..4ad5d69bbf2f0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -47,6 +47,7 @@ const filterCssImport = (url, ...args) => { return true; }; +/** @type {import("webpack").Configuration} */ export default { mode: isProduction ? 'production' : 'development', entry: { From 7caa0b7f78e99a25e3684c7ad45f56e961b9e1f0 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 18 Nov 2022 18:54:32 +0100 Subject: [PATCH 29/49] Fix webpack license warning (#21815) #19999 introduced a indirect dependency with a license that was not on our allowlist yet which produced this warning during webpack: ```` WARNING in License: citeproc@2.4.62 has disallowed license CPAL-1.0 OR AGPL-1.0 ```` I've added both licenses to the allowed list and made it so webpack will now abort on such license errors so that we don't miss those next time. Co-authored-by: John Olheiser Co-authored-by: Lunny Xiao --- webpack.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index 4ad5d69bbf2f0..a8363051dfa2a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -229,7 +229,8 @@ export default { override: { 'jquery.are-you-sure@*': {licenseName: 'MIT'}, }, - allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC)', + emitError: true, + allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0)', ignore: [ 'font-awesome', ], From fbad0fcb1251735b232e7e7806a307ce9379d320 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 19 Nov 2022 05:02:30 +0100 Subject: [PATCH 30/49] Timeline and color tweaks (#21799) Followup to https://github.com/go-gitea/gitea/pull/21784. - Restore muted effect on timeline author and issuelist comment icon - Remove whitespace inside shared user templates, fixing link hover underline - Use shared author link template more - Use `bold` class instead of CSS - Fix grey-light color being too dark on arc-green - Add missing black-light color - Fix issuelist progress bar color - Fix various other cases of missing `.muted` Screenshot 2022-11-13 at 12 15 22 Screenshot 2022-11-13 at 12 16 52 Screenshot 2022-11-13 at 12 30 55 Screenshot 2022-11-13 at 12 41 03 Screenshot 2022-11-13 at 12 52 54 Screenshot 2022-11-13 at 12 56 16 Co-authored-by: Lauris BH Co-authored-by: techknowlogick Co-authored-by: wxiaoguang --- templates/explore/repo_list.tmpl | 6 +++--- templates/org/home.tmpl | 4 ++-- templates/repo/diff/comments.tmpl | 2 +- templates/repo/issue/view_content.tmpl | 4 ++-- .../repo/issue/view_content/comments.tmpl | 20 +++++++++---------- .../repo/issue/view_content/sidebar.tmpl | 2 +- templates/shared/issuelist.tmpl | 2 +- templates/shared/user/authorlink.tmpl | 4 +--- templates/shared/user/avatarlink.tmpl | 4 +--- templates/shared/user/namelink.tmpl | 4 +--- web_src/less/_base.less | 7 +++++-- web_src/less/_repository.less | 18 +++++++---------- web_src/less/shared/issuelist.less | 8 ++++++++ web_src/less/themes/theme-arc-green.less | 9 +++++---- 14 files changed, 47 insertions(+), 47 deletions(-) diff --git a/templates/explore/repo_list.tmpl b/templates/explore/repo_list.tmpl index 2a5c444dce2f1..044af9522e6e1 100644 --- a/templates/explore/repo_list.tmpl +++ b/templates/explore/repo_list.tmpl @@ -38,10 +38,10 @@ {{end}} -
+
{{if .PrimaryLanguage}} - - {{.PrimaryLanguage.Language}} + + {{.PrimaryLanguage.Language}} {{end}} {{if not $.DisableStars}} diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index 3ff86259d53f2..448639975f895 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -68,8 +68,8 @@ {{end}} diff --git a/templates/repo/diff/comments.tmpl b/templates/repo/diff/comments.tmpl index e5039ed6883de..3b84b3cea1f38 100644 --- a/templates/repo/diff/comments.tmpl +++ b/templates/repo/diff/comments.tmpl @@ -11,7 +11,7 @@
{{if .OriginalAuthor}} - + {{svg (MigrationIcon $.root.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index b63640af46ca1..15d04241b366e 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -30,7 +30,7 @@
{{if .Issue.OriginalAuthor}} - + {{svg (MigrationIcon .Repository.GetOriginalURLHostname)}} {{.Issue.OriginalAuthor}} @@ -45,7 +45,7 @@ {{avatar .Issue.Poster}} - {{.Issue.Poster.GetDisplayName}} + {{template "shared/user/authorlink" .Issue.Poster}} {{.locale.Tr "repo.issues.commented_at" (.Issue.HashTag|Escape) $createdStr | Safe}} {{end}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 938ec7e2bbef7..e126880bb70e4 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -25,7 +25,7 @@
{{if .OriginalAuthor}} - + {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} @@ -42,9 +42,7 @@ {{end}} - - {{.Poster.GetDisplayName}} - + {{template "shared/user/authorlink" .Poster}} {{$.locale.Tr "repo.issues.commented_at" (.HashTag|Escape) $createdStr | Safe}} {{end}} @@ -151,14 +149,14 @@ {{svg "octicon-bookmark"}} {{template "shared/user/avatarlink" .Poster}} {{if eq .RefAction 3}}{{end}} - + {{template "shared/user/authorlink" .Poster}} {{$.locale.Tr $refTr (.EventTag|Escape) $createdStr (.RefCommentHTMLURL|Escape) $refFrom | Safe}} {{if eq .RefAction 3}}{{end}}
{{else if eq .Type 4}} @@ -207,7 +205,7 @@ {{if .RemovedAssignee}} {{template "shared/user/avatarlink" .Assignee}} - {{.Assignee.GetDisplayName}} + {{template "shared/user/authorlink" .Assignee}} {{if eq .Poster.ID .Assignee.ID}} {{$.locale.Tr "repo.issues.remove_self_assignment" $createdStr | Safe}} {{else}} @@ -331,7 +329,7 @@
{{svg "octicon-plus"}} - + {{if eq .DependentIssue.RepoID .Issue.RepoID}} #{{.DependentIssue.Index}} {{.DependentIssue.Title}} {{else}} @@ -354,7 +352,7 @@
{{svg "octicon-trash"}} - + {{if eq .DependentIssue.RepoID .Issue.RepoID}} #{{.DependentIssue.Index}} {{.DependentIssue.Title}} {{else}} @@ -408,7 +406,7 @@
{{if .OriginalAuthor}} - + {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} @@ -536,7 +534,7 @@ {{end}} {{if .OriginalAuthor}} - + {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index eb95674b13d2e..af648387db58b 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -389,7 +389,7 @@ {{avatar $user}}
- {{$user.DisplayName}} + {{template "shared/user/authorlink" $user}}
{{$trackedtime}}
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl index 6fce412ffa140..e8ad8406cd2d5 100644 --- a/templates/shared/issuelist.tmpl +++ b/templates/shared/issuelist.tmpl @@ -160,7 +160,7 @@
{{if .NumComments}} - + {{svg "octicon-comment" 16 "mr-2"}}{{.NumComments}} {{end}} diff --git a/templates/shared/user/authorlink.tmpl b/templates/shared/user/authorlink.tmpl index 81c2a4ed5e508..4a6672181f43b 100644 --- a/templates/shared/user/authorlink.tmpl +++ b/templates/shared/user/authorlink.tmpl @@ -1,3 +1 @@ - - {{.GetDisplayName}} - +{{.GetDisplayName}} diff --git a/templates/shared/user/avatarlink.tmpl b/templates/shared/user/avatarlink.tmpl index 40f5ee71297fe..90f5d96700e30 100644 --- a/templates/shared/user/avatarlink.tmpl +++ b/templates/shared/user/avatarlink.tmpl @@ -1,3 +1 @@ - - {{avatar .}} - +{{avatar .}} diff --git a/templates/shared/user/namelink.tmpl b/templates/shared/user/namelink.tmpl index 25dff36a78802..a122f4f45b543 100644 --- a/templates/shared/user/namelink.tmpl +++ b/templates/shared/user/namelink.tmpl @@ -1,3 +1 @@ - - {{.GetDisplayName}} - +{{.GetDisplayName}} diff --git a/web_src/less/_base.less b/web_src/less/_base.less index dc0e69c6d1ba7..f2173d6d2b24f 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -79,6 +79,7 @@ --color-pink: #e03997; --color-brown: #a5673f; --color-grey: #888888; + --color-black: #1b1c1d; /* light variants - produced via Sass scale-color(color, $lightness: +25%) */ --color-red-light: #e45e5e; --color-orange-light: #f59555; @@ -92,9 +93,9 @@ --color-pink-light: #e86bb1; --color-brown-light: #c58b66; --color-grey-light: #a6a6a6; + --color-black-light: #525558; /* other colors */ --color-gold: #a1882b; - --color-black: #1b1c1d; --color-white: #ffffff; --color-diff-removed-word-bg: #fdb8c0; --color-diff-added-word-bg: #acf2bd; @@ -293,13 +294,15 @@ a, text-decoration-skip-ink: all; } -a.muted { +a.muted, +.muted-links a { color: inherit; } a:hover, a.muted:hover, a.muted:hover [class*="color-text"], +.muted-links a:hover, .ui.breadcrumb a:hover { color: var(--color-primary); } diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index bf1fb53e2b80e..63f1f954a0c9f 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -829,7 +829,7 @@ .timeline-avatar { position: absolute; - left: -72px; + left: -68px; img { width: 40px !important; @@ -846,7 +846,6 @@ .avatar img { width: 20px; height: 20px; - margin: 0 .25rem; vertical-align: middle; } @@ -981,10 +980,6 @@ margin-top: 4px; } - .author { - font-weight: 600; - } - .comment-form-reply .footer { padding-bottom: 1em; } @@ -1165,9 +1160,12 @@ padding-left: 15px; .detail { - font-size: .9rem; - margin-top: 5px; - margin-left: 8px; + margin-top: 4px; + margin-left: 14px; + + .svg { + margin-right: 2px; + } } .segments { @@ -2723,12 +2721,10 @@ a { color: var(--color-text); - text-decoration: none; } a:hover { color: var(--color-primary); - text-decoration: none; } } diff --git a/web_src/less/shared/issuelist.less b/web_src/less/shared/issuelist.less index 2dffe19909a28..8d4cfc46d491c 100644 --- a/web_src/less/shared/issuelist.less +++ b/web_src/less/shared/issuelist.less @@ -91,6 +91,14 @@ border-radius: 3px; vertical-align: 2px !important; } + + progress::-webkit-progress-value { + background-color: var(--color-secondary-dark-4); + } + + progress::-moz-progress-bar { + background-color: var(--color-secondary-dark-4); + } } .conflicting { diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index 370a866abb40e..b793f99509160 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -67,8 +67,9 @@ --color-purple: #b259d0; --color-pink: #d22e8b; --color-brown: #a47252; - --color-grey: #5e626a; - /* light variants */ + --color-grey: #9ea2aa; + --color-black: #1e222e; + /* light variants - produced via Sass scale-color(color, $lightness: -10%) */ --color-red-light: #c23636; --color-orange-light: #b84f0b; --color-yellow-light: #b88a03; @@ -80,9 +81,9 @@ --color-purple-light: #a742c9; --color-pink-light: #be297d; --color-brown-light: #94674a; - --color-grey-light: #55585f; + --color-grey-light: #8d919b; + --color-black-light: #1b1f29; /* other colors */ - --color-black: #1e222e; --color-gold: #b1983b; --color-white: #ffffff; --color-diff-removed-word-bg: #6f3333; From 82110fec7c1f33356f7faa9894e740eee2b3e008 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Sat, 19 Nov 2022 09:12:33 +0100 Subject: [PATCH 31/49] Add `context.Context` to more methods (#21546) This PR adds a context parameter to a bunch of methods. Some helper `xxxCtx()` methods got replaced with the normal name now. Co-authored-by: delvh Co-authored-by: Lunny Xiao --- cmd/admin.go | 2 +- models/activities/action.go | 18 +- models/activities/action_test.go | 10 +- models/activities/notification.go | 96 +++--- models/activities/notification_test.go | 8 +- models/db/consistency.go | 15 +- models/db/engine_test.go | 4 +- models/db/sequence.go | 5 +- models/fixture_generation.go | 2 +- models/git/protected_tag.go | 17 +- models/git/protected_tag_test.go | 19 +- models/issues/assignees.go | 9 +- models/issues/assignees_test.go | 10 +- models/issues/comment.go | 63 ++-- models/issues/comment_list.go | 30 +- models/issues/issue.go | 114 +++---- models/issues/issue_list.go | 38 +-- models/issues/issue_list_test.go | 3 +- models/issues/issue_project.go | 12 +- models/issues/issue_test.go | 4 +- models/issues/issue_xref.go | 2 +- models/issues/label.go | 44 +-- models/issues/label_test.go | 4 +- models/issues/pull.go | 66 ++-- models/issues/pull_list.go | 2 +- models/issues/pull_test.go | 30 +- models/issues/review.go | 20 +- models/issues/review_test.go | 2 +- models/org_team_test.go | 2 +- models/perm/access/access_test.go | 14 +- models/perm/access/repo_permission.go | 12 +- models/repo/attachment.go | 12 +- models/repo/pushmirror.go | 4 +- models/repo/release.go | 16 +- models/repo/repo.go | 24 +- models/repo/repo_list.go | 11 +- models/repo/repo_list_test.go | 18 +- models/repo/user_repo.go | 10 +- models/user/user.go | 12 +- models/user/user_test.go | 8 +- modules/convert/issue.go | 29 +- modules/convert/issue_comment.go | 27 +- modules/convert/pull.go | 6 +- modules/convert/pull_test.go | 9 +- modules/doctor/dbconsistency.go | 22 +- modules/indexer/issues/indexer.go | 18 +- modules/notification/action/action.go | 117 +++---- modules/notification/action/action_test.go | 3 +- modules/notification/base/notifier.go | 90 ++--- modules/notification/base/null.go | 92 ++--- modules/notification/indexer/indexer.go | 44 +-- modules/notification/mail/mail.go | 91 ++--- modules/notification/mirror/mirror.go | 14 +- modules/notification/notification.go | 180 +++++----- modules/notification/ui/ui.go | 47 +-- modules/notification/webhook/webhook.go | 321 +++++++----------- modules/repository/repo.go | 2 +- routers/api/packages/conan/conan.go | 2 +- routers/api/v1/misc/nodeinfo.go | 2 +- routers/api/v1/notify/repo.go | 8 +- routers/api/v1/notify/threads.go | 8 +- routers/api/v1/notify/user.go | 8 +- routers/api/v1/org/team.go | 8 +- routers/api/v1/repo/branch.go | 12 +- routers/api/v1/repo/fork.go | 2 +- routers/api/v1/repo/issue.go | 28 +- routers/api/v1/repo/issue_comment.go | 24 +- routers/api/v1/repo/issue_reaction.go | 4 +- routers/api/v1/repo/issue_tracked_time.go | 10 +- routers/api/v1/repo/migrate.go | 2 +- routers/api/v1/repo/pull.go | 52 +-- routers/api/v1/repo/pull_review.go | 4 +- routers/api/v1/repo/release.go | 8 +- routers/api/v1/repo/release_attachment.go | 2 +- routers/api/v1/repo/release_tags.go | 2 +- routers/api/v1/repo/repo.go | 4 +- routers/api/v1/repo/wiki.go | 6 +- routers/api/v1/user/repo.go | 6 +- routers/api/v1/user/star.go | 11 +- routers/api/v1/user/watch.go | 11 +- routers/private/hook_post_receive.go | 2 +- routers/private/hook_pre_receive.go | 4 +- routers/web/explore/repo.go | 2 +- routers/web/home.go | 2 +- routers/web/org/home.go | 2 +- routers/web/repo/branch.go | 8 +- routers/web/repo/compare.go | 4 +- routers/web/repo/issue.go | 60 ++-- routers/web/repo/issue_label.go | 2 +- routers/web/repo/projects.go | 4 +- routers/web/repo/pull.go | 30 +- routers/web/repo/pull_review.go | 4 +- routers/web/repo/release.go | 8 +- routers/web/repo/repo.go | 2 +- routers/web/repo/tag.go | 4 +- routers/web/repo/wiki.go | 6 +- routers/web/user/home.go | 6 +- routers/web/user/notification.go | 220 ++++++------ routers/web/user/profile.go | 6 +- services/agit/agit.go | 10 +- services/asymkey/sign.go | 2 +- services/automerge/automerge.go | 8 +- services/comments/comments.go | 34 +- services/issue/assignee.go | 10 +- services/issue/content.go | 3 +- services/issue/issue.go | 18 +- services/issue/label.go | 10 +- services/issue/milestone.go | 2 +- services/issue/status.go | 2 +- services/lfs/locks.go | 8 +- services/mailer/mail.go | 9 +- services/mailer/mail_issue.go | 20 +- services/mailer/mail_release.go | 2 +- services/mailer/mail_repo.go | 6 +- services/migrations/gitea_uploader_test.go | 12 +- services/mirror/mirror_pull.go | 8 +- services/packages/packages.go | 6 +- services/pull/check.go | 14 +- services/pull/commit_status.go | 4 +- services/pull/edits.go | 2 +- services/pull/merge.go | 36 +- services/pull/patch.go | 2 +- services/pull/pull.go | 48 +-- services/pull/pull_test.go | 13 +- services/pull/review.go | 18 +- services/pull/temp_repo.go | 4 +- services/pull/update.go | 8 +- services/release/release.go | 42 +-- services/release/release_test.go | 12 +- services/repository/adopt.go | 2 +- services/repository/branch.go | 5 +- services/repository/fork.go | 2 +- services/repository/push.go | 14 +- services/repository/repository.go | 4 +- services/repository/template.go | 2 +- services/repository/transfer.go | 6 +- services/task/migrate.go | 2 +- services/user/user.go | 2 +- services/webhook/webhook.go | 2 +- .../user/notification/notification_div.tmpl | 5 +- tests/integration/api_comment_test.go | 5 +- tests/integration/api_issue_reaction_test.go | 2 +- tests/integration/api_notification_test.go | 5 +- tests/integration/api_pull_commits_test.go | 9 +- tests/integration/api_pull_test.go | 5 +- tests/integration/eventsource_test.go | 3 +- tests/integration/pull_update_test.go | 8 +- tests/integration/repo_tag_test.go | 9 +- 148 files changed, 1408 insertions(+), 1561 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index d33d17a53ddf0..80b5d4853c077 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -727,7 +727,7 @@ func runRepoSyncReleases(_ *cli.Context) error { log.Trace("Synchronizing repository releases (this may take a while)") for page := 1; ; page++ { - repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: repo_model.RepositoryListDefaultPageSize, Page: page, diff --git a/models/activities/action.go b/models/activities/action.go index 5c3419c5ecf90..bbb6073265724 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -461,7 +461,8 @@ func DeleteOldActions(olderThan time.Duration) (err error) { return err } -func notifyWatchers(ctx context.Context, actions ...*Action) error { +// NotifyWatchers creates batch of actions for every watcher. +func NotifyWatchers(ctx context.Context, actions ...*Action) error { var watchers []*repo_model.Watch var repo *repo_model.Repository var err error @@ -565,11 +566,6 @@ func notifyWatchers(ctx context.Context, actions ...*Action) error { return nil } -// NotifyWatchers creates batch of actions for every watcher. -func NotifyWatchers(actions ...*Action) error { - return notifyWatchers(db.DefaultContext, actions...) -} - // NotifyWatchersActions creates batch of actions for every watcher. func NotifyWatchersActions(acts []*Action) error { ctx, committer, err := db.TxContext(db.DefaultContext) @@ -578,7 +574,7 @@ func NotifyWatchersActions(acts []*Action) error { } defer committer.Close() for _, act := range acts { - if err := notifyWatchers(ctx, act); err != nil { + if err := NotifyWatchers(ctx, act); err != nil { return err } } @@ -603,17 +599,17 @@ func DeleteIssueActions(ctx context.Context, repoID, issueID int64) error { } // CountActionCreatedUnixString count actions where created_unix is an empty string -func CountActionCreatedUnixString() (int64, error) { +func CountActionCreatedUnixString(ctx context.Context) (int64, error) { if setting.Database.UseSQLite3 { - return db.GetEngine(db.DefaultContext).Where(`created_unix = ""`).Count(new(Action)) + return db.GetEngine(ctx).Where(`created_unix = ""`).Count(new(Action)) } return 0, nil } // FixActionCreatedUnixString set created_unix to zero if it is an empty string -func FixActionCreatedUnixString() (int64, error) { +func FixActionCreatedUnixString(ctx context.Context) (int64, error) { if setting.Database.UseSQLite3 { - res, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`) + res, err := db.GetEngine(ctx).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`) if err != nil { return 0, err } diff --git a/models/activities/action_test.go b/models/activities/action_test.go index ac2a3043a6a27..b79eb0d08d06e 100644 --- a/models/activities/action_test.go +++ b/models/activities/action_test.go @@ -188,7 +188,7 @@ func TestNotifyWatchers(t *testing.T) { RepoID: 1, OpType: activities_model.ActionStarRepo, } - assert.NoError(t, activities_model.NotifyWatchers(action)) + assert.NoError(t, activities_model.NotifyWatchers(db.DefaultContext, action)) // One watchers are inactive, thus action is only created for user 8, 1, 4, 11 unittest.AssertExistsAndLoadBean(t, &activities_model.Action{ @@ -256,17 +256,17 @@ func TestConsistencyUpdateAction(t *testing.T) { // // Get rid of incorrectly set created_unix // - count, err := activities_model.CountActionCreatedUnixString() + count, err := activities_model.CountActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 1, count) - count, err = activities_model.FixActionCreatedUnixString() + count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 1, count) - count, err = activities_model.CountActionCreatedUnixString() + count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 0, count) - count, err = activities_model.FixActionCreatedUnixString() + count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) assert.NoError(t, err) assert.EqualValues(t, 0, count) diff --git a/models/activities/notification.go b/models/activities/notification.go index 28adc8cc4efa1..10b3a76713572 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -136,49 +136,41 @@ func GetNotifications(ctx context.Context, options *FindNotificationOptions) (nl } // CountNotifications count all notifications that fit to the given options and ignore pagination. -func CountNotifications(opts *FindNotificationOptions) (int64, error) { - return db.GetEngine(db.DefaultContext).Where(opts.ToCond()).Count(&Notification{}) +func CountNotifications(ctx context.Context, opts *FindNotificationOptions) (int64, error) { + return db.GetEngine(ctx).Where(opts.ToCond()).Count(&Notification{}) } // CreateRepoTransferNotification creates notification for the user a repository was transferred to -func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_model.Repository) error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - var notify []*Notification +func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { + return db.AutoTx(ctx, func(ctx context.Context) error { + var notify []*Notification - if newOwner.IsOrganization() { - users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID) - if err != nil || len(users) == 0 { - return err - } - for i := range users { - notify = append(notify, &Notification{ - UserID: users[i].ID, + if newOwner.IsOrganization() { + users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID) + if err != nil || len(users) == 0 { + return err + } + for i := range users { + notify = append(notify, &Notification{ + UserID: users[i].ID, + RepoID: repo.ID, + Status: NotificationStatusUnread, + UpdatedBy: doer.ID, + Source: NotificationSourceRepository, + }) + } + } else { + notify = []*Notification{{ + UserID: newOwner.ID, RepoID: repo.ID, Status: NotificationStatusUnread, UpdatedBy: doer.ID, Source: NotificationSourceRepository, - }) + }} } - } else { - notify = []*Notification{{ - UserID: newOwner.ID, - RepoID: repo.ID, - Status: NotificationStatusUnread, - UpdatedBy: doer.ID, - Source: NotificationSourceRepository, - }} - } - - if err := db.Insert(ctx, notify); err != nil { - return err - } - return committer.Commit() + return db.Insert(ctx, notify) + }) } // CreateOrUpdateIssueNotifications creates an issue notification @@ -379,11 +371,7 @@ func CountUnread(ctx context.Context, userID int64) int64 { } // LoadAttributes load Repo Issue User and Comment if not loaded -func (n *Notification) LoadAttributes() (err error) { - return n.loadAttributes(db.DefaultContext) -} - -func (n *Notification) loadAttributes(ctx context.Context) (err error) { +func (n *Notification) LoadAttributes(ctx context.Context) (err error) { if err = n.loadRepo(ctx); err != nil { return } @@ -481,10 +469,10 @@ func (n *Notification) APIURL() string { type NotificationList []*Notification // LoadAttributes load Repo Issue User and Comment if not loaded -func (nl NotificationList) LoadAttributes() error { +func (nl NotificationList) LoadAttributes(ctx context.Context) error { var err error for i := 0; i < len(nl); i++ { - err = nl[i].LoadAttributes() + err = nl[i].LoadAttributes(ctx) if err != nil && !issues_model.IsErrCommentNotExist(err) { return err } @@ -504,7 +492,7 @@ func (nl NotificationList) getPendingRepoIDs() []int64 { } // LoadRepos loads repositories from database -func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error) { +func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { if len(nl) == 0 { return repo_model.RepositoryList{}, []int{}, nil } @@ -517,7 +505,7 @@ func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error) if left < limit { limit = left } - rows, err := db.GetEngine(db.DefaultContext). + rows, err := db.GetEngine(ctx). In("id", repoIDs[:limit]). Rows(new(repo_model.Repository)) if err != nil { @@ -578,7 +566,7 @@ func (nl NotificationList) getPendingIssueIDs() []int64 { } // LoadIssues loads issues from database -func (nl NotificationList) LoadIssues() ([]int, error) { +func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { if len(nl) == 0 { return []int{}, nil } @@ -591,7 +579,7 @@ func (nl NotificationList) LoadIssues() ([]int, error) { if left < limit { limit = left } - rows, err := db.GetEngine(db.DefaultContext). + rows, err := db.GetEngine(ctx). In("id", issueIDs[:limit]). Rows(new(issues_model.Issue)) if err != nil { @@ -662,7 +650,7 @@ func (nl NotificationList) getPendingCommentIDs() []int64 { } // LoadComments loads comments from database -func (nl NotificationList) LoadComments() ([]int, error) { +func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { if len(nl) == 0 { return []int{}, nil } @@ -675,7 +663,7 @@ func (nl NotificationList) LoadComments() ([]int, error) { if left < limit { limit = left } - rows, err := db.GetEngine(db.DefaultContext). + rows, err := db.GetEngine(ctx). In("id", commentIDs[:limit]). Rows(new(issues_model.Comment)) if err != nil { @@ -775,8 +763,8 @@ func SetRepoReadBy(ctx context.Context, userID, repoID int64) error { } // SetNotificationStatus change the notification status -func SetNotificationStatus(notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) { - notification, err := getNotificationByID(db.DefaultContext, notificationID) +func SetNotificationStatus(ctx context.Context, notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) { + notification, err := GetNotificationByID(ctx, notificationID) if err != nil { return notification, err } @@ -787,16 +775,12 @@ func SetNotificationStatus(notificationID int64, user *user_model.User, status N notification.Status = status - _, err = db.GetEngine(db.DefaultContext).ID(notificationID).Update(notification) + _, err = db.GetEngine(ctx).ID(notificationID).Update(notification) return notification, err } // GetNotificationByID return notification by ID -func GetNotificationByID(notificationID int64) (*Notification, error) { - return getNotificationByID(db.DefaultContext, notificationID) -} - -func getNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) { +func GetNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) { notification := new(Notification) ok, err := db.GetEngine(ctx). Where("id = ?", notificationID). @@ -813,9 +797,9 @@ func getNotificationByID(ctx context.Context, notificationID int64) (*Notificati } // UpdateNotificationStatuses updates the statuses of all of a user's notifications that are of the currentStatus type to the desiredStatus -func UpdateNotificationStatuses(user *user_model.User, currentStatus, desiredStatus NotificationStatus) error { +func UpdateNotificationStatuses(ctx context.Context, user *user_model.User, currentStatus, desiredStatus NotificationStatus) error { n := &Notification{Status: desiredStatus, UpdatedBy: user.ID} - _, err := db.GetEngine(db.DefaultContext). + _, err := db.GetEngine(ctx). Where("user_id = ? AND status = ?", user.ID, currentStatus). Cols("status", "updated_by", "updated_unix"). Update(n) diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index 4ee16af076e5a..d871891001a02 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -82,14 +82,14 @@ func TestSetNotificationStatus(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead}) - _, err := activities_model.SetNotificationStatus(notf.ID, user, activities_model.NotificationStatusPinned) + _, err := activities_model.SetNotificationStatus(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned}) - _, err = activities_model.SetNotificationStatus(1, user, activities_model.NotificationStatusRead) + _, err = activities_model.SetNotificationStatus(db.DefaultContext, 1, user, activities_model.NotificationStatusRead) assert.Error(t, err) - _, err = activities_model.SetNotificationStatus(unittest.NonexistentID, user, activities_model.NotificationStatusRead) + _, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead) assert.Error(t, err) } @@ -102,7 +102,7 @@ func TestUpdateNotificationStatuses(t *testing.T) { &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead}) notfPinned := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned}) - assert.NoError(t, activities_model.UpdateNotificationStatuses(user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) + assert.NoError(t, activities_model.UpdateNotificationStatuses(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead}) unittest.AssertExistsAndLoadBean(t, diff --git a/models/db/consistency.go b/models/db/consistency.go index 7addb174c4a43..5a7878c74dd6e 100644 --- a/models/db/consistency.go +++ b/models/db/consistency.go @@ -4,11 +4,16 @@ package db -import "xorm.io/builder" +import ( + "context" + + "xorm.io/builder" +) // CountOrphanedObjects count subjects with have no existing refobject anymore -func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) { - return GetEngine(DefaultContext).Table("`"+subject+"`"). +func CountOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) (int64, error) { + return GetEngine(ctx). + Table("`"+subject+"`"). Join("LEFT", "`"+refobject+"`", joinCond). Where(builder.IsNull{"`" + refobject + "`.id"}). Select("COUNT(`" + subject + "`.`id`)"). @@ -16,12 +21,12 @@ func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) { } // DeleteOrphanedObjects delete subjects with have no existing refobject anymore -func DeleteOrphanedObjects(subject, refobject, joinCond string) error { +func DeleteOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) error { subQuery := builder.Select("`"+subject+"`.id"). From("`"+subject+"`"). Join("LEFT", "`"+refobject+"`", joinCond). Where(builder.IsNull{"`" + refobject + "`.id"}) b := builder.Delete(builder.In("id", subQuery)).From("`" + subject + "`") - _, err := GetEngine(DefaultContext).Exec(b) + _, err := GetEngine(ctx).Exec(b) return err } diff --git a/models/db/engine_test.go b/models/db/engine_test.go index c26d94c3405e7..c2ba9614aa4ff 100644 --- a/models/db/engine_test.go +++ b/models/db/engine_test.go @@ -41,11 +41,11 @@ func TestDeleteOrphanedObjects(t *testing.T) { _, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) assert.NoError(t, err) - orphaned, err := db.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) assert.EqualValues(t, 3, orphaned) - err = db.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) diff --git a/models/db/sequence.go b/models/db/sequence.go index 48e4a8f1ac41b..0daacee70c316 100644 --- a/models/db/sequence.go +++ b/models/db/sequence.go @@ -5,6 +5,7 @@ package db import ( + "context" "fmt" "regexp" @@ -12,7 +13,7 @@ import ( ) // CountBadSequences looks for broken sequences from recreate-table mistakes -func CountBadSequences() (int64, error) { +func CountBadSequences(_ context.Context) (int64, error) { if !setting.Database.UsePostgreSQL { return 0, nil } @@ -33,7 +34,7 @@ func CountBadSequences() (int64, error) { } // FixBadSequences fixes for broken sequences from recreate-table mistakes -func FixBadSequences() error { +func FixBadSequences(_ context.Context) error { if !setting.Database.UsePostgreSQL { return nil } diff --git a/models/fixture_generation.go b/models/fixture_generation.go index f4644859eb63e..50b983fa82072 100644 --- a/models/fixture_generation.go +++ b/models/fixture_generation.go @@ -22,7 +22,7 @@ func GetYamlFixturesAccess() (string, error) { } for _, repo := range repos { - repo.MustOwner() + repo.MustOwner(db.DefaultContext) if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil { return "", err } diff --git a/models/git/protected_tag.go b/models/git/protected_tag.go index 7c3881643de7e..4640a77b20f81 100644 --- a/models/git/protected_tag.go +++ b/models/git/protected_tag.go @@ -5,6 +5,7 @@ package git import ( + "context" "regexp" "strings" @@ -69,13 +70,13 @@ func UpdateProtectedTag(pt *ProtectedTag) error { } // DeleteProtectedTag deletes a protected tag by ID -func DeleteProtectedTag(pt *ProtectedTag) error { - _, err := db.GetEngine(db.DefaultContext).ID(pt.ID).Delete(&ProtectedTag{}) +func DeleteProtectedTag(ctx context.Context, pt *ProtectedTag) error { + _, err := db.GetEngine(ctx).ID(pt.ID).Delete(&ProtectedTag{}) return err } // IsUserAllowedModifyTag returns true if the user is allowed to modify the tag -func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) { +func IsUserAllowedModifyTag(ctx context.Context, pt *ProtectedTag, userID int64) (bool, error) { if base.Int64sContains(pt.AllowlistUserIDs, userID) { return true, nil } @@ -84,7 +85,7 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) { return false, nil } - in, err := organization.IsUserInTeams(db.DefaultContext, userID, pt.AllowlistTeamIDs) + in, err := organization.IsUserInTeams(ctx, userID, pt.AllowlistTeamIDs) if err != nil { return false, err } @@ -92,9 +93,9 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) { } // GetProtectedTags gets all protected tags of the repository -func GetProtectedTags(repoID int64) ([]*ProtectedTag, error) { +func GetProtectedTags(ctx context.Context, repoID int64) ([]*ProtectedTag, error) { tags := make([]*ProtectedTag, 0) - return tags, db.GetEngine(db.DefaultContext).Find(&tags, &ProtectedTag{RepoID: repoID}) + return tags, db.GetEngine(ctx).Find(&tags, &ProtectedTag{RepoID: repoID}) } // GetProtectedTagByID gets the protected tag with the specific id @@ -112,7 +113,7 @@ func GetProtectedTagByID(id int64) (*ProtectedTag, error) { // IsUserAllowedToControlTag checks if a user can control the specific tag. // It returns true if the tag name is not protected or the user is allowed to control it. -func IsUserAllowedToControlTag(tags []*ProtectedTag, tagName string, userID int64) (bool, error) { +func IsUserAllowedToControlTag(ctx context.Context, tags []*ProtectedTag, tagName string, userID int64) (bool, error) { isAllowed := true for _, tag := range tags { err := tag.EnsureCompiledPattern() @@ -124,7 +125,7 @@ func IsUserAllowedToControlTag(tags []*ProtectedTag, tagName string, userID int6 continue } - isAllowed, err = IsUserAllowedModifyTag(tag, userID) + isAllowed, err = IsUserAllowedModifyTag(ctx, tag, userID) if err != nil { return false, err } diff --git a/models/git/protected_tag_test.go b/models/git/protected_tag_test.go index b496688b253f4..352eed00603da 100644 --- a/models/git/protected_tag_test.go +++ b/models/git/protected_tag_test.go @@ -7,6 +7,7 @@ package git_test import ( "testing" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/models/unittest" @@ -17,29 +18,29 @@ func TestIsUserAllowed(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pt := &git_model.ProtectedTag{} - allowed, err := git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err := git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.False(t, allowed) pt = &git_model.ProtectedTag{ AllowlistUserIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.True(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) assert.NoError(t, err) assert.False(t, allowed) pt = &git_model.ProtectedTag{ AllowlistTeamIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.False(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) assert.NoError(t, err) assert.True(t, allowed) @@ -47,11 +48,11 @@ func TestIsUserAllowed(t *testing.T) { AllowlistUserIDs: []int64{1}, AllowlistTeamIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) assert.NoError(t, err) assert.True(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) assert.NoError(t, err) assert.True(t, allowed) } @@ -135,7 +136,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) { } for n, c := range cases { - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, c.name, c.userid) + isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) assert.NoError(t, err) assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n) } @@ -157,7 +158,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) { } for n, c := range cases { - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, c.name, c.userid) + isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) assert.NoError(t, err) assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n) } diff --git a/models/issues/assignees.go b/models/issues/assignees.go index ce497b116dec1..19480fa1e1f70 100644 --- a/models/issues/assignees.go +++ b/models/issues/assignees.go @@ -48,9 +48,10 @@ func (issue *Issue) LoadAssignees(ctx context.Context) (err error) { // GetAssigneeIDsByIssue returns the IDs of users assigned to an issue // but skips joining with `user` for performance reasons. // User permissions must be verified elsewhere if required. -func GetAssigneeIDsByIssue(issueID int64) ([]int64, error) { +func GetAssigneeIDsByIssue(ctx context.Context, issueID int64) ([]int64, error) { userIDs := make([]int64, 0, 5) - return userIDs, db.GetEngine(db.DefaultContext).Table("issue_assignees"). + return userIDs, db.GetEngine(ctx). + Table("issue_assignees"). Cols("assignee_id"). Where("issue_id = ?", issueID). Distinct("assignee_id"). @@ -151,7 +152,7 @@ func toggleUserAssignee(ctx context.Context, issue *Issue, assigneeID int64) (re } // MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs -func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) { +func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) { var requestAssignees []string // Keeping the old assigning method for compatibility reasons @@ -165,7 +166,7 @@ func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string } // Get the IDs of all assignees - assigneeIDs, err = user_model.GetUserIDsByNames(requestAssignees, false) + assigneeIDs, err = user_model.GetUserIDsByNames(ctx, requestAssignees, false) return assigneeIDs, err } diff --git a/models/issues/assignees_test.go b/models/issues/assignees_test.go index 291bb673da84b..4286bdd7eebe7 100644 --- a/models/issues/assignees_test.go +++ b/models/issues/assignees_test.go @@ -71,22 +71,22 @@ func TestMakeIDsFromAPIAssigneesToAdd(t *testing.T) { _ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) _ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{""}) + IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{""}) assert.NoError(t, err) assert.Equal(t, []int64{}, IDs) - _, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"none_existing_user"}) + _, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"none_existing_user"}) assert.Error(t, err) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("user1", []string{"user1"}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user1", []string{"user1"}) assert.NoError(t, err) assert.Equal(t, []int64{1}, IDs) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("user2", []string{""}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user2", []string{""}) assert.NoError(t, err) assert.Equal(t, []int64{2}, IDs) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"user1", "user2"}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"user1", "user2"}) assert.NoError(t, err) assert.Equal(t, []int64{1, 2}, IDs) } diff --git a/models/issues/comment.go b/models/issues/comment.go index d71c675d23472..9483814a19e04 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -309,13 +309,8 @@ type PushActionContent struct { CommitIDs []string `json:"commit_ids"` } -// LoadIssue loads issue from database -func (c *Comment) LoadIssue() (err error) { - return c.LoadIssueCtx(db.DefaultContext) -} - -// LoadIssueCtx loads issue from database -func (c *Comment) LoadIssueCtx(ctx context.Context) (err error) { +// LoadIssue loads the issue reference for the comment +func (c *Comment) LoadIssue(ctx context.Context) (err error) { if c.Issue != nil { return nil } @@ -350,7 +345,8 @@ func (c *Comment) AfterLoad(session *xorm.Session) { } } -func (c *Comment) loadPoster(ctx context.Context) (err error) { +// LoadPoster loads comment poster +func (c *Comment) LoadPoster(ctx context.Context) (err error) { if c.PosterID <= 0 || c.Poster != nil { return nil } @@ -381,7 +377,7 @@ func (c *Comment) AfterDelete() { // HTMLURL formats a URL-string to the issue-comment func (c *Comment) HTMLURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -410,7 +406,7 @@ func (c *Comment) HTMLURL() string { // APIURL formats a API-string to the issue-comment func (c *Comment) APIURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -426,7 +422,7 @@ func (c *Comment) APIURL() string { // IssueURL formats a URL-string to the issue func (c *Comment) IssueURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -446,7 +442,7 @@ func (c *Comment) IssueURL() string { // PRURL formats a URL-string to the pull-request func (c *Comment) PRURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -521,10 +517,10 @@ func (c *Comment) LoadProject() error { } // LoadMilestone if comment.Type is CommentTypeMilestone, then load milestone -func (c *Comment) LoadMilestone() error { +func (c *Comment) LoadMilestone(ctx context.Context) error { if c.OldMilestoneID > 0 { var oldMilestone Milestone - has, err := db.GetEngine(db.DefaultContext).ID(c.OldMilestoneID).Get(&oldMilestone) + has, err := db.GetEngine(ctx).ID(c.OldMilestoneID).Get(&oldMilestone) if err != nil { return err } else if has { @@ -534,7 +530,7 @@ func (c *Comment) LoadMilestone() error { if c.MilestoneID > 0 { var milestone Milestone - has, err := db.GetEngine(db.DefaultContext).ID(c.MilestoneID).Get(&milestone) + has, err := db.GetEngine(ctx).ID(c.MilestoneID).Get(&milestone) if err != nil { return err } else if has { @@ -544,19 +540,14 @@ func (c *Comment) LoadMilestone() error { return nil } -// LoadPoster loads comment poster -func (c *Comment) LoadPoster() error { - return c.loadPoster(db.DefaultContext) -} - // LoadAttachments loads attachments (it never returns error, the error during `GetAttachmentsByCommentIDCtx` is ignored) -func (c *Comment) LoadAttachments() error { +func (c *Comment) LoadAttachments(ctx context.Context) error { if len(c.Attachments) > 0 { return nil } var err error - c.Attachments, err = repo_model.GetAttachmentsByCommentID(db.DefaultContext, c.ID) + c.Attachments, err = repo_model.GetAttachmentsByCommentID(ctx, c.ID) if err != nil { log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err) } @@ -598,7 +589,7 @@ func (c *Comment) LoadAssigneeUserAndTeam() error { c.Assignee = user_model.NewGhostUser() } } else if c.AssigneeTeamID > 0 && c.AssigneeTeam == nil { - if err = c.LoadIssue(); err != nil { + if err = c.LoadIssue(db.DefaultContext); err != nil { return err } @@ -740,7 +731,7 @@ func (c *Comment) UnsignedLine() uint64 { // CodeCommentURL returns the url to a comment in code func (c *Comment) CodeCommentURL() string { - err := c.LoadIssue() + err := c.LoadIssue(db.DefaultContext) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -1145,7 +1136,7 @@ func UpdateComment(c *Comment, doer *user_model.User) error { if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil { return err } - if err := c.LoadIssueCtx(ctx); err != nil { + if err := c.LoadIssue(ctx); err != nil { return err } if err := c.AddCrossReferences(ctx, doer, true); err != nil { @@ -1245,7 +1236,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu return nil, err } - if err := CommentList(comments).loadPosters(ctx); err != nil { + if err := CommentList(comments).LoadPosters(ctx); err != nil { return nil, err } @@ -1363,11 +1354,11 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge { return nil, fmt.Errorf("comment type %d cannot be used to create an auto merge comment", typ) } - if err = pr.LoadIssueCtx(ctx); err != nil { + if err = pr.LoadIssue(ctx); err != nil { return } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return } @@ -1512,18 +1503,18 @@ func (c *Comment) GetExternalName() string { return c.OriginalAuthor } func (c *Comment) GetExternalID() int64 { return c.OriginalAuthorID } // CountCommentTypeLabelWithEmptyLabel count label comments with empty label -func CountCommentTypeLabelWithEmptyLabel() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment)) +func CountCommentTypeLabelWithEmptyLabel(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment)) } // FixCommentTypeLabelWithEmptyLabel count label comments with empty label -func FixCommentTypeLabelWithEmptyLabel() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment)) +func FixCommentTypeLabelWithEmptyLabel(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment)) } // CountCommentTypeLabelWithOutsideLabels count label comments with outside label -func CountCommentTypeLabelWithOutsideLabels() (int64, error) { - return db.GetEngine(db.DefaultContext).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel). +func CountCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel). Table("comment"). Join("inner", "label", "label.id = comment.label_id"). Join("inner", "issue", "issue.id = comment.issue_id "). @@ -1532,8 +1523,8 @@ func CountCommentTypeLabelWithOutsideLabels() (int64, error) { } // FixCommentTypeLabelWithOutsideLabels count label comments with outside label -func FixCommentTypeLabelWithOutsideLabels() (int64, error) { - res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM comment WHERE comment.id IN ( +func FixCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) { + res, err := db.GetEngine(ctx).Exec(`DELETE FROM comment WHERE comment.id IN ( SELECT il_too.id FROM ( SELECT com.id FROM comment AS com diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index 70105d7ff056e..e42b8605f94e2 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -24,7 +24,8 @@ func (comments CommentList) getPosterIDs() []int64 { return posterIDs.Values() } -func (comments CommentList) loadPosters(ctx context.Context) error { +// LoadPosters loads posters +func (comments CommentList) LoadPosters(ctx context.Context) error { if len(comments) == 0 { return nil } @@ -277,7 +278,8 @@ func (comments CommentList) Issues() IssueList { return issueList } -func (comments CommentList) loadIssues(ctx context.Context) error { +// LoadIssues loads issues of comments +func (comments CommentList) LoadIssues(ctx context.Context) error { if len(comments) == 0 { return nil } @@ -382,7 +384,8 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error { return nil } -func (comments CommentList) loadAttachments(ctx context.Context) (err error) { +// LoadAttachments loads attachments +func (comments CommentList) LoadAttachments(ctx context.Context) (err error) { if len(comments) == 0 { return nil } @@ -476,7 +479,7 @@ func (comments CommentList) loadReviews(ctx context.Context) error { //nolint // loadAttributes loads all attributes func (comments CommentList) loadAttributes(ctx context.Context) (err error) { - if err = comments.loadPosters(ctx); err != nil { + if err = comments.LoadPosters(ctx); err != nil { return } @@ -496,7 +499,7 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { return } - if err = comments.loadAttachments(ctx); err != nil { + if err = comments.LoadAttachments(ctx); err != nil { return } @@ -504,7 +507,7 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { return } - if err = comments.loadIssues(ctx); err != nil { + if err = comments.LoadIssues(ctx); err != nil { return } @@ -520,18 +523,3 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) { func (comments CommentList) LoadAttributes() error { return comments.loadAttributes(db.DefaultContext) } - -// LoadAttachments loads attachments -func (comments CommentList) LoadAttachments() error { - return comments.loadAttachments(db.DefaultContext) -} - -// LoadPosters loads posters -func (comments CommentList) LoadPosters() error { - return comments.loadPosters(db.DefaultContext) -} - -// LoadIssues loads issues of comments -func (comments CommentList) LoadIssues() error { - return comments.loadIssues(db.DefaultContext) -} diff --git a/models/issues/issue.go b/models/issues/issue.go index c2f7cb6578006..69d6657d46454 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -241,11 +241,7 @@ func (issue *Issue) LoadLabels(ctx context.Context) (err error) { } // LoadPoster loads poster -func (issue *Issue) LoadPoster() error { - return issue.loadPoster(db.DefaultContext) -} - -func (issue *Issue) loadPoster(ctx context.Context) (err error) { +func (issue *Issue) LoadPoster(ctx context.Context) (err error) { if issue.Poster == nil { issue.Poster, err = user_model.GetUserByIDCtx(ctx, issue.PosterID) if err != nil { @@ -261,7 +257,8 @@ func (issue *Issue) loadPoster(ctx context.Context) (err error) { return err } -func (issue *Issue) loadPullRequest(ctx context.Context) (err error) { +// LoadPullRequest loads pull request info +func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) { if issue.IsPull && issue.PullRequest == nil { issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID) if err != nil { @@ -275,18 +272,13 @@ func (issue *Issue) loadPullRequest(ctx context.Context) (err error) { return nil } -// LoadPullRequest loads pull request info -func (issue *Issue) LoadPullRequest() error { - return issue.loadPullRequest(db.DefaultContext) -} - func (issue *Issue) loadComments(ctx context.Context) (err error) { return issue.loadCommentsByType(ctx, CommentTypeUnknown) } // LoadDiscussComments loads discuss comments -func (issue *Issue) LoadDiscussComments() error { - return issue.loadCommentsByType(db.DefaultContext, CommentTypeComment) +func (issue *Issue) LoadDiscussComments(ctx context.Context) error { + return issue.loadCommentsByType(ctx, CommentTypeComment) } func (issue *Issue) loadCommentsByType(ctx context.Context, tp CommentType) (err error) { @@ -357,7 +349,8 @@ func (issue *Issue) loadForeignReference(ctx context.Context) (err error) { return nil } -func (issue *Issue) loadMilestone(ctx context.Context) (err error) { +// LoadMilestone load milestone of this issue. +func (issue *Issue) LoadMilestone(ctx context.Context) (err error) { if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 { issue.Milestone, err = GetMilestoneByRepoID(ctx, issue.RepoID, issue.MilestoneID) if err != nil && !IsErrMilestoneNotExist(err) { @@ -373,7 +366,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadPoster(ctx); err != nil { + if err = issue.LoadPoster(ctx); err != nil { return } @@ -381,7 +374,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadMilestone(ctx); err != nil { + if err = issue.LoadMilestone(ctx); err != nil { return } @@ -393,7 +386,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return } - if err = issue.loadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) { + if err = issue.LoadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) { // It is possible pull request is not yet created. return err } @@ -425,11 +418,6 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { return issue.loadReactions(ctx) } -// LoadMilestone load milestone of this issue. -func (issue *Issue) LoadMilestone() error { - return issue.loadMilestone(db.DefaultContext) -} - // GetIsRead load the `IsRead` field of the issue func (issue *Issue) GetIsRead(userID int64) error { issueUser := &IssueUser{IssueID: issue.ID, UID: userID} @@ -548,7 +536,7 @@ func ClearIssueLabels(issue *Issue, doer *user_model.User) (err error) { if err := issue.LoadRepo(ctx); err != nil { return err - } else if err = issue.loadPullRequest(ctx); err != nil { + } else if err = issue.LoadPullRequest(ctx); err != nil { return err } @@ -751,7 +739,7 @@ func ChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, if err := issue.LoadRepo(ctx); err != nil { return nil, err } - if err := issue.loadPoster(ctx); err != nil { + if err := issue.LoadPoster(ctx); err != nil { return nil, err } @@ -1027,7 +1015,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue return fmt.Errorf("find all labels [label_ids: %v]: %w", opts.LabelIDs, err) } - if err = opts.Issue.loadPoster(ctx); err != nil { + if err = opts.Issue.LoadPoster(ctx); err != nil { return err } @@ -1505,10 +1493,9 @@ func applySubscribedCondition(sess *xorm.Session, subscriberID int64) *xorm.Sess } // CountIssuesByRepo map from repoID to number of issues matching the options -func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) { - e := db.GetEngine(db.DefaultContext) - - sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") +func CountIssuesByRepo(ctx context.Context, opts *IssuesOptions) (map[int64]int64, error) { + sess := db.GetEngine(ctx). + Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSessionNoLimit(sess) @@ -1551,10 +1538,9 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]i } // Issues returns a list of issues by given conditions. -func Issues(opts *IssuesOptions) ([]*Issue, error) { - e := db.GetEngine(db.DefaultContext) - - sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") +func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) { + sess := db.GetEngine(ctx). + Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSessionWithLimit(sess) sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID) @@ -1572,11 +1558,11 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) { } // CountIssues number return of issues by given conditions. -func CountIssues(opts *IssuesOptions) (int64, error) { - e := db.GetEngine(db.DefaultContext) - - sess := e.Select("COUNT(issue.id) AS count").Table("issue") - sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") +func CountIssues(ctx context.Context, opts *IssuesOptions) (int64, error) { + sess := db.GetEngine(ctx). + Select("COUNT(issue.id) AS count"). + Table("issue"). + Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSessionNoLimit(sess) return sess.Count() @@ -1585,9 +1571,10 @@ func CountIssues(opts *IssuesOptions) (int64, error) { // GetParticipantsIDsByIssueID returns the IDs of all users who participated in comments of an issue, // but skips joining with `user` for performance reasons. // User permissions must be verified elsewhere if required. -func GetParticipantsIDsByIssueID(issueID int64) ([]int64, error) { +func GetParticipantsIDsByIssueID(ctx context.Context, issueID int64) ([]int64, error) { userIDs := make([]int64, 0, 5) - return userIDs, db.GetEngine(db.DefaultContext).Table("comment"). + return userIDs, db.GetEngine(ctx). + Table("comment"). Cols("poster_id"). Where("issue_id = ?", issueID). And("type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview). @@ -2426,8 +2413,9 @@ func (issue *Issue) GetExternalName() string { return issue.OriginalAuthor } func (issue *Issue) GetExternalID() int64 { return issue.OriginalAuthorID } // CountOrphanedIssues count issues without a repo -func CountOrphanedIssues() (int64, error) { - return db.GetEngine(db.DefaultContext).Table("issue"). +func CountOrphanedIssues(ctx context.Context) (int64, error) { + return db.GetEngine(ctx). + Table("issue"). Join("LEFT", "repository", "issue.repo_id=repository.id"). Where(builder.IsNull{"repository.id"}). Select("COUNT(`issue`.`id`)"). @@ -2435,35 +2423,31 @@ func CountOrphanedIssues() (int64, error) { } // DeleteOrphanedIssues delete issues without a repo -func DeleteOrphanedIssues() error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - var ids []int64 - - if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id"). - Join("LEFT", "repository", "issue.repo_id=repository.id"). - Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id"). - Find(&ids); err != nil { - return err - } - +func DeleteOrphanedIssues(ctx context.Context) error { var attachmentPaths []string - for i := range ids { - paths, err := DeleteIssuesByRepoID(ctx, ids[i]) - if err != nil { + err := db.AutoTx(ctx, func(ctx context.Context) error { + var ids []int64 + + if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id"). + Join("LEFT", "repository", "issue.repo_id=repository.id"). + Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id"). + Find(&ids); err != nil { return err } - attachmentPaths = append(attachmentPaths, paths...) - } - if err := committer.Commit(); err != nil { + for i := range ids { + paths, err := DeleteIssuesByRepoID(ctx, ids[i]) + if err != nil { + return err + } + attachmentPaths = append(attachmentPaths, paths...) + } + + return nil + }) + if err != nil { return err } - committer.Close() // Remove issue attachment files. for i := range attachmentPaths { diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index bbe2292dd1de0..d9dff4cb4d6cf 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -34,7 +34,8 @@ func (issues IssueList) getRepoIDs() []int64 { return repoIDs.Values() } -func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Repository, error) { +// LoadRepositories loads issues' all repositories +func (issues IssueList) LoadRepositories(ctx context.Context) ([]*repo_model.Repository, error) { if len(issues) == 0 { return nil, nil } @@ -73,11 +74,6 @@ func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Rep return repo_model.ValuesRepository(repoMaps), nil } -// LoadRepositories loads issues' all repositories -func (issues IssueList) LoadRepositories() ([]*repo_model.Repository, error) { - return issues.loadRepositories(db.DefaultContext) -} - func (issues IssueList) getPosterIDs() []int64 { posterIDs := make(container.Set[int64], len(issues)) for _, issue := range issues { @@ -317,7 +313,8 @@ func (issues IssueList) getPullIssueIDs() []int64 { return ids } -func (issues IssueList) loadPullRequests(ctx context.Context) error { +// LoadPullRequests loads pull requests +func (issues IssueList) LoadPullRequests(ctx context.Context) error { issuesIDs := issues.getPullIssueIDs() if len(issuesIDs) == 0 { return nil @@ -361,7 +358,8 @@ func (issues IssueList) loadPullRequests(ctx context.Context) error { return nil } -func (issues IssueList) loadAttachments(ctx context.Context) (err error) { +// LoadAttachments loads attachments +func (issues IssueList) LoadAttachments(ctx context.Context) (err error) { if len(issues) == 0 { return nil } @@ -513,8 +511,8 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) { // loadAttributes loads all attributes, expect for attachments and comments func (issues IssueList) loadAttributes(ctx context.Context) error { - if _, err := issues.loadRepositories(ctx); err != nil { - return fmt.Errorf("issue.loadAttributes: loadRepositories: %w", err) + if _, err := issues.LoadRepositories(ctx); err != nil { + return fmt.Errorf("issue.loadAttributes: LoadRepositories: %w", err) } if err := issues.loadPosters(ctx); err != nil { @@ -537,7 +535,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error { return fmt.Errorf("issue.loadAttributes: loadAssignees: %w", err) } - if err := issues.loadPullRequests(ctx); err != nil { + if err := issues.LoadPullRequests(ctx); err != nil { return fmt.Errorf("issue.loadAttributes: loadPullRequests: %w", err) } @@ -554,24 +552,14 @@ func (issues IssueList) LoadAttributes() error { return issues.loadAttributes(db.DefaultContext) } -// LoadAttachments loads attachments -func (issues IssueList) LoadAttachments() error { - return issues.loadAttachments(db.DefaultContext) -} - // LoadComments loads comments -func (issues IssueList) LoadComments() error { - return issues.loadComments(db.DefaultContext, builder.NewCond()) +func (issues IssueList) LoadComments(ctx context.Context) error { + return issues.loadComments(ctx, builder.NewCond()) } // LoadDiscussComments loads discuss comments -func (issues IssueList) LoadDiscussComments() error { - return issues.loadComments(db.DefaultContext, builder.Eq{"comment.type": CommentTypeComment}) -} - -// LoadPullRequests loads pull requests -func (issues IssueList) LoadPullRequests() error { - return issues.loadPullRequests(db.DefaultContext) +func (issues IssueList) LoadDiscussComments(ctx context.Context) error { + return issues.loadComments(ctx, builder.Eq{"comment.type": CommentTypeComment}) } // GetApprovalCounts returns a map of issue ID to slice of approval counts diff --git a/models/issues/issue_list_test.go b/models/issues/issue_list_test.go index f2cfca9bc0afc..c38a405e02a78 100644 --- a/models/issues/issue_list_test.go +++ b/models/issues/issue_list_test.go @@ -7,6 +7,7 @@ package issues_test import ( "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" @@ -23,7 +24,7 @@ func TestIssueList_LoadRepositories(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}), } - repos, err := issueList.LoadRepositories() + repos, err := issueList.LoadRepositories(db.DefaultContext) assert.NoError(t, err) assert.Len(t, repos, 2) for _, issue := range issueList { diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 0c59f4e82b713..39a27abd3e091 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -61,11 +61,11 @@ func (issue *Issue) projectBoardID(ctx context.Context) int64 { } // LoadIssuesFromBoard load issues assigned to this board -func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { +func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) { issueList := make([]*Issue, 0, 10) if b.ID != 0 { - issues, err := Issues(&IssuesOptions{ + issues, err := Issues(ctx, &IssuesOptions{ ProjectBoardID: b.ID, ProjectID: b.ProjectID, SortType: "project-column-sorting", @@ -77,7 +77,7 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { } if b.Default { - issues, err := Issues(&IssuesOptions{ + issues, err := Issues(ctx, &IssuesOptions{ ProjectBoardID: -1, // Issues without ProjectBoardID ProjectID: b.ProjectID, SortType: "project-column-sorting", @@ -88,7 +88,7 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { issueList = append(issueList, issues...) } - if err := IssueList(issueList).LoadComments(); err != nil { + if err := IssueList(issueList).LoadComments(ctx); err != nil { return nil, err } @@ -96,10 +96,10 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) { } // LoadIssuesFromBoardList load issues assigned to the boards -func LoadIssuesFromBoardList(bs project_model.BoardList) (map[int64]IssueList, error) { +func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) { issuesMap := make(map[int64]IssueList, len(bs)) for i := range bs { - il, err := LoadIssuesFromBoard(bs[i]) + il, err := LoadIssuesFromBoard(ctx, bs[i]) if err != nil { return nil, err } diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go index bef5d03e8afa8..2c8728e71a3af 100644 --- a/models/issues/issue_test.go +++ b/models/issues/issue_test.go @@ -189,7 +189,7 @@ func TestIssues(t *testing.T) { []int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests }, } { - issues, err := issues_model.Issues(&test.Opts) + issues, err := issues_model.Issues(db.DefaultContext, &test.Opts) assert.NoError(t, err) if assert.Len(t, issues, len(test.ExpectedIssueIDs)) { for i, issue := range issues { @@ -556,7 +556,7 @@ func TestLoadTotalTrackedTime(t *testing.T) { func TestCountIssues(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - count, err := issues_model.CountIssues(&issues_model.IssuesOptions{}) + count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{}) assert.NoError(t, err) assert.EqualValues(t, 17, count) } diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go index e389f63d72acd..4c6601a0a2e55 100644 --- a/models/issues/issue_xref.go +++ b/models/issues/issue_xref.go @@ -235,7 +235,7 @@ func (c *Comment) AddCrossReferences(stdCtx context.Context, doer *user_model.Us if c.Type != CommentTypeCode && c.Type != CommentTypeComment { return nil } - if err := c.LoadIssueCtx(stdCtx); err != nil { + if err := c.LoadIssue(stdCtx); err != nil { return err } ctx := &crossReferencesContext{ diff --git a/models/issues/label.go b/models/issues/label.go index 0b0d1419b16b0..dc7058d643556 100644 --- a/models/issues/label.go +++ b/models/issues/label.go @@ -116,8 +116,8 @@ func (label *Label) CalOpenIssues() { } // CalOpenOrgIssues calculates the open issues of a label for a specific repo -func (label *Label) CalOpenOrgIssues(repoID, labelID int64) { - counts, _ := CountIssuesByRepo(&IssuesOptions{ +func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) { + counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{ RepoID: repoID, LabelIDs: []int64{labelID}, IsClosed: util.OptionalBoolFalse, @@ -395,9 +395,9 @@ func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder { // GetLabelsInRepoByIDs returns a list of labels by IDs in given repository, // it silently ignores label IDs that do not belong to the repository. -func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) { +func GetLabelsInRepoByIDs(ctx context.Context, repoID int64, labelIDs []int64) ([]*Label, error) { labels := make([]*Label, 0, len(labelIDs)) - return labels, db.GetEngine(db.DefaultContext). + return labels, db.GetEngine(ctx). Where("repo_id = ?", repoID). In("id", labelIDs). Asc("name"). @@ -498,9 +498,9 @@ func GetLabelIDsInOrgByNames(orgID int64, labelNames []string) ([]int64, error) // GetLabelsInOrgByIDs returns a list of labels by IDs in given organization, // it silently ignores label IDs that do not belong to the organization. -func GetLabelsInOrgByIDs(orgID int64, labelIDs []int64) ([]*Label, error) { +func GetLabelsInOrgByIDs(ctx context.Context, orgID int64, labelIDs []int64) ([]*Label, error) { labels := make([]*Label, 0, len(labelIDs)) - return labels, db.GetEngine(db.DefaultContext). + return labels, db.GetEngine(ctx). Where("org_id = ?", orgID). In("id", labelIDs). Asc("name"). @@ -746,13 +746,13 @@ func DeleteLabelsByRepoID(ctx context.Context, repoID int64) error { } // CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore -func CountOrphanedLabels() (int64, error) { - noref, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count() +func CountOrphanedLabels(ctx context.Context) (int64, error) { + noref, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count() if err != nil { return 0, err } - norepo, err := db.GetEngine(db.DefaultContext).Table("label"). + norepo, err := db.GetEngine(ctx).Table("label"). Where(builder.And( builder.Gt{"repo_id": 0}, builder.NotIn("repo_id", builder.Select("id").From("repository")), @@ -762,7 +762,7 @@ func CountOrphanedLabels() (int64, error) { return 0, err } - noorg, err := db.GetEngine(db.DefaultContext).Table("label"). + noorg, err := db.GetEngine(ctx).Table("label"). Where(builder.And( builder.Gt{"org_id": 0}, builder.NotIn("org_id", builder.Select("id").From("user")), @@ -776,14 +776,14 @@ func CountOrphanedLabels() (int64, error) { } // DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore -func DeleteOrphanedLabels() error { +func DeleteOrphanedLabels(ctx context.Context) error { // delete labels with no reference - if _, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil { + if _, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil { return err } // delete labels with none existing repos - if _, err := db.GetEngine(db.DefaultContext). + if _, err := db.GetEngine(ctx). Where(builder.And( builder.Gt{"repo_id": 0}, builder.NotIn("repo_id", builder.Select("id").From("repository")), @@ -793,7 +793,7 @@ func DeleteOrphanedLabels() error { } // delete labels with none existing orgs - if _, err := db.GetEngine(db.DefaultContext). + if _, err := db.GetEngine(ctx). Where(builder.And( builder.Gt{"org_id": 0}, builder.NotIn("org_id", builder.Select("id").From("user")), @@ -806,23 +806,23 @@ func DeleteOrphanedLabels() error { } // CountOrphanedIssueLabels return count of IssueLabels witch have no label behind anymore -func CountOrphanedIssueLabels() (int64, error) { - return db.GetEngine(db.DefaultContext).Table("issue_label"). +func CountOrphanedIssueLabels(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Table("issue_label"). NotIn("label_id", builder.Select("id").From("label")). Count() } // DeleteOrphanedIssueLabels delete IssueLabels witch have no label behind anymore -func DeleteOrphanedIssueLabels() error { - _, err := db.GetEngine(db.DefaultContext). +func DeleteOrphanedIssueLabels(ctx context.Context) error { + _, err := db.GetEngine(ctx). NotIn("label_id", builder.Select("id").From("label")). Delete(IssueLabel{}) return err } // CountIssueLabelWithOutsideLabels count label comments with outside label -func CountIssueLabelWithOutsideLabels() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")). +func CountIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")). Table("issue_label"). Join("inner", "label", "issue_label.label_id = label.id "). Join("inner", "issue", "issue.id = issue_label.issue_id "). @@ -831,8 +831,8 @@ func CountIssueLabelWithOutsideLabels() (int64, error) { } // FixIssueLabelWithOutsideLabels fix label comments with outside label -func FixIssueLabelWithOutsideLabels() (int64, error) { - res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM issue_label WHERE issue_label.id IN ( +func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) { + res, err := db.GetEngine(ctx).Exec(`DELETE FROM issue_label WHERE issue_label.id IN ( SELECT il_too.id FROM ( SELECT il_too_too.id FROM issue_label AS il_too_too diff --git a/models/issues/label_test.go b/models/issues/label_test.go index 5e6cc9a2a0895..077e0eeb67ba4 100644 --- a/models/issues/label_test.go +++ b/models/issues/label_test.go @@ -121,7 +121,7 @@ func TestGetLabelInRepoByID(t *testing.T) { func TestGetLabelsInRepoByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsInRepoByIDs(1, []int64{1, 2, unittest.NonexistentID}) + labels, err := issues_model.GetLabelsInRepoByIDs(db.DefaultContext, 1, []int64{1, 2, unittest.NonexistentID}) assert.NoError(t, err) if assert.Len(t, labels, 2) { assert.EqualValues(t, 1, labels[0].ID) @@ -212,7 +212,7 @@ func TestGetLabelInOrgByID(t *testing.T) { func TestGetLabelsInOrgByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsInOrgByIDs(3, []int64{3, 4, unittest.NonexistentID}) + labels, err := issues_model.GetLabelsInOrgByIDs(db.DefaultContext, 3, []int64{3, 4, unittest.NonexistentID}) assert.NoError(t, err) if assert.Len(t, labels, 2) { assert.EqualValues(t, 3, labels[0].ID) diff --git a/models/issues/pull.go b/models/issues/pull.go index e906407d312ab..993a1ba8bdf76 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -205,8 +205,8 @@ func DeletePullsByBaseRepoID(ctx context.Context, repoID int64) error { } // MustHeadUserName returns the HeadRepo's username if failed return blank -func (pr *PullRequest) MustHeadUserName() string { - if err := pr.LoadHeadRepo(); err != nil { +func (pr *PullRequest) MustHeadUserName(ctx context.Context) string { + if err := pr.LoadHeadRepo(ctx); err != nil { if !repo_model.IsErrRepoNotExist(err) { log.Error("LoadHeadRepo: %v", err) } else { @@ -220,8 +220,9 @@ func (pr *PullRequest) MustHeadUserName() string { return pr.HeadRepo.OwnerName } +// LoadAttributes loads pull request attributes from database // Note: don't try to get Issue because will end up recursive querying. -func (pr *PullRequest) loadAttributes(ctx context.Context) (err error) { +func (pr *PullRequest) LoadAttributes(ctx context.Context) (err error) { if pr.HasMerged && pr.Merger == nil { pr.Merger, err = user_model.GetUserByIDCtx(ctx, pr.MergerID) if user_model.IsErrUserNotExist(err) { @@ -235,13 +236,8 @@ func (pr *PullRequest) loadAttributes(ctx context.Context) (err error) { return nil } -// LoadAttributes loads pull request attributes from database -func (pr *PullRequest) LoadAttributes() error { - return pr.loadAttributes(db.DefaultContext) -} - -// LoadHeadRepoCtx loads the head repository -func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) { +// LoadHeadRepo loads the head repository +func (pr *PullRequest) LoadHeadRepo(ctx context.Context) (err error) { if !pr.isHeadRepoLoaded && pr.HeadRepo == nil && pr.HeadRepoID > 0 { if pr.HeadRepoID == pr.BaseRepoID { if pr.BaseRepo != nil { @@ -262,18 +258,8 @@ func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) { return nil } -// LoadHeadRepo loads the head repository -func (pr *PullRequest) LoadHeadRepo() error { - return pr.LoadHeadRepoCtx(db.DefaultContext) -} - // LoadBaseRepo loads the target repository -func (pr *PullRequest) LoadBaseRepo() error { - return pr.LoadBaseRepoCtx(db.DefaultContext) -} - -// LoadBaseRepoCtx loads the target repository -func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) { +func (pr *PullRequest) LoadBaseRepo(ctx context.Context) (err error) { if pr.BaseRepo != nil { return nil } @@ -296,12 +282,7 @@ func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) { } // LoadIssue loads issue information from database -func (pr *PullRequest) LoadIssue() (err error) { - return pr.LoadIssueCtx(db.DefaultContext) -} - -// LoadIssueCtx loads issue information from database -func (pr *PullRequest) LoadIssueCtx(ctx context.Context) (err error) { +func (pr *PullRequest) LoadIssue(ctx context.Context) (err error) { if pr.Issue != nil { return nil } @@ -392,7 +373,7 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error { break } - if err := review.loadReviewer(ctx); err != nil && !user_model.IsErrUserNotExist(err) { + if err := review.LoadReviewer(ctx); err != nil && !user_model.IsErrUserNotExist(err) { log.Error("Unable to LoadReviewer[%d] for PR ID %d : %v", review.ReviewerID, pr.ID, err) return err } else if review.Reviewer == nil { @@ -458,7 +439,7 @@ func (pr *PullRequest) SetMerged(ctx context.Context) (bool, error) { } pr.Issue = nil - if err := pr.LoadIssueCtx(ctx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { return false, err } @@ -541,9 +522,9 @@ func NewPullRequest(outerCtx context.Context, repo *repo_model.Repository, issue // GetUnmergedPullRequest returns a pull request that is open and has not been merged // by given head/base and repo/branch. -func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) { +func GetUnmergedPullRequest(ctx context.Context, headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) { pr := new(PullRequest) - has, err := db.GetEngine(db.DefaultContext). + has, err := db.GetEngine(ctx). Where("head_repo_id=? AND head_branch=? AND base_repo_id=? AND base_branch=? AND has_merged=? AND flow = ? AND issue.is_closed=?", headRepoID, headBranch, baseRepoID, baseBranch, false, flow, false). Join("INNER", "issue", "issue.id=pull_request.issue_id"). @@ -588,10 +569,10 @@ func GetPullRequestByIndex(ctx context.Context, repoID, index int64) (*PullReque return nil, ErrPullRequestNotExist{0, 0, 0, repoID, "", ""} } - if err = pr.loadAttributes(ctx); err != nil { + if err = pr.LoadAttributes(ctx); err != nil { return nil, err } - if err = pr.LoadIssueCtx(ctx); err != nil { + if err = pr.LoadIssue(ctx); err != nil { return nil, err } @@ -607,7 +588,7 @@ func GetPullRequestByID(ctx context.Context, id int64) (*PullRequest, error) { } else if !has { return nil, ErrPullRequestNotExist{id, 0, 0, 0, "", ""} } - return pr, pr.loadAttributes(ctx) + return pr, pr.LoadAttributes(ctx) } // GetPullRequestByIssueIDWithNoAttributes returns pull request with no attributes loaded by given issue ID. @@ -634,7 +615,7 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest, } else if !has { return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""} } - return pr, pr.loadAttributes(ctx) + return pr, pr.LoadAttributes(ctx) } // GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request @@ -664,14 +645,15 @@ func (pr *PullRequest) UpdateCols(cols ...string) error { } // UpdateColsIfNotMerged updates specific fields of a pull request if it has not been merged -func (pr *PullRequest) UpdateColsIfNotMerged(cols ...string) error { - _, err := db.GetEngine(db.DefaultContext).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr) +func (pr *PullRequest) UpdateColsIfNotMerged(ctx context.Context, cols ...string) error { + _, err := db.GetEngine(ctx).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr) return err } // IsWorkInProgress determine if the Pull Request is a Work In Progress by its title +// Issue must be set before this method can be called. func (pr *PullRequest) IsWorkInProgress() bool { - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(db.DefaultContext); err != nil { log.Error("LoadIssue: %v", err) return false } @@ -695,8 +677,8 @@ func (pr *PullRequest) IsFilesConflicted() bool { // GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress. // It returns an empty string when none were found -func (pr *PullRequest) GetWorkInProgressPrefix() string { - if err := pr.LoadIssue(); err != nil { +func (pr *PullRequest) GetWorkInProgressPrefix(ctx context.Context) string { + if err := pr.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return "" } @@ -739,7 +721,7 @@ func GetPullRequestsByHeadBranch(ctx context.Context, headBranch string, headRep // GetBaseBranchHTMLURL returns the HTML URL of the base branch func (pr *PullRequest) GetBaseBranchHTMLURL() string { - if err := pr.LoadBaseRepo(); err != nil { + if err := pr.LoadBaseRepo(db.DefaultContext); err != nil { log.Error("LoadBaseRepo: %v", err) return "" } @@ -755,7 +737,7 @@ func (pr *PullRequest) GetHeadBranchHTMLURL() string { return "" } - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(db.DefaultContext); err != nil { log.Error("LoadHeadRepo: %v", err) return "" } diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index c69f18492b4cf..6110ba77fa72f 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -79,7 +79,7 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user * for _, pr := range prs { if pr.AllowMaintainerEdit { - err = pr.LoadBaseRepo() + err = pr.LoadBaseRepo(db.DefaultContext) if err != nil { continue } diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go index fb46e3071e39f..d88f9d4f54f15 100644 --- a/models/issues/pull_test.go +++ b/models/issues/pull_test.go @@ -17,7 +17,7 @@ import ( func TestPullRequest_LoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadAttributes()) + assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) assert.NotNil(t, pr.Merger) assert.Equal(t, pr.MergerID, pr.Merger.ID) } @@ -25,10 +25,10 @@ func TestPullRequest_LoadAttributes(t *testing.T) { func TestPullRequest_LoadIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) assert.NotNil(t, pr.Issue) assert.Equal(t, int64(2), pr.Issue.ID) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) assert.NotNil(t, pr.Issue) assert.Equal(t, int64(2), pr.Issue.ID) } @@ -36,10 +36,10 @@ func TestPullRequest_LoadIssue(t *testing.T) { func TestPullRequest_LoadBaseRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) assert.NotNil(t, pr.BaseRepo) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) assert.NotNil(t, pr.BaseRepo) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) } @@ -47,7 +47,7 @@ func TestPullRequest_LoadBaseRepo(t *testing.T) { func TestPullRequest_LoadHeadRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadHeadRepo()) + assert.NoError(t, pr.LoadHeadRepo(db.DefaultContext)) assert.NotNil(t, pr.HeadRepo) assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID) } @@ -96,11 +96,11 @@ func TestPullRequestsOldest(t *testing.T) { func TestGetUnmergedPullRequest(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetUnmergedPullRequest(1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) assert.NoError(t, err) assert.Equal(t, int64(2), pr.ID) - _, err = issues_model.GetUnmergedPullRequest(1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) + _, err = issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) } @@ -228,7 +228,7 @@ func TestPullRequest_IsWorkInProgress(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - pr.LoadIssue() + pr.LoadIssue(db.DefaultContext) assert.False(t, pr.IsWorkInProgress()) @@ -243,16 +243,16 @@ func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - pr.LoadIssue() + pr.LoadIssue(db.DefaultContext) - assert.Empty(t, pr.GetWorkInProgressPrefix()) + assert.Empty(t, pr.GetWorkInProgressPrefix(db.DefaultContext)) original := pr.Issue.Title pr.Issue.Title = "WIP: " + original - assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix()) + assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix(db.DefaultContext)) pr.Issue.Title = "[wip] " + original - assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix()) + assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix(db.DefaultContext)) } func TestDeleteOrphanedObjects(t *testing.T) { @@ -264,11 +264,11 @@ func TestDeleteOrphanedObjects(t *testing.T) { _, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) assert.NoError(t, err) - orphaned, err := db.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) assert.EqualValues(t, 3, orphaned) - err = db.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id") + err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) diff --git a/models/issues/review.go b/models/issues/review.go index f66c70c1fc007..5cf7d4c3da728 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -154,7 +154,8 @@ func (r *Review) loadIssue(ctx context.Context) (err error) { return err } -func (r *Review) loadReviewer(ctx context.Context) (err error) { +// LoadReviewer loads reviewer +func (r *Review) LoadReviewer(ctx context.Context) (err error) { if r.ReviewerID == 0 || r.Reviewer != nil { return } @@ -162,7 +163,8 @@ func (r *Review) loadReviewer(ctx context.Context) (err error) { return err } -func (r *Review) loadReviewerTeam(ctx context.Context) (err error) { +// LoadReviewerTeam loads reviewer team +func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) { if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil { return } @@ -171,16 +173,6 @@ func (r *Review) loadReviewerTeam(ctx context.Context) (err error) { return err } -// LoadReviewer loads reviewer -func (r *Review) LoadReviewer() error { - return r.loadReviewer(db.DefaultContext) -} - -// LoadReviewerTeam loads reviewer team -func (r *Review) LoadReviewerTeam() error { - return r.loadReviewerTeam(db.DefaultContext) -} - // LoadAttributes loads all attributes except CodeComments func (r *Review) LoadAttributes(ctx context.Context) (err error) { if err = r.loadIssue(ctx); err != nil { @@ -189,10 +181,10 @@ func (r *Review) LoadAttributes(ctx context.Context) (err error) { if err = r.LoadCodeComments(ctx); err != nil { return } - if err = r.loadReviewer(ctx); err != nil { + if err = r.LoadReviewer(ctx); err != nil { return } - if err = r.loadReviewerTeam(ctx); err != nil { + if err = r.LoadReviewerTeam(ctx); err != nil { return } return err diff --git a/models/issues/review_test.go b/models/issues/review_test.go index 46d1cc777b65b..39ad14c65fc2f 100644 --- a/models/issues/review_test.go +++ b/models/issues/review_test.go @@ -135,7 +135,7 @@ func TestGetReviewersByIssueID(t *testing.T) { allReviews, err := issues_model.GetReviewersByIssueID(issue.ID) for _, reviewer := range allReviews { - assert.NoError(t, reviewer.LoadReviewer()) + assert.NoError(t, reviewer.LoadReviewer(db.DefaultContext)) } assert.NoError(t, err) if assert.Len(t, allReviews, 3) { diff --git a/models/org_team_test.go b/models/org_team_test.go index a600d07c0c9b3..3b1fabf1c34a6 100644 --- a/models/org_team_test.go +++ b/models/org_team_test.go @@ -143,7 +143,7 @@ func TestDeleteTeam(t *testing.T) { // check that team members don't have "leftover" access to repos user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - accessMode, err := access_model.AccessLevel(user, repo) + accessMode, err := access_model.AccessLevel(db.DefaultContext, user, repo) assert.NoError(t, err) assert.True(t, accessMode < perm.AccessModeWrite) } diff --git a/models/perm/access/access_test.go b/models/perm/access/access_test.go index 7f58be4f393b5..dc707b971be96 100644 --- a/models/perm/access/access_test.go +++ b/models/perm/access/access_test.go @@ -36,34 +36,34 @@ func TestAccessLevel(t *testing.T) { // org. owned private repo repo24 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24}) - level, err := access_model.AccessLevel(user2, repo1) + level, err := access_model.AccessLevel(db.DefaultContext, user2, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeOwner, level) - level, err = access_model.AccessLevel(user2, repo3) + level, err = access_model.AccessLevel(db.DefaultContext, user2, repo3) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeOwner, level) - level, err = access_model.AccessLevel(user5, repo1) + level, err = access_model.AccessLevel(db.DefaultContext, user5, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeRead, level) - level, err = access_model.AccessLevel(user5, repo3) + level, err = access_model.AccessLevel(db.DefaultContext, user5, repo3) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeNone, level) // restricted user has no access to a public repo - level, err = access_model.AccessLevel(user29, repo1) + level, err = access_model.AccessLevel(db.DefaultContext, user29, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeNone, level) // ... unless he's a collaborator - level, err = access_model.AccessLevel(user29, repo4) + level, err = access_model.AccessLevel(db.DefaultContext, user29, repo4) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeWrite, level) // ... or a team member - level, err = access_model.AccessLevel(user29, repo24) + level, err = access_model.AccessLevel(db.DefaultContext, user29, repo24) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeRead, level) } diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 93e3bdd6d8468..3b709a3e85538 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -326,17 +326,13 @@ func IsUserRepoAdmin(ctx context.Context, repo *repo_model.Repository, user *use // AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the // user does not have access. -func AccessLevel(user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint - return AccessLevelUnit(user, repo, unit.TypeCode) +func AccessLevel(ctx context.Context, user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint + return AccessLevelUnit(ctx, user, repo, unit.TypeCode) } // AccessLevelUnit returns the Access a user has to a repository's. Will return NoneAccess if the // user does not have access. -func AccessLevelUnit(user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint - return accessLevelUnit(db.DefaultContext, user, repo, unitType) -} - -func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { +func AccessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint perm, err := GetUserRepoPermission(ctx, repo, user) if err != nil { return perm_model.AccessModeNone, err @@ -346,7 +342,7 @@ func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_mode // HasAccessUnit returns true if user has testMode to the unit of the repository func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) { - mode, err := accessLevelUnit(ctx, user, repo, unitType) + mode, err := AccessLevelUnit(ctx, user, repo, unitType) return testMode <= mode, err } diff --git a/models/repo/attachment.go b/models/repo/attachment.go index df7528df09c9c..428f370a0baa9 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -226,20 +226,20 @@ func UpdateAttachment(ctx context.Context, atta *Attachment) error { } // DeleteAttachmentsByRelease deletes all attachments associated with the given release. -func DeleteAttachmentsByRelease(releaseID int64) error { - _, err := db.GetEngine(db.DefaultContext).Where("release_id = ?", releaseID).Delete(&Attachment{}) +func DeleteAttachmentsByRelease(ctx context.Context, releaseID int64) error { + _, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Delete(&Attachment{}) return err } // CountOrphanedAttachments returns the number of bad attachments -func CountOrphanedAttachments() (int64, error) { - return db.GetEngine(db.DefaultContext).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). +func CountOrphanedAttachments(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). Count(new(Attachment)) } // DeleteOrphanedAttachments delete all bad attachments -func DeleteOrphanedAttachments() error { - _, err := db.GetEngine(db.DefaultContext).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). +func DeleteOrphanedAttachments(ctx context.Context) error { + _, err := db.GetEngine(ctx).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))"). Delete(new(Attachment)) return err } diff --git a/models/repo/pushmirror.go b/models/repo/pushmirror.go index 38d6e72019700..fa876ee560ac8 100644 --- a/models/repo/pushmirror.go +++ b/models/repo/pushmirror.go @@ -120,9 +120,9 @@ func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.Li } // GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits -func GetPushMirrorsSyncedOnCommit(repoID int64) ([]*PushMirror, error) { +func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMirror, error) { mirrors := make([]*PushMirror, 0, 10) - return mirrors, db.GetEngine(db.DefaultContext). + return mirrors, db.GetEngine(ctx). Where("repo_id=? AND sync_on_commit=?", repoID, true). Find(&mirrors) } diff --git a/models/repo/release.go b/models/repo/release.go index 14428f15f73f6..a92e4bb6e555b 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -90,7 +90,8 @@ func init() { db.RegisterModel(new(Release)) } -func (r *Release) loadAttributes(ctx context.Context) error { +// LoadAttributes load repo and publisher attributes for a release +func (r *Release) LoadAttributes(ctx context.Context) error { var err error if r.Repo == nil { r.Repo, err = GetRepositoryByIDCtx(ctx, r.RepoID) @@ -111,11 +112,6 @@ func (r *Release) loadAttributes(ctx context.Context) error { return GetReleaseAttachments(ctx, r) } -// LoadAttributes load repo and publisher attributes for a release -func (r *Release) LoadAttributes() error { - return r.loadAttributes(db.DefaultContext) -} - // APIURL the api url for a release. release must have attributes loaded func (r *Release) APIURL() string { return r.Repo.APIURL() + "/releases/" + strconv.FormatInt(r.ID, 10) @@ -241,8 +237,8 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { } // GetReleasesByRepoID returns a list of releases of repository. -func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, error) { - sess := db.GetEngine(db.DefaultContext). +func GetReleasesByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) ([]*Release, error) { + sess := db.GetEngine(ctx). Desc("created_unix", "id"). Where(opts.toConds(repoID)) @@ -381,8 +377,8 @@ func SortReleases(rels []*Release) { } // DeleteReleaseByID deletes a release from database by given ID. -func DeleteReleaseByID(id int64) error { - _, err := db.GetEngine(db.DefaultContext).ID(id).Delete(new(Release)) +func DeleteReleaseByID(ctx context.Context, id int64) error { + _, err := db.GetEngine(ctx).ID(id).Delete(new(Release)) return err } diff --git a/models/repo/repo.go b/models/repo/repo.go index 77e0367a5a5c7..a3dac8383f7bc 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -236,14 +236,6 @@ func (repo *Repository) AfterLoad() { repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects } -// MustOwner always returns a valid *user_model.User object to avoid -// conceptually impossible error handling. -// It creates a fake object that contains error details -// when error occurs. -func (repo *Repository) MustOwner() *user_model.User { - return repo.mustOwner(db.DefaultContext) -} - // LoadAttributes loads attributes of the repository. func (repo *Repository) LoadAttributes(ctx context.Context) error { // Load owner @@ -403,7 +395,11 @@ func (repo *Repository) GetOwner(ctx context.Context) (err error) { return err } -func (repo *Repository) mustOwner(ctx context.Context) *user_model.User { +// MustOwner always returns a valid *user_model.User object to avoid +// conceptually impossible error handling. +// It creates a fake object that contains error details +// when error occurs. +func (repo *Repository) MustOwner(ctx context.Context) *user_model.User { if err := repo.GetOwner(ctx); err != nil { return &user_model.User{ Name: "error", @@ -438,7 +434,7 @@ func (repo *Repository) ComposeMetas() map[string]string { } } - repo.MustOwner() + repo.MustOwner(db.DefaultContext) if repo.Owner.IsOrganization() { teams := make([]string, 0, 5) _ = db.GetEngine(db.DefaultContext).Table("team_repo"). @@ -792,13 +788,13 @@ func UpdateRepoIssueNumbers(ctx context.Context, repoID int64, isPull, isClosed } // CountNullArchivedRepository counts the number of repositories with is_archived is null -func CountNullArchivedRepository() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Count(new(Repository)) +func CountNullArchivedRepository(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Count(new(Repository)) } // FixNullArchivedRepository sets is_archived to false where it is null -func FixNullArchivedRepository() (int64, error) { - return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{ +func FixNullArchivedRepository(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{ IsArchived: false, }) } diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 191970d275681..abfa73abb9058 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -518,14 +518,13 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { // SearchRepository returns repositories based on search options, // it returns results in given range and number of total results. -func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { +func SearchRepository(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { cond := SearchRepositoryCondition(opts) - return SearchRepositoryByCondition(opts, cond, true) + return SearchRepositoryByCondition(ctx, opts, cond, true) } // SearchRepositoryByCondition search repositories by condition -func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { - ctx := db.DefaultContext +func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { sess, count, err := searchRepositoryByCondition(ctx, opts, cond) if err != nil { return nil, 0, err @@ -652,9 +651,9 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu // SearchRepositoryByName takes keyword and part of repository name to search, // it returns results in given range and number of total results. -func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) { +func SearchRepositoryByName(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { opts.IncludeDescription = false - return SearchRepository(opts) + return SearchRepository(ctx, opts) } // SearchRepositoryIDs takes keyword and part of repository name to search, diff --git a/models/repo/repo_list_test.go b/models/repo/repo_list_test.go index f9c84a0f3f910..926ed07e9e9e3 100644 --- a/models/repo/repo_list_test.go +++ b/models/repo/repo_list_test.go @@ -20,7 +20,7 @@ func TestSearchRepository(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // test search public repository on explore page - repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -35,7 +35,7 @@ func TestSearchRepository(t *testing.T) { } assert.Equal(t, int64(1), count) - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -49,7 +49,7 @@ func TestSearchRepository(t *testing.T) { assert.Len(t, repos, 2) // test search private repository on explore page - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -65,7 +65,7 @@ func TestSearchRepository(t *testing.T) { } assert.Equal(t, int64(1), count) - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -80,14 +80,14 @@ func TestSearchRepository(t *testing.T) { assert.Len(t, repos, 3) // Test non existing owner - repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) + repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) assert.NoError(t, err) assert.Empty(t, repos) assert.Equal(t, int64(0), count) // Test search within description - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -104,7 +104,7 @@ func TestSearchRepository(t *testing.T) { assert.Equal(t, int64(1), count) // Test NOT search within description - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -277,7 +277,7 @@ func TestSearchRepository(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - repos, count, err := repo_model.SearchRepositoryByName(testCase.opts) + repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) @@ -377,7 +377,7 @@ func TestSearchRepositoryByTopicName(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - _, count, err := repo_model.SearchRepositoryByName(testCase.opts) + _, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) }) diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index e7125f70f8f94..9ca367f556b71 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -17,8 +17,9 @@ import ( ) // GetStarredRepos returns the repos starred by a particular user -func GetStarredRepos(userID int64, private bool, listOptions db.ListOptions) ([]*Repository, error) { - sess := db.GetEngine(db.DefaultContext).Where("star.uid=?", userID). +func GetStarredRepos(ctx context.Context, userID int64, private bool, listOptions db.ListOptions) ([]*Repository, error) { + sess := db.GetEngine(ctx). + Where("star.uid=?", userID). Join("LEFT", "star", "`repository`.id=`star`.repo_id") if !private { sess = sess.And("is_private=?", false) @@ -36,8 +37,9 @@ func GetStarredRepos(userID int64, private bool, listOptions db.ListOptions) ([] } // GetWatchedRepos returns the repos watched by a particular user -func GetWatchedRepos(userID int64, private bool, listOptions db.ListOptions) ([]*Repository, int64, error) { - sess := db.GetEngine(db.DefaultContext).Where("watch.user_id=?", userID). +func GetWatchedRepos(ctx context.Context, userID int64, private bool, listOptions db.ListOptions) ([]*Repository, int64, error) { + sess := db.GetEngine(ctx). + Where("watch.user_id=?", userID). And("`watch`.mode<>?", WatchModeDont). Join("LEFT", "watch", "`repository`.id=`watch`.repo_id") if !private { diff --git a/models/user/user.go b/models/user/user.go index c36fc21c770ec..1a71acb0b7273 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -1042,14 +1042,15 @@ func GetUserEmailsByNames(ctx context.Context, names []string) []string { } // GetMaileableUsersByIDs gets users from ids, but only if they can receive mails -func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) { +func GetMaileableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([]*User, error) { if len(ids) == 0 { return nil, nil } ous := make([]*User, 0, len(ids)) if isMention { - return ous, db.GetEngine(db.DefaultContext).In("id", ids). + return ous, db.GetEngine(ctx). + In("id", ids). Where("`type` = ?", UserTypeIndividual). And("`prohibit_login` = ?", false). And("`is_active` = ?", true). @@ -1057,7 +1058,8 @@ func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) { Find(&ous) } - return ous, db.GetEngine(db.DefaultContext).In("id", ids). + return ous, db.GetEngine(ctx). + In("id", ids). Where("`type` = ?", UserTypeIndividual). And("`prohibit_login` = ?", false). And("`is_active` = ?", true). @@ -1090,10 +1092,10 @@ func GetUserNameByID(ctx context.Context, id int64) (string, error) { } // GetUserIDsByNames returns a slice of ids corresponds to names. -func GetUserIDsByNames(names []string, ignoreNonExistent bool) ([]int64, error) { +func GetUserIDsByNames(ctx context.Context, names []string, ignoreNonExistent bool) ([]int64, error) { ids := make([]int64, 0, len(names)) for _, name := range names { - u, err := GetUserByName(db.DefaultContext, name) + u, err := GetUserByName(ctx, name) if err != nil { if ignoreNonExistent { continue diff --git a/models/user/user_test.go b/models/user/user_test.go index 5f2ac0a60c17d..1cdfb5978c865 100644 --- a/models/user/user_test.go +++ b/models/user/user_test.go @@ -257,12 +257,12 @@ func TestGetUserIDsByNames(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // ignore non existing - IDs, err := user_model.GetUserIDsByNames([]string{"user1", "user2", "none_existing_user"}, true) + IDs, err := user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "user2", "none_existing_user"}, true) assert.NoError(t, err) assert.Equal(t, []int64{1, 2}, IDs) // ignore non existing - IDs, err = user_model.GetUserIDsByNames([]string{"user1", "do_not_exist"}, false) + IDs, err = user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "do_not_exist"}, false) assert.Error(t, err) assert.Equal(t, []int64(nil), IDs) } @@ -270,14 +270,14 @@ func TestGetUserIDsByNames(t *testing.T) { func TestGetMaileableUsersByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - results, err := user_model.GetMaileableUsersByIDs([]int64{1, 4}, false) + results, err := user_model.GetMaileableUsersByIDs(db.DefaultContext, []int64{1, 4}, false) assert.NoError(t, err) assert.Len(t, results, 1) if len(results) > 1 { assert.Equal(t, results[0].ID, 1) } - results, err = user_model.GetMaileableUsersByIDs([]int64{1, 4}, true) + results, err = user_model.GetMaileableUsersByIDs(db.DefaultContext, []int64{1, 4}, true) assert.NoError(t, err) assert.Len(t, results, 2) if len(results) > 2 { diff --git a/modules/convert/issue.go b/modules/convert/issue.go index 5364367a80964..7c11b2a89f874 100644 --- a/modules/convert/issue.go +++ b/modules/convert/issue.go @@ -5,6 +5,7 @@ package convert import ( + "context" "fmt" "net/url" "strings" @@ -22,17 +23,17 @@ import ( // it assumes some fields assigned with values: // Required - Poster, Labels, // Optional - Milestone, Assignee, PullRequest -func ToAPIIssue(issue *issues_model.Issue) *api.Issue { - if err := issue.LoadLabels(db.DefaultContext); err != nil { +func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { + if err := issue.LoadLabels(ctx); err != nil { return &api.Issue{} } - if err := issue.LoadPoster(); err != nil { + if err := issue.LoadPoster(ctx); err != nil { return &api.Issue{} } - if err := issue.LoadRepo(db.DefaultContext); err != nil { + if err := issue.LoadRepo(ctx); err != nil { return &api.Issue{} } - if err := issue.Repo.GetOwner(db.DefaultContext); err != nil { + if err := issue.Repo.GetOwner(ctx); err != nil { return &api.Issue{} } @@ -64,14 +65,14 @@ func ToAPIIssue(issue *issues_model.Issue) *api.Issue { apiIssue.Closed = issue.ClosedUnix.AsTimePtr() } - if err := issue.LoadMilestone(); err != nil { + if err := issue.LoadMilestone(ctx); err != nil { return &api.Issue{} } if issue.Milestone != nil { apiIssue.Milestone = ToAPIMilestone(issue.Milestone) } - if err := issue.LoadAssignees(db.DefaultContext); err != nil { + if err := issue.LoadAssignees(ctx); err != nil { return &api.Issue{} } if len(issue.Assignees) > 0 { @@ -81,7 +82,7 @@ func ToAPIIssue(issue *issues_model.Issue) *api.Issue { apiIssue.Assignee = ToUser(issue.Assignees[0], nil) // For compatibility, we're keeping the first assignee as `apiIssue.Assignee` } if issue.IsPull { - if err := issue.LoadPullRequest(); err != nil { + if err := issue.LoadPullRequest(ctx); err != nil { return &api.Issue{} } apiIssue.PullRequest = &api.PullRequestMeta{ @@ -99,16 +100,16 @@ func ToAPIIssue(issue *issues_model.Issue) *api.Issue { } // ToAPIIssueList converts an IssueList to API format -func ToAPIIssueList(il issues_model.IssueList) []*api.Issue { +func ToAPIIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue { result := make([]*api.Issue, len(il)) for i := range il { - result[i] = ToAPIIssue(il[i]) + result[i] = ToAPIIssue(ctx, il[i]) } return result } // ToTrackedTime converts TrackedTime to API format -func ToTrackedTime(t *issues_model.TrackedTime) (apiT *api.TrackedTime) { +func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.TrackedTime) { apiT = &api.TrackedTime{ ID: t.ID, IssueID: t.IssueID, @@ -118,7 +119,7 @@ func ToTrackedTime(t *issues_model.TrackedTime) (apiT *api.TrackedTime) { Created: t.Created, } if t.Issue != nil { - apiT.Issue = ToAPIIssue(t.Issue) + apiT.Issue = ToAPIIssue(ctx, t.Issue) } if t.User != nil { apiT.UserName = t.User.Name @@ -169,10 +170,10 @@ func ToStopWatches(sws []*issues_model.Stopwatch) (api.StopWatches, error) { } // ToTrackedTimeList converts TrackedTimeList to API format -func ToTrackedTimeList(tl issues_model.TrackedTimeList) api.TrackedTimeList { +func ToTrackedTimeList(ctx context.Context, tl issues_model.TrackedTimeList) api.TrackedTimeList { result := make([]*api.TrackedTime, 0, len(tl)) for _, t := range tl { - result = append(result, ToTrackedTime(t)) + result = append(result, ToTrackedTime(ctx, t)) } return result } diff --git a/modules/convert/issue_comment.go b/modules/convert/issue_comment.go index 73ad345fa43f9..c33cf5c1116de 100644 --- a/modules/convert/issue_comment.go +++ b/modules/convert/issue_comment.go @@ -5,7 +5,8 @@ package convert import ( - "code.gitea.io/gitea/models/db" + "context" + issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -28,8 +29,8 @@ func ToComment(c *issues_model.Comment) *api.Comment { } // ToTimelineComment converts a issues_model.Comment to the api.TimelineComment format -func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.TimelineComment { - err := c.LoadMilestone() +func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User) *api.TimelineComment { + err := c.LoadMilestone(ctx) if err != nil { log.Error("LoadMilestone: %v", err) return nil @@ -107,25 +108,25 @@ func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.Time return nil } - comment.TrackedTime = ToTrackedTime(c.Time) + comment.TrackedTime = ToTrackedTime(ctx, c.Time) } if c.RefIssueID != 0 { - issue, err := issues_model.GetIssueByID(db.DefaultContext, c.RefIssueID) + issue, err := issues_model.GetIssueByID(ctx, c.RefIssueID) if err != nil { log.Error("GetIssueByID(%d): %v", c.RefIssueID, err) return nil } - comment.RefIssue = ToAPIIssue(issue) + comment.RefIssue = ToAPIIssue(ctx, issue) } if c.RefCommentID != 0 { - com, err := issues_model.GetCommentByID(db.DefaultContext, c.RefCommentID) + com, err := issues_model.GetCommentByID(ctx, c.RefCommentID) if err != nil { log.Error("GetCommentByID(%d): %v", c.RefCommentID, err) return nil } - err = com.LoadPoster() + err = com.LoadPoster(ctx) if err != nil { log.Error("LoadPoster: %v", err) return nil @@ -138,17 +139,17 @@ func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.Time var repo *repo_model.Repository if c.Label.BelongsToOrg() { var err error - org, err = user_model.GetUserByID(c.Label.OrgID) + org, err = user_model.GetUserByIDCtx(ctx, c.Label.OrgID) if err != nil { - log.Error("GetUserByID(%d): %v", c.Label.OrgID, err) + log.Error("GetUserByIDCtx(%d): %v", c.Label.OrgID, err) return nil } } if c.Label.BelongsToRepo() { var err error - repo, err = repo_model.GetRepositoryByID(c.Label.RepoID) + repo, err = repo_model.GetRepositoryByIDCtx(ctx, c.Label.RepoID) if err != nil { - log.Error("GetRepositoryByID(%d): %v", c.Label.RepoID, err) + log.Error("GetRepositoryByIDCtx(%d): %v", c.Label.RepoID, err) return nil } } @@ -167,7 +168,7 @@ func ToTimelineComment(c *issues_model.Comment, doer *user_model.User) *api.Time } if c.DependentIssue != nil { - comment.DependentIssue = ToAPIIssue(c.DependentIssue) + comment.DependentIssue = ToAPIIssue(ctx, c.DependentIssue) } return comment diff --git a/modules/convert/pull.go b/modules/convert/pull.go index 9c31f9bd2c182..ca9a4c39c5a5b 100644 --- a/modules/convert/pull.go +++ b/modules/convert/pull.go @@ -33,13 +33,13 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u return nil } - apiIssue := ToAPIIssue(pr.Issue) - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + apiIssue := ToAPIIssue(ctx, pr.Issue) + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("GetRepositoryById[%d]: %v", pr.ID, err) return nil } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("GetRepositoryById[%d]: %v", pr.ID, err) return nil } diff --git a/modules/convert/pull_test.go b/modules/convert/pull_test.go index a6ccbaca5897d..a0a672d3a5178 100644 --- a/modules/convert/pull_test.go +++ b/modules/convert/pull_test.go @@ -7,6 +7,7 @@ package convert import ( "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" @@ -22,8 +23,8 @@ func TestPullRequest_APIFormat(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadAttributes()) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) apiPullRequest := ToAPIPullRequest(git.DefaultContext, pr, nil) assert.NotNil(t, apiPullRequest) assert.EqualValues(t, &structs.PRBranchInfo{ @@ -36,8 +37,8 @@ func TestPullRequest_APIFormat(t *testing.T) { // withOut HeadRepo pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadIssue()) - assert.NoError(t, pr.LoadAttributes()) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) + assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) // simulate fork deletion pr.HeadRepo = nil pr.HeadRepoID = 100000 diff --git a/modules/doctor/dbconsistency.go b/modules/doctor/dbconsistency.go index 89d974a35002d..602b2e523ed19 100644 --- a/modules/doctor/dbconsistency.go +++ b/modules/doctor/dbconsistency.go @@ -18,13 +18,13 @@ import ( type consistencyCheck struct { Name string - Counter func() (int64, error) - Fixer func() (int64, error) + Counter func(context.Context) (int64, error) + Fixer func(context.Context) (int64, error) FixedMessage string } func (c *consistencyCheck) Run(ctx context.Context, logger log.Logger, autofix bool) error { - count, err := c.Counter() + count, err := c.Counter(ctx) if err != nil { logger.Critical("Error: %v whilst counting %s", err, c.Name) return err @@ -32,7 +32,7 @@ func (c *consistencyCheck) Run(ctx context.Context, logger log.Logger, autofix b if count > 0 { if autofix { var fixed int64 - if fixed, err = c.Fixer(); err != nil { + if fixed, err = c.Fixer(ctx); err != nil { logger.Critical("Error: %v whilst fixing %s", err, c.Name) return err } @@ -54,9 +54,9 @@ func (c *consistencyCheck) Run(ctx context.Context, logger log.Logger, autofix b return nil } -func asFixer(fn func() error) func() (int64, error) { - return func() (int64, error) { - err := fn() +func asFixer(fn func(ctx context.Context) error) func(ctx context.Context) (int64, error) { + return func(ctx context.Context) (int64, error) { + err := fn(ctx) return -1, err } } @@ -64,11 +64,11 @@ func asFixer(fn func() error) func() (int64, error) { func genericOrphanCheck(name, subject, refobject, joincond string) consistencyCheck { return consistencyCheck{ Name: name, - Counter: func() (int64, error) { - return db.CountOrphanedObjects(subject, refobject, joincond) + Counter: func(ctx context.Context) (int64, error) { + return db.CountOrphanedObjects(ctx, subject, refobject, joincond) }, - Fixer: func() (int64, error) { - err := db.DeleteOrphanedObjects(subject, refobject, joincond) + Fixer: func(ctx context.Context) (int64, error) { + err := db.DeleteOrphanedObjects(ctx, subject, refobject, joincond) return -1, err }, } diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index da6a200aef2ff..5b0279d1abb62 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -291,7 +291,7 @@ func populateIssueIndexer(ctx context.Context) { return default: } - repos, _, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ + repos, _, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{Page: page, PageSize: repo_model.RepositoryListDefaultPageSize}, OrderBy: db.SearchOrderByID, Private: true, @@ -313,14 +313,14 @@ func populateIssueIndexer(ctx context.Context) { return default: } - UpdateRepoIndexer(repo) + UpdateRepoIndexer(ctx, repo) } } } // UpdateRepoIndexer add/update all issues of the repositories -func UpdateRepoIndexer(repo *repo_model.Repository) { - is, err := issues_model.Issues(&issues_model.IssuesOptions{ +func UpdateRepoIndexer(ctx context.Context, repo *repo_model.Repository) { + is, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ RepoID: repo.ID, IsClosed: util.OptionalBoolNone, IsPull: util.OptionalBoolNone, @@ -329,8 +329,8 @@ func UpdateRepoIndexer(repo *repo_model.Repository) { log.Error("Issues: %v", err) return } - if err = issues_model.IssueList(is).LoadDiscussComments(); err != nil { - log.Error("LoadComments: %v", err) + if err = issues_model.IssueList(is).LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments: %v", err) return } for _, issue := range is { @@ -360,11 +360,11 @@ func UpdateIssueIndexer(issue *issues_model.Issue) { } // DeleteRepoIssueIndexer deletes repo's all issues indexes -func DeleteRepoIssueIndexer(repo *repo_model.Repository) { +func DeleteRepoIssueIndexer(ctx context.Context, repo *repo_model.Repository) { var ids []int64 - ids, err := issues_model.GetIssueIDsByRepoID(db.DefaultContext, repo.ID) + ids, err := issues_model.GetIssueIDsByRepoID(ctx, repo.ID) if err != nil { - log.Error("getIssueIDsByRepoID failed: %v", err) + log.Error("GetIssueIDsByRepoID failed: %v", err) return } diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index 44d115f3d72a1..d029405664be5 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -5,20 +5,18 @@ package action import ( + "context" "fmt" "path" "strings" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" - "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/util" ) @@ -34,18 +32,18 @@ func NewNotifier() base.Notifier { return &actionNotifier{} } -func (a *actionNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := issue.LoadPoster(); err != nil { +func (a *actionNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := issue.LoadPoster(ctx); err != nil { log.Error("issue.LoadPoster: %v", err) return } - if err := issue.LoadRepo(db.DefaultContext); err != nil { + if err := issue.LoadRepo(ctx); err != nil { log.Error("issue.LoadRepo: %v", err) return } repo := issue.Repo - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: issue.Poster.ID, ActUser: issue.Poster, OpType: activities_model.ActionCreateIssue, @@ -59,7 +57,7 @@ func (a *actionNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*u } // NotifyIssueChangeStatus notifies close or reopen issue to notifiers -func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { +func (a *actionNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { // Compose comment action, could be plain comment, close or reopen issue/pull request. // This object will be used to notify watchers in the end of function. act := &activities_model.Action{ @@ -86,13 +84,13 @@ func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *i } // Notify watchers for whatever action comes in, ignore if no action type. - if err := activities_model.NotifyWatchers(act); err != nil { + if err := activities_model.NotifyWatchers(ctx, act); err != nil { log.Error("NotifyWatchers: %v", err) } } // NotifyCreateIssueComment notifies comment on an issue to notifiers -func (a *actionNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (a *actionNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { act := &activities_model.Action{ @@ -122,26 +120,26 @@ func (a *actionNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *r } // Notify watchers for whatever action comes in, ignore if no action type. - if err := activities_model.NotifyWatchers(act); err != nil { + if err := activities_model.NotifyWatchers(ctx, act); err != nil { log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, mentions []*user_model.User) { - if err := pull.LoadIssue(); err != nil { +func (a *actionNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) { + if err := pull.LoadIssue(ctx); err != nil { log.Error("pull.LoadIssue: %v", err) return } - if err := pull.Issue.LoadRepo(db.DefaultContext); err != nil { + if err := pull.Issue.LoadRepo(ctx); err != nil { log.Error("pull.Issue.LoadRepo: %v", err) return } - if err := pull.Issue.LoadPoster(); err != nil { + if err := pull.Issue.LoadPoster(ctx); err != nil { log.Error("pull.Issue.LoadPoster: %v", err) return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: pull.Issue.Poster.ID, ActUser: pull.Issue.Poster, OpType: activities_model.ActionCreatePullRequest, @@ -154,8 +152,8 @@ func (a *actionNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, me } } -func (a *actionNotifier) NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionRenameRepo, @@ -168,8 +166,8 @@ func (a *actionNotifier) NotifyRenameRepository(doer *user_model.User, repo *rep } } -func (a *actionNotifier) NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionTransferRepo, @@ -182,8 +180,8 @@ func (a *actionNotifier) NotifyTransferRepository(doer *user_model.User, repo *r } } -func (a *actionNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionCreateRepo, @@ -195,8 +193,8 @@ func (a *actionNotifier) NotifyCreateRepository(doer, u *user_model.User, repo * } } -func (a *actionNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionCreateRepo, @@ -208,11 +206,8 @@ func (a *actionNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, re } } -func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("actionNotifier.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - - if err := review.LoadReviewer(); err != nil { +func (a *actionNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { + if err := review.LoadReviewer(ctx); err != nil { log.Error("LoadReviewer '%d/%d': %v", review.ID, review.ReviewerID, err) return } @@ -269,8 +264,8 @@ func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r } } -func (*actionNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (*actionNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionMergePullRequest, @@ -283,8 +278,8 @@ func (*actionNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer } } -func (*actionNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (*actionNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionAutoMergePullRequest, @@ -297,12 +292,12 @@ func (*actionNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, } } -func (*actionNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +func (*actionNotifier) NotifyPullRevieweDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { reviewerName := review.Reviewer.Name if len(review.OriginalAuthor) > 0 { reviewerName = review.OriginalAuthor } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: activities_model.ActionPullReviewDismissed, @@ -317,7 +312,7 @@ func (*actionNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *i } } -func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (a *actionNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { data, err := json.Marshal(commits) if err != nil { log.Error("Marshal: %v", err) @@ -336,7 +331,7 @@ func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_m opType = activities_model.ActionDeleteBranch } - if err = activities_model.NotifyWatchers(&activities_model.Action{ + if err = activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: pusher.ID, ActUser: pusher, OpType: opType, @@ -346,17 +341,17 @@ func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_m RefName: opts.RefFullName, IsPrivate: repo.IsPrivate, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (a *actionNotifier) NotifyCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { opType := activities_model.ActionCommitRepo if refType == "tag" { // has sent same action in `NotifyPushCommits`, so skip it. return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: opType, @@ -365,17 +360,17 @@ func (a *actionNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (a *actionNotifier) NotifyDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { opType := activities_model.ActionDeleteBranch if refType == "tag" { // has sent same action in `NotifyPushCommits`, so skip it. return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: opType, @@ -384,20 +379,20 @@ func (a *actionNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (a *actionNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { data, err := json.Marshal(commits) if err != nil { log.Error("json.Marshal: %v", err) return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: repo.OwnerID, - ActUser: repo.MustOwner(), + ActUser: repo.MustOwner(ctx), OpType: activities_model.ActionMirrorSyncPush, RepoID: repo.ID, Repo: repo, @@ -405,44 +400,44 @@ func (a *actionNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *re RefName: opts.RefFullName, Content: string(data), }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifySyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: repo.OwnerID, - ActUser: repo.MustOwner(), + ActUser: repo.MustOwner(ctx), OpType: activities_model.ActionMirrorSyncCreate, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { - if err := activities_model.NotifyWatchers(&activities_model.Action{ +func (a *actionNotifier) NotifySyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: repo.OwnerID, - ActUser: repo.MustOwner(), + ActUser: repo.MustOwner(ctx), OpType: activities_model.ActionMirrorSyncDelete, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, RefName: refFullName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } -func (a *actionNotifier) NotifyNewRelease(rel *repo_model.Release) { - if err := rel.LoadAttributes(); err != nil { - log.Error("NotifyNewRelease: %v", err) +func (a *actionNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + if err := rel.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) return } - if err := activities_model.NotifyWatchers(&activities_model.Action{ + if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{ ActUserID: rel.PublisherID, ActUser: rel.Publisher, OpType: activities_model.ActionPublishRelease, @@ -452,6 +447,6 @@ func (a *actionNotifier) NotifyNewRelease(rel *repo_model.Release) { Content: rel.Title, RefName: rel.TagName, }); err != nil { - log.Error("notifyWatchers: %v", err) + log.Error("NotifyWatchers: %v", err) } } diff --git a/modules/notification/action/action_test.go b/modules/notification/action/action_test.go index 79a938d6cddc6..dc31b3189b5d6 100644 --- a/modules/notification/action/action_test.go +++ b/modules/notification/action/action_test.go @@ -10,6 +10,7 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -46,7 +47,7 @@ func TestRenameRepoAction(t *testing.T) { } unittest.AssertNotExistsBean(t, actionBean) - NewNotifier().NotifyRenameRepository(user, repo, oldRepoName) + NewNotifier().NotifyRenameRepository(db.DefaultContext, user, repo, oldRepoName) unittest.AssertExistsAndLoadBean(t, actionBean) unittest.CheckConsistencyFor(t, &activities_model.Action{}) diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index 9edab8213fab4..2f7deac88e230 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -5,6 +5,8 @@ package base import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -15,50 +17,50 @@ import ( // Notifier defines an interface to notify receiver type Notifier interface { Run() - NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) - NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) - NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) - NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) - NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) - NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) - NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) - NotifyIssueChangeStatus(*user_model.User, *issues_model.Issue, *issues_model.Comment, bool) - NotifyDeleteIssue(*user_model.User, *issues_model.Issue) - NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) - NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) - NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) - NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) - NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) - NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) - NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldRef string) - NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, + NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) + NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) + NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) + NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) + NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldRepoName string) + NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) + NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) + NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) + NotifyDeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) + NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) + NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) + NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) + NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) + NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) + NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) + NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) + NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label) - NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) - NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) - NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) - NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) - NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) - NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) - NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) - NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) - NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) - NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, + NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) + NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) + NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) + NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) + NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) + NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) + NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) + NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) + NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) + NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User) - NotifyUpdateComment(*user_model.User, *issues_model.Comment, string) - NotifyDeleteComment(*user_model.User, *issues_model.Comment) - NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) - NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) - NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) - NotifyNewRelease(rel *repo_model.Release) - NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) - NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) - NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) - NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) - NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) - NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) - NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) - NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) - NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) - NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) - NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) + NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) + NotifyDeleteComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment) + NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) + NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) + NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) + NotifyNewRelease(ctx context.Context, rel *repo_model.Release) + NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) + NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) + NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) + NotifyCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) + NotifyDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) + NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) + NotifySyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) + NotifySyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) + NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) + NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) + NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) } diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index f051fbc26f461..88e0c93de1923 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -5,6 +5,8 @@ package base import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -22,179 +24,179 @@ func (*NullNotifier) Run() { } // NotifyCreateIssueComment places a place holder function -func (*NullNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (*NullNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User) { } // NotifyNewIssue places a place holder function -func (*NullNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func (*NullNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { } // NotifyIssueChangeStatus places a place holder function -func (*NullNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { +func (*NullNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { } // NotifyDeleteIssue notify when some issue deleted -func (*NullNotifier) NotifyDeleteIssue(doer *user_model.User, issue *issues_model.Issue) { +func (*NullNotifier) NotifyDeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { } // NotifyNewPullRequest places a place holder function -func (*NullNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { +func (*NullNotifier) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { } // NotifyPullRequestReview places a place holder function -func (*NullNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { +func (*NullNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { } // NotifyPullRequestCodeComment places a place holder function -func (*NullNotifier) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { +func (*NullNotifier) NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { } // NotifyMergePullRequest places a place holder function -func (*NullNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (*NullNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { } // NotifyAutoMergePullRequest places a place holder function -func (*NullNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (*NullNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { } // NotifyPullRequestSynchronized places a place holder function -func (*NullNotifier) NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { +func (*NullNotifier) NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { } // NotifyPullRequestChangeTargetBranch places a place holder function -func (*NullNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { +func (*NullNotifier) NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { } // NotifyPullRequestPushCommits notifies when push commits to pull request's head branch -func (*NullNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { +func (*NullNotifier) NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { } -// NotifyPullRevieweDismiss notifies when a review was dismissed by repo admin -func (*NullNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +// NotifyPullReviewDismiss notifies when a review was dismissed by repo admin +func (*NullNotifier) NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { } // NotifyUpdateComment places a place holder function -func (*NullNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { +func (*NullNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { } // NotifyDeleteComment places a place holder function -func (*NullNotifier) NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) { +func (*NullNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment) { } // NotifyNewWikiPage places a place holder function -func (*NullNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (*NullNotifier) NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { } // NotifyEditWikiPage places a place holder function -func (*NullNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (*NullNotifier) NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { } // NotifyDeleteWikiPage places a place holder function -func (*NullNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) { +func (*NullNotifier) NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { } // NotifyNewRelease places a place holder function -func (*NullNotifier) NotifyNewRelease(rel *repo_model.Release) { +func (*NullNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { } // NotifyUpdateRelease places a place holder function -func (*NullNotifier) NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { +func (*NullNotifier) NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { } // NotifyDeleteRelease places a place holder function -func (*NullNotifier) NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { +func (*NullNotifier) NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { } // NotifyIssueChangeMilestone places a place holder function -func (*NullNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { +func (*NullNotifier) NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { } // NotifyIssueChangeContent places a place holder function -func (*NullNotifier) NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { +func (*NullNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { } // NotifyIssueChangeAssignee places a place holder function -func (*NullNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func (*NullNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { } // NotifyPullReviewRequest places a place holder function -func (*NullNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func (*NullNotifier) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { } // NotifyIssueClearLabels places a place holder function -func (*NullNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) { +func (*NullNotifier) NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { } // NotifyIssueChangeTitle places a place holder function -func (*NullNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func (*NullNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { } // NotifyIssueChangeRef places a place holder function -func (*NullNotifier) NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func (*NullNotifier) NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { } // NotifyIssueChangeLabels places a place holder function -func (*NullNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, +func (*NullNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label) { } // NotifyCreateRepository places a place holder function -func (*NullNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { } // NotifyDeleteRepository places a place holder function -func (*NullNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { } // NotifyForkRepository places a place holder function -func (*NullNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { +func (*NullNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { } // NotifyMigrateRepository places a place holder function -func (*NullNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { } // NotifyPushCommits notifies commits pushed to notifiers -func (*NullNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (*NullNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { } // NotifyCreateRef notifies branch or tag creation to notifiers -func (*NullNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (*NullNotifier) NotifyCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { } // NotifyDeleteRef notifies branch or tag deletion to notifiers -func (*NullNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (*NullNotifier) NotifyDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { } // NotifyRenameRepository places a place holder function -func (*NullNotifier) NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { +func (*NullNotifier) NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { } // NotifyTransferRepository places a place holder function -func (*NullNotifier) NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { +func (*NullNotifier) NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { } // NotifySyncPushCommits places a place holder function -func (*NullNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (*NullNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { } // NotifySyncCreateRef places a place holder function -func (*NullNotifier) NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (*NullNotifier) NotifySyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { } // NotifySyncDeleteRef places a place holder function -func (*NullNotifier) NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (*NullNotifier) NotifySyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { } // NotifyRepoPendingTransfer places a place holder function -func (*NullNotifier) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { +func (*NullNotifier) NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { } // NotifyPackageCreate places a place holder function -func (*NullNotifier) NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func (*NullNotifier) NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { } // NotifyPackageDelete places a place holder function -func (*NullNotifier) NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func (*NullNotifier) NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { } diff --git a/modules/notification/indexer/indexer.go b/modules/notification/indexer/indexer.go index fc9afdd4bcf9b..2bacd5dec02e8 100644 --- a/modules/notification/indexer/indexer.go +++ b/modules/notification/indexer/indexer.go @@ -5,6 +5,8 @@ package indexer import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -29,13 +31,13 @@ func NewNotifier() base.Notifier { return &indexerNotifier{} } -func (r *indexerNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (r *indexerNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { if comment.Type == issues_model.CommentTypeComment { if issue.Comments == nil { - if err := issue.LoadDiscussComments(); err != nil { - log.Error("LoadComments failed: %v", err) + if err := issue.LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments failed: %v", err) return } } else { @@ -46,15 +48,15 @@ func (r *indexerNotifier) NotifyCreateIssueComment(doer *user_model.User, repo * } } -func (r *indexerNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func (r *indexerNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { issue_indexer.UpdateIssueIndexer(issue) } -func (r *indexerNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { +func (r *indexerNotifier) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { issue_indexer.UpdateIssueIndexer(pr.Issue) } -func (r *indexerNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { +func (r *indexerNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { if c.Type == issues_model.CommentTypeComment { var found bool if c.Issue.Comments != nil { @@ -68,8 +70,8 @@ func (r *indexerNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m } if !found { - if err := c.Issue.LoadDiscussComments(); err != nil { - log.Error("LoadComments failed: %v", err) + if err := c.Issue.LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments failed: %v", err) return } } @@ -78,9 +80,9 @@ func (r *indexerNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m } } -func (r *indexerNotifier) NotifyDeleteComment(doer *user_model.User, comment *issues_model.Comment) { +func (r *indexerNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { if comment.Type == issues_model.CommentTypeComment { - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } @@ -97,8 +99,8 @@ func (r *indexerNotifier) NotifyDeleteComment(doer *user_model.User, comment *is } if !found { - if err := comment.Issue.LoadDiscussComments(); err != nil { - log.Error("LoadComments failed: %v", err) + if err := comment.Issue.LoadDiscussComments(ctx); err != nil { + log.Error("LoadDiscussComments failed: %v", err) return } } @@ -107,15 +109,15 @@ func (r *indexerNotifier) NotifyDeleteComment(doer *user_model.User, comment *is } } -func (r *indexerNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { - issue_indexer.DeleteRepoIssueIndexer(repo) +func (r *indexerNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { + issue_indexer.DeleteRepoIssueIndexer(ctx, repo) if setting.Indexer.RepoIndexerEnabled { code_indexer.UpdateRepoIndexer(repo) } } -func (r *indexerNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { - issue_indexer.UpdateRepoIndexer(repo) +func (r *indexerNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + issue_indexer.UpdateRepoIndexer(ctx, repo) if setting.Indexer.RepoIndexerEnabled && !repo.IsEmpty { code_indexer.UpdateRepoIndexer(repo) } @@ -124,7 +126,7 @@ func (r *indexerNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo } } -func (r *indexerNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (r *indexerNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { if setting.Indexer.RepoIndexerEnabled && opts.RefFullName == git.BranchPrefix+repo.DefaultBranch { code_indexer.UpdateRepoIndexer(repo) } @@ -133,7 +135,7 @@ func (r *indexerNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_ } } -func (r *indexerNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func (r *indexerNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { if setting.Indexer.RepoIndexerEnabled && opts.RefFullName == git.BranchPrefix+repo.DefaultBranch { code_indexer.UpdateRepoIndexer(repo) } @@ -142,14 +144,14 @@ func (r *indexerNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *r } } -func (r *indexerNotifier) NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { +func (r *indexerNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { issue_indexer.UpdateIssueIndexer(issue) } -func (r *indexerNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func (r *indexerNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { issue_indexer.UpdateIssueIndexer(issue) } -func (r *indexerNotifier) NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldRef string) { +func (r *indexerNotifier) NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) { issue_indexer.UpdateIssueIndexer(issue) } diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index 54f561839d0f4..123fa0e65aefb 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -5,16 +5,15 @@ package mail import ( + "context" "fmt" activities_model "code.gitea.io/gitea/models/activities" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" - "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/services/mailer" ) @@ -29,12 +28,9 @@ func NewNotifier() base.Notifier { return &mailNotifier{} } -func (m *mailNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (m *mailNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyCreateIssueComment Issue[%d] #%d in [%d]", issue.ID, issue.Index, issue.RepoID)) - defer finished() - var act activities_model.ActionType if comment.Type == issues_model.CommentTypeClose { act = activities_model.ActionCloseIssue @@ -53,13 +49,13 @@ func (m *mailNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *rep } } -func (m *mailNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := mailer.MailParticipants(issue, issue.Poster, activities_model.ActionCreateIssue, mentions); err != nil { +func (m *mailNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := mailer.MailParticipants(ctx, issue, issue.Poster, activities_model.ActionCreateIssue, mentions); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { +func (m *mailNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { var actionType activities_model.ActionType if issue.IsPull { if isClosed { @@ -75,33 +71,30 @@ func (m *mailNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *iss } } - if err := mailer.MailParticipants(issue, doer, actionType, nil); err != nil { + if err := mailer.MailParticipants(ctx, issue, doer, actionType, nil); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { - if err := issue.LoadPullRequest(); err != nil { +func (m *mailNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + if err := issue.LoadPullRequest(ctx); err != nil { log.Error("issue.LoadPullRequest: %v", err) return } if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issue.PullRequest.IsWorkInProgress() { - if err := mailer.MailParticipants(issue, doer, activities_model.ActionPullRequestReadyForReview, nil); err != nil { + if err := mailer.MailParticipants(ctx, issue, doer, activities_model.ActionPullRequestReadyForReview, nil); err != nil { log.Error("MailParticipants: %v", err) } } } -func (m *mailNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { - if err := mailer.MailParticipants(pr.Issue, pr.Issue.Poster, activities_model.ActionCreatePullRequest, mentions); err != nil { +func (m *mailNotifier) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { + if err := mailer.MailParticipants(ctx, pr.Issue, pr.Issue.Poster, activities_model.ActionCreatePullRequest, mentions); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *mailNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, r *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { var act activities_model.ActionType if comment.Type == issues_model.CommentTypeClose { act = activities_model.ActionCloseIssue @@ -115,60 +108,54 @@ func (m *mailNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r * } } -func (m *mailNotifier) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestCodeComment Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *mailNotifier) NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { if err := mailer.MailMentionsComment(ctx, pr, comment, mentions); err != nil { log.Error("MailMentionsComment: %v", err) } } -func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func (m *mailNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { // mail only sent to added assignees and not self-assignee if !removed && doer.ID != assignee.ID && assignee.EmailNotifications() != user_model.EmailNotificationsDisabled { ct := fmt.Sprintf("Assigned #%d.", issue.Index) - if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{assignee}); err != nil { + if err := mailer.SendIssueAssignedMail(ctx, issue, doer, ct, comment, []*user_model.User{assignee}); err != nil { log.Error("Error in SendIssueAssignedMail for issue[%d] to assignee[%d]: %v", issue.ID, assignee.ID, err) } } } -func (m *mailNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func (m *mailNotifier) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { if isRequest && doer.ID != reviewer.ID && reviewer.EmailNotifications() != user_model.EmailNotificationsDisabled { ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL()) - if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil { + if err := mailer.SendIssueAssignedMail(ctx, issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil { log.Error("Error in SendIssueAssignedMail for issue[%d] to reviewer[%d]: %v", issue.ID, reviewer.ID, err) } } } -func (m *mailNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := pr.LoadIssue(); err != nil { - log.Error("pr.LoadIssue: %v", err) +func (m *mailNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - if err := mailer.MailParticipants(pr.Issue, doer, activities_model.ActionMergePullRequest, nil); err != nil { + if err := mailer.MailParticipants(ctx, pr.Issue, doer, activities_model.ActionMergePullRequest, nil); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := pr.LoadIssue(); err != nil { +func (m *mailNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { log.Error("pr.LoadIssue: %v", err) return } - if err := mailer.MailParticipants(pr.Issue, doer, activities_model.ActionAutoMergePullRequest, nil); err != nil { + if err := mailer.MailParticipants(ctx, pr.Issue, doer, activities_model.ActionAutoMergePullRequest, nil); err != nil { log.Error("MailParticipants: %v", err) } } -func (m *mailNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestPushCommits Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *mailNotifier) NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { var err error - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { log.Error("comment.LoadIssue: %v", err) return } @@ -176,35 +163,29 @@ func (m *mailNotifier) NotifyPullRequestPushCommits(doer *user_model.User, pr *i log.Error("comment.Issue.LoadRepo: %v", err) return } - if err = comment.Issue.LoadPullRequest(); err != nil { + if err = comment.Issue.LoadPullRequest(ctx); err != nil { log.Error("comment.Issue.LoadPullRequest: %v", err) return } - if err = comment.Issue.PullRequest.LoadBaseRepoCtx(ctx); err != nil { + if err = comment.Issue.PullRequest.LoadBaseRepo(ctx); err != nil { log.Error("comment.Issue.PullRequest.LoadBaseRepo: %v", err) return } if err := comment.LoadPushCommits(ctx); err != nil { log.Error("comment.LoadPushCommits: %v", err) } - m.NotifyCreateIssueComment(doer, comment.Issue.Repo, comment.Issue, comment, nil) + m.NotifyCreateIssueComment(ctx, doer, comment.Issue.Repo, comment.Issue, comment, nil) } -func (m *mailNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRevieweDismiss Review[%d] in Issue[%d]", review.ID, review.IssueID)) - defer finished() - +func (m *mailNotifier) NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { if err := mailer.MailParticipantsComment(ctx, comment, activities_model.ActionPullReviewDismissed, review.Issue, nil); err != nil { log.Error("MailParticipantsComment: %v", err) } } -func (m *mailNotifier) NotifyNewRelease(rel *repo_model.Release) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyNewRelease rel[%d]%s in [%d]", rel.ID, rel.Title, rel.RepoID)) - defer finished() - - if err := rel.LoadAttributes(); err != nil { - log.Error("NotifyNewRelease: %v", err) +func (m *mailNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + if err := rel.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) return } @@ -215,8 +196,8 @@ func (m *mailNotifier) NotifyNewRelease(rel *repo_model.Release) { mailer.MailNewRelease(ctx, rel) } -func (m *mailNotifier) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { - if err := mailer.SendRepoTransferNotifyMail(doer, newOwner, repo); err != nil { - log.Error("NotifyRepoPendingTransfer: %v", err) +func (m *mailNotifier) NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { + if err := mailer.SendRepoTransferNotifyMail(ctx, doer, newOwner, repo); err != nil { + log.Error("SendRepoTransferNotifyMail: %v", err) } } diff --git a/modules/notification/mirror/mirror.go b/modules/notification/mirror/mirror.go index 646b09a4ab6e6..159c44ee6cd06 100644 --- a/modules/notification/mirror/mirror.go +++ b/modules/notification/mirror/mirror.go @@ -5,6 +5,8 @@ package mirror import ( + "context" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -24,16 +26,16 @@ func NewNotifier() base.Notifier { return &mirrorNotifier{} } -func (m *mirrorNotifier) NotifyPushCommits(_ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { - syncPushMirrorWithSyncOnCommit(repo.ID) +func (m *mirrorNotifier) NotifyPushCommits(ctx context.Context, _ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { + syncPushMirrorWithSyncOnCommit(ctx, repo.ID) } -func (m *mirrorNotifier) NotifySyncPushCommits(_ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { - syncPushMirrorWithSyncOnCommit(repo.ID) +func (m *mirrorNotifier) NotifySyncPushCommits(ctx context.Context, _ *user_model.User, repo *repo_model.Repository, _ *repository.PushUpdateOptions, _ *repository.PushCommits) { + syncPushMirrorWithSyncOnCommit(ctx, repo.ID) } -func syncPushMirrorWithSyncOnCommit(repoID int64) { - pushMirrors, err := repo_model.GetPushMirrorsSyncedOnCommit(repoID) +func syncPushMirrorWithSyncOnCommit(ctx context.Context, repoID int64) { + pushMirrors, err := repo_model.GetPushMirrorsSyncedOnCommit(ctx, repoID) if err != nil { log.Error("repo_model.GetPushMirrorsSyncedOnCommit failed: %v", err) return diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 7bdc0a04c4969..a117a60815b47 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -5,6 +5,8 @@ package notification import ( + "context" + issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -41,313 +43,313 @@ func NewContext() { } // NotifyNewWikiPage notifies creating new wiki pages to notifiers -func NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { for _, notifier := range notifiers { - notifier.NotifyNewWikiPage(doer, repo, page, comment) + notifier.NotifyNewWikiPage(ctx, doer, repo, page, comment) } } // NotifyEditWikiPage notifies editing or renaming wiki pages to notifiers -func NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { for _, notifier := range notifiers { - notifier.NotifyEditWikiPage(doer, repo, page, comment) + notifier.NotifyEditWikiPage(ctx, doer, repo, page, comment) } } // NotifyDeleteWikiPage notifies deleting wiki pages to notifiers -func NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) { +func NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { for _, notifier := range notifiers { - notifier.NotifyDeleteWikiPage(doer, repo, page) + notifier.NotifyDeleteWikiPage(ctx, doer, repo, page) } } // NotifyCreateIssueComment notifies issue comment related message to notifiers -func NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { for _, notifier := range notifiers { - notifier.NotifyCreateIssueComment(doer, repo, issue, comment, mentions) + notifier.NotifyCreateIssueComment(ctx, doer, repo, issue, comment, mentions) } } // NotifyNewIssue notifies new issue to notifiers -func NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyNewIssue(issue, mentions) + notifier.NotifyNewIssue(ctx, issue, mentions) } } // NotifyIssueChangeStatus notifies close or reopen issue to notifiers -func NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { +func NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeStatus(doer, issue, actionComment, closeOrReopen) + notifier.NotifyIssueChangeStatus(ctx, doer, issue, actionComment, closeOrReopen) } } // NotifyDeleteIssue notify when some issue deleted -func NotifyDeleteIssue(doer *user_model.User, issue *issues_model.Issue) { +func NotifyDeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { for _, notifier := range notifiers { - notifier.NotifyDeleteIssue(doer, issue) + notifier.NotifyDeleteIssue(ctx, doer, issue) } } // NotifyMergePullRequest notifies merge pull request to notifiers -func NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { for _, notifier := range notifiers { - notifier.NotifyMergePullRequest(pr, doer) + notifier.NotifyMergePullRequest(ctx, doer, pr) } } // NotifyAutoMergePullRequest notifies merge pull request to notifiers -func NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { for _, notifier := range notifiers { - notifier.NotifyAutoMergePullRequest(pr, doer) + notifier.NotifyAutoMergePullRequest(ctx, doer, pr) } } // NotifyNewPullRequest notifies new pull request to notifiers -func NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { +func NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyNewPullRequest(pr, mentions) + notifier.NotifyNewPullRequest(ctx, pr, mentions) } } // NotifyPullRequestSynchronized notifies Synchronized pull request -func NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { +func NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { for _, notifier := range notifiers { - notifier.NotifyPullRequestSynchronized(doer, pr) + notifier.NotifyPullRequestSynchronized(ctx, doer, pr) } } // NotifyPullRequestReview notifies new pull request review -func NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { +func NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyPullRequestReview(pr, review, comment, mentions) + notifier.NotifyPullRequestReview(ctx, pr, review, comment, mentions) } } // NotifyPullRequestCodeComment notifies new pull request code comment -func NotifyPullRequestCodeComment(pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { +func NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User) { for _, notifier := range notifiers { - notifier.NotifyPullRequestCodeComment(pr, comment, mentions) + notifier.NotifyPullRequestCodeComment(ctx, pr, comment, mentions) } } // NotifyPullRequestChangeTargetBranch notifies when a pull request's target branch was changed -func NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { +func NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { for _, notifier := range notifiers { - notifier.NotifyPullRequestChangeTargetBranch(doer, pr, oldBranch) + notifier.NotifyPullRequestChangeTargetBranch(ctx, doer, pr, oldBranch) } } // NotifyPullRequestPushCommits notifies when push commits to pull request's head branch -func NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { +func NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyPullRequestPushCommits(doer, pr, comment) + notifier.NotifyPullRequestPushCommits(ctx, doer, pr, comment) } } -// NotifyPullRevieweDismiss notifies when a review was dismissed by repo admin -func NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +// NotifyPullReviewDismiss notifies when a review was dismissed by repo admin +func NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyPullRevieweDismiss(doer, review, comment) + notifier.NotifyPullReviewDismiss(ctx, doer, review, comment) } } // NotifyUpdateComment notifies update comment to notifiers -func NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { +func NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { for _, notifier := range notifiers { - notifier.NotifyUpdateComment(doer, c, oldContent) + notifier.NotifyUpdateComment(ctx, doer, c, oldContent) } } // NotifyDeleteComment notifies delete comment to notifiers -func NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) { +func NotifyDeleteComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyDeleteComment(doer, c) + notifier.NotifyDeleteComment(ctx, doer, c) } } // NotifyNewRelease notifies new release to notifiers -func NotifyNewRelease(rel *repo_model.Release) { +func NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { for _, notifier := range notifiers { - notifier.NotifyNewRelease(rel) + notifier.NotifyNewRelease(ctx, rel) } } // NotifyUpdateRelease notifies update release to notifiers -func NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { +func NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { for _, notifier := range notifiers { - notifier.NotifyUpdateRelease(doer, rel) + notifier.NotifyUpdateRelease(ctx, doer, rel) } } // NotifyDeleteRelease notifies delete release to notifiers -func NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { +func NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { for _, notifier := range notifiers { - notifier.NotifyDeleteRelease(doer, rel) + notifier.NotifyDeleteRelease(ctx, doer, rel) } } // NotifyIssueChangeMilestone notifies change milestone to notifiers -func NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { +func NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeMilestone(doer, issue, oldMilestoneID) + notifier.NotifyIssueChangeMilestone(ctx, doer, issue, oldMilestoneID) } } // NotifyIssueChangeContent notifies change content to notifiers -func NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { +func NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeContent(doer, issue, oldContent) + notifier.NotifyIssueChangeContent(ctx, doer, issue, oldContent) } } // NotifyIssueChangeAssignee notifies change content to notifiers -func NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeAssignee(doer, issue, assignee, removed, comment) + notifier.NotifyIssueChangeAssignee(ctx, doer, issue, assignee, removed, comment) } } // NotifyPullReviewRequest notifies Request Review change -func NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { for _, notifier := range notifiers { - notifier.NotifyPullReviewRequest(doer, issue, reviewer, isRequest, comment) + notifier.NotifyPullReviewRequest(ctx, doer, issue, reviewer, isRequest, comment) } } // NotifyIssueClearLabels notifies clear labels to notifiers -func NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) { +func NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { for _, notifier := range notifiers { - notifier.NotifyIssueClearLabels(doer, issue) + notifier.NotifyIssueClearLabels(ctx, doer, issue) } } // NotifyIssueChangeTitle notifies change title to notifiers -func NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { +func NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeTitle(doer, issue, oldTitle) + notifier.NotifyIssueChangeTitle(ctx, doer, issue, oldTitle) } } // NotifyIssueChangeRef notifies change reference to notifiers -func NotifyIssueChangeRef(doer *user_model.User, issue *issues_model.Issue, oldRef string) { +func NotifyIssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeRef(doer, issue, oldRef) + notifier.NotifyIssueChangeRef(ctx, doer, issue, oldRef) } } // NotifyIssueChangeLabels notifies change labels to notifiers -func NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, +func NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label, ) { for _, notifier := range notifiers { - notifier.NotifyIssueChangeLabels(doer, issue, addedLabels, removedLabels) + notifier.NotifyIssueChangeLabels(ctx, doer, issue, addedLabels, removedLabels) } } // NotifyCreateRepository notifies create repository to notifiers -func NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyCreateRepository(doer, u, repo) + notifier.NotifyCreateRepository(ctx, doer, u, repo) } } // NotifyMigrateRepository notifies create repository to notifiers -func NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyMigrateRepository(doer, u, repo) + notifier.NotifyMigrateRepository(ctx, doer, u, repo) } } // NotifyTransferRepository notifies create repository to notifiers -func NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, newOwnerName string) { +func NotifyTransferRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, newOwnerName string) { for _, notifier := range notifiers { - notifier.NotifyTransferRepository(doer, repo, newOwnerName) + notifier.NotifyTransferRepository(ctx, doer, repo, newOwnerName) } } // NotifyDeleteRepository notifies delete repository to notifiers -func NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { +func NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyDeleteRepository(doer, repo) + notifier.NotifyDeleteRepository(ctx, doer, repo) } } // NotifyForkRepository notifies fork repository to notifiers -func NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { +func NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyForkRepository(doer, oldRepo, repo) + notifier.NotifyForkRepository(ctx, doer, oldRepo, repo) } } // NotifyRenameRepository notifies repository renamed -func NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldName string) { +func NotifyRenameRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldName string) { for _, notifier := range notifiers { - notifier.NotifyRenameRepository(doer, repo, oldName) + notifier.NotifyRenameRepository(ctx, doer, repo, oldName) } } // NotifyPushCommits notifies commits pushed to notifiers -func NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { for _, notifier := range notifiers { - notifier.NotifyPushCommits(pusher, repo, opts, commits) + notifier.NotifyPushCommits(ctx, pusher, repo, opts, commits) } } // NotifyCreateRef notifies branch or tag creation to notifiers -func NotifyCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func NotifyCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { for _, notifier := range notifiers { - notifier.NotifyCreateRef(pusher, repo, refType, refFullName, refID) + notifier.NotifyCreateRef(ctx, pusher, repo, refType, refFullName, refID) } } // NotifyDeleteRef notifies branch or tag deletion to notifiers -func NotifyDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func NotifyDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { for _, notifier := range notifiers { - notifier.NotifyDeleteRef(pusher, repo, refType, refFullName) + notifier.NotifyDeleteRef(ctx, pusher, repo, refType, refFullName) } } // NotifySyncPushCommits notifies commits pushed to notifiers -func NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { +func NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { for _, notifier := range notifiers { - notifier.NotifySyncPushCommits(pusher, repo, opts, commits) + notifier.NotifySyncPushCommits(ctx, pusher, repo, opts, commits) } } // NotifySyncCreateRef notifies branch or tag creation to notifiers -func NotifySyncCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func NotifySyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { for _, notifier := range notifiers { - notifier.NotifySyncCreateRef(pusher, repo, refType, refFullName, refID) + notifier.NotifySyncCreateRef(ctx, pusher, repo, refType, refFullName, refID) } } // NotifySyncDeleteRef notifies branch or tag deletion to notifiers -func NotifySyncDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func NotifySyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { for _, notifier := range notifiers { - notifier.NotifySyncDeleteRef(pusher, repo, refType, refFullName) + notifier.NotifySyncDeleteRef(ctx, pusher, repo, refType, refFullName) } } // NotifyRepoPendingTransfer notifies creation of pending transfer to notifiers -func NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { +func NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { for _, notifier := range notifiers { - notifier.NotifyRepoPendingTransfer(doer, newOwner, repo) + notifier.NotifyRepoPendingTransfer(ctx, doer, newOwner, repo) } } // NotifyPackageCreate notifies creation of a package to notifiers -func NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { for _, notifier := range notifiers { - notifier.NotifyPackageCreate(doer, pd) + notifier.NotifyPackageCreate(ctx, doer, pd) } } // NotifyPackageDelete notifies deletion of a package to notifiers -func NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) { +func NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { for _, notifier := range notifiers { - notifier.NotifyPackageDelete(doer, pd) + notifier.NotifyPackageDelete(ctx, doer, pd) } } diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index 0e2b3e67c7f6e..a38289c9768d3 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -5,6 +5,8 @@ package ui import ( + "context" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" @@ -54,7 +56,7 @@ func (ns *notificationService) Run() { graceful.GetManager().RunWithShutdownFns(ns.issueQueue.Run) } -func (ns *notificationService) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (ns *notificationService) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { opts := issueNotificationOpts{ @@ -78,7 +80,7 @@ func (ns *notificationService) NotifyCreateIssueComment(doer *user_model.User, r } } -func (ns *notificationService) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { +func (ns *notificationService) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: issue.ID, NotificationAuthorID: issue.Poster.ID, @@ -92,15 +94,15 @@ func (ns *notificationService) NotifyNewIssue(issue *issues_model.Issue, mention } } -func (ns *notificationService) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { +func (ns *notificationService) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: issue.ID, NotificationAuthorID: doer.ID, }) } -func (ns *notificationService) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { - if err := issue.LoadPullRequest(); err != nil { +func (ns *notificationService) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + if err := issue.LoadPullRequest(ctx); err != nil { log.Error("issue.LoadPullRequest: %v", err) return } @@ -112,24 +114,24 @@ func (ns *notificationService) NotifyIssueChangeTitle(doer *user_model.User, iss } } -func (ns *notificationService) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (ns *notificationService) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: pr.Issue.ID, NotificationAuthorID: doer.ID, }) } -func (ns *notificationService) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - ns.NotifyMergePullRequest(pr, doer) +func (ns *notificationService) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + ns.NotifyMergePullRequest(ctx, doer, pr) } -func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { - if err := pr.LoadIssue(); err != nil { +func (ns *notificationService) NotifyNewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) { + if err := pr.LoadIssue(ctx); err != nil { log.Error("Unable to load issue: %d for pr: %d: Error: %v", pr.IssueID, pr.ID, err) return } toNotify := make(container.Set[int64], 32) - repoWatchers, err := repo_model.GetRepoWatchersIDs(db.DefaultContext, pr.Issue.RepoID) + repoWatchers, err := repo_model.GetRepoWatchersIDs(ctx, pr.Issue.RepoID) if err != nil { log.Error("GetRepoWatchersIDs: %v", err) return @@ -137,7 +139,7 @@ func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest for _, id := range repoWatchers { toNotify.Add(id) } - issueParticipants, err := issues_model.GetParticipantsIDsByIssueID(pr.IssueID) + issueParticipants, err := issues_model.GetParticipantsIDsByIssueID(ctx, pr.IssueID) if err != nil { log.Error("GetParticipantsIDsByIssueID: %v", err) return @@ -158,7 +160,7 @@ func (ns *notificationService) NotifyNewPullRequest(pr *issues_model.PullRequest } } -func (ns *notificationService) NotifyPullRequestReview(pr *issues_model.PullRequest, r *issues_model.Review, c *issues_model.Comment, mentions []*user_model.User) { +func (ns *notificationService) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, r *issues_model.Review, c *issues_model.Comment, mentions []*user_model.User) { opts := issueNotificationOpts{ IssueID: pr.Issue.ID, NotificationAuthorID: r.Reviewer.ID, @@ -180,7 +182,7 @@ func (ns *notificationService) NotifyPullRequestReview(pr *issues_model.PullRequ } } -func (ns *notificationService) NotifyPullRequestCodeComment(pr *issues_model.PullRequest, c *issues_model.Comment, mentions []*user_model.User) { +func (ns *notificationService) NotifyPullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, c *issues_model.Comment, mentions []*user_model.User) { for _, mention := range mentions { _ = ns.issueQueue.Push(issueNotificationOpts{ IssueID: pr.Issue.ID, @@ -191,7 +193,7 @@ func (ns *notificationService) NotifyPullRequestCodeComment(pr *issues_model.Pul } } -func (ns *notificationService) NotifyPullRequestPushCommits(doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { +func (ns *notificationService) NotifyPullRequestPushCommits(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, comment *issues_model.Comment) { opts := issueNotificationOpts{ IssueID: pr.IssueID, NotificationAuthorID: doer.ID, @@ -200,7 +202,7 @@ func (ns *notificationService) NotifyPullRequestPushCommits(doer *user_model.Use _ = ns.issueQueue.Push(opts) } -func (ns *notificationService) NotifyPullRevieweDismiss(doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { +func (ns *notificationService) NotifyPullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) { opts := issueNotificationOpts{ IssueID: review.IssueID, NotificationAuthorID: doer.ID, @@ -209,7 +211,7 @@ func (ns *notificationService) NotifyPullRevieweDismiss(doer *user_model.User, r _ = ns.issueQueue.Push(opts) } -func (ns *notificationService) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { +func (ns *notificationService) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { if !removed && doer.ID != assignee.ID { opts := issueNotificationOpts{ IssueID: issue.ID, @@ -225,7 +227,7 @@ func (ns *notificationService) NotifyIssueChangeAssignee(doer *user_model.User, } } -func (ns *notificationService) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { +func (ns *notificationService) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { if isRequest { opts := issueNotificationOpts{ IssueID: issue.ID, @@ -241,8 +243,11 @@ func (ns *notificationService) NotifyPullReviewRequest(doer *user_model.User, is } } -func (ns *notificationService) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { - if err := activities_model.CreateRepoTransferNotification(doer, newOwner, repo); err != nil { - log.Error("NotifyRepoPendingTransfer: %v", err) +func (ns *notificationService) NotifyRepoPendingTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) { + err := db.AutoTx(ctx, func(ctx context.Context) error { + return activities_model.CreateRepoTransferNotification(ctx, doer, newOwner, repo) + }) + if err != nil { + log.Error("CreateRepoTransferNotification: %v", err) } } diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index c591e1e34dbcd..37ce7661f220c 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -5,9 +5,8 @@ package webhook import ( - "fmt" + "context" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/perm" @@ -18,10 +17,8 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" - "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -39,12 +36,9 @@ func NewNotifier() base.Notifier { return &webhookNotifier{} } -func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *issues_model.Issue) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueClearLabels User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - if err := issue.LoadPoster(); err != nil { - log.Error("loadPoster: %v", err) +func (m *webhookNotifier) NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { + if err := issue.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) return } @@ -53,10 +47,10 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i return } - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest: %v", err) return } @@ -72,7 +66,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueLabel, &api.IssuePayload{ Action: api.HookIssueLabelCleared, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -82,12 +76,12 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i } } -func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { - oldMode, _ := access_model.AccessLevel(doer, oldRepo) - mode, _ := access_model.AccessLevel(doer, repo) +func (m *webhookNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { + oldMode, _ := access_model.AccessLevel(ctx, doer, oldRepo) + mode, _ := access_model.AccessLevel(ctx, doer, repo) // forked webhook - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: oldRepo}, webhook.HookEventFork, &api.ForkPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: oldRepo}, webhook.HookEventFork, &api.ForkPayload{ Forkee: convert.ToRepo(oldRepo, oldMode), Repo: convert.ToRepo(repo, mode), Sender: convert.ToUser(doer, nil), @@ -95,11 +89,11 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err) } - u := repo.MustOwner() + u := repo.MustOwner(ctx) // Add to hook queue for created repo after session commit. if u.IsOrganization() { - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -110,9 +104,9 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r } } -func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (m *webhookNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { // Add to hook queue for created repo after session commit. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -122,22 +116,20 @@ func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo } } -func (m *webhookNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) { - u := repo.MustOwner() - - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ +func (m *webhookNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoDeleted, Repository: convert.ToRepo(repo, perm.AccessModeOwner), - Organization: convert.ToUser(u, nil), + Organization: convert.ToUser(repo.MustOwner(ctx), nil), Sender: convert.ToUser(doer, nil), }); err != nil { log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) } } -func (m *webhookNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) { +func (m *webhookNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { // Add to hook queue for created repo after session commit. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{ Action: api.HookRepoCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Organization: convert.ToUser(u, nil), @@ -147,14 +139,11 @@ func (m *webhookNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo } } -func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeAssignee User: %s[%d] Issue[%d] #%d in [%d] Assignee %s[%d] removed: %t", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID, assignee.Name, assignee.ID, removed)) - defer finished() - +func (m *webhookNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { if issue.IsPull { - mode, _ := access_model.AccessLevelUnit(doer, issue.Repo, unit.TypePullRequests) + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypePullRequests) - if err := issue.LoadPullRequest(); err != nil { + if err := issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest failed: %v", err) return } @@ -176,10 +165,10 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue return } } else { - mode, _ := access_model.AccessLevelUnit(doer, issue.Repo, unit.TypeIssues) + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypeIssues) apiIssue := &api.IssuePayload{ Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), } @@ -196,14 +185,11 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue } } -func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issues_model.Issue, oldTitle string) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeTitle User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) +func (m *webhookNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest failed: %v", err) return } @@ -229,7 +215,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *i From: oldTitle, }, }, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -240,14 +226,11 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *i } } -func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeStatus User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) +func (m *webhookNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("LoadPullRequest: %v", err) return } @@ -267,7 +250,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue * } else { apiIssue := &api.IssuePayload{ Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), } @@ -283,21 +266,21 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue * } } -func (m *webhookNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := issue.LoadRepo(db.DefaultContext); err != nil { +func (m *webhookNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := issue.LoadRepo(ctx); err != nil { log.Error("issue.LoadRepo: %v", err) return } - if err := issue.LoadPoster(); err != nil { + if err := issue.LoadPoster(ctx); err != nil { log.Error("issue.LoadPoster: %v", err) return } - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{ + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{ Action: api.HookIssueOpened, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(issue.Poster, nil), }); err != nil { @@ -305,11 +288,8 @@ func (m *webhookNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []* } } -func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyNewPullRequest Pull[%d] #%d in [%d]", pull.ID, pull.Index, pull.BaseRepoID)) - defer finished() - - if err := pull.LoadIssue(); err != nil { +func (m *webhookNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) { + if err := pull.LoadIssue(ctx); err != nil { log.Error("pull.LoadIssue: %v", err) return } @@ -317,12 +297,12 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, m log.Error("pull.Issue.LoadRepo: %v", err) return } - if err := pull.Issue.LoadPoster(); err != nil { + if err := pull.Issue.LoadPoster(ctx); err != nil { log.Error("pull.Issue.LoadPoster: %v", err) return } - mode, _ := access_model.AccessLevel(pull.Issue.Poster, pull.Issue.Repo) + mode, _ := access_model.AccessLevel(ctx, pull.Issue.Poster, pull.Issue.Repo) if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pull.Issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueOpened, Index: pull.Issue.Index, @@ -334,11 +314,8 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, m } } -func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue *issues_model.Issue, oldContent string) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeContent User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) +func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) var err error if issue.IsPull { issue.PullRequest.Issue = issue @@ -363,7 +340,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue From: oldContent, }, }, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -373,17 +350,17 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue } } -func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) { - if err := c.LoadPoster(); err != nil { +func (m *webhookNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { + if err := c.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return } - if err := c.LoadIssue(); err != nil { + if err := c.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } - if err := c.Issue.LoadAttributes(db.DefaultContext); err != nil { + if err := c.Issue.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } @@ -395,10 +372,10 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m eventType = webhook.HookEventIssueComment } - mode, _ := access_model.AccessLevel(doer, c.Issue.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ + mode, _ := access_model.AccessLevel(ctx, doer, c.Issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentEdited, - Issue: convert.ToAPIIssue(c.Issue), + Issue: convert.ToAPIIssue(ctx, c.Issue), Comment: convert.ToComment(c), Changes: &api.ChangesPayload{ Body: &api.ChangesFromPayload{ @@ -413,7 +390,7 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m } } -func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, +func (m *webhookNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { var eventType webhook.HookEventType @@ -423,10 +400,10 @@ func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo * eventType = webhook.HookEventIssueComment } - mode, _ := access_model.AccessLevel(doer, repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ + mode, _ := access_model.AccessLevel(ctx, doer, repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentCreated, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Comment: convert.ToComment(comment), Repository: convert.ToRepo(repo, mode), Sender: convert.ToUser(doer, nil), @@ -436,19 +413,19 @@ func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo * } } -func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *issues_model.Comment) { +func (m *webhookNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { var err error - if err = comment.LoadPoster(); err != nil { + if err = comment.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return } - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } - if err = comment.Issue.LoadAttributes(db.DefaultContext); err != nil { + if err = comment.Issue.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } @@ -460,10 +437,10 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is eventType = webhook.HookEventIssueComment } - mode, _ := access_model.AccessLevel(doer, comment.Issue.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ + mode, _ := access_model.AccessLevel(ctx, doer, comment.Issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ Action: api.HookIssueCommentDeleted, - Issue: convert.ToAPIIssue(comment.Issue), + Issue: convert.ToAPIIssue(ctx, comment.Issue), Comment: convert.ToComment(comment), Repository: convert.ToRepo(comment.Issue.Repo, mode), Sender: convert.ToUser(doer, nil), @@ -473,9 +450,9 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is } } -func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (m *webhookNotifier) NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { // Add to hook queue for created wiki page. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ Action: api.HookWikiCreated, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Sender: convert.ToUser(doer, nil), @@ -486,9 +463,9 @@ func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_mo } } -func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) { +func (m *webhookNotifier) NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { // Add to hook queue for edit wiki page. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ Action: api.HookWikiEdited, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Sender: convert.ToUser(doer, nil), @@ -499,9 +476,9 @@ func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_m } } -func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) { +func (m *webhookNotifier) NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { // Add to hook queue for edit wiki page. - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{ Action: api.HookWikiDeleted, Repository: convert.ToRepo(repo, perm.AccessModeOwner), Sender: convert.ToUser(doer, nil), @@ -511,12 +488,9 @@ func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo } } -func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue, +func (m *webhookNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, addedLabels, removedLabels []*issues_model.Label, ) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeLabels User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - var err error if err = issue.LoadRepo(ctx); err != nil { @@ -524,18 +498,18 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * return } - if err = issue.LoadPoster(); err != nil { + if err = issue.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return } - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) if issue.IsPull { - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { log.Error("loadPullRequest: %v", err) return } - if err = issue.PullRequest.LoadIssue(); err != nil { + if err = issue.PullRequest.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return } @@ -550,7 +524,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueLabel, &api.IssuePayload{ Action: api.HookIssueLabelUpdated, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -560,10 +534,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * } } -func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeMilestone User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) - defer finished() - +func (m *webhookNotifier) NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { var hookAction api.HookIssueAction var err error if issue.MilestoneID > 0 { @@ -572,14 +543,14 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu hookAction = api.HookIssueDemilestoned } - if err = issue.LoadAttributes(db.DefaultContext); err != nil { + if err = issue.LoadAttributes(ctx); err != nil { log.Error("issue.LoadAttributes failed: %v", err) return } - mode, _ := access_model.AccessLevel(doer, issue.Repo) + mode, _ := access_model.AccessLevel(ctx, doer, issue.Repo) if issue.IsPull { - err = issue.PullRequest.LoadIssue() + err = issue.PullRequest.LoadIssue(ctx) if err != nil { log.Error("LoadIssue: %v", err) return @@ -595,7 +566,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueMilestone, &api.IssuePayload{ Action: hookAction, Index: issue.Index, - Issue: convert.ToAPIIssue(issue), + Issue: convert.ToAPIIssue(ctx, issue), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), }) @@ -605,10 +576,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu } } -func (m *webhookNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPushCommits User: %s[%d] in %s[%d]", pusher.Name, pusher.ID, repo.FullName(), repo.ID)) - defer finished() - +func (m *webhookNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { apiPusher := convert.ToUser(pusher, nil) apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) if err != nil { @@ -632,23 +600,20 @@ func (m *webhookNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_ } } -func (m *webhookNotifier) NotifyAutoMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { +func (m *webhookNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { // just redirect to the NotifyMergePullRequest - m.NotifyMergePullRequest(pr, doer) + m.NotifyMergePullRequest(ctx, doer, pr) } -func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyMergePullRequest Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (*webhookNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { // Reload pull request information. - if err := pr.LoadAttributes(); err != nil { + if err := pr.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } - if err := pr.LoadIssue(); err != nil { - log.Error("LoadAttributes: %v", err) + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } @@ -657,7 +622,7 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doe return } - mode, err := access_model.AccessLevel(doer, pr.Issue.Repo) + mode, err := access_model.AccessLevel(ctx, doer, pr.Issue.Repo) if err != nil { log.Error("models.AccessLevel: %v", err) return @@ -672,29 +637,21 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doe Action: api.HookIssueClosed, } - err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pr.Issue.Repo}, webhook.HookEventPullRequest, apiPullRequest) - if err != nil { + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pr.Issue.Repo}, webhook.HookEventPullRequest, apiPullRequest); err != nil { log.Error("PrepareWebhooks: %v", err) } } -func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPullRequestChangeTargetBranch Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - - issue := pr.Issue - if !issue.IsPull { +func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - var err error - if err = issue.LoadPullRequest(); err != nil { - log.Error("LoadPullRequest failed: %v", err) - return - } - issue.PullRequest.Issue = issue - mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) - err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{ + issue := pr.Issue + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueEdited, Index: issue.Index, Changes: &api.ChangesPayload{ @@ -702,20 +659,15 @@ func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.U From: oldBranch, }, }, - PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), Repository: convert.ToRepo(issue.Repo, mode), Sender: convert.ToUser(doer, nil), - }) - - if err != nil { - log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + }); err != nil { + log.Error("PrepareWebhooks [pr: %d]: %v", pr.ID, err) } } -func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - +func (m *webhookNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { var reviewHookType webhook.HookEventType switch review.Type { @@ -731,12 +683,12 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, return } - if err := pr.LoadIssue(); err != nil { - log.Error("pr.LoadIssue: %v", err) + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - mode, err := access_model.AccessLevel(review.Issue.Poster, review.Issue.Repo) + mode, err := access_model.AccessLevel(ctx, review.Issue.Poster, review.Issue.Repo) if err != nil { log.Error("models.AccessLevel: %v", err) return @@ -756,12 +708,12 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, } } -func (m *webhookNotifier) NotifyCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { +func (m *webhookNotifier) NotifyCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { apiPusher := convert.ToUser(pusher, nil) apiRepo := convert.ToRepo(repo, perm.AccessModeNone) refName := git.RefEndName(refFullName) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventCreate, &api.CreatePayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventCreate, &api.CreatePayload{ Ref: refName, Sha: refID, RefType: refType, @@ -772,15 +724,12 @@ func (m *webhookNotifier) NotifyCreateRef(pusher *user_model.User, repo *repo_mo } } -func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *user_model.User, pr *issues_model.PullRequest) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyPullRequestSynchronized Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) - defer finished() - - if err := pr.LoadIssue(); err != nil { - log.Error("pr.LoadIssue: %v", err) +func (m *webhookNotifier) NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) return } - if err := pr.Issue.LoadAttributes(db.DefaultContext); err != nil { + if err := pr.Issue.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } @@ -796,12 +745,12 @@ func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *user_model.User, p } } -func (m *webhookNotifier) NotifyDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { +func (m *webhookNotifier) NotifyDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { apiPusher := convert.ToUser(pusher, nil) apiRepo := convert.ToRepo(repo, perm.AccessModeNone) refName := git.RefEndName(refFullName) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventDelete, &api.DeletePayload{ + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventDelete, &api.DeletePayload{ Ref: refName, RefType: refType, PusherType: api.PusherTypeUser, @@ -812,14 +761,14 @@ func (m *webhookNotifier) NotifyDeleteRef(pusher *user_model.User, repo *repo_mo } } -func sendReleaseHook(doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) { - if err := rel.LoadAttributes(); err != nil { +func sendReleaseHook(ctx context.Context, doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) { + if err := rel.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return } - mode, _ := access_model.AccessLevel(doer, rel.Repo) - if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: rel.Repo}, webhook.HookEventRelease, &api.ReleasePayload{ + mode, _ := access_model.AccessLevel(ctx, doer, rel.Repo) + if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: rel.Repo}, webhook.HookEventRelease, &api.ReleasePayload{ Action: action, Release: convert.ToRelease(rel), Repository: convert.ToRepo(rel.Repo, mode), @@ -829,22 +778,19 @@ func sendReleaseHook(doer *user_model.User, rel *repo_model.Release, action api. } } -func (m *webhookNotifier) NotifyNewRelease(rel *repo_model.Release) { - sendReleaseHook(rel.Publisher, rel, api.HookReleasePublished) +func (m *webhookNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + sendReleaseHook(ctx, rel.Publisher, rel, api.HookReleasePublished) } -func (m *webhookNotifier) NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { - sendReleaseHook(doer, rel, api.HookReleaseUpdated) +func (m *webhookNotifier) NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + sendReleaseHook(ctx, doer, rel, api.HookReleaseUpdated) } -func (m *webhookNotifier) NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { - sendReleaseHook(doer, rel, api.HookReleaseDeleted) +func (m *webhookNotifier) NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + sendReleaseHook(ctx, doer, rel, api.HookReleaseDeleted) } -func (m *webhookNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifySyncPushCommits User: %s[%d] in %s[%d]", pusher.Name, pusher.ID, repo.FullName(), repo.ID)) - defer finished() - +func (m *webhookNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { apiPusher := convert.ToUser(pusher, nil) apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) if err != nil { @@ -868,31 +814,28 @@ func (m *webhookNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *r } } -func (m *webhookNotifier) NotifySyncCreateRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { - m.NotifyCreateRef(pusher, repo, refType, refFullName, refID) +func (m *webhookNotifier) NotifySyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { + m.NotifyCreateRef(ctx, pusher, repo, refType, refFullName, refID) } -func (m *webhookNotifier) NotifySyncDeleteRef(pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { - m.NotifyDeleteRef(pusher, repo, refType, refFullName) +func (m *webhookNotifier) NotifySyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { + m.NotifyDeleteRef(ctx, pusher, repo, refType, refFullName) } -func (m *webhookNotifier) NotifyPackageCreate(doer *user_model.User, pd *packages_model.PackageDescriptor) { - notifyPackage(doer, pd, api.HookPackageCreated) +func (m *webhookNotifier) NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + notifyPackage(ctx, doer, pd, api.HookPackageCreated) } -func (m *webhookNotifier) NotifyPackageDelete(doer *user_model.User, pd *packages_model.PackageDescriptor) { - notifyPackage(doer, pd, api.HookPackageDeleted) +func (m *webhookNotifier) NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + notifyPackage(ctx, doer, pd, api.HookPackageDeleted) } -func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) { +func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) { source := webhook_services.EventSource{ Repository: pd.Repository, Owner: pd.Owner, } - ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.notifyPackage Package: %s[%d]", pd.Package.Name, pd.Package.ID)) - defer finished() - apiPackage, err := convert.ToPackage(ctx, pd, sender) if err != nil { log.Error("Error converting package: %v", err) diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 1d3a4658c20ea..f1360f4478837 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -288,7 +288,7 @@ func SyncReleasesWithTags(repo *repo_model.Repository, gitRepo *git.Repository) } for page := 1; ; page++ { opts.Page = page - rels, err := repo_model.GetReleasesByRepoID(repo.ID, opts) + rels, err := repo_model.GetReleasesByRepoID(gitRepo.Ctx, repo.ID, opts) if err != nil { return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) } diff --git a/routers/api/packages/conan/conan.go b/routers/api/packages/conan/conan.go index b69a674106ce7..188cfce2879a8 100644 --- a/routers/api/packages/conan/conan.go +++ b/routers/api/packages/conan/conan.go @@ -676,7 +676,7 @@ func deleteRecipeOrPackage(apictx *context.Context, rref *conan_module.RecipeRef } if versionDeleted { - notification.NotifyPackageDelete(apictx.Doer, pd) + notification.NotifyPackageDelete(apictx, apictx.Doer, pd) } return nil diff --git a/routers/api/v1/misc/nodeinfo.go b/routers/api/v1/misc/nodeinfo.go index bd629b87ca445..a4ba440356b43 100644 --- a/routers/api/v1/misc/nodeinfo.go +++ b/routers/api/v1/misc/nodeinfo.go @@ -42,7 +42,7 @@ func NodeInfo(ctx *context.APIContext) { usersActiveMonth := int(user_model.CountUsers(&user_model.CountUserFilter{LastLoginSince: &timeOneMonthAgo})) usersActiveHalfyear := int(user_model.CountUsers(&user_model.CountUserFilter{LastLoginSince: &timeHaveYearAgo})) - allIssues, _ := issues_model.CountIssues(&issues_model.IssuesOptions{}) + allIssues, _ := issues_model.CountIssues(ctx, &issues_model.IssuesOptions{}) allComments, _ := issues_model.CountComments(&issues_model.FindCommentsOptions{}) nodeInfoUsage = structs.NodeInfoUsage{ diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index f8e1fb0865aa3..6d9664400a55d 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -109,7 +109,7 @@ func ListRepoNotifications(ctx *context.APIContext) { } opts.RepoID = ctx.Repo.Repository.ID - totalCount, err := activities_model.CountNotifications(opts) + totalCount, err := activities_model.CountNotifications(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -120,7 +120,7 @@ func ListRepoNotifications(ctx *context.APIContext) { ctx.InternalServerError(err) return } - err = nl.LoadAttributes() + err = nl.LoadAttributes(ctx) if err != nil { ctx.InternalServerError(err) return @@ -217,12 +217,12 @@ func ReadRepoNotifications(ctx *context.APIContext) { changed := make([]*structs.NotificationThread, 0, len(nl)) for _, n := range nl { - notif, err := activities_model.SetNotificationStatus(n.ID, ctx.Doer, targetStatus) + notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) if err != nil { ctx.InternalServerError(err) return } - _ = notif.LoadAttributes() + _ = notif.LoadAttributes(ctx) changed = append(changed, convert.ToNotificationThread(notif)) } ctx.JSON(http.StatusResetContent, changed) diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go index 44a1d30a55db3..f8e4960912464 100644 --- a/routers/api/v1/notify/threads.go +++ b/routers/api/v1/notify/threads.go @@ -42,7 +42,7 @@ func GetThread(ctx *context.APIContext) { if n == nil { return } - if err := n.LoadAttributes(); err != nil && !issues_model.IsErrCommentNotExist(err) { + if err := n.LoadAttributes(ctx); err != nil && !issues_model.IsErrCommentNotExist(err) { ctx.InternalServerError(err) return } @@ -89,12 +89,12 @@ func ReadThread(ctx *context.APIContext) { targetStatus = activities_model.NotificationStatusRead } - notif, err := activities_model.SetNotificationStatus(n.ID, ctx.Doer, targetStatus) + notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) if err != nil { ctx.InternalServerError(err) return } - if err = notif.LoadAttributes(); err != nil && !issues_model.IsErrCommentNotExist(err) { + if err = notif.LoadAttributes(ctx); err != nil && !issues_model.IsErrCommentNotExist(err) { ctx.InternalServerError(err) return } @@ -102,7 +102,7 @@ func ReadThread(ctx *context.APIContext) { } func getThread(ctx *context.APIContext) *activities_model.Notification { - n, err := activities_model.GetNotificationByID(ctx.ParamsInt64(":id")) + n, err := activities_model.GetNotificationByID(ctx, ctx.ParamsInt64(":id")) if err != nil { if db.IsErrNotExist(err) { ctx.Error(http.StatusNotFound, "GetNotificationByID", err) diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 1b6706e16f1c0..5f4d8b35c2d5f 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -69,7 +69,7 @@ func ListNotifications(ctx *context.APIContext) { return } - totalCount, err := activities_model.CountNotifications(opts) + totalCount, err := activities_model.CountNotifications(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -80,7 +80,7 @@ func ListNotifications(ctx *context.APIContext) { ctx.InternalServerError(err) return } - err = nl.LoadAttributes() + err = nl.LoadAttributes(ctx) if err != nil { ctx.InternalServerError(err) return @@ -162,12 +162,12 @@ func ReadNotifications(ctx *context.APIContext) { changed := make([]*structs.NotificationThread, 0, len(nl)) for _, n := range nl { - notif, err := activities_model.SetNotificationStatus(n.ID, ctx.Doer, targetStatus) + notif, err := activities_model.SetNotificationStatus(ctx, n.ID, ctx.Doer, targetStatus) if err != nil { ctx.InternalServerError(err) return } - _ = notif.LoadAttributes() + _ = notif.LoadAttributes(ctx) changed = append(changed, convert.ToNotificationThread(notif)) } diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index f3e7834a4931c..b2bcc4d586084 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -542,7 +542,7 @@ func GetTeamRepos(ctx *context.APIContext) { } repos := make([]*api.Repository, len(teamRepos)) for i, repo := range teamRepos { - access, err := access_model.AccessLevel(ctx.Doer, repo) + access, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) return @@ -593,7 +593,7 @@ func GetTeamRepo(ctx *context.APIContext) { return } - access, err := access_model.AccessLevel(ctx.Doer, repo) + access, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) return @@ -650,7 +650,7 @@ func AddTeamRepository(ctx *context.APIContext) { if ctx.Written() { return } - if access, err := access_model.AccessLevel(ctx.Doer, repo); err != nil { + if access, err := access_model.AccessLevel(ctx, ctx.Doer, repo); err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return } else if access < perm.AccessModeAdmin { @@ -700,7 +700,7 @@ func RemoveTeamRepository(ctx *context.APIContext) { if ctx.Written() { return } - if access, err := access_model.AccessLevel(ctx.Doer, repo); err != nil { + if access, err := access_model.AccessLevel(ctx, ctx.Doer, repo); err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return } else if access < perm.AccessModeAdmin { diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 84a172e92bf00..d10a308df3a79 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -427,7 +427,7 @@ func CreateBranchProtection(ctx *context.APIContext) { requiredApprovals = form.RequiredApprovals } - whitelistUsers, err := user_model.GetUserIDsByNames(form.PushWhitelistUsernames, false) + whitelistUsers, err := user_model.GetUserIDsByNames(ctx, form.PushWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -436,7 +436,7 @@ func CreateBranchProtection(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } - mergeWhitelistUsers, err := user_model.GetUserIDsByNames(form.MergeWhitelistUsernames, false) + mergeWhitelistUsers, err := user_model.GetUserIDsByNames(ctx, form.MergeWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -445,7 +445,7 @@ func CreateBranchProtection(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err) return } - approvalsWhitelistUsers, err := user_model.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false) + approvalsWhitelistUsers, err := user_model.GetUserIDsByNames(ctx, form.ApprovalsWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -656,7 +656,7 @@ func EditBranchProtection(ctx *context.APIContext) { var whitelistUsers []int64 if form.PushWhitelistUsernames != nil { - whitelistUsers, err = user_model.GetUserIDsByNames(form.PushWhitelistUsernames, false) + whitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.PushWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -670,7 +670,7 @@ func EditBranchProtection(ctx *context.APIContext) { } var mergeWhitelistUsers []int64 if form.MergeWhitelistUsernames != nil { - mergeWhitelistUsers, err = user_model.GetUserIDsByNames(form.MergeWhitelistUsernames, false) + mergeWhitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.MergeWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) @@ -684,7 +684,7 @@ func EditBranchProtection(ctx *context.APIContext) { } var approvalsWhitelistUsers []int64 if form.ApprovalsWhitelistUsernames != nil { - approvalsWhitelistUsers, err = user_model.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false) + approvalsWhitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.ApprovalsWhitelistUsernames, false) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err) diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index 112a9562f0fdf..c0a79d1a63286 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -59,7 +59,7 @@ func ListForks(ctx *context.APIContext) { } apiForks := make([]*api.Repository, len(forks)) for i, fork := range forks { - access, err := access_model.AccessLevel(ctx.Doer, fork) + access, err := access_model.AccessLevel(ctx, ctx.Doer, fork) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 08e3e037417c0..60f9859e107ad 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -179,7 +179,7 @@ func SearchIssues(ctx *context.APIContext) { repoCond := repo_model.SearchRepositoryCondition(opts) repoIDs, _, err := repo_model.SearchRepositoryIDs(opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err) + ctx.Error(http.StatusInternalServerError, "SearchRepositoryIDs", err) return } @@ -268,7 +268,7 @@ func SearchIssues(ctx *context.APIContext) { issuesOpt.ReviewRequestedID = ctxUserID } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err) return } @@ -276,7 +276,7 @@ func SearchIssues(ctx *context.APIContext) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "CountIssues", err) return } @@ -284,7 +284,7 @@ func SearchIssues(ctx *context.APIContext) { ctx.SetLinkHeader(int(filteredCount), limit) ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } // ListIssues list the issues of a repository @@ -477,7 +477,7 @@ func ListIssues(ctx *context.APIContext) { MentionedID: mentionedByID, } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err) return } @@ -485,7 +485,7 @@ func ListIssues(ctx *context.APIContext) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "CountIssues", err) return } @@ -493,7 +493,7 @@ func ListIssues(ctx *context.APIContext) { ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize) ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } func getUserIDForFilter(ctx *context.APIContext, queryName string) int64 { @@ -555,7 +555,7 @@ func GetIssue(ctx *context.APIContext) { } return } - ctx.JSON(http.StatusOK, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) } // CreateIssue create an issue of a repository @@ -612,7 +612,7 @@ func CreateIssue(ctx *context.APIContext) { var err error if ctx.Repo.CanWrite(unit.TypeIssues) { issue.MilestoneID = form.Milestone - assigneeIDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) + assigneeIDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(ctx, form.Assignee, form.Assignees) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) @@ -671,7 +671,7 @@ func CreateIssue(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetIssueByID", err) return } - ctx.JSON(http.StatusCreated, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue)) } // EditIssue modify an issue of a repository @@ -823,11 +823,11 @@ func EditIssue(ctx *context.APIContext) { } if titleChanged { - notification.NotifyIssueChangeTitle(ctx.Doer, issue, oldTitle) + notification.NotifyIssueChangeTitle(ctx, ctx.Doer, issue, oldTitle) } if statusChangeComment != nil { - notification.NotifyIssueChangeStatus(ctx.Doer, issue, statusChangeComment, issue.IsClosed) + notification.NotifyIssueChangeStatus(ctx, ctx.Doer, issue, statusChangeComment, issue.IsClosed) } // Refetch from database to assign some automatic values @@ -836,11 +836,11 @@ func EditIssue(ctx *context.APIContext) { ctx.InternalServerError(err) return } - if err = issue.LoadMilestone(); err != nil { + if err = issue.LoadMilestone(ctx); err != nil { ctx.InternalServerError(err) return } - ctx.JSON(http.StatusCreated, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue)) } func DeleteIssue(ctx *context.APIContext) { diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 89038e4f16304..a5da09172797e 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -91,7 +91,7 @@ func ListIssueComments(ctx *context.APIContext) { return } - if err := issues_model.CommentList(comments).LoadPosters(); err != nil { + if err := issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } @@ -178,7 +178,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { return } - if err := issues_model.CommentList(comments).LoadPosters(); err != nil { + if err := issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } @@ -187,7 +187,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { for _, comment := range comments { if comment.Type != issues_model.CommentTypeCode && isXRefCommentAccessible(ctx, ctx.Doer, comment, issue.RepoID) { comment.Issue = issue - apiComments = append(apiComments, convert.ToTimelineComment(comment, ctx.Doer)) + apiComments = append(apiComments, convert.ToTimelineComment(ctx, comment, ctx.Doer)) } } @@ -281,21 +281,21 @@ func ListRepoIssueComments(ctx *context.APIContext) { return } - if err = issues_model.CommentList(comments).LoadPosters(); err != nil { + if err = issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } apiComments := make([]*api.Comment, len(comments)) - if err := issues_model.CommentList(comments).LoadIssues(); err != nil { + if err := issues_model.CommentList(comments).LoadIssues(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssues", err) return } - if err := issues_model.CommentList(comments).LoadPosters(); err != nil { + if err := issues_model.CommentList(comments).LoadPosters(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadPosters", err) return } - if _, err := issues_model.CommentList(comments).Issues().LoadRepositories(); err != nil { + if _, err := issues_model.CommentList(comments).Issues().LoadRepositories(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadRepositories", err) return } @@ -354,7 +354,7 @@ func CreateIssueComment(ctx *context.APIContext) { return } - comment, err := comment_service.CreateIssueComment(ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil) + comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil) if err != nil { ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err) return @@ -409,7 +409,7 @@ func GetIssueComment(ctx *context.APIContext) { return } - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { ctx.InternalServerError(err) return } @@ -423,7 +423,7 @@ func GetIssueComment(ctx *context.APIContext) { return } - if err := comment.LoadPoster(); err != nil { + if err := comment.LoadPoster(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "comment.LoadPoster", err) return } @@ -548,7 +548,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) oldContent := comment.Content comment.Content = form.Body - if err := comment_service.UpdateComment(comment, ctx.Doer, oldContent); err != nil { + if err := comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateComment", err) return } @@ -647,7 +647,7 @@ func deleteIssueComment(ctx *context.APIContext) { return } - if err = comment_service.DeleteComment(ctx.Doer, comment); err != nil { + if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil { ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err) return } diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index f4c40d2bcd828..fb7fd713b38a2 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -58,7 +58,7 @@ func GetIssueCommentReactions(ctx *context.APIContext) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "comment.LoadIssue", err) } @@ -185,7 +185,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp return } - err = comment.LoadIssue() + err = comment.LoadIssue(ctx) if err != nil { ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err) } diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index 1e26403ec827d..e3abb973be43d 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -139,7 +139,7 @@ func ListTrackedTimes(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } // AddTime add time manual to the given issue @@ -224,7 +224,7 @@ func AddTime(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToTrackedTime(trackedTime)) + ctx.JSON(http.StatusOK, convert.ToTrackedTime(ctx, trackedTime)) } // ResetIssueTime reset time manual to the given issue @@ -448,7 +448,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } // ListTrackedTimesByRepository lists all tracked times of the repository @@ -558,7 +558,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } // ListMyTrackedTimes lists all tracked times of the current user @@ -620,5 +620,5 @@ func ListMyTrackedTimes(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes)) + ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) } diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index ed371d787ccb6..aeef862b1f8a3 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -195,7 +195,7 @@ func Migrate(ctx *context.APIContext) { } if err == nil { - notification.NotifyMigrateRepository(ctx.Doer, repoOwner, repo) + notification.NotifyMigrateRepository(ctx, ctx.Doer, repoOwner, repo) return } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index f7e82dab37240..fba7ed646274f 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -109,19 +109,19 @@ func ListPullRequests(ctx *context.APIContext) { apiPrs := make([]*api.PullRequest, len(prs)) for i := range prs { - if err = prs[i].LoadIssue(); err != nil { + if err = prs[i].LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } - if err = prs[i].LoadAttributes(); err != nil { + if err = prs[i].LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - if err = prs[i].LoadBaseRepoCtx(ctx); err != nil { + if err = prs[i].LoadBaseRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) return } - if err = prs[i].LoadHeadRepoCtx(ctx); err != nil { + if err = prs[i].LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } @@ -173,11 +173,11 @@ func GetPullRequest(ctx *context.APIContext) { return } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) return } - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } @@ -300,7 +300,7 @@ func CreatePullRequest(ctx *context.APIContext) { defer headGitRepo.Close() // Check if another PR exists with the same targets - existingPr, err := issues_model.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch, issues_model.PullRequestFlowGithub) + existingPr, err := issues_model.GetUnmergedPullRequest(ctx, headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch, issues_model.PullRequestFlowGithub) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { ctx.Error(http.StatusInternalServerError, "GetUnmergedPullRequest", err) @@ -320,7 +320,7 @@ func CreatePullRequest(ctx *context.APIContext) { } if len(form.Labels) > 0 { - labels, err := issues_model.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) + labels, err := issues_model.GetLabelsInRepoByIDs(ctx, ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDs", err) return @@ -334,7 +334,7 @@ func CreatePullRequest(ctx *context.APIContext) { } if ctx.Repo.Owner.IsOrganization() { - orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx.Repo.Owner.ID, form.Labels) + orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx, ctx.Repo.Owner.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInOrgByIDs", err) return @@ -389,7 +389,7 @@ func CreatePullRequest(ctx *context.APIContext) { } // Get all assignee IDs - assigneeIDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) + assigneeIDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(ctx, form.Assignee, form.Assignees) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) @@ -400,7 +400,7 @@ func CreatePullRequest(ctx *context.APIContext) { } // Check if the passed assignees is assignable for _, aID := range assigneeIDs { - assignee, err := user_model.GetUserByID(aID) + assignee, err := user_model.GetUserByIDCtx(ctx, aID) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserByID", err) return @@ -483,7 +483,7 @@ func EditPullRequest(ctx *context.APIContext) { return } - err = pr.LoadIssue() + err = pr.LoadIssue(ctx) if err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return @@ -551,14 +551,14 @@ func EditPullRequest(ctx *context.APIContext) { } if ctx.Repo.CanWrite(unit.TypePullRequests) && form.Labels != nil { - labels, err := issues_model.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) + labels, err := issues_model.GetLabelsInRepoByIDs(ctx, ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInRepoByIDsError", err) return } if ctx.Repo.Owner.IsOrganization() { - orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx.Repo.Owner.ID, form.Labels) + orgLabels, err := issues_model.GetLabelsInOrgByIDs(ctx, ctx.Repo.Owner.ID, form.Labels) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsInOrgByIDs", err) return @@ -591,11 +591,11 @@ func EditPullRequest(ctx *context.APIContext) { } if titleChanged { - notification.NotifyIssueChangeTitle(ctx.Doer, issue, oldTitle) + notification.NotifyIssueChangeTitle(ctx, ctx.Doer, issue, oldTitle) } if statusChangeComment != nil { - notification.NotifyIssueChangeStatus(ctx.Doer, issue, statusChangeComment, issue.IsClosed) + notification.NotifyIssueChangeStatus(ctx, ctx.Doer, issue, statusChangeComment, issue.IsClosed) } // change pull target branch @@ -619,7 +619,7 @@ func EditPullRequest(ctx *context.APIContext) { } return } - notification.NotifyPullRequestChangeTargetBranch(ctx.Doer, pr, form.Base) + notification.NotifyPullRequestChangeTargetBranch(ctx, ctx.Doer, pr, form.Base) } // update allow edits @@ -743,12 +743,12 @@ func MergePullRequest(ctx *context.APIContext) { return } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } - if err := pr.LoadIssueCtx(ctx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } @@ -811,7 +811,7 @@ func MergePullRequest(ctx *context.APIContext) { message := strings.TrimSpace(form.MergeTitleField) if len(message) == 0 { - message, err = pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) + message, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) if err != nil { ctx.Error(http.StatusInternalServerError, "GetDefaultMergeMessage", err) return @@ -1097,7 +1097,7 @@ func UpdatePullRequest(ctx *context.APIContext) { return } - if err = pr.LoadIssue(); err != nil { + if err = pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } @@ -1107,11 +1107,11 @@ func UpdatePullRequest(ctx *context.APIContext) { return } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) return } - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) return } @@ -1267,7 +1267,7 @@ func GetPullRequestCommits(ctx *context.APIContext) { return } - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { ctx.InternalServerError(err) return } @@ -1383,12 +1383,12 @@ func GetPullRequestFiles(ctx *context.APIContext) { return } - if err := pr.LoadBaseRepo(); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { ctx.InternalServerError(err) return } - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { ctx.InternalServerError(err) return } diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index f36d0586ab6b9..df88e2a57bff7 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -71,7 +71,7 @@ func ListPullReviews(ctx *context.APIContext) { return } - if err = pr.LoadIssue(); err != nil { + if err = pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return } @@ -476,7 +476,7 @@ func SubmitPullReview(ctx *context.APIContext) { // preparePullReviewType return ReviewType and false or nil and true if an error happen func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest, event api.ReviewStateType, body string, hasComments bool) (issues_model.ReviewType, bool) { - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadIssue", err) return -1, true } diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index acc9696e1bef1..60cc19d5653b1 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -61,7 +61,7 @@ func GetRelease(ctx *context.APIContext) { return } - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -123,14 +123,14 @@ func ListReleases(ctx *context.APIContext) { IsPreRelease: ctx.FormOptionalBool("pre-release"), } - releases, err := repo_model.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) return } rels := make([]*api.Release, len(releases)) for i, release := range releases { - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } @@ -313,7 +313,7 @@ func EditRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err) return } - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index a469877c13e56..02f85d384a32a 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -114,7 +114,7 @@ func ListReleaseAttachments(ctx *context.APIContext) { ctx.NotFound() return } - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 2cb97c58a0263..77395bb469293 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -60,7 +60,7 @@ func GetReleaseByTag(ctx *context.APIContext) { return } - if err = release.LoadAttributes(); err != nil { + if err = release.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index de8a4d186489c..29febe751cb91 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -191,7 +191,7 @@ func Search(ctx *context.APIContext) { } var err error - repos, count, err := repo_model.SearchRepository(opts) + repos, count, err := repo_model.SearchRepository(ctx, opts) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, @@ -209,7 +209,7 @@ func Search(ctx *context.APIContext) { }) return } - accessMode, err := access_model.AccessLevel(ctx.Doer, repo) + accessMode, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 6d9564854278e..734a550a71559 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -86,7 +86,7 @@ func NewWikiPage(ctx *context.APIContext) { wikiPage := getWikiPage(ctx, wikiName) if !ctx.Written() { - notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) + notification.NotifyNewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) ctx.JSON(http.StatusCreated, wikiPage) } } @@ -154,7 +154,7 @@ func EditWikiPage(ctx *context.APIContext) { wikiPage := getWikiPage(ctx, newWikiName) if !ctx.Written() { - notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) + notification.NotifyEditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) ctx.JSON(http.StatusOK, wikiPage) } } @@ -245,7 +245,7 @@ func DeleteWikiPage(ctx *context.APIContext) { return } - notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName) + notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName) ctx.Status(http.StatusNoContent) } diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index 709e3a6c5457d..d1917a9938bae 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -39,7 +39,7 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { apiRepos := make([]*api.Repository, 0, len(repos)) for i := range repos { - access, err := access_model.AccessLevel(ctx.Doer, repos[i]) + access, err := access_model.AccessLevel(ctx, ctx.Doer, repos[i]) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return @@ -112,7 +112,7 @@ func ListMyRepos(ctx *context.APIContext) { } var err error - repos, count, err := repo_model.SearchRepository(opts) + repos, count, err := repo_model.SearchRepository(ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchRepository", err) return @@ -124,7 +124,7 @@ func ListMyRepos(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetOwner", err) return } - accessMode, err := access_model.AccessLevel(ctx.Doer, repo) + accessMode, err := access_model.AccessLevel(ctx, ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) } diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go index 9cb9ec79b8794..96748c630d6b4 100644 --- a/routers/api/v1/user/star.go +++ b/routers/api/v1/user/star.go @@ -6,6 +6,7 @@ package user import ( + std_context "context" "net/http" "code.gitea.io/gitea/models/db" @@ -20,15 +21,15 @@ import ( // getStarredRepos returns the repos that the user with the specified userID has // starred -func getStarredRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) { - starredRepos, err := repo_model.GetStarredRepos(user.ID, private, listOptions) +func getStarredRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) { + starredRepos, err := repo_model.GetStarredRepos(ctx, user.ID, private, listOptions) if err != nil { return nil, err } repos := make([]*api.Repository, len(starredRepos)) for i, starred := range starredRepos { - access, err := access_model.AccessLevel(user, starred) + access, err := access_model.AccessLevel(ctx, user, starred) if err != nil { return nil, err } @@ -63,7 +64,7 @@ func GetStarredRepos(ctx *context.APIContext) { // "$ref": "#/responses/RepositoryList" private := ctx.ContextUser.ID == ctx.Doer.ID - repos, err := getStarredRepos(ctx.ContextUser, private, utils.GetListOptions(ctx)) + repos, err := getStarredRepos(ctx, ctx.ContextUser, private, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) return @@ -93,7 +94,7 @@ func GetMyStarredRepos(ctx *context.APIContext) { // "200": // "$ref": "#/responses/RepositoryList" - repos, err := getStarredRepos(ctx.Doer, true, utils.GetListOptions(ctx)) + repos, err := getStarredRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) } diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go index 83f23db15ca03..7765a399f381e 100644 --- a/routers/api/v1/user/watch.go +++ b/routers/api/v1/user/watch.go @@ -5,6 +5,7 @@ package user import ( + std_context "context" "net/http" "code.gitea.io/gitea/models/db" @@ -18,15 +19,15 @@ import ( ) // getWatchedRepos returns the repos that the user with the specified userID is watching -func getWatchedRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) { - watchedRepos, total, err := repo_model.GetWatchedRepos(user.ID, private, listOptions) +func getWatchedRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) { + watchedRepos, total, err := repo_model.GetWatchedRepos(ctx, user.ID, private, listOptions) if err != nil { return nil, 0, err } repos := make([]*api.Repository, len(watchedRepos)) for i, watched := range watchedRepos { - access, err := access_model.AccessLevel(user, watched) + access, err := access_model.AccessLevel(ctx, user, watched) if err != nil { return nil, 0, err } @@ -61,7 +62,7 @@ func GetWatchedRepos(ctx *context.APIContext) { // "$ref": "#/responses/RepositoryList" private := ctx.ContextUser.ID == ctx.Doer.ID - repos, total, err := getWatchedRepos(ctx.ContextUser, private, utils.GetListOptions(ctx)) + repos, total, err := getWatchedRepos(ctx, ctx.ContextUser, private, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) } @@ -90,7 +91,7 @@ func GetMyWatchedRepos(ctx *context.APIContext) { // "200": // "$ref": "#/responses/RepositoryList" - repos, total, err := getWatchedRepos(ctx.Doer, true, utils.GetListOptions(ctx)) + repos, total, err := getWatchedRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) } diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 93aa450f9c3b7..1370e5302b71d 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -202,7 +202,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { continue } - pr, err := issues_model.GetUnmergedPullRequest(repo.ID, baseRepo.ID, branch, baseRepo.DefaultBranch, issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, baseRepo.ID, branch, baseRepo.DefaultBranch, issues_model.PullRequestFlowGithub) if err != nil && !issues_model.IsErrPullRequestNotExist(err) { log.Error("Failed to get active PR in: %-v Branch: %s to: %-v Branch: %s Error: %v", repo, branch, baseRepo, baseRepo.DefaultBranch, err) ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index fdd0a0bc3a042..86bdf60ab98b7 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -372,7 +372,7 @@ func preReceiveTag(ctx *preReceiveContext, oldCommitID, newCommitID, refFullName if !ctx.gotProtectedTags { var err error - ctx.protectedTags, err = git_model.GetProtectedTags(ctx.Repo.Repository.ID) + ctx.protectedTags, err = git_model.GetProtectedTags(ctx, ctx.Repo.Repository.ID) if err != nil { log.Error("Unable to get protected tags for %-v Error: %v", ctx.Repo.Repository, err) ctx.JSON(http.StatusInternalServerError, private.Response{ @@ -383,7 +383,7 @@ func preReceiveTag(ctx *preReceiveContext, oldCommitID, newCommitID, refFullName ctx.gotProtectedTags = true } - isAllowed, err := git_model.IsUserAllowedToControlTag(ctx.protectedTags, tagName, ctx.opts.UserID) + isAllowed, err := git_model.IsUserAllowedToControlTag(ctx, ctx.protectedTags, tagName, ctx.opts.UserID) if err != nil { ctx.JSON(http.StatusInternalServerError, private.Response{ Err: err.Error(), diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go index 8cb615b7bcbfa..8d4ecf1bc08bc 100644 --- a/routers/web/explore/repo.go +++ b/routers/web/explore/repo.go @@ -98,7 +98,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { language := ctx.FormTrim("language") ctx.Data["Language"] = language - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: opts.PageSize, diff --git a/routers/web/home.go b/routers/web/home.go index 0c74987ba7c47..7640243ba076f 100644 --- a/routers/web/home.go +++ b/routers/web/home.go @@ -88,7 +88,7 @@ func HomeSitemap(ctx *context.Context) { } } - _, cnt, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + _, cnt, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: 1, }, diff --git a/routers/web/org/home.go b/routers/web/org/home.go index 63243a391f0e6..6bd8a89d12371 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -99,7 +99,7 @@ func Home(ctx *context.Context) { count int64 err error ) - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index d1f1255db4656..a7588d275d4a5 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -275,14 +275,14 @@ func loadOneBranch(ctx *context.Context, rawBranch, defaultBranch *git.Branch, p mergeMovedOn := false if pr != nil { pr.HeadRepo = ctx.Repo.Repository - if err := pr.LoadIssue(); err != nil { - ctx.ServerError("pr.LoadIssue", err) + if err := pr.LoadIssue(ctx); err != nil { + ctx.ServerError("LoadIssue", err) return nil } if repo, ok := repoIDToRepo[pr.BaseRepoID]; ok { pr.BaseRepo = repo - } else if err := pr.LoadBaseRepoCtx(ctx); err != nil { - ctx.ServerError("pr.LoadBaseRepo", err) + } else if err := pr.LoadBaseRepo(ctx); err != nil { + ctx.ServerError("LoadBaseRepo", err) return nil } else { repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index db6b59471ff47..0fb8e44725245 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -747,7 +747,7 @@ func CompareDiff(ctx *context.Context) { ctx.Data["HeadTags"] = headTags if ctx.Data["PageIsComparePull"] == true { - pr, err := issues_model.GetUnmergedPullRequest(ci.HeadRepo.ID, ctx.Repo.Repository.ID, ci.HeadBranch, ci.BaseBranch, issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(ctx, ci.HeadRepo.ID, ctx.Repo.Repository.ID, ci.HeadBranch, ci.BaseBranch, issues_model.PullRequestFlowGithub) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { ctx.ServerError("GetUnmergedPullRequest", err) @@ -755,7 +755,7 @@ func CompareDiff(ctx *context.Context) { } } else { ctx.Data["HasPullRequest"] = true - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { ctx.ServerError("LoadIssue", err) return } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 9c52d45877d0d..3cfddffc10c7b 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -246,7 +246,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti if forceEmpty { issues = []*issues_model.Issue{} } else { - issues, err = issues_model.Issues(&issues_model.IssuesOptions{ + issues, err = issues_model.Issues(ctx, &issues_model.IssuesOptions{ ListOptions: db.ListOptions{ Page: pager.Paginater.Current(), PageSize: setting.UI.IssuePagingNum, @@ -608,7 +608,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is currentPullReviewers := make([]*repoReviewerSelection, 0, len(pullReviews)) for _, item := range pullReviews { if item.Review.ReviewerID > 0 { - if err = item.Review.LoadReviewer(); err != nil { + if err = item.Review.LoadReviewer(ctx); err != nil { if user_model.IsErrUserNotExist(err) { continue } @@ -617,7 +617,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is } item.User = item.Review.Reviewer } else if item.Review.ReviewerTeamID > 0 { - if err = item.Review.LoadReviewerTeam(); err != nil { + if err = item.Review.LoadReviewerTeam(ctx); err != nil { if organization.IsErrTeamNotExist(err) { continue } @@ -1163,7 +1163,7 @@ func getBranchData(ctx *context.Context, issue *issues_model.Issue) { pull := issue.PullRequest ctx.Data["BaseBranch"] = pull.BaseBranch ctx.Data["HeadBranch"] = pull.HeadBranch - ctx.Data["HeadUserName"] = pull.MustHeadUserName() + ctx.Data["HeadUserName"] = pull.MustHeadUserName(ctx) } } @@ -1426,13 +1426,13 @@ func ViewIssue(ctx *context.Context) { for _, comment = range issue.Comments { comment.Issue = issue - if err := comment.LoadPoster(); err != nil { + if err := comment.LoadPoster(ctx); err != nil { ctx.ServerError("LoadPoster", err) return } if comment.Type == issues_model.CommentTypeComment || comment.Type == issues_model.CommentTypeReview { - if err := comment.LoadAttachments(); err != nil { + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } @@ -1467,7 +1467,7 @@ func ViewIssue(ctx *context.Context) { return } } else if comment.Type == issues_model.CommentTypeMilestone { - if err = comment.LoadMilestone(); err != nil { + if err = comment.LoadMilestone(ctx); err != nil { ctx.ServerError("LoadMilestone", err) return } @@ -1591,7 +1591,7 @@ func ViewIssue(ctx *context.Context) { ctx.Data["AllowMerge"] = false if ctx.IsSigned { - if err := pull.LoadHeadRepoCtx(ctx); err != nil { + if err := pull.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) } else if pull.HeadRepo != nil { perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer) @@ -1613,7 +1613,7 @@ func ViewIssue(ctx *context.Context) { } } - if err := pull.LoadBaseRepoCtx(ctx); err != nil { + if err := pull.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) } perm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, ctx.Doer) @@ -1662,14 +1662,14 @@ func ViewIssue(ctx *context.Context) { ctx.Data["MergeStyle"] = mergeStyle - defaultMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pull, mergeStyle) + defaultMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, mergeStyle) if err != nil { ctx.ServerError("GetDefaultMergeMessage", err) return } ctx.Data["DefaultMergeMessage"] = defaultMergeMessage - defaultSquashMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash) + defaultSquashMergeMessage, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash) if err != nil { ctx.ServerError("GetDefaultSquashMergeMessage", err) return @@ -1885,7 +1885,7 @@ func GetIssueInfo(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, convert.ToAPIIssue(issue)) + ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) } // UpdateIssueTitle change issue's title @@ -2280,7 +2280,7 @@ func SearchIssues(ctx *context.Context) { repoCond := repo_model.SearchRepositoryCondition(opts) repoIDs, _, err := repo_model.SearchRepositoryIDs(opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err.Error()) + ctx.Error(http.StatusInternalServerError, "SearchRepositoryIDs", err.Error()) return } @@ -2369,7 +2369,7 @@ func SearchIssues(ctx *context.Context) { issuesOpt.ReviewRequestedID = ctxUserID } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "Issues", err.Error()) return } @@ -2377,14 +2377,14 @@ func SearchIssues(ctx *context.Context) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, "CountIssues", err.Error()) return } } ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } func getUserIDForFilter(ctx *context.Context, queryName string) int64 { @@ -2527,7 +2527,7 @@ func ListIssues(ctx *context.Context) { MentionedID: mentionedByID, } - if issues, err = issues_model.Issues(issuesOpt); err != nil { + if issues, err = issues_model.Issues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } @@ -2535,14 +2535,14 @@ func ListIssues(ctx *context.Context) { issuesOpt.ListOptions = db.ListOptions{ Page: -1, } - if filteredCount, err = issues_model.CountIssues(issuesOpt); err != nil { + if filteredCount, err = issues_model.CountIssues(ctx, issuesOpt); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } } ctx.SetTotalCountHeader(filteredCount) - ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues)) + ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) } // UpdateIssueStatus change issue's status @@ -2562,7 +2562,7 @@ func UpdateIssueStatus(ctx *context.Context) { log.Warn("Unrecognized action: %s", action) } - if _, err := issues_model.IssueList(issues).LoadRepositories(); err != nil { + if _, err := issues_model.IssueList(issues).LoadRepositories(ctx); err != nil { ctx.ServerError("LoadRepositories", err) return } @@ -2646,7 +2646,7 @@ func NewComment(ctx *context.Context) { if form.Status == "reopen" && issue.IsPull { pull := issue.PullRequest var err error - pr, err = issues_model.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow) + pr, err = issues_model.GetUnmergedPullRequest(ctx, pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { ctx.ServerError("GetUnmergedPullRequest", err) @@ -2706,7 +2706,7 @@ func NewComment(ctx *context.Context) { return } - comment, err := comment_service.CreateIssueComment(ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments) + comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments) if err != nil { ctx.ServerError("CreateIssueComment", err) return @@ -2723,7 +2723,7 @@ func UpdateCommentContent(ctx *context.Context) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err) return } @@ -2746,12 +2746,12 @@ func UpdateCommentContent(ctx *context.Context) { }) return } - if err = comment_service.UpdateComment(comment, ctx.Doer, oldContent); err != nil { + if err = comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil { ctx.ServerError("UpdateComment", err) return } - if err := comment.LoadAttachments(); err != nil { + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } @@ -2789,7 +2789,7 @@ func DeleteComment(ctx *context.Context) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err) return } @@ -2802,8 +2802,8 @@ func DeleteComment(ctx *context.Context) { return } - if err = comment_service.DeleteComment(ctx.Doer, comment); err != nil { - ctx.ServerError("DeleteCommentByID", err) + if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil { + ctx.ServerError("DeleteComment", err) return } @@ -2916,7 +2916,7 @@ func ChangeCommentReaction(ctx *context.Context) { return } - if err := comment.LoadIssue(); err != nil { + if err := comment.LoadIssue(ctx); err != nil { ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err) return } @@ -3063,7 +3063,7 @@ func GetCommentAttachments(ctx *context.Context) { } attachments := make([]*api.Attachment, 0) if comment.Type == issues_model.CommentTypeComment { - if err := comment.LoadAttachments(); err != nil { + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 7af415a8faed1..560f25a0af77f 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -75,7 +75,7 @@ func RetrieveLabels(ctx *context.Context) { return } for _, l := range orgLabels { - l.CalOpenOrgIssues(ctx.Repo.Repository.ID, l.ID) + l.CalOpenOrgIssues(ctx, ctx.Repo.Repository.ID, l.ID) } ctx.Data["OrgLabels"] = orgLabels diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index f054ad6e540bd..fb2d25a22b813 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -297,7 +297,7 @@ func ViewProject(ctx *context.Context) { boards[0].Title = ctx.Tr("repo.projects.type.uncategorized") } - issuesMap, err := issues_model.LoadIssuesFromBoardList(boards) + issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards) if err != nil { ctx.ServerError("LoadIssuesOfBoards", err) return @@ -314,7 +314,7 @@ func ViewProject(ctx *context.Context) { } if len(referencedIds) > 0 { - if linkedPrs, err := issues_model.Issues(&issues_model.IssuesOptions{ + if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ IssueIDs: referencedIds, IsPull: util.OptionalBoolTrue, }); err == nil { diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 41eac7cc39232..870bc1773b967 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -281,7 +281,7 @@ func checkPullInfo(ctx *context.Context) *issues_model.Issue { } return nil } - if err = issue.LoadPoster(); err != nil { + if err = issue.LoadPoster(ctx); err != nil { ctx.ServerError("LoadPoster", err) return nil } @@ -297,12 +297,12 @@ func checkPullInfo(ctx *context.Context) *issues_model.Issue { return nil } - if err = issue.LoadPullRequest(); err != nil { + if err = issue.LoadPullRequest(ctx); err != nil { ctx.ServerError("LoadPullRequest", err) return nil } - if err = issue.PullRequest.LoadHeadRepoCtx(ctx); err != nil { + if err = issue.PullRequest.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return nil } @@ -319,12 +319,12 @@ func checkPullInfo(ctx *context.Context) *issues_model.Issue { } func setMergeTarget(ctx *context.Context, pull *issues_model.PullRequest) { - if ctx.Repo.Owner.Name == pull.MustHeadUserName() { + if ctx.Repo.Owner.Name == pull.MustHeadUserName(ctx) { ctx.Data["HeadTarget"] = pull.HeadBranch } else if pull.HeadRepo == nil { - ctx.Data["HeadTarget"] = pull.MustHeadUserName() + ":" + pull.HeadBranch + ctx.Data["HeadTarget"] = pull.MustHeadUserName(ctx) + ":" + pull.HeadBranch } else { - ctx.Data["HeadTarget"] = pull.MustHeadUserName() + "/" + pull.HeadRepo.Name + ":" + pull.HeadBranch + ctx.Data["HeadTarget"] = pull.MustHeadUserName(ctx) + "/" + pull.HeadRepo.Name + ":" + pull.HeadBranch } ctx.Data["BaseTarget"] = pull.BaseBranch ctx.Data["HeadBranchHTMLURL"] = pull.GetHeadBranchHTMLURL() @@ -416,12 +416,12 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C repo := ctx.Repo.Repository pull := issue.PullRequest - if err := pull.LoadHeadRepoCtx(ctx); err != nil { + if err := pull.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return nil } - if err := pull.LoadBaseRepoCtx(ctx); err != nil { + if err := pull.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return nil } @@ -606,7 +606,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C if pull.IsWorkInProgress() { ctx.Data["IsPullWorkInProgress"] = true - ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix() + ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix(ctx) } if pull.IsFilesConflicted() { @@ -834,11 +834,11 @@ func UpdatePullRequest(ctx *context.Context) { rebase := ctx.FormString("style") == "rebase" - if err := issue.PullRequest.LoadBaseRepoCtx(ctx); err != nil { + if err := issue.PullRequest.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return } - if err := issue.PullRequest.LoadHeadRepoCtx(ctx); err != nil { + if err := issue.PullRequest.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return } @@ -974,7 +974,7 @@ func MergePullRequest(ctx *context.Context) { message := strings.TrimSpace(form.MergeTitleField) if len(message) == 0 { var err error - message, err = pull_service.GetDefaultMergeMessage(ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) + message, err = pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pr, repo_model.MergeStyle(form.Do)) if err != nil { ctx.ServerError("GetDefaultMergeMessage", err) return @@ -1296,14 +1296,14 @@ func CleanUpPullRequest(ctx *context.Context) { return } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return } else if pr.HeadRepo == nil { // Forked repository has already been deleted ctx.NotFound("CleanUpPullRequest", nil) return - } else if err = pr.LoadBaseRepoCtx(ctx); err != nil { + } else if err = pr.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return } else if err = pr.HeadRepo.GetOwner(ctx); err != nil { @@ -1499,7 +1499,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { } return } - notification.NotifyPullRequestChangeTargetBranch(ctx.Doer, pr, targetBranch) + notification.NotifyPullRequestChangeTargetBranch(ctx, ctx.Doer, pr, targetBranch) ctx.JSON(http.StatusOK, map[string]interface{}{ "base_branch": pr.BaseBranch, diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go index bc64f35472ea4..bbaacc234c0c6 100644 --- a/routers/web/repo/pull_review.go +++ b/routers/web/repo/pull_review.go @@ -114,7 +114,7 @@ func UpdateResolveConversation(ctx *context.Context) { return } - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(ctx); err != nil { ctx.ServerError("comment.LoadIssue", err) return } @@ -169,7 +169,7 @@ func renderConversation(ctx *context.Context, comment *issues_model.Comment) { ctx.Data["comments"] = comments ctx.Data["CanMarkConversation"] = true ctx.Data["Issue"] = comment.Issue - if err = comment.Issue.LoadPullRequest(); err != nil { + if err = comment.Issue.LoadPullRequest(ctx); err != nil { ctx.ServerError("comment.Issue.LoadPullRequest", err) return } diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 0cb85f37984f5..0373d5b158d1a 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -130,7 +130,7 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { opts.IncludeDrafts = writeAccess } - releases, err := repo_model.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) if err != nil { ctx.ServerError("GetReleasesByRepoID", err) return @@ -266,7 +266,7 @@ func LatestRelease(ctx *context.Context) { return } - if err := release.LoadAttributes(); err != nil { + if err := release.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } @@ -289,7 +289,7 @@ func NewRelease(ctx *context.Context) { if rel != nil { rel.Repo = ctx.Repo.Repository - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } @@ -454,7 +454,7 @@ func EditRelease(ctx *context.Context) { ctx.Data["IsDraft"] = rel.IsDraft rel.Repo = ctx.Repo.Repository - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 3e746d3f058cf..7bcca1d02a9a5 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -540,7 +540,7 @@ func SearchRepo(ctx *context.Context) { } var err error - repos, count, err := repo_model.SearchRepository(opts) + repos, count, err := repo_model.SearchRepository(ctx, opts) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, diff --git a/routers/web/repo/tag.go b/routers/web/repo/tag.go index f63a50782be09..4d46716c303a5 100644 --- a/routers/web/repo/tag.go +++ b/routers/web/repo/tag.go @@ -124,7 +124,7 @@ func DeleteProtectedTagPost(ctx *context.Context) { return } - if err := git_model.DeleteProtectedTag(pt); err != nil { + if err := git_model.DeleteProtectedTag(ctx, pt); err != nil { ctx.ServerError("DeleteProtectedTag", err) return } @@ -137,7 +137,7 @@ func setTagsContext(ctx *context.Context) error { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsTags"] = true - protectedTags, err := git_model.GetProtectedTags(ctx.Repo.Repository.ID) + protectedTags, err := git_model.GetProtectedTags(ctx, ctx.Repo.Repository.ID) if err != nil { ctx.ServerError("GetProtectedTags", err) return err diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index a10e12ee63269..24d851762b248 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -706,7 +706,7 @@ func NewWikiPost(ctx *context.Context) { return } - notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) + notification.NotifyNewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Message) ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName)) } @@ -750,7 +750,7 @@ func EditWikiPost(ctx *context.Context) { return } - notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) + notification.NotifyEditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message) ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName)) } @@ -767,7 +767,7 @@ func DeleteWikiPagePost(ctx *context.Context) { return } - notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName) + notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName) ctx.JSON(http.StatusOK, map[string]interface{}{ "redirect": ctx.Repo.RepoLink + "/wiki/", diff --git a/routers/web/user/home.go b/routers/web/user/home.go index 95ec1aa2fa148..e67202b284e17 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -202,7 +202,7 @@ func Milestones(ctx *context.Context) { return } - showRepos, _, err := repo_model.SearchRepositoryByCondition(&repoOpts, userRepoCond, false) + showRepos, _, err := repo_model.SearchRepositoryByCondition(ctx, &repoOpts, userRepoCond, false) if err != nil { ctx.ServerError("SearchRepositoryByCondition", err) return @@ -461,7 +461,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { // USING NON-FINAL STATE OF opts FOR A QUERY. var issueCountByRepo map[int64]int64 if !forceEmpty { - issueCountByRepo, err = issues_model.CountIssuesByRepo(opts) + issueCountByRepo, err = issues_model.CountIssuesByRepo(ctx, opts) if err != nil { ctx.ServerError("CountIssuesByRepo", err) return @@ -504,7 +504,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { // USING FINAL STATE OF opts FOR A QUERY. var issues []*issues_model.Issue if !forceEmpty { - issues, err = issues_model.Issues(opts) + issues, err = issues_model.Issues(ctx, opts) if err != nil { ctx.ServerError("Issues", err) return diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index b4753a603e8a5..323422a1b9dc1 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -33,20 +33,20 @@ const ( ) // GetNotificationCount is the middleware that sets the notification count in the context -func GetNotificationCount(c *context.Context) { - if strings.HasPrefix(c.Req.URL.Path, "/api") { +func GetNotificationCount(ctx *context.Context) { + if strings.HasPrefix(ctx.Req.URL.Path, "/api") { return } - if !c.IsSigned { + if !ctx.IsSigned { return } - c.Data["NotificationUnreadCount"] = func() int64 { - count, err := activities_model.GetNotificationCount(c, c.Doer, activities_model.NotificationStatusUnread) + ctx.Data["NotificationUnreadCount"] = func() int64 { + count, err := activities_model.GetNotificationCount(ctx, ctx.Doer, activities_model.NotificationStatusUnread) if err != nil { if err != goctx.Canceled { - log.Error("Unable to GetNotificationCount for user:%-v: %v", c.Doer, err) + log.Error("Unable to GetNotificationCount for user:%-v: %v", ctx.Doer, err) } return -1 } @@ -56,25 +56,25 @@ func GetNotificationCount(c *context.Context) { } // Notifications is the notifications page -func Notifications(c *context.Context) { - getNotifications(c) - if c.Written() { +func Notifications(ctx *context.Context) { + getNotifications(ctx) + if ctx.Written() { return } - if c.FormBool("div-only") { - c.Data["SequenceNumber"] = c.FormString("sequence-number") - c.HTML(http.StatusOK, tplNotificationDiv) + if ctx.FormBool("div-only") { + ctx.Data["SequenceNumber"] = ctx.FormString("sequence-number") + ctx.HTML(http.StatusOK, tplNotificationDiv) return } - c.HTML(http.StatusOK, tplNotification) + ctx.HTML(http.StatusOK, tplNotification) } -func getNotifications(c *context.Context) { +func getNotifications(ctx *context.Context) { var ( - keyword = c.FormTrim("q") + keyword = ctx.FormTrim("q") status activities_model.NotificationStatus - page = c.FormInt("page") - perPage = c.FormInt("perPage") + page = ctx.FormInt("page") + perPage = ctx.FormInt("perPage") ) if page < 1 { page = 1 @@ -90,74 +90,74 @@ func getNotifications(c *context.Context) { status = activities_model.NotificationStatusUnread } - total, err := activities_model.GetNotificationCount(c, c.Doer, status) + total, err := activities_model.GetNotificationCount(ctx, ctx.Doer, status) if err != nil { - c.ServerError("ErrGetNotificationCount", err) + ctx.ServerError("ErrGetNotificationCount", err) return } // redirect to last page if request page is more than total pages pager := context.NewPagination(int(total), perPage, page, 5) if pager.Paginater.Current() < page { - c.Redirect(fmt.Sprintf("%s/notifications?q=%s&page=%d", setting.AppSubURL, url.QueryEscape(c.FormString("q")), pager.Paginater.Current())) + ctx.Redirect(fmt.Sprintf("%s/notifications?q=%s&page=%d", setting.AppSubURL, url.QueryEscape(ctx.FormString("q")), pager.Paginater.Current())) return } statuses := []activities_model.NotificationStatus{status, activities_model.NotificationStatusPinned} - notifications, err := activities_model.NotificationsForUser(c, c.Doer, statuses, page, perPage) + notifications, err := activities_model.NotificationsForUser(ctx, ctx.Doer, statuses, page, perPage) if err != nil { - c.ServerError("ErrNotificationsForUser", err) + ctx.ServerError("ErrNotificationsForUser", err) return } failCount := 0 - repos, failures, err := notifications.LoadRepos() + repos, failures, err := notifications.LoadRepos(ctx) if err != nil { - c.ServerError("LoadRepos", err) + ctx.ServerError("LoadRepos", err) return } notifications = notifications.Without(failures) - if err := repos.LoadAttributes(); err != nil { - c.ServerError("LoadAttributes", err) + if err := repos.LoadAttributes(); err != nil { // TODO + ctx.ServerError("LoadAttributes", err) return } failCount += len(failures) - failures, err = notifications.LoadIssues() + failures, err = notifications.LoadIssues(ctx) if err != nil { - c.ServerError("LoadIssues", err) + ctx.ServerError("LoadIssues", err) return } notifications = notifications.Without(failures) failCount += len(failures) - failures, err = notifications.LoadComments() + failures, err = notifications.LoadComments(ctx) if err != nil { - c.ServerError("LoadComments", err) + ctx.ServerError("LoadComments", err) return } notifications = notifications.Without(failures) failCount += len(failures) if failCount > 0 { - c.Flash.Error(fmt.Sprintf("ERROR: %d notifications were removed due to missing parts - check the logs", failCount)) + ctx.Flash.Error(fmt.Sprintf("ERROR: %d notifications were removed due to missing parts - check the logs", failCount)) } - c.Data["Title"] = c.Tr("notifications") - c.Data["Keyword"] = keyword - c.Data["Status"] = status - c.Data["Notifications"] = notifications + ctx.Data["Title"] = ctx.Tr("notifications") + ctx.Data["Keyword"] = keyword + ctx.Data["Status"] = status + ctx.Data["Notifications"] = notifications - pager.SetDefaultParams(c) - c.Data["Page"] = pager + pager.SetDefaultParams(ctx) + ctx.Data["Page"] = pager } // NotificationStatusPost is a route for changing the status of a notification -func NotificationStatusPost(c *context.Context) { +func NotificationStatusPost(ctx *context.Context) { var ( - notificationID = c.FormInt64("notification_id") - statusStr = c.FormString("status") + notificationID = ctx.FormInt64("notification_id") + statusStr = ctx.FormString("status") status activities_model.NotificationStatus ) @@ -169,56 +169,56 @@ func NotificationStatusPost(c *context.Context) { case "pinned": status = activities_model.NotificationStatusPinned default: - c.ServerError("InvalidNotificationStatus", errors.New("Invalid notification status")) + ctx.ServerError("InvalidNotificationStatus", errors.New("Invalid notification status")) return } - if _, err := activities_model.SetNotificationStatus(notificationID, c.Doer, status); err != nil { - c.ServerError("SetNotificationStatus", err) + if _, err := activities_model.SetNotificationStatus(ctx, notificationID, ctx.Doer, status); err != nil { + ctx.ServerError("SetNotificationStatus", err) return } - if !c.FormBool("noredirect") { - url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, url.QueryEscape(c.FormString("page"))) - c.Redirect(url, http.StatusSeeOther) + if !ctx.FormBool("noredirect") { + url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, url.QueryEscape(ctx.FormString("page"))) + ctx.Redirect(url, http.StatusSeeOther) } - getNotifications(c) - if c.Written() { + getNotifications(ctx) + if ctx.Written() { return } - c.Data["Link"] = setting.AppURL + "notifications" - c.Data["SequenceNumber"] = c.Req.PostFormValue("sequence-number") + ctx.Data["Link"] = setting.AppURL + "notifications" + ctx.Data["SequenceNumber"] = ctx.Req.PostFormValue("sequence-number") - c.HTML(http.StatusOK, tplNotificationDiv) + ctx.HTML(http.StatusOK, tplNotificationDiv) } // NotificationPurgePost is a route for 'purging' the list of notifications - marking all unread as read -func NotificationPurgePost(c *context.Context) { - err := activities_model.UpdateNotificationStatuses(c.Doer, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead) +func NotificationPurgePost(ctx *context.Context) { + err := activities_model.UpdateNotificationStatuses(ctx, ctx.Doer, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead) if err != nil { - c.ServerError("ErrUpdateNotificationStatuses", err) + ctx.ServerError("UpdateNotificationStatuses", err) return } - c.Redirect(setting.AppSubURL+"/notifications", http.StatusSeeOther) + ctx.Redirect(setting.AppSubURL+"/notifications", http.StatusSeeOther) } // NotificationSubscriptions returns the list of subscribed issues -func NotificationSubscriptions(c *context.Context) { - page := c.FormInt("page") +func NotificationSubscriptions(ctx *context.Context) { + page := ctx.FormInt("page") if page < 1 { page = 1 } - sortType := c.FormString("sort") - c.Data["SortType"] = sortType + sortType := ctx.FormString("sort") + ctx.Data["SortType"] = sortType - state := c.FormString("state") + state := ctx.FormString("state") if !util.IsStringInSlice(state, []string{"all", "open", "closed"}, true) { state = "all" } - c.Data["State"] = state + ctx.Data["State"] = state var showClosed util.OptionalBool switch state { case "all": @@ -230,7 +230,7 @@ func NotificationSubscriptions(c *context.Context) { } var issueTypeBool util.OptionalBool - issueType := c.FormString("issueType") + issueType := ctx.FormString("issueType") switch issueType { case "issues": issueTypeBool = util.OptionalBoolFalse @@ -239,71 +239,71 @@ func NotificationSubscriptions(c *context.Context) { default: issueTypeBool = util.OptionalBoolNone } - c.Data["IssueType"] = issueType + ctx.Data["IssueType"] = issueType var labelIDs []int64 - selectedLabels := c.FormString("labels") - c.Data["Labels"] = selectedLabels + selectedLabels := ctx.FormString("labels") + ctx.Data["Labels"] = selectedLabels if len(selectedLabels) > 0 && selectedLabels != "0" { var err error labelIDs, err = base.StringsToInt64s(strings.Split(selectedLabels, ",")) if err != nil { - c.ServerError("StringsToInt64s", err) + ctx.ServerError("StringsToInt64s", err) return } } - count, err := issues_model.CountIssues(&issues_model.IssuesOptions{ - SubscriberID: c.Doer.ID, + count, err := issues_model.CountIssues(ctx, &issues_model.IssuesOptions{ + SubscriberID: ctx.Doer.ID, IsClosed: showClosed, IsPull: issueTypeBool, LabelIDs: labelIDs, }) if err != nil { - c.ServerError("CountIssues", err) + ctx.ServerError("CountIssues", err) return } - issues, err := issues_model.Issues(&issues_model.IssuesOptions{ + issues, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.IssuePagingNum, Page: page, }, - SubscriberID: c.Doer.ID, + SubscriberID: ctx.Doer.ID, SortType: sortType, IsClosed: showClosed, IsPull: issueTypeBool, LabelIDs: labelIDs, }) if err != nil { - c.ServerError("Issues", err) + ctx.ServerError("Issues", err) return } - commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(c, issues) + commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, issues) if err != nil { - c.ServerError("GetIssuesAllCommitStatus", err) + ctx.ServerError("GetIssuesAllCommitStatus", err) return } - c.Data["CommitLastStatus"] = lastStatus - c.Data["CommitStatuses"] = commitStatuses - c.Data["Issues"] = issues + ctx.Data["CommitLastStatus"] = lastStatus + ctx.Data["CommitStatuses"] = commitStatuses + ctx.Data["Issues"] = issues - c.Data["IssueRefEndNames"], c.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, "") + ctx.Data["IssueRefEndNames"], ctx.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, "") - commitStatus, err := pull_service.GetIssuesLastCommitStatus(c, issues) + commitStatus, err := pull_service.GetIssuesLastCommitStatus(ctx, issues) if err != nil { - c.ServerError("GetIssuesLastCommitStatus", err) + ctx.ServerError("GetIssuesLastCommitStatus", err) return } - c.Data["CommitStatus"] = commitStatus + ctx.Data["CommitStatus"] = commitStatus issueList := issues_model.IssueList(issues) - approvalCounts, err := issueList.GetApprovalCounts(c) + approvalCounts, err := issueList.GetApprovalCounts(ctx) if err != nil { - c.ServerError("ApprovalCounts", err) + ctx.ServerError("ApprovalCounts", err) return } - c.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 { + ctx.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 { counts, ok := approvalCounts[issueID] if !ok || len(counts) == 0 { return 0 @@ -322,32 +322,32 @@ func NotificationSubscriptions(c *context.Context) { return 0 } - c.Data["Status"] = 1 - c.Data["Title"] = c.Tr("notification.subscriptions") + ctx.Data["Status"] = 1 + ctx.Data["Title"] = ctx.Tr("notification.subscriptions") // redirect to last page if request page is more than total pages pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) if pager.Paginater.Current() < page { - c.Redirect(fmt.Sprintf("/notifications/subscriptions?page=%d", pager.Paginater.Current())) + ctx.Redirect(fmt.Sprintf("/notifications/subscriptions?page=%d", pager.Paginater.Current())) return } - pager.AddParam(c, "sort", "SortType") - pager.AddParam(c, "state", "State") - c.Data["Page"] = pager + pager.AddParam(ctx, "sort", "SortType") + pager.AddParam(ctx, "state", "State") + ctx.Data["Page"] = pager - c.HTML(http.StatusOK, tplNotificationSubscriptions) + ctx.HTML(http.StatusOK, tplNotificationSubscriptions) } // NotificationWatching returns the list of watching repos -func NotificationWatching(c *context.Context) { - page := c.FormInt("page") +func NotificationWatching(ctx *context.Context) { + page := ctx.FormInt("page") if page < 1 { page = 1 } var orderBy db.SearchOrderBy - c.Data["SortType"] = c.FormString("sort") - switch c.FormString("sort") { + ctx.Data["SortType"] = ctx.FormString("sort") + switch ctx.FormString("sort") { case "newest": orderBy = db.SearchOrderByNewest case "oldest": @@ -369,41 +369,41 @@ func NotificationWatching(c *context.Context) { case "fewestforks": orderBy = db.SearchOrderByForks default: - c.Data["SortType"] = "recentupdate" + ctx.Data["SortType"] = "recentupdate" orderBy = db.SearchOrderByRecentUpdated } - repos, count, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, }, - Actor: c.Doer, - Keyword: c.FormTrim("q"), + Actor: ctx.Doer, + Keyword: ctx.FormTrim("q"), OrderBy: orderBy, - Private: c.IsSigned, - WatchedByID: c.Doer.ID, + Private: ctx.IsSigned, + WatchedByID: ctx.Doer.ID, Collaborate: util.OptionalBoolFalse, - TopicOnly: c.FormBool("topic"), + TopicOnly: ctx.FormBool("topic"), IncludeDescription: setting.UI.SearchRepoDescription, }) if err != nil { - c.ServerError("ErrSearchRepository", err) + ctx.ServerError("SearchRepository", err) return } total := int(count) - c.Data["Total"] = total - c.Data["Repos"] = repos + ctx.Data["Total"] = total + ctx.Data["Repos"] = repos // redirect to last page if request page is more than total pages pager := context.NewPagination(total, setting.UI.User.RepoPagingNum, page, 5) - pager.SetDefaultParams(c) - c.Data["Page"] = pager + pager.SetDefaultParams(ctx) + ctx.Data["Page"] = pager - c.Data["Status"] = 2 - c.Data["Title"] = c.Tr("notification.watching") + ctx.Data["Status"] = 2 + ctx.Data["Title"] = ctx.Tr("notification.watching") - c.HTML(http.StatusOK, tplNotificationSubscriptions) + ctx.HTML(http.StatusOK, tplNotificationSubscriptions) } // NewAvailable returns the notification counts diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 6e16b377dbc3b..982290e0ab2e8 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -203,7 +203,7 @@ func Profile(ctx *context.Context) { } case "stars": ctx.Data["PageIsProfileStarList"] = true - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, @@ -235,7 +235,7 @@ func Profile(ctx *context.Context) { return } case "watching": - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, @@ -257,7 +257,7 @@ func Profile(ctx *context.Context) { total = int(count) default: - repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, diff --git a/services/agit/agit.go b/services/agit/agit.go index a7e701d6c4f46..803ff696b0eb8 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -96,7 +96,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. headBranch = curentTopicBranch } - pr, err := issues_model.GetUnmergedPullRequest(repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit) + pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit) if err != nil { if !issues_model.IsErrPullRequestNotExist(err) { return nil, fmt.Errorf("Failed to get unmerged agit flow pull request in repository: %s/%s Error: %w", ownerName, repoName, err) @@ -159,7 +159,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. } // update exist pull request - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return nil, fmt.Errorf("Unable to load base repository for PR[%d] Error: %w", pr.ID, err) } @@ -203,15 +203,15 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. if err != nil { return nil, fmt.Errorf("Failed to get user. Error: %w", err) } - err = pr.LoadIssue() + err = pr.LoadIssue(ctx) if err != nil { return nil, fmt.Errorf("Failed to load pull issue. Error: %w", err) } comment, err := issues_model.CreatePushPullComment(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i]) if err == nil && comment != nil { - notification.NotifyPullRequestPushCommits(pusher, pr, comment) + notification.NotifyPullRequestPushCommits(ctx, pusher, pr, comment) } - notification.NotifyPullRequestSynchronized(pusher, pr) + notification.NotifyPullRequestSynchronized(ctx, pusher, pr) isForcePush := comment != nil && comment.IsForcePush results = append(results, private.HookProcReceiveRefResult{ diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index edfd0f6cadf25..a9d1e179aedba 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -272,7 +272,7 @@ Loop: // SignMerge determines if we should sign a PR merge commit to the base repository func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, string, *git.Signature, error) { - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to get Base Repo for pull request") return false, "", nil, err } diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index 5c38367e3be52..3291ed31f0da1 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -188,8 +188,8 @@ func handlePull(pullID int64, sha string) { // We get the latest sha commit hash again to handle the case where the check of a previous push // did not succeed or was not finished yet. - if err = pr.LoadHeadRepoCtx(ctx); err != nil { - log.Error("pull[%d] LoadHeadRepoCtx: %v", pr.ID, err) + if err = pr.LoadHeadRepo(ctx); err != nil { + log.Error("pull[%d] LoadHeadRepo: %v", pr.ID, err) return } @@ -244,8 +244,8 @@ func handlePull(pullID int64, sha string) { if pr.BaseRepoID == pr.HeadRepoID { baseGitRepo = headGitRepo } else { - if err = pr.LoadBaseRepoCtx(ctx); err != nil { - log.Error("LoadBaseRepoCtx: %v", err) + if err = pr.LoadBaseRepo(ctx); err != nil { + log.Error("LoadBaseRepo: %v", err) return } diff --git a/services/comments/comments.go b/services/comments/comments.go index 7167219c20ce0..190b8a6725b0b 100644 --- a/services/comments/comments.go +++ b/services/comments/comments.go @@ -5,6 +5,8 @@ package comments import ( + "context" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" @@ -14,7 +16,7 @@ import ( ) // CreateIssueComment creates a plain issue comment. -func CreateIssueComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) { +func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) { comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{ Type: issues_model.CommentTypeComment, Doer: doer, @@ -27,27 +29,27 @@ func CreateIssueComment(doer *user_model.User, repo *repo_model.Repository, issu return nil, err } - mentions, err := issues_model.FindAndUpdateIssueMentions(db.DefaultContext, issue, doer, comment.Content) + mentions, err := issues_model.FindAndUpdateIssueMentions(ctx, issue, doer, comment.Content) if err != nil { return nil, err } - notification.NotifyCreateIssueComment(doer, repo, issue, comment, mentions) + notification.NotifyCreateIssueComment(ctx, doer, repo, issue, comment, mentions) return comment, nil } // UpdateComment updates information of comment. -func UpdateComment(c *issues_model.Comment, doer *user_model.User, oldContent string) error { +func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User, oldContent string) error { needsContentHistory := c.Content != oldContent && (c.Type == issues_model.CommentTypeComment || c.Type == issues_model.CommentTypeReview || c.Type == issues_model.CommentTypeCode) if needsContentHistory { - hasContentHistory, err := issues_model.HasIssueContentHistory(db.DefaultContext, c.IssueID, c.ID) + hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID) if err != nil { return err } if !hasContentHistory { - if err = issues_model.SaveIssueContentHistory(db.DefaultContext, c.PosterID, c.IssueID, c.ID, + if err = issues_model.SaveIssueContentHistory(ctx, c.PosterID, c.IssueID, c.ID, c.CreatedUnix, oldContent, true); err != nil { return err } @@ -59,33 +61,27 @@ func UpdateComment(c *issues_model.Comment, doer *user_model.User, oldContent st } if needsContentHistory { - err := issues_model.SaveIssueContentHistory(db.DefaultContext, doer.ID, c.IssueID, c.ID, timeutil.TimeStampNow(), c.Content, false) + err := issues_model.SaveIssueContentHistory(ctx, doer.ID, c.IssueID, c.ID, timeutil.TimeStampNow(), c.Content, false) if err != nil { return err } } - notification.NotifyUpdateComment(doer, c, oldContent) + notification.NotifyUpdateComment(ctx, doer, c, oldContent) return nil } // DeleteComment deletes the comment -func DeleteComment(doer *user_model.User, comment *issues_model.Comment) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) error { + err := db.AutoTx(ctx, func(ctx context.Context) error { + return issues_model.DeleteComment(ctx, comment) + }) if err != nil { return err } - defer committer.Close() - - if err := issues_model.DeleteComment(ctx, comment); err != nil { - return err - } - if err := committer.Commit(); err != nil { - return err - } - notification.NotifyDeleteComment(doer, comment) + notification.NotifyDeleteComment(ctx, doer, comment) return nil } diff --git a/services/issue/assignee.go b/services/issue/assignee.go index e24f8500c9ae2..291fc31637141 100644 --- a/services/issue/assignee.go +++ b/services/issue/assignee.go @@ -51,13 +51,13 @@ func ToggleAssignee(issue *issues_model.Issue, doer *user_model.User, assigneeID return } - assignee, err1 := user_model.GetUserByID(assigneeID) + assignee, err1 := user_model.GetUserByIDCtx(db.DefaultContext, assigneeID) if err1 != nil { err = err1 return } - notification.NotifyIssueChangeAssignee(doer, issue, assignee, removed, comment) + notification.NotifyIssueChangeAssignee(db.DefaultContext, doer, issue, assignee, removed, comment) return removed, comment, err } @@ -75,7 +75,7 @@ func ReviewRequest(issue *issues_model.Issue, doer, reviewer *user_model.User, i } if comment != nil { - notification.NotifyPullReviewRequest(doer, issue, reviewer, isAdd, comment) + notification.NotifyPullReviewRequest(db.DefaultContext, doer, issue, reviewer, isAdd, comment) } return comment, err @@ -246,7 +246,7 @@ func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewe } // notify all user in this team - if err = comment.LoadIssue(); err != nil { + if err = comment.LoadIssue(db.DefaultContext); err != nil { return } @@ -262,7 +262,7 @@ func TeamReviewRequest(issue *issues_model.Issue, doer *user_model.User, reviewe continue } comment.AssigneeID = member.ID - notification.NotifyPullReviewRequest(doer, issue, member, isAdd, comment) + notification.NotifyPullReviewRequest(db.DefaultContext, doer, issue, member, isAdd, comment) } return comment, err diff --git a/services/issue/content.go b/services/issue/content.go index 6f493892f4cb5..851d986de3010 100644 --- a/services/issue/content.go +++ b/services/issue/content.go @@ -5,6 +5,7 @@ package issue import ( + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/notification" @@ -18,7 +19,7 @@ func ChangeContent(issue *issues_model.Issue, doer *user_model.User, content str return err } - notification.NotifyIssueChangeContent(doer, issue, oldContent) + notification.NotifyIssueChangeContent(db.DefaultContext, doer, issue, oldContent) return nil } diff --git a/services/issue/issue.go b/services/issue/issue.go index 8342d7f5d2de7..ba9b17a0c8ab1 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -38,12 +38,12 @@ func NewIssue(repo *repo_model.Repository, issue *issues_model.Issue, labelIDs [ return err } - notification.NotifyNewIssue(issue, mentions) + notification.NotifyNewIssue(db.DefaultContext, issue, mentions) if len(issue.Labels) > 0 { - notification.NotifyIssueChangeLabels(issue.Poster, issue, issue.Labels, nil) + notification.NotifyIssueChangeLabels(db.DefaultContext, issue.Poster, issue, issue.Labels, nil) } if issue.Milestone != nil { - notification.NotifyIssueChangeMilestone(issue.Poster, issue, 0) + notification.NotifyIssueChangeMilestone(db.DefaultContext, issue.Poster, issue, 0) } return nil @@ -58,7 +58,7 @@ func ChangeTitle(issue *issues_model.Issue, doer *user_model.User, title string) return } - notification.NotifyIssueChangeTitle(doer, issue, oldTitle) + notification.NotifyIssueChangeTitle(db.DefaultContext, doer, issue, oldTitle) return nil } @@ -72,7 +72,7 @@ func ChangeIssueRef(issue *issues_model.Issue, doer *user_model.User, ref string return err } - notification.NotifyIssueChangeRef(doer, issue, oldRef) + notification.NotifyIssueChangeRef(db.DefaultContext, doer, issue, oldRef) return nil } @@ -135,10 +135,10 @@ func UpdateAssignees(issue *issues_model.Issue, oneAssignee string, multipleAssi // DeleteIssue deletes an issue func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue) error { // load issue before deleting it - if err := issue.LoadAttributes(db.DefaultContext); err != nil { + if err := issue.LoadAttributes(gitRepo.Ctx); err != nil { return err } - if err := issue.LoadPullRequest(); err != nil { + if err := issue.LoadPullRequest(gitRepo.Ctx); err != nil { return err } @@ -154,7 +154,7 @@ func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_m } } - notification.NotifyDeleteIssue(doer, issue) + notification.NotifyDeleteIssue(gitRepo.Ctx, doer, issue) return nil } @@ -162,7 +162,7 @@ func DeleteIssue(doer *user_model.User, gitRepo *git.Repository, issue *issues_m // AddAssigneeIfNotAssigned adds an assignee only if he isn't already assigned to the issue. // Also checks for access of assigned user func AddAssigneeIfNotAssigned(issue *issues_model.Issue, doer *user_model.User, assigneeID int64) (err error) { - assignee, err := user_model.GetUserByID(assigneeID) + assignee, err := user_model.GetUserByIDCtx(db.DefaultContext, assigneeID) if err != nil { return err } diff --git a/services/issue/label.go b/services/issue/label.go index a9a0c20b01492..cd29fcebaebf4 100644 --- a/services/issue/label.go +++ b/services/issue/label.go @@ -18,7 +18,7 @@ func ClearLabels(issue *issues_model.Issue, doer *user_model.User) (err error) { return } - notification.NotifyIssueClearLabels(doer, issue) + notification.NotifyIssueClearLabels(db.DefaultContext, doer, issue) return nil } @@ -29,7 +29,7 @@ func AddLabel(issue *issues_model.Issue, doer *user_model.User, label *issues_mo return err } - notification.NotifyIssueChangeLabels(doer, issue, []*issues_model.Label{label}, nil) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, []*issues_model.Label{label}, nil) return nil } @@ -39,7 +39,7 @@ func AddLabels(issue *issues_model.Issue, doer *user_model.User, labels []*issue return err } - notification.NotifyIssueChangeLabels(doer, issue, labels, nil) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, labels, nil) return nil } @@ -74,7 +74,7 @@ func RemoveLabel(issue *issues_model.Issue, doer *user_model.User, label *issues return err } - notification.NotifyIssueChangeLabels(doer, issue, nil, []*issues_model.Label{label}) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, nil, []*issues_model.Label{label}) return nil } @@ -89,6 +89,6 @@ func ReplaceLabels(issue *issues_model.Issue, doer *user_model.User, labels []*i return err } - notification.NotifyIssueChangeLabels(doer, issue, labels, old) + notification.NotifyIssueChangeLabels(db.DefaultContext, doer, issue, labels, old) return nil } diff --git a/services/issue/milestone.go b/services/issue/milestone.go index 965b07556d1e0..2be4a9e70a2e5 100644 --- a/services/issue/milestone.go +++ b/services/issue/milestone.go @@ -79,7 +79,7 @@ func ChangeMilestoneAssign(issue *issues_model.Issue, doer *user_model.User, old return fmt.Errorf("Commit: %w", err) } - notification.NotifyIssueChangeMilestone(doer, issue, oldMilestoneID) + notification.NotifyIssueChangeMilestone(db.DefaultContext, doer, issue, oldMilestoneID) return nil } diff --git a/services/issue/status.go b/services/issue/status.go index 0da5c88762c81..2d4622324ca9f 100644 --- a/services/issue/status.go +++ b/services/issue/status.go @@ -38,7 +38,7 @@ func changeStatusCtx(ctx context.Context, issue *issues_model.Issue, doer *user_ } } - notification.NotifyIssueChangeStatus(doer, issue, comment, closed) + notification.NotifyIssueChangeStatus(ctx, doer, issue, comment, closed) return nil } diff --git a/services/lfs/locks.go b/services/lfs/locks.go index e87589d124684..45ba8faacd238 100644 --- a/services/lfs/locks.go +++ b/services/lfs/locks.go @@ -57,7 +57,7 @@ func GetListLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, rv.Authorization, true, false) if !authenticated { @@ -144,7 +144,7 @@ func PostLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { @@ -211,7 +211,7 @@ func VerifyLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { @@ -277,7 +277,7 @@ func UnLockHandler(ctx *context.Context) { }) return } - repository.MustOwner() + repository.MustOwner(ctx) authenticated := authenticate(ctx, repository, authorization, true, true) if !authenticated { diff --git a/services/mailer/mail.go b/services/mailer/mail.go index 85a7d107e5275..a9e36e10f89b8 100644 --- a/services/mailer/mail.go +++ b/services/mailer/mail.go @@ -18,7 +18,6 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -265,7 +264,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient "Issue": ctx.Issue, "Comment": ctx.Comment, "IsPull": ctx.Issue.IsPull, - "User": ctx.Issue.Repo.MustOwner(), + "User": ctx.Issue.Repo.MustOwner(ctx), "Repo": ctx.Issue.Repo.FullName(), "Doer": ctx.Doer, "IsMention": fromMention, @@ -395,13 +394,13 @@ func sanitizeSubject(subject string) string { } // SendIssueAssignedMail composes and sends issue assigned email -func SendIssueAssignedMail(issue *issues_model.Issue, doer *user_model.User, content string, comment *issues_model.Comment, recipients []*user_model.User) error { +func SendIssueAssignedMail(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, content string, comment *issues_model.Comment, recipients []*user_model.User) error { if setting.MailService == nil { // No mail service configured return nil } - if err := issue.LoadRepo(db.DefaultContext); err != nil { + if err := issue.LoadRepo(ctx); err != nil { log.Error("Unable to load repo [%d] for issue #%d [%d]. Error: %v", issue.RepoID, issue.Index, issue.ID, err) return err } @@ -417,7 +416,7 @@ func SendIssueAssignedMail(issue *issues_model.Issue, doer *user_model.User, con for lang, tos := range langMap { msgs, err := composeIssueCommentMessages(&mailCommentContext{ - Context: context.TODO(), // TODO: use a correct context + Context: ctx, Issue: issue, Doer: doer, ActionType: activities_model.ActionType(0), diff --git a/services/mailer/mail_issue.go b/services/mailer/mail_issue.go index 61e276805dbfb..e7ff1d59d6c05 100644 --- a/services/mailer/mail_issue.go +++ b/services/mailer/mail_issue.go @@ -45,13 +45,13 @@ const ( func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_model.User) error { // Required by the mail composer; make sure to load these before calling the async function if err := ctx.Issue.LoadRepo(ctx); err != nil { - return fmt.Errorf("LoadRepo(): %w", err) + return fmt.Errorf("LoadRepo: %w", err) } - if err := ctx.Issue.LoadPoster(); err != nil { - return fmt.Errorf("LoadPoster(): %w", err) + if err := ctx.Issue.LoadPoster(ctx); err != nil { + return fmt.Errorf("LoadPoster: %w", err) } - if err := ctx.Issue.LoadPullRequest(); err != nil { - return fmt.Errorf("LoadPullRequest(): %w", err) + if err := ctx.Issue.LoadPullRequest(ctx); err != nil { + return fmt.Errorf("LoadPullRequest: %w", err) } // Enough room to avoid reallocations @@ -61,14 +61,14 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_mo unfiltered[0] = ctx.Issue.PosterID // =========== Assignees =========== - ids, err := issues_model.GetAssigneeIDsByIssue(ctx.Issue.ID) + ids, err := issues_model.GetAssigneeIDsByIssue(ctx, ctx.Issue.ID) if err != nil { return fmt.Errorf("GetAssigneeIDsByIssue(%d): %w", ctx.Issue.ID, err) } unfiltered = append(unfiltered, ids...) // =========== Participants (i.e. commenters, reviewers) =========== - ids, err = issues_model.GetParticipantsIDsByIssueID(ctx.Issue.ID) + ids, err = issues_model.GetParticipantsIDsByIssueID(ctx, ctx.Issue.ID) if err != nil { return fmt.Errorf("GetParticipantsIDsByIssueID(%d): %w", ctx.Issue.ID, err) } @@ -110,7 +110,7 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_mo } visited.AddMultiple(ids...) - unfilteredUsers, err := user_model.GetMaileableUsersByIDs(unfiltered, false) + unfilteredUsers, err := user_model.GetMaileableUsersByIDs(ctx, unfiltered, false) if err != nil { return err } @@ -173,7 +173,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, users []*user_model.User, vi // MailParticipants sends new issue thread created emails to repository watchers // and mentioned people. -func MailParticipants(issue *issues_model.Issue, doer *user_model.User, opType activities_model.ActionType, mentions []*user_model.User) error { +func MailParticipants(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, opType activities_model.ActionType, mentions []*user_model.User) error { if setting.MailService == nil { // No mail service configured return nil @@ -188,7 +188,7 @@ func MailParticipants(issue *issues_model.Issue, doer *user_model.User, opType a forceDoerNotification := opType == activities_model.ActionAutoMergePullRequest if err := mailIssueCommentToParticipants( &mailCommentContext{ - Context: context.TODO(), // TODO: use a correct context + Context: ctx, Issue: issue, Doer: doer, ActionType: opType, diff --git a/services/mailer/mail_release.go b/services/mailer/mail_release.go index 6df3fbbf1d0d6..b15fc05ce92f4 100644 --- a/services/mailer/mail_release.go +++ b/services/mailer/mail_release.go @@ -36,7 +36,7 @@ func MailNewRelease(ctx context.Context, rel *repo_model.Release) { return } - recipients, err := user_model.GetMaileableUsersByIDs(watcherIDList, false) + recipients, err := user_model.GetMaileableUsersByIDs(ctx, watcherIDList, false) if err != nil { log.Error("user_model.GetMaileableUsersByIDs: %v", err) return diff --git a/services/mailer/mail_repo.go b/services/mailer/mail_repo.go index 6fe9df0926e88..d3f5120929d20 100644 --- a/services/mailer/mail_repo.go +++ b/services/mailer/mail_repo.go @@ -6,9 +6,9 @@ package mailer import ( "bytes" + "context" "fmt" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -18,14 +18,14 @@ import ( ) // SendRepoTransferNotifyMail triggers a notification e-mail when a pending repository transfer was created -func SendRepoTransferNotifyMail(doer, newOwner *user_model.User, repo *repo_model.Repository) error { +func SendRepoTransferNotifyMail(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { if setting.MailService == nil { // No mail service configured return nil } if newOwner.IsOrganization() { - users, err := organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, newOwner.ID) + users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID) if err != nil { return err } diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 68a7182b07e09..362492631fa87 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -84,7 +84,7 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, labels, 12) - releases, err := repo_model.GetReleasesByRepoID(repo.ID, repo_model.FindReleasesOptions{ + releases, err := repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ ListOptions: db.ListOptions{ PageSize: 10, Page: 0, @@ -94,7 +94,7 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, releases, 8) - releases, err = repo_model.GetReleasesByRepoID(repo.ID, repo_model.FindReleasesOptions{ + releases, err = repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ ListOptions: db.ListOptions{ PageSize: 10, Page: 0, @@ -104,14 +104,14 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, releases, 1) - issues, err := issues_model.Issues(&issues_model.IssuesOptions{ + issues, err := issues_model.Issues(db.DefaultContext, &issues_model.IssuesOptions{ RepoID: repo.ID, IsPull: util.OptionalBoolFalse, SortType: "oldest", }) assert.NoError(t, err) assert.Len(t, issues, 15) - assert.NoError(t, issues[0].LoadDiscussComments()) + assert.NoError(t, issues[0].LoadDiscussComments(db.DefaultContext)) assert.Empty(t, issues[0].Comments) pulls, _, err := issues_model.PullRequests(repo.ID, &issues_model.PullRequestsOptions{ @@ -119,8 +119,8 @@ func TestGiteaUploadRepo(t *testing.T) { }) assert.NoError(t, err) assert.Len(t, pulls, 30) - assert.NoError(t, pulls[0].LoadIssue()) - assert.NoError(t, pulls[0].Issue.LoadDiscussComments()) + assert.NoError(t, pulls[0].LoadIssue(db.DefaultContext)) + assert.NoError(t, pulls[0].Issue.LoadDiscussComments(db.DefaultContext)) assert.Len(t, pulls[0].Issue.Comments, 2) } diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 6002e6b8edb28..4a77569d869c1 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -459,18 +459,18 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { log.Error("SyncMirrors [repo: %-v]: unable to GetRefCommitID [ref_name: %s]: %v", m.Repo, result.refName, err) continue } - notification.NotifySyncPushCommits(m.Repo.MustOwner(), m.Repo, &repo_module.PushUpdateOptions{ + notification.NotifySyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{ RefFullName: result.refName, OldCommitID: git.EmptySHA, NewCommitID: commitID, }, repo_module.NewPushCommits()) - notification.NotifySyncCreateRef(m.Repo.MustOwner(), m.Repo, tp, result.refName, commitID) + notification.NotifySyncCreateRef(ctx, m.Repo.MustOwner(ctx), m.Repo, tp, result.refName, commitID) continue } // Delete reference if result.newCommitID == gitShortEmptySha { - notification.NotifySyncDeleteRef(m.Repo.MustOwner(), m.Repo, tp, result.refName) + notification.NotifySyncDeleteRef(ctx, m.Repo.MustOwner(ctx), m.Repo, tp, result.refName) continue } @@ -498,7 +498,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { theCommits.CompareURL = m.Repo.ComposeCompareURL(oldCommitID, newCommitID) - notification.NotifySyncPushCommits(m.Repo.MustOwner(), m.Repo, &repo_module.PushUpdateOptions{ + notification.NotifySyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{ RefFullName: result.refName, OldCommitID: oldCommitID, NewCommitID: newCommitID, diff --git a/services/packages/packages.go b/services/packages/packages.go index 4513215ae14d9..76fdd02bf265c 100644 --- a/services/packages/packages.go +++ b/services/packages/packages.go @@ -108,12 +108,12 @@ func createPackageAndAddFile(pvci *PackageCreationInfo, pfci *PackageFileCreatio } if created { - pd, err := packages_model.GetPackageDescriptor(ctx, pv) + pd, err := packages_model.GetPackageDescriptor(db.DefaultContext, pv) if err != nil { return nil, nil, err } - notification.NotifyPackageCreate(pvci.Creator, pd) + notification.NotifyPackageCreate(db.DefaultContext, pvci.Creator, pd) } return pv, pf, nil @@ -409,7 +409,7 @@ func RemovePackageVersion(doer *user_model.User, pv *packages_model.PackageVersi return err } - notification.NotifyPackageDelete(doer, pd) + notification.NotifyPackageDelete(db.DefaultContext, doer, pd) return nil } diff --git a/services/pull/check.go b/services/pull/check.go index 6e91c22f3ea63..faf3459f16f3b 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -48,7 +48,7 @@ var ( func AddToTaskQueue(pr *issues_model.PullRequest) { err := prPatchCheckerQueue.PushFunc(strconv.FormatInt(pr.ID, 10), func() error { pr.Status = issues_model.PullRequestStatusChecking - err := pr.UpdateColsIfNotMerged("status") + err := pr.UpdateColsIfNotMerged(db.DefaultContext, "status") if err != nil { log.Error("AddToTaskQueue.UpdateCols[%d].(add to queue): %v", pr.ID, err) } else { @@ -68,7 +68,7 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce return ErrHasMerged } - if err := pr.LoadIssueCtx(ctx); err != nil { + if err := pr.LoadIssue(ctx); err != nil { return err } else if pr.Issue.IsClosed { return ErrIsClosed @@ -142,7 +142,7 @@ func isSignedIfRequired(ctx context.Context, pr *issues_model.PullRequest, doer // checkAndUpdateStatus checks if pull request is possible to leaving checking status, // and set to be either conflict or mergeable. -func checkAndUpdateStatus(pr *issues_model.PullRequest) { +func checkAndUpdateStatus(ctx context.Context, pr *issues_model.PullRequest) { // Status is not changed to conflict means mergeable. if pr.Status == issues_model.PullRequestStatusChecking { pr.Status = issues_model.PullRequestStatusMergeable @@ -155,7 +155,7 @@ func checkAndUpdateStatus(pr *issues_model.PullRequest) { } if !has { - if err := pr.UpdateColsIfNotMerged("merge_base", "status", "conflicted_files", "changed_protected_files"); err != nil { + if err := pr.UpdateColsIfNotMerged(ctx, "merge_base", "status", "conflicted_files", "changed_protected_files"); err != nil { log.Error("Update[%d]: %v", pr.ID, err) } } @@ -232,7 +232,7 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com // manuallyMerged checks if a pull request got manually merged // When a pull request got manually merged mark the pull request as merged func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool { - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("PullRequest[%d].LoadBaseRepo: %v", pr.ID, err) return false } @@ -278,7 +278,7 @@ func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool { return false } - notification.NotifyMergePullRequest(pr, merger) + notification.NotifyMergePullRequest(ctx, merger, pr) log.Info("manuallyMerged[%d]: Marked as manually merged into %s/%s by commit id: %s", pr.ID, pr.BaseRepo.Name, pr.BaseBranch, commit.ID.String()) return true @@ -346,7 +346,7 @@ func testPR(id int64) { } return } - checkAndUpdateStatus(pr) + checkAndUpdateStatus(ctx, pr) } // CheckPrsForBaseBranch check all pulls with bseBrannch diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go index 5d846129f6ce4..10692221a4100 100644 --- a/services/pull/commit_status.go +++ b/services/pull/commit_status.go @@ -101,7 +101,7 @@ func IsPullCommitStatusPass(ctx context.Context, pr *issues_model.PullRequest) ( // GetPullRequestCommitStatusState returns pull request merged commit status state func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullRequest) (structs.CommitStatusState, error) { // Ensure HeadRepo is loaded - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { return "", errors.Wrap(err, "LoadHeadRepo") } @@ -129,7 +129,7 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR return "", err } - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return "", errors.Wrap(err, "LoadBaseRepo") } diff --git a/services/pull/edits.go b/services/pull/edits.go index 2938f2b108b93..84f7c80da7b76 100644 --- a/services/pull/edits.go +++ b/services/pull/edits.go @@ -23,7 +23,7 @@ func SetAllowEdits(ctx context.Context, doer *user_model.User, pr *issues_model. return ErrUserHasNoPermissionForAction } - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { return err } diff --git a/services/pull/merge.go b/services/pull/merge.go index 6f37a887db438..b29c9bc859932 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -40,18 +40,18 @@ import ( ) // GetDefaultMergeMessage returns default message used when merging pull request -func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (string, error) { - if err := pr.LoadHeadRepo(); err != nil { +func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (string, error) { + if err := pr.LoadHeadRepo(ctx); err != nil { return "", err } - if err := pr.LoadBaseRepo(); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return "", err } if pr.BaseRepo == nil { return "", repo_model.ErrRepoNotExist{ID: pr.BaseRepoID} } - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { return "", err } @@ -90,7 +90,7 @@ func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRe vars["HeadRepoOwnerName"] = pr.HeadRepo.OwnerName vars["HeadRepoName"] = pr.HeadRepo.Name } - refs, err := pr.ResolveCrossReferences(baseGitRepo.Ctx) + refs, err := pr.ResolveCrossReferences(ctx) if err == nil { closeIssueIndexes := make([]string, 0, len(refs)) closeWord := "close" @@ -134,10 +134,10 @@ func GetDefaultMergeMessage(baseGitRepo *git.Repository, pr *issues_model.PullRe // Merge merges pull request to base repository. // Caller should check PR is ready to be merged (review and status checks) func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error { - if err := pr.LoadHeadRepo(); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %w", err) - } else if err := pr.LoadBaseRepo(); err != nil { + } else if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) return fmt.Errorf("LoadBaseRepo: %w", err) } @@ -179,24 +179,24 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U pr.MergerID = doer.ID if _, err := pr.SetMerged(hammerCtx); err != nil { - log.Error("setMerged [%d]: %v", pr.ID, err) + log.Error("SetMerged [%d]: %v", pr.ID, err) } - if err := pr.LoadIssueCtx(hammerCtx); err != nil { - log.Error("loadIssue [%d]: %v", pr.ID, err) + if err := pr.LoadIssue(hammerCtx); err != nil { + log.Error("LoadIssue [%d]: %v", pr.ID, err) } if err := pr.Issue.LoadRepo(hammerCtx); err != nil { - log.Error("loadRepo for issue [%d]: %v", pr.ID, err) + log.Error("LoadRepo for issue [%d]: %v", pr.ID, err) } if err := pr.Issue.Repo.GetOwner(hammerCtx); err != nil { - log.Error("GetOwner for issue repo [%d]: %v", pr.ID, err) + log.Error("GetOwner for PR [%d]: %v", pr.ID, err) } if wasAutoMerged { - notification.NotifyAutoMergePullRequest(pr, doer) + notification.NotifyAutoMergePullRequest(hammerCtx, doer, pr) } else { - notification.NotifyMergePullRequest(pr, doer) + notification.NotifyMergePullRequest(hammerCtx, doer, pr) } // Reset cached commit count @@ -210,7 +210,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U } for _, ref := range refs { - if err = ref.LoadIssueCtx(hammerCtx); err != nil { + if err = ref.LoadIssue(hammerCtx); err != nil { return err } if err = ref.Issue.LoadRepo(hammerCtx); err != nil { @@ -511,7 +511,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode return "", err } - if err = pr.Issue.LoadPoster(); err != nil { + if err = pr.Issue.LoadPoster(ctx); err != nil { log.Error("LoadPoster: %v", err) return "", fmt.Errorf("LoadPoster: %w", err) } @@ -767,7 +767,7 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a // CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks) func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) { - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return fmt.Errorf("LoadBaseRepo: %w", err) } @@ -878,7 +878,7 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit return err } - notification.NotifyMergePullRequest(pr, doer) + notification.NotifyMergePullRequest(baseGitRepo.Ctx, doer, pr) log.Info("manuallyMerged[%d]: Marked as manually merged into %s/%s by commit id: %s", pr.ID, pr.BaseRepo.Name, pr.BaseBranch, commitID) return nil } diff --git a/services/pull/patch.go b/services/pull/patch.go index 9b87ac22e296c..1046095ff1103 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -30,7 +30,7 @@ import ( // DownloadDiffOrPatch will write the patch for the pr to the writer func DownloadDiffOrPatch(ctx context.Context, pr *issues_model.PullRequest, w io.Writer, patch, binary bool) error { - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to load base repository ID %d for pr #%d [%d]", pr.BaseRepoID, pr.Index, pr.ID) return err } diff --git a/services/pull/pull.go b/services/pull/pull.go index 5f8bd6b67120c..e0dcefe1410b8 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -82,12 +82,12 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *issu return err } - notification.NotifyNewPullRequest(pr, mentions) + notification.NotifyNewPullRequest(prCtx, pr, mentions) if len(pull.Labels) > 0 { - notification.NotifyIssueChangeLabels(pull.Poster, pull, pull.Labels, nil) + notification.NotifyIssueChangeLabels(prCtx, pull.Poster, pull, pull.Labels, nil) } if pull.Milestone != nil { - notification.NotifyIssueChangeMilestone(pull.Poster, pull, 0) + notification.NotifyIssueChangeMilestone(prCtx, pull.Poster, pull, 0) } // add first push codes comment @@ -172,7 +172,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer } // Check if pull request for the new target branch already exists - existingPr, err := issues_model.GetUnmergedPullRequest(pr.HeadRepoID, pr.BaseRepoID, pr.HeadBranch, targetBranch, issues_model.PullRequestFlowGithub) + existingPr, err := issues_model.GetUnmergedPullRequest(ctx, pr.HeadRepoID, pr.BaseRepoID, pr.HeadBranch, targetBranch, issues_model.PullRequestFlowGithub) if existingPr != nil { return issues_model.ErrPullRequestAlreadyExists{ ID: existingPr.ID, @@ -210,7 +210,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer pr.CommitsAhead = divergence.Ahead pr.CommitsBehind = divergence.Behind - if err := pr.UpdateColsIfNotMerged("merge_base", "status", "conflicted_files", "changed_protected_files", "base_branch", "commits_ahead", "commits_behind"); err != nil { + if err := pr.UpdateColsIfNotMerged(ctx, "merge_base", "status", "conflicted_files", "changed_protected_files", "base_branch", "commits_ahead", "commits_behind"); err != nil { return err } @@ -231,9 +231,9 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer } func checkForInvalidation(ctx context.Context, requests issues_model.PullRequestList, repoID int64, doer *user_model.User, branch string) error { - repo, err := repo_model.GetRepositoryByID(repoID) + repo, err := repo_model.GetRepositoryByIDCtx(ctx, repoID) if err != nil { - return fmt.Errorf("GetRepositoryByID: %w", err) + return fmt.Errorf("GetRepositoryByIDCtx: %w", err) } gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) if err != nil { @@ -301,7 +301,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, } pr.Issue.PullRequest = pr - notification.NotifyPullRequestSynchronized(doer, pr) + notification.NotifyPullRequestSynchronized(ctx, doer, pr) } } } @@ -320,7 +320,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, AddToTaskQueue(pr) comment, err := issues_model.CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID) if err == nil && comment != nil { - notification.NotifyPullRequestPushCommits(doer, pr, comment) + notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment) } } @@ -352,14 +352,14 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, // checkIfPRContentChanged checks if diff to target branch has changed by push // A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) { - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { return false, fmt.Errorf("LoadHeadRepo: %w", err) } else if pr.HeadRepo == nil { // corrupt data assumed changed return true, nil } - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return false, fmt.Errorf("LoadBaseRepo: %w", err) } @@ -430,22 +430,22 @@ func PushToBaseRepo(ctx context.Context, pr *issues_model.PullRequest) (err erro func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, prefixHeadBranch string) (err error) { log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName()) - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("Unable to load head repository for PR[%d] Error: %v", pr.ID, err) return err } headRepoPath := pr.HeadRepo.RepoPath() - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) return err } baseRepoPath := pr.BaseRepo.RepoPath() - if err = pr.LoadIssue(); err != nil { + if err = pr.LoadIssue(ctx); err != nil { return fmt.Errorf("unable to load issue %d for pr %d: %w", pr.IssueID, pr.ID, err) } - if err = pr.Issue.LoadPoster(); err != nil { + if err = pr.Issue.LoadPoster(ctx); err != nil { return fmt.Errorf("unable to load poster %d for pr %d: %w", pr.Issue.PosterID, pr.ID, err) } @@ -485,7 +485,7 @@ func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, pre // UpdateRef update refs/pull/id/head directly for agit flow pull request func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) { log.Trace("UpdateRef[%d]: upgate pull request ref in base repo '%s'", pr.ID, pr.GetGitRefName()) - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) return err } @@ -583,21 +583,21 @@ var commitMessageTrailersPattern = regexp.MustCompile(`(?:^|\n\n)(?:[\w-]+[ \t]* // GetSquashMergeCommitMessages returns the commit messages between head and merge base (if there is one) func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequest) string { - if err := pr.LoadIssue(); err != nil { + if err := pr.LoadIssue(ctx); err != nil { log.Error("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err) return "" } - if err := pr.Issue.LoadPoster(); err != nil { + if err := pr.Issue.LoadPoster(ctx); err != nil { log.Error("Cannot load poster %d for pr id %d, index %d Error: %v", pr.Issue.PosterID, pr.ID, pr.Index, err) return "" } if pr.HeadRepo == nil { var err error - pr.HeadRepo, err = repo_model.GetRepositoryByID(pr.HeadRepoID) + pr.HeadRepo, err = repo_model.GetRepositoryByIDCtx(ctx, pr.HeadRepoID) if err != nil { - log.Error("GetRepositoryById[%d]: %v", pr.HeadRepoID, err) + log.Error("GetRepositoryByIdCtx[%d]: %v", pr.HeadRepoID, err) return "" } } @@ -743,10 +743,10 @@ func GetIssuesLastCommitStatus(ctx context.Context, issues issues_model.IssueLis // GetIssuesAllCommitStatus returns a map of issue ID to a list of all statuses for the most recent commit as well as a map of issue ID to only the commit's latest status func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64][]*git_model.CommitStatus, map[int64]*git_model.CommitStatus, error) { - if err := issues.LoadPullRequests(); err != nil { + if err := issues.LoadPullRequests(ctx); err != nil { return nil, nil, err } - if _, err := issues.LoadRepositories(); err != nil { + if _, err := issues.LoadRepositories(ctx); err != nil { return nil, nil, err } @@ -802,7 +802,7 @@ func getAllCommitStatus(gitRepo *git.Repository, pr *issues_model.PullRequest) ( // IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, branchName string) (bool, error) { var err error - if err = pr.LoadBaseRepoCtx(ctx); err != nil { + if err = pr.LoadBaseRepo(ctx); err != nil { return false, err } baseGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) @@ -816,7 +816,7 @@ func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, br return false, err } - if err = pr.LoadHeadRepoCtx(ctx); err != nil { + if err = pr.LoadHeadRepo(ctx); err != nil { return false, err } var headGitRepo *git.Repository diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index 769e3c72e9d2b..22eefd1624a3d 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -8,6 +8,7 @@ package pull import ( "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -40,18 +41,18 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) gitRepo, err := git.OpenRepository(git.DefaultContext, pr.BaseRepo.RepoPath()) assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, err := GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", mergeMessage) pr.BaseRepoID = 1 pr.HeadRepoID = 2 - mergeMessage, err = GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo1:branch2 into master", mergeMessage) } @@ -70,12 +71,12 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2, BaseRepo: baseRepo}) - assert.NoError(t, pr.LoadBaseRepo()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) gitRepo, err := git.OpenRepository(git.DefaultContext, pr.BaseRepo.RepoPath()) assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, err := GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (!3) from branch2 into master", mergeMessage) @@ -84,7 +85,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr.HeadRepoID = 2 pr.BaseRepo = nil pr.HeadRepo = nil - mergeMessage, err = GetDefaultMergeMessage(gitRepo, pr, "") + mergeMessage, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo2:branch2 into master", mergeMessage) diff --git a/services/pull/review.go b/services/pull/review.go index 16c9e108ee741..2555e1b3b35e2 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -67,7 +67,7 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git. return nil, err } - notification.NotifyCreateIssueComment(doer, issue.Repo, issue, comment, mentions) + notification.NotifyCreateIssueComment(ctx, doer, issue.Repo, issue, comment, mentions) return comment, nil } @@ -119,12 +119,12 @@ var notEnoughLines = regexp.MustCompile(`exit status 128 - fatal: file .* has on // createCodeComment creates a plain code comment at the specified line / path func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, treePath string, line, reviewID int64) (*issues_model.Comment, error) { var commitID, patch string - if err := issue.LoadPullRequest(); err != nil { - return nil, fmt.Errorf("GetPullRequestByIssueID: %w", err) + if err := issue.LoadPullRequest(ctx); err != nil { + return nil, fmt.Errorf("LoadPullRequest: %w", err) } pr := issue.PullRequest - if err := pr.LoadBaseRepoCtx(ctx); err != nil { - return nil, fmt.Errorf("LoadHeadRepo: %w", err) + if err := pr.LoadBaseRepo(ctx); err != nil { + return nil, fmt.Errorf("LoadBaseRepo: %w", err) } gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) if err != nil { @@ -254,7 +254,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos return nil, nil, err } - notification.NotifyPullRequestReview(pr, review, comm, mentions) + notification.NotifyPullRequestReview(ctx, pr, review, comm, mentions) for _, lines := range review.CodeComments { for _, comments := range lines { @@ -263,7 +263,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos if err != nil { return nil, nil, err } - notification.NotifyPullRequestCodeComment(pr, codeComment, mentions) + notification.NotifyPullRequestCodeComment(ctx, pr, codeComment, mentions) } } } @@ -316,7 +316,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string, return nil, nil } - if err = review.Issue.LoadPullRequest(); err != nil { + if err = review.Issue.LoadPullRequest(ctx); err != nil { return } if err = review.Issue.LoadAttributes(ctx); err != nil { @@ -339,7 +339,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string, comment.Poster = doer comment.Issue = review.Issue - notification.NotifyPullRevieweDismiss(doer, review, comment) + notification.NotifyPullReviewDismiss(ctx, doer, review, comment) return comment, err } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 15e776c4b9ce4..9c04aa1c92fe6 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -23,7 +23,7 @@ import ( // createTemporaryRepo creates a temporary repo with "base" for pr.BaseBranch and "tracking" for pr.HeadBranch // it also create a second base branch called "original_base" func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (string, error) { - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) return "", fmt.Errorf("LoadHeadRepo: %w", err) } else if pr.HeadRepo == nil { @@ -31,7 +31,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str return "", &repo_model.ErrRepoNotExist{ ID: pr.HeadRepoID, } - } else if err := pr.LoadBaseRepoCtx(ctx); err != nil { + } else if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) return "", fmt.Errorf("LoadBaseRepo: %w", err) } else if pr.BaseRepo == nil { diff --git a/services/pull/update.go b/services/pull/update.go index bd4880a2fc7a0..36e66bb7a9d50 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -48,10 +48,10 @@ func Update(ctx context.Context, pull *issues_model.PullRequest, doer *user_mode return fmt.Errorf("Not support update agit flow pull request's head branch") } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %w", err) - } else if err = pr.LoadBaseRepoCtx(ctx); err != nil { + } else if err = pr.LoadBaseRepo(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) return fmt.Errorf("LoadBaseRepo: %w", err) } @@ -145,10 +145,10 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest, // GetDiverging determines how many commits a PR is ahead or behind the PR base branch func GetDiverging(ctx context.Context, pr *issues_model.PullRequest) (*git.DivergeObject, error) { log.Trace("GetDiverging[%d]: compare commits", pr.ID) - if err := pr.LoadBaseRepoCtx(ctx); err != nil { + if err := pr.LoadBaseRepo(ctx); err != nil { return nil, err } - if err := pr.LoadHeadRepoCtx(ctx); err != nil { + if err := pr.LoadHeadRepo(ctx); err != nil { return nil, err } diff --git a/services/release/release.go b/services/release/release.go index cf398debbb8eb..eb989381f0f57 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -24,24 +24,24 @@ import ( "code.gitea.io/gitea/modules/timeutil" ) -func createTag(gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) { +func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) { var created bool // Only actual create when publish. if !rel.IsDraft { if !gitRepo.IsTagExist(rel.TagName) { - if err := rel.LoadAttributes(); err != nil { + if err := rel.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) return false, err } - protectedTags, err := git_model.GetProtectedTags(rel.Repo.ID) + protectedTags, err := git_model.GetProtectedTags(ctx, rel.Repo.ID) if err != nil { return false, fmt.Errorf("GetProtectedTags: %w", err) } // Trim '--' prefix to prevent command line argument vulnerability. rel.TagName = strings.TrimPrefix(rel.TagName, "--") - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, rel.TagName, rel.PublisherID) + isAllowed, err := git_model.IsUserAllowedToControlTag(ctx, protectedTags, rel.TagName, rel.PublisherID) if err != nil { return false, err } @@ -81,13 +81,13 @@ func createTag(gitRepo *git.Repository, rel *repo_model.Release, msg string) (bo commits.CompareURL = rel.Repo.ComposeCompareURL(git.EmptySHA, commit.ID.String()) notification.NotifyPushCommits( - rel.Publisher, rel.Repo, + ctx, rel.Publisher, rel.Repo, &repository.PushUpdateOptions{ RefFullName: git.TagPrefix + rel.TagName, OldCommitID: git.EmptySHA, NewCommitID: commit.ID.String(), }, commits) - notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName, commit.ID.String()) + notification.NotifyCreateRef(ctx, rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName, commit.ID.String()) rel.CreatedUnix = timeutil.TimeStampNow() } commit, err := gitRepo.GetTagCommit(rel.TagName) @@ -102,7 +102,7 @@ func createTag(gitRepo *git.Repository, rel *repo_model.Release, msg string) (bo } if rel.PublisherID <= 0 { - u, err := user_model.GetUserByEmail(commit.Author.Email) + u, err := user_model.GetUserByEmailContext(ctx, commit.Author.Email) if err == nil { rel.PublisherID = u.ID } @@ -124,7 +124,7 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU } } - if _, err = createTag(gitRepo, rel, msg); err != nil { + if _, err = createTag(gitRepo.Ctx, gitRepo, rel, msg); err != nil { return err } @@ -138,7 +138,7 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU } if !rel.IsDraft { - notification.NotifyNewRelease(rel) + notification.NotifyNewRelease(gitRepo.Ctx, rel) } return nil @@ -173,7 +173,7 @@ func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.R IsTag: true, } - if _, err = createTag(gitRepo, rel, msg); err != nil { + if _, err = createTag(ctx, gitRepo, rel, msg); err != nil { return err } @@ -190,7 +190,7 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod if rel.ID == 0 { return errors.New("UpdateRelease only accepts an exist release") } - isCreated, err := createTag(gitRepo, rel, "") + isCreated, err := createTag(gitRepo.Ctx, gitRepo, rel, "") if err != nil { return err } @@ -272,12 +272,12 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod } if !isCreated { - notification.NotifyUpdateRelease(doer, rel) + notification.NotifyUpdateRelease(gitRepo.Ctx, doer, rel) return } if !rel.IsDraft { - notification.NotifyNewRelease(rel) + notification.NotifyNewRelease(gitRepo.Ctx, rel) } return err @@ -296,11 +296,11 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } if delTag { - protectedTags, err := git_model.GetProtectedTags(rel.RepoID) + protectedTags, err := git_model.GetProtectedTags(ctx, rel.RepoID) if err != nil { return fmt.Errorf("GetProtectedTags: %w", err) } - isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, rel.TagName, rel.PublisherID) + isAllowed, err := git_model.IsUserAllowedToControlTag(ctx, protectedTags, rel.TagName, rel.PublisherID) if err != nil { return err } @@ -318,15 +318,15 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } notification.NotifyPushCommits( - doer, repo, + ctx, doer, repo, &repository.PushUpdateOptions{ RefFullName: git.TagPrefix + rel.TagName, OldCommitID: rel.Sha1, NewCommitID: git.EmptySHA, }, repository.NewPushCommits()) - notification.NotifyDeleteRef(doer, repo, "tag", git.TagPrefix+rel.TagName) + notification.NotifyDeleteRef(ctx, doer, repo, "tag", git.TagPrefix+rel.TagName) - if err := repo_model.DeleteReleaseByID(id); err != nil { + if err := repo_model.DeleteReleaseByID(ctx, id); err != nil { return fmt.Errorf("DeleteReleaseByID: %w", err) } } else { @@ -338,11 +338,11 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } rel.Repo = repo - if err = rel.LoadAttributes(); err != nil { + if err = rel.LoadAttributes(ctx); err != nil { return fmt.Errorf("LoadAttributes: %w", err) } - if err := repo_model.DeleteAttachmentsByRelease(rel.ID); err != nil { + if err := repo_model.DeleteAttachmentsByRelease(ctx, rel.ID); err != nil { return fmt.Errorf("DeleteAttachments: %w", err) } @@ -353,7 +353,7 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del } } - notification.NotifyDeleteRelease(doer, rel) + notification.NotifyDeleteRelease(ctx, doer, rel) return nil } diff --git a/services/release/release_test.go b/services/release/release_test.go index c0cafb5fcc081..1ade9bed37afa 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -297,13 +297,13 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.NotEmpty(t, release.CreatedUnix) releaseCreatedUnix := release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Note = "Changed note" - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -321,12 +321,12 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -344,13 +344,13 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: true, IsTag: false, } - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" release.Note = "Changed note" - _, err = createTag(gitRepo, release, "") + _, err = createTag(db.DefaultContext, gitRepo, release, "") assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) } diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 57a21f500cd56..3895c54c7b957 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -96,7 +96,7 @@ func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOption return nil, err } - notification.NotifyCreateRepository(doer, u, repo) + notification.NotifyCreateRepository(db.DefaultContext, doer, u, repo) return repo, nil } diff --git a/services/repository/branch.go b/services/repository/branch.go index 1328422582980..e1f26b89afc2e 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -11,6 +11,7 @@ import ( "strings" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -141,8 +142,8 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g return "", err } - notification.NotifyDeleteRef(doer, repo, "branch", git.BranchPrefix+from) - notification.NotifyCreateRef(doer, repo, "branch", git.BranchPrefix+to, refID) + notification.NotifyDeleteRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+from) + notification.NotifyCreateRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+to, refID) return "", nil } diff --git a/services/repository/fork.go b/services/repository/fork.go index e597bfa449d4a..a9a2b33ed8472 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -177,7 +177,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork } } - notification.NotifyForkRepository(doer, opts.BaseRepo, repo) + notification.NotifyForkRepository(ctx, doer, opts.BaseRepo, repo) return repo, nil } diff --git a/services/repository/push.go b/services/repository/push.go index 6776ff9f740f1..e2db18e1f7599 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -117,7 +117,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { tagName := opts.TagName() if opts.IsDelRef() { notification.NotifyPushCommits( - pusher, repo, + db.DefaultContext, pusher, repo, &repo_module.PushUpdateOptions{ RefFullName: git.TagPrefix + tagName, OldCommitID: opts.OldCommitID, @@ -125,7 +125,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { }, repo_module.NewPushCommits()) delTags = append(delTags, tagName) - notification.NotifyDeleteRef(pusher, repo, "tag", opts.RefFullName) + notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName) } else { // is new tag newCommit, err := gitRepo.GetCommit(opts.NewCommitID) if err != nil { @@ -137,7 +137,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { commits.CompareURL = repo.ComposeCompareURL(git.EmptySHA, opts.NewCommitID) notification.NotifyPushCommits( - pusher, repo, + db.DefaultContext, pusher, repo, &repo_module.PushUpdateOptions{ RefFullName: git.TagPrefix + tagName, OldCommitID: git.EmptySHA, @@ -145,7 +145,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { }, commits) addTags = append(addTags, tagName) - notification.NotifyCreateRef(pusher, repo, "tag", opts.RefFullName, opts.NewCommitID) + notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName, opts.NewCommitID) } } else if opts.IsBranch() { // If is branch reference if pusher == nil || pusher.ID != opts.PusherID { @@ -190,7 +190,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { if err != nil { return fmt.Errorf("newCommit.CommitsBeforeLimit: %w", err) } - notification.NotifyCreateRef(pusher, repo, "branch", opts.RefFullName, opts.NewCommitID) + notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName, opts.NewCommitID) } else { l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID) if err != nil { @@ -250,7 +250,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum] } - notification.NotifyPushCommits(pusher, repo, opts, commits) + notification.NotifyPushCommits(db.DefaultContext, pusher, repo, opts, commits) if err = git_model.RemoveDeletedBranchByName(repo.ID, branch); err != nil { log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, branch, err) @@ -261,7 +261,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err) } } else { - notification.NotifyDeleteRef(pusher, repo, "branch", opts.RefFullName) + notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName) if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil { // close all related pulls log.Error("close related pull request failed: %v", err) diff --git a/services/repository/repository.go b/services/repository/repository.go index 2f2c27ff20bf6..c369b98aae091 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -32,7 +32,7 @@ func CreateRepository(doer, owner *user_model.User, opts repo_module.CreateRepoO return nil, err } - notification.NotifyCreateRepository(doer, owner, repo) + notification.NotifyCreateRepository(db.DefaultContext, doer, owner, repo) return repo, nil } @@ -45,7 +45,7 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod if notify { // If the repo itself has webhooks, we need to trigger them before deleting it... - notification.NotifyDeleteRepository(doer, repo) + notification.NotifyDeleteRepository(ctx, doer, repo) } if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil { diff --git a/services/repository/template.go b/services/repository/template.go index bb5e3f46689cd..625bc305de7ad 100644 --- a/services/repository/template.go +++ b/services/repository/template.go @@ -101,7 +101,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R return nil, err } - notification.NotifyCreateRepository(doer, owner, generateRepo) + notification.NotifyCreateRepository(db.DefaultContext, doer, owner, generateRepo) return generateRepo, nil } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index a0f4a7685ccbd..2778f2e744234 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -55,7 +55,7 @@ func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Reposit } } - notification.NotifyTransferRepository(doer, repo, oldOwner.Name) + notification.NotifyTransferRepository(db.DefaultContext, doer, repo, oldOwner.Name) return nil } @@ -78,7 +78,7 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne repoWorkingPool.CheckOut(fmt.Sprint(repo.ID)) repo.Name = newRepoName - notification.NotifyRenameRepository(doer, repo, oldRepoName) + notification.NotifyRenameRepository(db.DefaultContext, doer, repo, oldRepoName) return nil } @@ -127,7 +127,7 @@ func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.R } // notify users who are able to accept / reject transfer - notification.NotifyRepoPendingTransfer(doer, newOwner, repo) + notification.NotifyRepoPendingTransfer(db.DefaultContext, doer, newOwner, repo) return nil } diff --git a/services/task/migrate.go b/services/task/migrate.go index faca6908a271b..307c60a09a337 100644 --- a/services/task/migrate.go +++ b/services/task/migrate.go @@ -51,7 +51,7 @@ func runMigrateTask(t *admin_model.Task) (err error) { if err == nil { err = admin_model.FinishMigrateTask(t) if err == nil { - notification.NotifyMigrateRepository(t.Doer, t.Owner, t.Repo) + notification.NotifyMigrateRepository(db.DefaultContext, t.Doer, t.Owner, t.Repo) return } diff --git a/services/user/user.go b/services/user/user.go index 4186efe68257a..9976bc7bd3464 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -78,7 +78,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { Actor: u, }) if err != nil { - return fmt.Errorf("SearchRepositoryByName: %w", err) + return fmt.Errorf("GetUserRepositories: %w", err) } if len(repos) == 0 { break diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 342e764f4da16..1780022eb4b2f 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -224,7 +224,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_mode } ws = append(ws, repoHooks...) - owner = source.Repository.MustOwner() + owner = source.Repository.MustOwner(ctx) } // check if owner is an org and append additional webhooks diff --git a/templates/user/notification/notification_div.tmpl b/templates/user/notification/notification_div.tmpl index 192652d06b2b3..18071549a0c59 100644 --- a/templates/user/notification/notification_div.tmpl +++ b/templates/user/notification/notification_div.tmpl @@ -34,7 +34,6 @@ {{range $notification := .Notifications}} {{$issue := .Issue}} {{$repo := .Repository}} - {{$repoOwner := $repo.MustOwner}} {{if eq .Status 3}} @@ -69,9 +68,7 @@ - - {{$repoOwner.Name}}/{{$repo.Name}} - + {{$repo.FullName}} {{if ne .Status 3}} diff --git a/tests/integration/api_comment_test.go b/tests/integration/api_comment_test.go index 126d886842e49..9cac32b9b9df4 100644 --- a/tests/integration/api_comment_test.go +++ b/tests/integration/api_comment_test.go @@ -10,6 +10,7 @@ import ( "net/url" "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -115,7 +116,7 @@ func TestAPIGetComment(t *testing.T) { defer tests.PrepareTestEnv(t)() comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2}) - assert.NoError(t, comment.LoadIssue()) + assert.NoError(t, comment.LoadIssue(db.DefaultContext)) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID}) repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) @@ -129,7 +130,7 @@ func TestAPIGetComment(t *testing.T) { var apiComment api.Comment DecodeJSON(t, resp, &apiComment) - assert.NoError(t, comment.LoadPoster()) + assert.NoError(t, comment.LoadPoster(db.DefaultContext)) expect := convert.ToComment(comment) assert.Equal(t, expect.ID, apiComment.ID) diff --git a/tests/integration/api_issue_reaction_test.go b/tests/integration/api_issue_reaction_test.go index a3cb9303fbcf9..9afc7475e2769 100644 --- a/tests/integration/api_issue_reaction_test.go +++ b/tests/integration/api_issue_reaction_test.go @@ -82,7 +82,7 @@ func TestAPICommentReactions(t *testing.T) { defer tests.PrepareTestEnv(t)() comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2}) - _ = comment.LoadIssue() + _ = comment.LoadIssue(db.DefaultContext) issue := comment.Issue _ = issue.LoadRepo(db.DefaultContext) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID}) diff --git a/tests/integration/api_notification_test.go b/tests/integration/api_notification_test.go index bf85520bb53b7..f14380222873e 100644 --- a/tests/integration/api_notification_test.go +++ b/tests/integration/api_notification_test.go @@ -10,6 +10,7 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -25,7 +26,7 @@ func TestAPINotification(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5}) - assert.NoError(t, thread5.LoadAttributes()) + assert.NoError(t, thread5.LoadAttributes(db.DefaultContext)) session := loginUser(t, user2.Name) token := getTokenForLoggedInUser(t, session) @@ -143,7 +144,7 @@ func TestAPINotificationPUT(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5}) - assert.NoError(t, thread5.LoadAttributes()) + assert.NoError(t, thread5.LoadAttributes(db.DefaultContext)) session := loginUser(t, user2.Name) token := getTokenForLoggedInUser(t, session) diff --git a/tests/integration/api_pull_commits_test.go b/tests/integration/api_pull_commits_test.go index aa58f44bbe510..6753ceaa97310 100644 --- a/tests/integration/api_pull_commits_test.go +++ b/tests/integration/api_pull_commits_test.go @@ -8,6 +8,7 @@ import ( "net/http" "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -19,12 +20,12 @@ import ( func TestAPIPullCommits(t *testing.T) { defer tests.PrepareTestEnv(t)() - pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - assert.NoError(t, pullIssue.LoadIssue()) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pullIssue.HeadRepoID}) + pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pr.HeadRepoID}) session := loginUser(t, "user2") - req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/%s/pulls/%d/commits", repo.OwnerName, repo.Name, pullIssue.Index) + req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/%s/pulls/%d/commits", repo.OwnerName, repo.Name, pr.Index) resp := session.MakeRequest(t, req, http.StatusOK) var commits []*api.Commit diff --git a/tests/integration/api_pull_test.go b/tests/integration/api_pull_test.go index 8ce92f3d4a622..81842b05fbb25 100644 --- a/tests/integration/api_pull_test.go +++ b/tests/integration/api_pull_test.go @@ -10,6 +10,7 @@ import ( "net/http" "testing" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -65,11 +66,11 @@ func TestAPIMergePullWIP(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Status: issues_model.PullRequestStatusMergeable}, unittest.Cond("has_merged = ?", false)) - pr.LoadIssue() + pr.LoadIssue(db.DefaultContext) issue_service.ChangeTitle(pr.Issue, owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title) // force reload - pr.LoadAttributes() + pr.LoadAttributes(db.DefaultContext) assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0]) diff --git a/tests/integration/eventsource_test.go b/tests/integration/eventsource_test.go index cd496e01292bb..2f698659cb963 100644 --- a/tests/integration/eventsource_test.go +++ b/tests/integration/eventsource_test.go @@ -11,6 +11,7 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -57,7 +58,7 @@ func TestEventSourceManagerRun(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5}) - assert.NoError(t, thread5.LoadAttributes()) + assert.NoError(t, thread5.LoadAttributes(db.DefaultContext)) session := loginUser(t, user2.Name) token := getTokenForLoggedInUser(t, session) diff --git a/tests/integration/pull_update_test.go b/tests/integration/pull_update_test.go index c08faaaeb6f4e..1bfe5c7050ddd 100644 --- a/tests/integration/pull_update_test.go +++ b/tests/integration/pull_update_test.go @@ -35,8 +35,8 @@ func TestAPIPullUpdate(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) - assert.NoError(t, pr.LoadBaseRepo()) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) session := loginUser(t, "user2") token := getTokenForLoggedInUser(t, session) @@ -63,8 +63,8 @@ func TestAPIPullUpdateByRebase(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) - assert.NoError(t, pr.LoadBaseRepo()) - assert.NoError(t, pr.LoadIssue()) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(db.DefaultContext)) session := loginUser(t, "user2") token := getTokenForLoggedInUser(t, session) diff --git a/tests/integration/repo_tag_test.go b/tests/integration/repo_tag_test.go index fb08895e212f3..e20c725915560 100644 --- a/tests/integration/repo_tag_test.go +++ b/tests/integration/repo_tag_test.go @@ -9,6 +9,7 @@ import ( "testing" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -74,22 +75,22 @@ func TestCreateNewTagProtected(t *testing.T) { }) // Cleanup - releases, err := repo_model.GetReleasesByRepoID(repo.ID, repo_model.FindReleasesOptions{ + releases, err := repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ IncludeTags: true, TagNames: []string{"v-1", "v-1.1"}, }) assert.NoError(t, err) for _, release := range releases { - err = repo_model.DeleteReleaseByID(release.ID) + err = repo_model.DeleteReleaseByID(db.DefaultContext, release.ID) assert.NoError(t, err) } - protectedTags, err := git_model.GetProtectedTags(repo.ID) + protectedTags, err := git_model.GetProtectedTags(db.DefaultContext, repo.ID) assert.NoError(t, err) for _, protectedTag := range protectedTags { - err = git_model.DeleteProtectedTag(protectedTag) + err = git_model.DeleteProtectedTag(db.DefaultContext, protectedTag) assert.NoError(t, err) } } From 1b2470cd2ddef3f3b1e306fe1ad049ab899a68e0 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 19 Nov 2022 12:08:06 +0100 Subject: [PATCH 32/49] Show syntax lexer name in file view/blame (#21814) Show which Chroma Lexer is used to highlight the file in the file header. It's useful for development to see what was detected, and I think it's not bad info to have for the user: Screenshot 2022-11-14 at 22 31 16 Screenshot 2022-11-14 at 22 36 06 Screenshot 2022-11-14 at 22 36 26 Also, I improved the way this header overflows on small screens: Screenshot 2022-11-14 at 22 44 36 Co-authored-by: delvh Co-authored-by: Lauris BH Co-authored-by: Lunny Xiao Co-authored-by: John Olheiser --- modules/highlight/highlight.go | 36 ++++++++++++------ modules/highlight/highlight_test.go | 59 +++++++++++++++++++---------- modules/indexer/code/search.go | 5 ++- modules/util/util.go | 10 ++++- routers/web/repo/blame.go | 13 ++++++- routers/web/repo/view.go | 3 +- services/gitdiff/gitdiff.go | 3 +- services/gitdiff/highlightdiff.go | 4 +- templates/repo/blame.tmpl | 13 ++----- templates/repo/file_info.tmpl | 28 ++++++++++++++ templates/repo/view_file.tmpl | 30 ++------------- 11 files changed, 132 insertions(+), 72 deletions(-) create mode 100644 templates/repo/file_info.tmpl diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go index 65ed74b019950..3836c05880884 100644 --- a/modules/highlight/highlight.go +++ b/modules/highlight/highlight.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/analyze" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "github.com/alecthomas/chroma/v2" "github.com/alecthomas/chroma/v2/formatters/html" @@ -56,18 +57,18 @@ func NewContext() { }) } -// Code returns a HTML version of code string with chroma syntax highlighting classes -func Code(fileName, language, code string) string { +// Code returns a HTML version of code string with chroma syntax highlighting classes and the matched lexer name +func Code(fileName, language, code string) (string, string) { NewContext() // diff view newline will be passed as empty, change to literal '\n' so it can be copied // preserve literal newline in blame view if code == "" || code == "\n" { - return "\n" + return "\n", "" } if len(code) > sizeLimit { - return code + return code, "" } var lexer chroma.Lexer @@ -103,7 +104,10 @@ func Code(fileName, language, code string) string { } cache.Add(fileName, lexer) } - return CodeFromLexer(lexer, code) + + lexerName := formatLexerName(lexer.Config().Name) + + return CodeFromLexer(lexer, code), lexerName } // CodeFromLexer returns a HTML version of code string with chroma syntax highlighting classes @@ -134,12 +138,12 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string { return strings.TrimSuffix(htmlbuf.String(), "\n") } -// File returns a slice of chroma syntax highlighted HTML lines of code -func File(fileName, language string, code []byte) ([]string, error) { +// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name +func File(fileName, language string, code []byte) ([]string, string, error) { NewContext() if len(code) > sizeLimit { - return PlainText(code), nil + return PlainText(code), "", nil } formatter := html.New(html.WithClasses(true), @@ -172,9 +176,11 @@ func File(fileName, language string, code []byte) ([]string, error) { } } + lexerName := formatLexerName(lexer.Config().Name) + iterator, err := lexer.Tokenise(nil, string(code)) if err != nil { - return nil, fmt.Errorf("can't tokenize code: %w", err) + return nil, "", fmt.Errorf("can't tokenize code: %w", err) } tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens()) @@ -185,13 +191,13 @@ func File(fileName, language string, code []byte) ([]string, error) { iterator = chroma.Literator(tokens...) err = formatter.Format(htmlBuf, styles.GitHub, iterator) if err != nil { - return nil, fmt.Errorf("can't format code: %w", err) + return nil, "", fmt.Errorf("can't format code: %w", err) } lines = append(lines, htmlBuf.String()) htmlBuf.Reset() } - return lines, nil + return lines, lexerName, nil } // PlainText returns non-highlighted HTML for code @@ -212,3 +218,11 @@ func PlainText(code []byte) []string { } return m } + +func formatLexerName(name string) string { + if name == "fallback" { + return "Plaintext" + } + + return util.ToTitleCaseNoLower(name) +} diff --git a/modules/highlight/highlight_test.go b/modules/highlight/highlight_test.go index 8f83f4a2f6128..189975374614a 100644 --- a/modules/highlight/highlight_test.go +++ b/modules/highlight/highlight_test.go @@ -17,34 +17,52 @@ func lines(s string) []string { func TestFile(t *testing.T) { tests := []struct { - name string - code string - want []string + name string + code string + want []string + lexerName string }{ { - name: "empty.py", - code: "", - want: lines(""), + name: "empty.py", + code: "", + want: lines(""), + lexerName: "Python", }, { - name: "tags.txt", - code: "<>", - want: lines("<>"), + name: "empty.js", + code: "", + want: lines(""), + lexerName: "JavaScript", }, { - name: "tags.py", - code: "<>", - want: lines(`<>`), + name: "empty.yaml", + code: "", + want: lines(""), + lexerName: "YAML", }, { - name: "eol-no.py", - code: "a=1", - want: lines(`a=1`), + name: "tags.txt", + code: "<>", + want: lines("<>"), + lexerName: "Plaintext", }, { - name: "eol-newline1.py", - code: "a=1\n", - want: lines(`a=1\n`), + name: "tags.py", + code: "<>", + want: lines(`<>`), + lexerName: "Python", + }, + { + name: "eol-no.py", + code: "a=1", + want: lines(`a=1`), + lexerName: "Python", + }, + { + name: "eol-newline1.py", + code: "a=1\n", + want: lines(`a=1\n`), + lexerName: "Python", }, { name: "eol-newline2.py", @@ -54,6 +72,7 @@ func TestFile(t *testing.T) { \n `, ), + lexerName: "Python", }, { name: "empty-line-with-space.py", @@ -73,17 +92,19 @@ c=2 \n c=2`, ), + lexerName: "Python", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - out, err := File(tt.name, "", []byte(tt.code)) + out, lexerName, err := File(tt.name, "", []byte(tt.code)) assert.NoError(t, err) expected := strings.Join(tt.want, "\n") actual := strings.Join(out, "\n") assert.Equal(t, strings.Count(actual, "")) assert.EqualValues(t, expected, actual) + assert.Equal(t, tt.lexerName, lexerName) }) } } diff --git a/modules/indexer/code/search.go b/modules/indexer/code/search.go index bb7715bafcdc6..df255fa8758f8 100644 --- a/modules/indexer/code/search.go +++ b/modules/indexer/code/search.go @@ -94,6 +94,9 @@ func searchResult(result *SearchResult, startIndex, endIndex int) (*Result, erro lineNumbers[i] = startLineNum + i index += len(line) } + + highlighted, _ := highlight.Code(result.Filename, "", formattedLinesBuffer.String()) + return &Result{ RepoID: result.RepoID, Filename: result.Filename, @@ -102,7 +105,7 @@ func searchResult(result *SearchResult, startIndex, endIndex int) (*Result, erro Language: result.Language, Color: result.Color, LineNumbers: lineNumbers, - FormattedLines: highlight.Code(result.Filename, "", formattedLinesBuffer.String()), + FormattedLines: highlighted, }, nil } diff --git a/modules/util/util.go b/modules/util/util.go index be60fe4b4bbdf..6df47ca56821f 100644 --- a/modules/util/util.go +++ b/modules/util/util.go @@ -186,13 +186,21 @@ func ToUpperASCII(s string) string { return string(b) } -var titleCaser = cases.Title(language.English) +var ( + titleCaser = cases.Title(language.English) + titleCaserNoLower = cases.Title(language.English, cases.NoLower) +) // ToTitleCase returns s with all english words capitalized func ToTitleCase(s string) string { return titleCaser.String(s) } +// ToTitleCaseNoLower returns s with all english words capitalized without lowercasing +func ToTitleCaseNoLower(s string) string { + return titleCaserNoLower.String(s) +} + var ( whitespaceOnly = regexp.MustCompile("(?m)^[ \t]+$") leadingWhitespace = regexp.MustCompile("(?m)(^[ \t]*)(?:[^ \t\n])") diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index 64a6f0ec53850..52d5c3c6e628f 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -100,6 +100,8 @@ func RefBlame(ctx *context.Context) { ctx.Data["FileName"] = blob.Name() ctx.Data["NumLines"], err = blob.GetBlobLineCount() + ctx.Data["NumLinesSet"] = true + if err != nil { ctx.NotFound("GetBlobLineCount", err) return @@ -237,6 +239,8 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m rows := make([]*blameRow, 0) escapeStatus := &charset.EscapeStatus{} + var lexerName string + i := 0 commitCnt := 0 for _, part := range blameParts { @@ -278,7 +282,13 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m line += "\n" } fileName := fmt.Sprintf("%v", ctx.Data["FileName"]) - line = highlight.Code(fileName, language, line) + line, lexerNameForLine := highlight.Code(fileName, language, line) + + // set lexer name to the first detected lexer. this is certainly suboptimal and + // we should instead highlight the whole file at once + if lexerName == "" { + lexerName = lexerNameForLine + } br.EscapeStatus, line = charset.EscapeControlHTML(line, ctx.Locale) br.Code = gotemplate.HTML(line) @@ -290,4 +300,5 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m ctx.Data["EscapeStatus"] = escapeStatus ctx.Data["BlameRows"] = rows ctx.Data["CommitCnt"] = commitCnt + ctx.Data["LexerName"] = lexerName } diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index e7aca04819296..7500dbb34bb35 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -568,7 +568,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st language = "" } } - fileContent, err := highlight.File(blob.Name(), language, buf) + fileContent, lexerName, err := highlight.File(blob.Name(), language, buf) + ctx.Data["LexerName"] = lexerName if err != nil { log.Error("highlight.File failed, fallback to plain text: %v", err) fileContent = highlight.PlainText(buf) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 3c8c5c81a5694..d24c0ac082698 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -280,7 +280,8 @@ func DiffInlineWithUnicodeEscape(s template.HTML, locale translation.Locale) Dif // DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped func DiffInlineWithHighlightCode(fileName, language, code string, locale translation.Locale) DiffInline { - status, content := charset.EscapeControlHTML(highlight.Code(fileName, language, code), locale) + highlighted, _ := highlight.Code(fileName, language, code) + status, content := charset.EscapeControlHTML(highlighted, locale) return DiffInline{EscapeStatus: status, Content: template.HTML(content)} } diff --git a/services/gitdiff/highlightdiff.go b/services/gitdiff/highlightdiff.go index 4ceada4d7ec95..727827232d618 100644 --- a/services/gitdiff/highlightdiff.go +++ b/services/gitdiff/highlightdiff.go @@ -91,8 +91,8 @@ func (hcd *highlightCodeDiff) diffWithHighlight(filename, language, codeA, codeB hcd.collectUsedRunes(codeA) hcd.collectUsedRunes(codeB) - highlightCodeA := highlight.Code(filename, language, codeA) - highlightCodeB := highlight.Code(filename, language, codeB) + highlightCodeA, _ := highlight.Code(filename, language, codeA) + highlightCodeB, _ := highlight.Code(filename, language, codeB) highlightCodeA = hcd.convertToPlaceholders(highlightCodeA) highlightCodeB = hcd.convertToPlaceholders(highlightCodeB) diff --git a/templates/repo/blame.tmpl b/templates/repo/blame.tmpl index b697573d24eaa..e4a10ee57dd56 100644 --- a/templates/repo/blame.tmpl +++ b/templates/repo/blame.tmpl @@ -1,14 +1,9 @@
-

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

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

-
+

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

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

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

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

+
+ + +
+
+ + +

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

+
+
+

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

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

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

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

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

+
+

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

+
+
+ + + + + + + + + + + + + {{range .VersionsToRemove}} + + + + + + + + + {{else}} + + + + {{end}} + +
{{.locale.Tr "admin.packages.type"}}{{.locale.Tr "admin.packages.name"}}{{.locale.Tr "admin.packages.version"}}{{.locale.Tr "admin.packages.creator"}}{{.locale.Tr "admin.packages.size"}}{{.locale.Tr "admin.packages.published"}}
{{.Package.Type.Name}}{{.Package.Name}}{{.Version.Version}}{{.Creator.Name}}{{FileSize .CalculateBlobSize}}
{{.locale.Tr "packages.owner.settings.cleanuprules.preview.none"}}
+
diff --git a/templates/user/settings/navbar.tmpl b/templates/user/settings/navbar.tmpl index 01ae055d79097..d17494fc04856 100644 --- a/templates/user/settings/navbar.tmpl +++ b/templates/user/settings/navbar.tmpl @@ -18,6 +18,11 @@ {{.locale.Tr "settings.ssh_gpg_keys"}} + {{if .EnablePackages}} + + {{.locale.Tr "packages.title"}} + + {{end}} {{.locale.Tr "settings.organization"}} diff --git a/templates/user/settings/packages.tmpl b/templates/user/settings/packages.tmpl new file mode 100644 index 0000000000000..2612313454e88 --- /dev/null +++ b/templates/user/settings/packages.tmpl @@ -0,0 +1,9 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "base/alert" .}} + {{template "package/shared/cleanup_rules/list" .}} +
+
+{{template "base/footer" .}} diff --git a/templates/user/settings/packages_cleanup_rules_edit.tmpl b/templates/user/settings/packages_cleanup_rules_edit.tmpl new file mode 100644 index 0000000000000..4cf642b7e166a --- /dev/null +++ b/templates/user/settings/packages_cleanup_rules_edit.tmpl @@ -0,0 +1,9 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "base/alert" .}} + {{template "package/shared/cleanup_rules/edit" .}} +
+
+{{template "base/footer" .}} diff --git a/templates/user/settings/packages_cleanup_rules_preview.tmpl b/templates/user/settings/packages_cleanup_rules_preview.tmpl new file mode 100644 index 0000000000000..20041f9a42fdc --- /dev/null +++ b/templates/user/settings/packages_cleanup_rules_preview.tmpl @@ -0,0 +1,8 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "package/shared/cleanup_rules/preview" .}} +
+
+{{template "base/footer" .}} diff --git a/tests/integration/api_packages_test.go b/tests/integration/api_packages_test.go index 815685ea79960..8efb70848bf6b 100644 --- a/tests/integration/api_packages_test.go +++ b/tests/integration/api_packages_test.go @@ -203,22 +203,171 @@ func TestPackageQuota(t *testing.T) { func TestPackageCleanup(t *testing.T) { defer tests.PrepareTestEnv(t)() - time.Sleep(time.Second) + duration, _ := time.ParseDuration("-1h") - pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0)) - assert.NoError(t, err) - assert.NotEmpty(t, pbs) + t.Run("Common", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration) + assert.NoError(t, err) + assert.NotEmpty(t, pbs) - _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) - assert.NoError(t, err) + _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) + assert.NoError(t, err) - err = packages_service.Cleanup(nil, time.Duration(0)) - assert.NoError(t, err) + err = packages_service.Cleanup(db.DefaultContext, duration) + assert.NoError(t, err) - pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0)) - assert.NoError(t, err) - assert.Empty(t, pbs) + pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, duration) + assert.NoError(t, err) + assert.Empty(t, pbs) + + _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) + assert.ErrorIs(t, err, packages_model.ErrPackageNotExist) + }) - _, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion) - assert.ErrorIs(t, err, packages_model.ErrPackageNotExist) + t.Run("CleanupRules", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + + type version struct { + Version string + ShouldExist bool + Created int64 + } + + cases := []struct { + Name string + Versions []version + Rule *packages_model.PackageCleanupRule + }{ + { + Name: "Disabled", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: false, + }, + }, + { + Name: "KeepCount", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "v1.0", ShouldExist: true}, + {Version: "test-3", ShouldExist: false, Created: 1}, + {Version: "test-4", ShouldExist: false, Created: 1}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + KeepCount: 2, + }, + }, + { + Name: "KeepPattern", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "v1.0", ShouldExist: false}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + KeepPattern: "k.+p", + }, + }, + { + Name: "RemoveDays", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "v1.0", ShouldExist: false, Created: 1}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + RemoveDays: 60, + }, + }, + { + Name: "RemovePattern", + Versions: []version{ + {Version: "test", ShouldExist: true}, + {Version: "test-3", ShouldExist: false}, + {Version: "test-4", ShouldExist: false}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + RemovePattern: `t[e]+st-\d+`, + }, + }, + { + Name: "MatchFullName", + Versions: []version{ + {Version: "keep", ShouldExist: true}, + {Version: "test", ShouldExist: false}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + RemovePattern: `package/test|different/keep`, + MatchFullName: true, + }, + }, + { + Name: "Mixed", + Versions: []version{ + {Version: "keep", ShouldExist: true, Created: time.Now().Add(time.Duration(10000)).Unix()}, + {Version: "dummy", ShouldExist: true, Created: 1}, + {Version: "test-3", ShouldExist: true}, + {Version: "test-4", ShouldExist: false, Created: 1}, + }, + Rule: &packages_model.PackageCleanupRule{ + Enabled: true, + KeepCount: 1, + KeepPattern: `dummy`, + RemoveDays: 7, + RemovePattern: `t[e]+st-\d+`, + }, + }, + } + + for _, c := range cases { + t.Run(c.Name, func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + for _, v := range c.Versions { + url := fmt.Sprintf("/api/packages/%s/generic/package/%s/file.bin", user.Name, v.Version) + req := NewRequestWithBody(t, "PUT", url, bytes.NewReader([]byte{1})) + AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusCreated) + + if v.Created != 0 { + pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeGeneric, "package", v.Version) + assert.NoError(t, err) + _, err = db.GetEngine(db.DefaultContext).Exec("UPDATE package_version SET created_unix = ? WHERE id = ?", v.Created, pv.ID) + assert.NoError(t, err) + } + } + + c.Rule.OwnerID = user.ID + c.Rule.Type = packages_model.TypeGeneric + + pcr, err := packages_model.InsertCleanupRule(db.DefaultContext, c.Rule) + assert.NoError(t, err) + + err = packages_service.Cleanup(db.DefaultContext, duration) + assert.NoError(t, err) + + for _, v := range c.Versions { + pv, err := packages_model.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages_model.TypeGeneric, "package", v.Version) + if v.ShouldExist { + assert.NoError(t, err) + err = packages_service.DeletePackageVersionAndReferences(db.DefaultContext, pv) + assert.NoError(t, err) + } else { + assert.ErrorIs(t, err, packages_model.ErrPackageNotExist) + } + } + + assert.NoError(t, packages_model.DeleteCleanupRuleByID(db.DefaultContext, pcr.ID)) + }) + } + }) } From cd47fb4cf3070ba92dbf0e31311188810bbb55f6 Mon Sep 17 00:00:00 2001 From: Andrew Buettner <82419291+KB3HNS@users.noreply.github.com> Date: Sun, 20 Nov 2022 14:14:03 -0600 Subject: [PATCH 36/49] Improve documentation for PAM and static deployment (#21866) ## Changes proposed in [referenced issue 21845][1] - Expand PAM configuration description with working examples. - Clarify `STATIC_URL_PREFIX` use (include "assets" and only works after database has been initialized) - Add note for HTTPS proxy support VIA Apache. [1]: https://github.com/go-gitea/gitea/issues/21845 --- .../doc/advanced/config-cheat-sheet.en-us.md | 7 ++- .../doc/features/authentication.en-us.md | 46 +++++++++++++++++-- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index aece6afc08020..92758c61e402e 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -289,8 +289,13 @@ The following configuration set `Content-Type: application/vnd.android.package-a This includes CSS files, images, JS files and web fonts. Avatar images are dynamic resources and still served by Gitea. The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`. - Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective. + Requests are then made as `%(ROOT_URL)s/static/assets/css/index.css` or `https://cdn.example.com/assets/css/index.css` respectively. The static files are located in the `public/` directory of the Gitea source repository. + You can proxy the STATIC_URL_PREFIX requests to Gitea server to serve the static + assets, or copy the manually built Gitea assets from `$GITEA_BUILD/public` to + the assets location, eg: `/var/www/assets`, make sure `$STATIC_URL_PREFIX/assets/css/index.css` + points to `/var/www/assets/css/index.css`. + - `HTTP_ADDR`: **0.0.0.0**: HTTP listen address. - If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings. diff --git a/docs/content/doc/features/authentication.en-us.md b/docs/content/doc/features/authentication.en-us.md index 7d555d1dcc4b0..f25065d9c48db 100644 --- a/docs/content/doc/features/authentication.en-us.md +++ b/docs/content/doc/features/authentication.en-us.md @@ -166,11 +166,47 @@ Uses the following fields: ## PAM (Pluggable Authentication Module) -To configure PAM, set the 'PAM Service Name' to a filename in `/etc/pam.d/`. To -work with normal Linux passwords, the user running Gitea must have read access -to `/etc/shadow`. - -**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build), and the official binaries provided do not have this enabled. +This procedure enables PAM authentication. Users may still be added to the +system manually using the user administration. PAM provides a mechanism to +automatically add users to the current database by testing them against PAM +authentication. To work with normal Linux passwords, the user running Gitea +must also have read access to `/etc/shadow` in order to check the validity of +the account when logging in using a public key. + +**Note**: If a user has added SSH public keys into Gitea, the use of these +keys _may_ bypass the login check system. Therefore, if you wish to disable a user who +authenticates with PAM, you _should_ also manually disable the account in Gitea using the +built-in user manager. + +1. Configure and prepare the installation. + - It is recommended that you create an administrative user. + - Deselecting automatic sign-up may also be desired. +1. Once the database has been initialized, log in as the newly created +administrative user. +1. Navigate to the user setting (icon in top-right corner), and select +`Site Administration` -> `Authentication Sources`, and select +`Add Authentication Source`. +1. Fill out the field as follows: + - `Authentication Type` : `PAM` + - `Name` : Any value should be valid here, use "System Authentication" if + you'd like. + - `PAM Service Name` : Select the appropriate file listed under `/etc/pam.d/` + that performs the authentication desired.[^1] + - `PAM Email Domain` : The e-mail suffix to append to user authentication. + For example, if the login system expects a user called `gituser`, and this + field is set to `mail.com`, then Gitea will expect the `user email` field + for an authenticated GIT instance to be `gituser@mail.com`.[^2] + +**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build), +and the official binaries provided do not have this enabled. PAM requires that +the necessary libpam dynamic library be available and the necessary PAM +development headers be accessible to the compiler. + +[^1]: For example, using standard Linux log-in on Debian "Bullseye" use +`common-session-noninteractive` - this value may be valid for other flavors of +Debian including Ubuntu and Mint, consult your distribution's documentation. +[^2]: **This is a required field for PAM**. Be aware: In the above example, the +user will log into the Gitea web interface as `gituser` and not `gituser@mail.com` ## SMTP (Simple Mail Transfer Protocol) From 5b4113cf9cd11693cc5adad55ffa94373c7af69e Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 21 Nov 2022 03:39:00 +0100 Subject: [PATCH 37/49] Consolidate security-check into checks-backend (#21882) Also, run it via exact version instead of relying on global binary. --- .drone.yml | 10 ---------- Makefile | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.drone.yml b/.drone.yml index f2b34ef7e3e49..5127b5437755d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -39,16 +39,6 @@ steps: - make lint-frontend depends_on: [deps-frontend] - - name: security-check - image: golang:1.19 - pull: always - commands: - - make security-check - depends_on: [deps-backend] - volumes: - - name: deps - path: /go - - name: lint-backend image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env pull: always diff --git a/Makefile b/Makefile index 4ca346c63e6cb..4d78944de152c 100644 --- a/Makefile +++ b/Makefile @@ -333,7 +333,7 @@ checks: checks-frontend checks-backend checks-frontend: lockfile-check svg-check .PHONY: checks-backend -checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate +checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check .PHONY: lint lint: lint-frontend lint-backend @@ -745,7 +745,7 @@ generate-go: $(TAGS_PREREQ) .PHONY: security-check security-check: - govulncheck -v ./... + go run $(GOVULNCHECK_PACKAGE) -v ./... $(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ) CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@ From 50af57fb4929be7b7fa6dd9666220314c757abe4 Mon Sep 17 00:00:00 2001 From: Xinyu Zhou Date: Mon, 21 Nov 2022 13:14:58 +0800 Subject: [PATCH 38/49] Allow disable RSS/Atom feed (#21622) This patch provide a mechanism to disable RSS/Atom feed. Signed-off-by: Xinyu Zhou Co-authored-by: Lunny Xiao Co-authored-by: 6543 <6543@obermui.de> --- custom/conf/app.example.ini | 4 +++- .../doc/advanced/config-cheat-sheet.en-us.md | 1 + modules/context/repo.go | 6 ++++-- modules/setting/setting.go | 2 ++ routers/web/repo/view.go | 15 +++++++++------ routers/web/web.go | 13 +++++++++++-- templates/base/head.tmpl | 2 +- templates/org/home.tmpl | 4 +++- templates/repo/header.tmpl | 4 +++- templates/user/profile.tmpl | 4 +++- 10 files changed, 40 insertions(+), 15 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 8e85394d34820..76482bf607afb 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -2234,7 +2234,9 @@ ROUTER = console ;; Show template execution time in the footer ;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true ;; Generate sitemap. Defaults to `true`. -; ENABLE_SITEMAP = true +;ENABLE_SITEMAP = true +;; Enable/Disable RSS/Atom feed +;ENABLE_FEED = true ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 92758c61e402e..4e7ef492f90b2 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -1288,3 +1288,4 @@ PROXY_HOSTS = *.github.com - `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer. - `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer. - `ENABLE_SITEMAP`: **true**: Generate sitemap. +- `ENABLE_FEED`: **true**: Enable/Disable RSS/Atom feed. diff --git a/modules/context/repo.go b/modules/context/repo.go index 1a0263a3307a1..c363c36994736 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -441,8 +441,10 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) { userName := ctx.Params(":username") repoName := ctx.Params(":reponame") repoName = strings.TrimSuffix(repoName, ".git") - repoName = strings.TrimSuffix(repoName, ".rss") - repoName = strings.TrimSuffix(repoName, ".atom") + if setting.EnableFeed { + repoName = strings.TrimSuffix(repoName, ".rss") + repoName = strings.TrimSuffix(repoName, ".atom") + } // Check if the user is the same as the repository owner if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 12558da494b2f..fb425c8717253 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -440,6 +440,7 @@ var ( ShowFooterBranding bool ShowFooterVersion bool ShowFooterTemplateLoadTime bool + EnableFeed bool // Global setting objects Cfg *ini.File @@ -1102,6 +1103,7 @@ func loadFromConf(allowEmpty bool, extraConfig string) { ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool(true) ShowFooterTemplateLoadTime = Cfg.Section("other").Key("SHOW_FOOTER_TEMPLATE_LOAD_TIME").MustBool(true) EnableSitemap = Cfg.Section("other").Key("ENABLE_SITEMAP").MustBool(true) + EnableFeed = Cfg.Section("other").Key("ENABLE_FEED").MustBool(true) UI.ShowUserEmail = Cfg.Section("ui").Key("SHOW_USER_EMAIL").MustBool(true) UI.DefaultShowFullName = Cfg.Section("ui").Key("DEFAULT_SHOW_FULL_NAME").MustBool(false) diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 7500dbb34bb35..7a9e44ff5e39b 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -771,13 +771,16 @@ func checkCitationFile(ctx *context.Context, entry *git.TreeEntry) { // Home render repository home page func Home(ctx *context.Context) { - isFeed, _, showFeedType := feed.GetFeedType(ctx.Params(":reponame"), ctx.Req) - if isFeed { - feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType) - return - } + if setting.EnableFeed { + isFeed, _, showFeedType := feed.GetFeedType(ctx.Params(":reponame"), ctx.Req) + if isFeed { + feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType) + return + } - ctx.Data["FeedURL"] = ctx.Repo.Repository.HTMLURL() + ctx.Data["EnableFeed"] = true + ctx.Data["FeedURL"] = ctx.Repo.Repository.HTMLURL() + } checkHomeCodeViewable(ctx) if ctx.Written() { diff --git a/routers/web/web.go b/routers/web/web.go index 142f2384eb3c4..fe5007abb76ac 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -310,6 +310,13 @@ func RegisterRoutes(m *web.Route) { } } + feedEnabled := func(ctx *context.Context) { + if !setting.EnableFeed { + ctx.Error(http.StatusNotFound) + return + } + } + // FIXME: not all routes need go through same middleware. // Especially some AJAX requests, we can reduce middleware number to improve performance. // Routers. @@ -633,9 +640,11 @@ func RegisterRoutes(m *web.Route) { m.Get(".png", func(ctx *context.Context) { ctx.Error(http.StatusNotFound) }) m.Get(".keys", user.ShowSSHKeys) m.Get(".gpg", user.ShowGPGKeys) - m.Get(".rss", feed.ShowUserFeedRSS) - m.Get(".atom", feed.ShowUserFeedAtom) + m.Get(".rss", feedEnabled, feed.ShowUserFeedRSS) + m.Get(".atom", feedEnabled, feed.ShowUserFeedAtom) m.Get("", user.Profile) + }, func(ctx *context.Context) { + ctx.Data["EnableFeed"] = setting.EnableFeed }, context_service.UserAssignmentWeb()) m.Get("/attachments/{uuid}", repo.GetAttachment) }, ignSignIn) diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 70a88ff75569a..e2fc8434aaa68 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -15,7 +15,7 @@ {{end}} -{{if .FeedURL}} +{{if and .EnableFeed .FeedURL}} {{end}} diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index 448639975f895..358f045bc6a66 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -5,7 +5,9 @@
{{.Org.DisplayName}} - {{svg "octicon-rss" 36}} + {{if .EnableFeed}} + {{svg "octicon-rss" 36}} + {{end}} {{if .Org.Visibility.IsLimited}}
{{.locale.Tr "org.settings.visibility.limited_shortname"}}
{{end}} {{if .Org.Visibility.IsPrivate}}
{{.locale.Tr "org.settings.visibility.private_shortname"}}
{{end}} diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 831784a623058..e6bd839f5704e 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -13,7 +13,9 @@ {{.Owner.Name}}
/
{{.Name}} - {{svg "octicon-rss" 18}} + {{if $.EnableFeed}} + {{svg "octicon-rss" 18}} + {{end}}
{{if .IsTemplate}} {{if .IsPrivate}} diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 3b776bc16d5e4..70a49235ede78 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -18,7 +18,9 @@
{{if .Owner.FullName}}{{.Owner.FullName}}{{end}} {{.Owner.Name}} - {{svg "octicon-rss" 18}} + {{if .EnableFeed}} + {{svg "octicon-rss" 18}} + {{end}} From 2faaf818c14a66b02d05fb54d0dbea9f041a73cd Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 21 Nov 2022 16:36:59 +0800 Subject: [PATCH 39/49] Replace yaml.v2 with yaml.v3 (#21832) I don't see why we have to use two versions of yaml. The difference between the two versions has nothing to do with our usage. --- go.mod | 2 +- modules/migration/file_format.go | 11 +++++------ modules/packages/helm/metadata.go | 2 +- modules/packages/pub/metadata.go | 2 +- modules/packages/rubygems/metadata.go | 4 ++-- routers/api/packages/helm/helm.go | 2 +- services/migrations/dump.go | 2 +- services/migrations/restore.go | 2 +- tests/integration/api_packages_helm_test.go | 2 +- tests/integration/dump_restore_test.go | 2 +- 10 files changed, 15 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index cf1397c468884..ca8c79c689003 100644 --- a/go.mod +++ b/go.mod @@ -102,7 +102,6 @@ require ( golang.org/x/tools v0.1.12 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/ini.v1 v1.67.0 - gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 mvdan.cc/xurls/v2 v2.4.0 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 @@ -293,6 +292,7 @@ require ( gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/modules/migration/file_format.go b/modules/migration/file_format.go index 30e1d256cd9fb..92cf71407d699 100644 --- a/modules/migration/file_format.go +++ b/modules/migration/file_format.go @@ -8,12 +8,13 @@ import ( "fmt" "os" "strings" + "time" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "github.com/santhosh-tekuri/jsonschema/v5" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) // Load project data from file, with optional validation @@ -84,13 +85,9 @@ func validate(bs []byte, datatype interface{}, isJSON bool) error { func toStringKeys(val interface{}) (interface{}, error) { var err error switch val := val.(type) { - case map[interface{}]interface{}: + case map[string]interface{}: m := make(map[string]interface{}) for k, v := range val { - k, ok := k.(string) - if !ok { - return nil, fmt.Errorf("found non-string key %T %s", k, k) - } m[k], err = toStringKeys(v) if err != nil { return nil, err @@ -106,6 +103,8 @@ func toStringKeys(val interface{}) (interface{}, error) { } } return l, nil + case time.Time: + return val.Format(time.RFC3339), nil default: return val, nil } diff --git a/modules/packages/helm/metadata.go b/modules/packages/helm/metadata.go index 9517448ca68bb..fb5e51d0c532e 100644 --- a/modules/packages/helm/metadata.go +++ b/modules/packages/helm/metadata.go @@ -14,7 +14,7 @@ import ( "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) var ( diff --git a/modules/packages/pub/metadata.go b/modules/packages/pub/metadata.go index 1fc4908b91212..f3e9bf20bcb49 100644 --- a/modules/packages/pub/metadata.go +++ b/modules/packages/pub/metadata.go @@ -15,7 +15,7 @@ import ( "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) var ( diff --git a/modules/packages/rubygems/metadata.go b/modules/packages/rubygems/metadata.go index 05c1a8a719cbe..f1fc399918474 100644 --- a/modules/packages/rubygems/metadata.go +++ b/modules/packages/rubygems/metadata.go @@ -14,7 +14,7 @@ import ( "code.gitea.io/gitea/modules/validation" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) var ( @@ -120,7 +120,7 @@ func (r requirement) AsVersionRequirement() []VersionRequirement { if !ok { continue } - vm, ok := req[1].(map[interface{}]interface{}) + vm, ok := req[1].(map[string]interface{}) if !ok { continue } diff --git a/routers/api/packages/helm/helm.go b/routers/api/packages/helm/helm.go index 662d9a5dda28f..17f0a0d3118c5 100644 --- a/routers/api/packages/helm/helm.go +++ b/routers/api/packages/helm/helm.go @@ -23,7 +23,7 @@ import ( "code.gitea.io/gitea/routers/api/packages/helper" packages_service "code.gitea.io/gitea/services/packages" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) func apiError(ctx *context.Context, status int, obj interface{}) { diff --git a/services/migrations/dump.go b/services/migrations/dump.go index 4ab4539c89a6f..8103e2faacd56 100644 --- a/services/migrations/dump.go +++ b/services/migrations/dump.go @@ -26,7 +26,7 @@ import ( "code.gitea.io/gitea/modules/structs" "github.com/google/uuid" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) var _ base.Uploader = &RepositoryDumper{} diff --git a/services/migrations/restore.go b/services/migrations/restore.go index c3fbcbb25fa88..10fe8c4ee8cd6 100644 --- a/services/migrations/restore.go +++ b/services/migrations/restore.go @@ -13,7 +13,7 @@ import ( base "code.gitea.io/gitea/modules/migration" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) // RepositoryRestorer implements an Downloader from the local directory diff --git a/tests/integration/api_packages_helm_test.go b/tests/integration/api_packages_helm_test.go index 393bf3cbe2cbb..3c30a6848e561 100644 --- a/tests/integration/api_packages_helm_test.go +++ b/tests/integration/api_packages_helm_test.go @@ -22,7 +22,7 @@ import ( "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) func TestPackageHelm(t *testing.T) { diff --git a/tests/integration/dump_restore_test.go b/tests/integration/dump_restore_test.go index 19513d0271e17..80c71810e35ec 100644 --- a/tests/integration/dump_restore_test.go +++ b/tests/integration/dump_restore_test.go @@ -25,7 +25,7 @@ import ( "code.gitea.io/gitea/services/migrations" "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) func TestDumpRestore(t *testing.T) { From 8c6bcda84f0de634f3551c13b0c5cf76518bd8e6 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 21 Nov 2022 10:59:42 +0100 Subject: [PATCH 40/49] Improvements for Content Copy (#21842) It now supports copying Markdown, SVG and Images (not in Firefox currently because of lacking [`ClipboardItem`](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) support, but can be enabled in `about:config` and works). It will fetch the data if in a rendered view or when it's an image. Followup to https://github.com/go-gitea/gitea/pull/21629. --- .eslintrc.yaml | 2 +- options/locale/locale_en-US.ini | 2 +- routers/web/repo/view.go | 9 ++++- templates/repo/view_file.tmpl | 6 +-- web_src/js/features/clipboard.js | 15 +++++--- web_src/js/features/copycontent.js | 59 ++++++++++++++++++++++++++++++ web_src/js/features/repo-code.js | 16 +------- web_src/js/index.js | 2 + web_src/js/modules/tippy.js | 1 + web_src/js/utils.js | 48 ++++++++++++++++++++++++ web_src/js/utils.test.js | 7 +++- web_src/less/animations.less | 6 +++ 12 files changed, 144 insertions(+), 29 deletions(-) create mode 100644 web_src/js/features/copycontent.js diff --git a/.eslintrc.yaml b/.eslintrc.yaml index cd86b680ee414..2f213db37d582 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -199,7 +199,7 @@ rules: newline-per-chained-call: [0] no-alert: [0] no-array-constructor: [2] - no-async-promise-executor: [2] + no-async-promise-executor: [0] no-await-in-loop: [0] no-bitwise: [0] no-buffer-constructor: [0] diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 5c61bfeb6c5ca..b2b7b206df277 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -95,6 +95,7 @@ copy_content = Copy content copy_branch = Copy branch name copy_success = Copied! copy_error = Copy failed +copy_type_unsupported = This file type can not be copied write = Write preview = Preview @@ -1096,7 +1097,6 @@ editor.cannot_edit_non_text_files = Binary files cannot be edited in the web int editor.edit_this_file = Edit File editor.this_file_locked = File is locked editor.must_be_on_a_branch = You must be on a branch to make or propose changes to this file. -editor.only_copy_raw = You may only copy raw text files. editor.fork_before_edit = You must fork this repository to make or propose changes to this file. editor.delete_this_file = Delete File editor.must_have_write_access = You must have write access to make or propose changes to this file. diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 7a9e44ff5e39b..1d1ba250646c1 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -443,7 +443,12 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["IsRepresentableAsText"] = isRepresentableAsText ctx.Data["IsDisplayingSource"] = isDisplayingSource ctx.Data["IsDisplayingRendered"] = isDisplayingRendered - ctx.Data["IsTextSource"] = isTextFile || isDisplayingSource + + isTextSource := isTextFile || isDisplayingSource + ctx.Data["IsTextSource"] = isTextSource + if isTextSource { + ctx.Data["CanCopyContent"] = true + } // Check LFS Lock lfsLock, err := git_model.GetTreePathLock(ctx.Repo.Repository.ID, ctx.Repo.TreePath) @@ -474,6 +479,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st case isRepresentableAsText: if st.IsSvgImage() { ctx.Data["IsImageFile"] = true + ctx.Data["CanCopyContent"] = true ctx.Data["HasSourceRenderedToggle"] = true } @@ -608,6 +614,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["IsAudioFile"] = true case st.IsImage() && (setting.UI.SVG.Enabled || !st.IsSvgImage()): ctx.Data["IsImageFile"] = true + ctx.Data["CanCopyContent"] = true default: if fileSize >= setting.UI.MaxDisplayFileSize { ctx.Data["IsFileTooLarge"] = true diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index 321600a9975fe..0fe0a131985dd 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -38,11 +38,7 @@ {{end}}
{{svg "octicon-download"}} - {{if or .IsMarkup .IsRenderedHTML (not .IsTextSource)}} - {{svg "octicon-copy" 14}} - {{else}} - {{svg "octicon-copy" 14}} - {{end}} + {{svg "octicon-copy" 14}} {{if .Repository.CanEnableEditor}} {{if .CanEditFile}} {{svg "octicon-pencil"}} diff --git a/web_src/js/features/clipboard.js b/web_src/js/features/clipboard.js index 85324303e347e..f266d4f64d11e 100644 --- a/web_src/js/features/clipboard.js +++ b/web_src/js/features/clipboard.js @@ -2,11 +2,16 @@ import {showTemporaryTooltip} from '../modules/tippy.js'; const {copy_success, copy_error} = window.config.i18n; -export async function copyToClipboard(text) { - try { - await navigator.clipboard.writeText(text); - } catch { - return fallbackCopyToClipboard(text); +export async function copyToClipboard(content) { + if (content instanceof Blob) { + const item = new window.ClipboardItem({[content.type]: content}); + await navigator.clipboard.write([item]); + } else { // text + try { + await navigator.clipboard.writeText(content); + } catch { + return fallbackCopyToClipboard(content); + } } return true; } diff --git a/web_src/js/features/copycontent.js b/web_src/js/features/copycontent.js new file mode 100644 index 0000000000000..9b791bedba569 --- /dev/null +++ b/web_src/js/features/copycontent.js @@ -0,0 +1,59 @@ +import {copyToClipboard} from './clipboard.js'; +import {showTemporaryTooltip} from '../modules/tippy.js'; +import {convertImage} from '../utils.js'; +const {i18n} = window.config; + +async function doCopy(content, btn) { + const success = await copyToClipboard(content); + showTemporaryTooltip(btn, success ? i18n.copy_success : i18n.copy_error); +} + +export function initCopyContent() { + const btn = document.getElementById('copy-content'); + if (!btn || btn.classList.contains('disabled')) return; + + btn.addEventListener('click', async () => { + if (btn.classList.contains('is-loading')) return; + let content, isImage; + const link = btn.getAttribute('data-link'); + + // when data-link is present, we perform a fetch. this is either because + // the text to copy is not in the DOM or it is an image which should be + // fetched to copy in full resolution + if (link) { + btn.classList.add('is-loading'); + try { + const res = await fetch(link, {credentials: 'include', redirect: 'follow'}); + const contentType = res.headers.get('content-type'); + + if (contentType.startsWith('image/') && !contentType.startsWith('image/svg')) { + isImage = true; + content = await res.blob(); + } else { + content = await res.text(); + } + } catch { + return showTemporaryTooltip(btn, i18n.copy_error); + } finally { + btn.classList.remove('is-loading'); + } + } else { // text, read from DOM + const lineEls = document.querySelectorAll('.file-view .lines-code'); + content = Array.from(lineEls).map((el) => el.textContent).join(''); + } + + try { + await doCopy(content, btn); + } catch { + if (isImage) { // convert image to png as last-resort as some browser only support png copy + try { + await doCopy(await convertImage(content, 'image/png'), btn); + } catch { + showTemporaryTooltip(btn, i18n.copy_error); + } + } else { + showTemporaryTooltip(btn, i18n.copy_error); + } + } + }); +} diff --git a/web_src/js/features/repo-code.js b/web_src/js/features/repo-code.js index ef6b61196b73e..083a17bf216fc 100644 --- a/web_src/js/features/repo-code.js +++ b/web_src/js/features/repo-code.js @@ -1,10 +1,9 @@ import $ from 'jquery'; import {svg} from '../svg.js'; import {invertFileFolding} from './file-fold.js'; -import {createTippy, showTemporaryTooltip} from '../modules/tippy.js'; +import {createTippy} from '../modules/tippy.js'; import {copyToClipboard} from './clipboard.js'; -const {i18n} = window.config; export const singleAnchorRegex = /^#(L|n)([1-9][0-9]*)$/; export const rangeAnchorRegex = /^#(L[1-9][0-9]*)-(L[1-9][0-9]*)$/; @@ -114,18 +113,6 @@ function showLineButton() { }); } -function initCopyFileContent() { - // get raw text for copy content button, at the moment, only one button (and one related file content) is supported. - const copyFileContent = document.querySelector('#copy-file-content'); - if (!copyFileContent) return; - - copyFileContent.addEventListener('click', async () => { - const text = Array.from(document.querySelectorAll('.file-view .lines-code')).map((el) => el.textContent).join(''); - const success = await copyToClipboard(text); - showTemporaryTooltip(copyFileContent, success ? i18n.copy_success : i18n.copy_error); - }); -} - export function initRepoCodeView() { if ($('.code-view .lines-num').length > 0) { $(document).on('click', '.lines-num span', function (e) { @@ -205,5 +192,4 @@ export function initRepoCodeView() { if (!success) return; document.querySelector('.code-line-button')?._tippy?.hide(); }); - initCopyFileContent(); } diff --git a/web_src/js/index.js b/web_src/js/index.js index a829deaf116ec..f4638a60e09a7 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -89,6 +89,7 @@ import {initRepoWikiForm} from './features/repo-wiki.js'; import {initRepoCommentForm, initRepository} from './features/repo-legacy.js'; import {initFormattingReplacements} from './features/formatting.js'; import {initMcaptcha} from './features/mcaptcha.js'; +import {initCopyContent} from './features/copycontent.js'; // Run time-critical code as soon as possible. This is safe to do because this // script appears at the end of and rendered HTML is accessible at that point. @@ -136,6 +137,7 @@ $(document).ready(() => { initStopwatch(); initTableSort(); initFindFileInRepo(); + initCopyContent(); initAdminCommon(); initAdminEmails(); diff --git a/web_src/js/modules/tippy.js b/web_src/js/modules/tippy.js index 045df6f0a023a..6a89151691a97 100644 --- a/web_src/js/modules/tippy.js +++ b/web_src/js/modules/tippy.js @@ -27,6 +27,7 @@ export function createTippy(target, opts = {}) { export function initTooltip(el, props = {}) { const content = el.getAttribute('data-content') || props.content; if (!content) return null; + if (!el.hasAttribute('aria-label')) el.setAttribute('aria-label', content); return createTippy(el, { content, delay: 100, diff --git a/web_src/js/utils.js b/web_src/js/utils.js index 9b8bf925a9ee6..62ee11c2eb789 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -85,3 +85,51 @@ export function translateMonth(month) { export function translateDay(day) { return new Date(Date.UTC(2022, 7, day)).toLocaleString(getCurrentLocale(), {weekday: 'short'}); } + +// convert a Blob to a DataURI +export function blobToDataURI(blob) { + return new Promise((resolve, reject) => { + try { + const reader = new FileReader(); + reader.addEventListener('load', (e) => { + resolve(e.target.result); + }); + reader.addEventListener('error', () => { + reject(new Error('FileReader failed')); + }); + reader.readAsDataURL(blob); + } catch (err) { + reject(err); + } + }); +} + +// convert image Blob to another mime-type format. +export function convertImage(blob, mime) { + return new Promise(async (resolve, reject) => { + try { + const img = new Image(); + const canvas = document.createElement('canvas'); + img.addEventListener('load', () => { + try { + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + const context = canvas.getContext('2d'); + context.drawImage(img, 0, 0); + canvas.toBlob((blob) => { + if (!(blob instanceof Blob)) return reject(new Error('imageBlobToPng failed')); + resolve(blob); + }, mime); + } catch (err) { + reject(err); + } + }); + img.addEventListener('error', () => { + reject(new Error('imageBlobToPng failed')); + }); + img.src = await blobToDataURI(blob); + } catch (err) { + reject(err); + } + }); +} diff --git a/web_src/js/utils.test.js b/web_src/js/utils.test.js index 0567a5c64af93..1df0caa211030 100644 --- a/web_src/js/utils.test.js +++ b/web_src/js/utils.test.js @@ -1,7 +1,7 @@ import {expect, test} from 'vitest'; import { basename, extname, isObject, uniq, stripTags, joinPaths, parseIssueHref, - prettyNumber, parseUrl, translateMonth, translateDay + prettyNumber, parseUrl, translateMonth, translateDay, blobToDataURI, } from './utils.js'; test('basename', () => { @@ -131,3 +131,8 @@ test('translateDay', () => { expect(translateDay(5)).toEqual('pt.'); document.documentElement.lang = originalLang; }); + +test('blobToDataURI', async () => { + const blob = new Blob([JSON.stringify({test: true})], {type: 'application/json'}); + expect(await blobToDataURI(blob)).toEqual('data:application/json;base64,eyJ0ZXN0Ijp0cnVlfQ=='); +}); diff --git a/web_src/less/animations.less b/web_src/less/animations.less index 6d32625704d77..689898da2ad06 100644 --- a/web_src/less/animations.less +++ b/web_src/less/animations.less @@ -33,6 +33,12 @@ height: var(--height-loading); } +.btn-octicon.is-loading::after { + border-width: 2px; + height: 1.25rem; + width: 1.25rem; +} + code.language-math.is-loading::after { padding: 0; border-width: 2px; From 77ad37b70cb7719c1749b6239f1662ab453dcae8 Mon Sep 17 00:00:00 2001 From: Percy Ma Date: Tue, 22 Nov 2022 04:09:55 +0800 Subject: [PATCH 41/49] fix(web): add `alt` for logo in home page (#21887) add `alt` for logo in home page --- templates/home.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/home.tmpl b/templates/home.tmpl index 7667db27a1128..87192fa55b6e2 100644 --- a/templates/home.tmpl +++ b/templates/home.tmpl @@ -3,7 +3,7 @@
- +

From 8248ae974365adee899a2d33e1ddae92dc878379 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 21 Nov 2022 21:25:26 +0100 Subject: [PATCH 42/49] Embed Matrix icon as SVG (#21890) Embed the SVG icon directly, making further invertion unnecessary because the icon color can now follow text color. Screenshot 2022-11-21 at 20 16 32 Screenshot 2022-11-21 at 20 16 46 --- public/img/svg/gitea-matrix.svg | 1 + templates/admin/hook_new.tmpl | 2 +- templates/org/settings/hook_new.tmpl | 2 +- templates/repo/settings/webhook/base_list.tmpl | 2 +- templates/repo/settings/webhook/new.tmpl | 2 +- web_src/less/_base.less | 3 +++ web_src/less/themes/theme-arc-green.less | 4 ---- public/img/matrix.svg => web_src/svg/gitea-matrix.svg | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 public/img/svg/gitea-matrix.svg rename public/img/matrix.svg => web_src/svg/gitea-matrix.svg (99%) diff --git a/public/img/svg/gitea-matrix.svg b/public/img/svg/gitea-matrix.svg new file mode 100644 index 0000000000000..cc5e08d3c7f16 --- /dev/null +++ b/public/img/svg/gitea-matrix.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/admin/hook_new.tmpl b/templates/admin/hook_new.tmpl index c5196fce4e7e6..407eae9646cba 100644 --- a/templates/admin/hook_new.tmpl +++ b/templates/admin/hook_new.tmpl @@ -31,7 +31,7 @@ {{else if eq .HookType "feishu"}} {{else if eq .HookType "matrix"}} - + {{svg "gitea-matrix" 26}} {{else if eq .HookType "wechatwork"}} {{else if eq .HookType "packagist"}} diff --git a/templates/org/settings/hook_new.tmpl b/templates/org/settings/hook_new.tmpl index 7308cafa202e2..081f5a2839487 100644 --- a/templates/org/settings/hook_new.tmpl +++ b/templates/org/settings/hook_new.tmpl @@ -26,7 +26,7 @@ {{else if eq .HookType "feishu"}} {{else if eq .HookType "matrix"}} - + {{svg "gitea-matrix" 26}} {{else if eq .HookType "wechatwork"}} {{else if eq .HookType "packagist"}} diff --git a/templates/repo/settings/webhook/base_list.tmpl b/templates/repo/settings/webhook/base_list.tmpl index fa68e12ce9f2a..f96c48d4cd866 100644 --- a/templates/repo/settings/webhook/base_list.tmpl +++ b/templates/repo/settings/webhook/base_list.tmpl @@ -29,7 +29,7 @@ {{.locale.Tr "repo.settings.web_hook_name_feishu_or_larksuite"}} - {{.locale.Tr "repo.settings.web_hook_name_matrix"}} + {{svg "gitea-matrix" 20 "img"}}{{.locale.Tr "repo.settings.web_hook_name_matrix"}} {{.locale.Tr "repo.settings.web_hook_name_wechatwork"}} diff --git a/templates/repo/settings/webhook/new.tmpl b/templates/repo/settings/webhook/new.tmpl index ea5a3eca3c4f0..2722e099beea9 100644 --- a/templates/repo/settings/webhook/new.tmpl +++ b/templates/repo/settings/webhook/new.tmpl @@ -24,7 +24,7 @@ {{else if eq .HookType "feishu"}} {{else if eq .HookType "matrix"}} - + {{svg "gitea-matrix" 26}} {{else if eq .HookType "wechatwork"}} {{else if eq .HookType "packagist"}} diff --git a/web_src/less/_base.less b/web_src/less/_base.less index f2173d6d2b24f..e49721f7e0e8d 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -784,6 +784,9 @@ a.commit-statuses-trigger { margin-top: -.25rem; margin-bottom: -.25rem; } +.ui.dropdown .menu > .item > svg.img { + margin-right: .78571429rem; +} .ui.selection.dropdown .menu > .item { border-color: var(--color-secondary); diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index b793f99509160..fab1b9c3b473b 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -182,7 +182,3 @@ .emoji[aria-label="musical notes"] { filter: invert(100%) hue-rotate(180deg); } - -img[src$="/img/matrix.svg"] { - filter: invert(80%); -} diff --git a/public/img/matrix.svg b/web_src/svg/gitea-matrix.svg similarity index 99% rename from public/img/matrix.svg rename to web_src/svg/gitea-matrix.svg index 9a255fd758adc..63b23fc671c32 100644 --- a/public/img/matrix.svg +++ b/web_src/svg/gitea-matrix.svg @@ -11,4 +11,4 @@ c-4.2-2.7-10.3-4.1-18.5-4.1c-2.4,0-5.6,0.5-9.5,1.6c-3.9,1.1-7.8,3.1-11.5,6.1c-3.7,3-6.9,7.3-9.5,12.9c-2.6,5.6-3.9,13-3.9,22.1 v107.6h-50.9V169.2H166.3z"/> - + \ No newline at end of file From 0451b2464d06660a07dcce6afea776aeb4edf59a Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 22 Nov 2022 00:10:42 +0100 Subject: [PATCH 43/49] Webhook list enhancements (#21893) --- templates/admin/queue.tmpl | 2 +- templates/repo/settings/webhook/base_list.tmpl | 8 +++----- web_src/less/_admin.less | 4 ++-- web_src/less/_base.less | 6 ++++++ web_src/less/_repository.less | 4 ++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/templates/admin/queue.tmpl b/templates/admin/queue.tmpl index cd50798f805d2..675ec417e40ee 100644 --- a/templates/admin/queue.tmpl +++ b/templates/admin/queue.tmpl @@ -161,7 +161,7 @@ {{DateFmtLong .Start}} {{if .HasTimeout}}{{DateFmtLong .Timeout}}{{else}}-{{end}} - {{svg "octicon-trash"}} + {{svg "octicon-trash"}} {{else}} diff --git a/templates/repo/settings/webhook/base_list.tmpl b/templates/repo/settings/webhook/base_list.tmpl index f96c48d4cd866..333764a7ebccb 100644 --- a/templates/repo/settings/webhook/base_list.tmpl +++ b/templates/repo/settings/webhook/base_list.tmpl @@ -55,11 +55,9 @@ {{else}} {{svg "octicon-dot-fill"}} {{end}} - {{.URL}} - + {{.URL}} + {{svg "octicon-pencil"}} + {{svg "octicon-trash"}}

{{end}}
diff --git a/web_src/less/_admin.less b/web_src/less/_admin.less index b18bc7c5e0253..26417d42eed6f 100644 --- a/web_src/less/_admin.less +++ b/web_src/less/_admin.less @@ -3,8 +3,8 @@ > .item { &:not(:first-child) { border-top: 1px solid var(--color-secondary); - padding: 1rem; - margin: 15px -1rem -1rem; + padding: .25rem 1rem; + margin: 12px -1rem -1rem; } } } diff --git a/web_src/less/_base.less b/web_src/less/_base.less index e49721f7e0e8d..6054331ec49ea 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -307,6 +307,11 @@ a.muted:hover [class*="color-text"], color: var(--color-primary); } +.delete-button, +.delete-button:hover { + color: var(--color-red); +} + a.label, .repository-menu a, .ui.search .results a, @@ -2571,6 +2576,7 @@ table th[data-sortt-desc] { .truncated-item-container { display: flex !important; + align-items: center; } .ellipsis-button { diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 63f1f954a0c9f..f89a5df33d9b6 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -2616,8 +2616,8 @@ > .item { &:not(:first-child) { border-top: 1px solid var(--color-secondary); - padding: 1rem; - margin: 15px -1rem -1rem; + padding: .25rem 1rem; + margin: 12px -1rem -1rem; } > .svg { From 0958e6cf136f569bf397dee56393217ded00b715 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 22 Nov 2022 01:58:55 +0100 Subject: [PATCH 44/49] Update JS dependencies (#21881) - Update all JS deps - Regenerate SVGs - Add new eslint rules, fix issues - Tested Mermaid, Swagger, Vue, Webpack, Citation Co-authored-by: Lunny Xiao --- .drone.yml | 2 +- .eslintrc.yaml | 5 + package-lock.json | 2339 ++++++++----------- package.json | 42 +- public/img/svg/octicon-arrow-down-left.svg | 1 + public/img/svg/octicon-arrow-down-right.svg | 1 + public/img/svg/octicon-arrow-up-left.svg | 1 + public/img/svg/octicon-arrow-up-right.svg | 1 + public/img/svg/octicon-clock-fill.svg | 1 + public/img/svg/octicon-issue-tracked-by.svg | 1 + public/img/svg/octicon-issue-tracked-in.svg | 1 + public/img/svg/octicon-project-roadmap.svg | 1 + public/img/svg/octicon-project-symlink.svg | 1 + public/img/svg/octicon-skip-fill.svg | 1 + web_src/js/features/clipboard.js | 2 +- web_src/js/features/repo-legacy.js | 4 +- web_src/js/features/repo-migrate.js | 2 +- web_src/js/features/tribute.js | 2 +- webpack.config.js | 5 +- 19 files changed, 1079 insertions(+), 1334 deletions(-) create mode 100644 public/img/svg/octicon-arrow-down-left.svg create mode 100644 public/img/svg/octicon-arrow-down-right.svg create mode 100644 public/img/svg/octicon-arrow-up-left.svg create mode 100644 public/img/svg/octicon-arrow-up-right.svg create mode 100644 public/img/svg/octicon-clock-fill.svg create mode 100644 public/img/svg/octicon-issue-tracked-by.svg create mode 100644 public/img/svg/octicon-issue-tracked-in.svg create mode 100644 public/img/svg/octicon-project-roadmap.svg create mode 100644 public/img/svg/octicon-project-symlink.svg create mode 100644 public/img/svg/octicon-skip-fill.svg diff --git a/.drone.yml b/.drone.yml index 5127b5437755d..d349a5f2fc1d8 100644 --- a/.drone.yml +++ b/.drone.yml @@ -551,7 +551,7 @@ steps: # TODO: We should probably build all dependencies into a test image - name: test-e2e - image: mcr.microsoft.com/playwright:v1.27.1-focal + image: mcr.microsoft.com/playwright:v1.28.0-focal commands: - curl -sLO https://go.dev/dl/go1.19.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz - groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 2f213db37d582..5e5cda7dc84de 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -229,6 +229,7 @@ rules: no-empty-character-class: [2] no-empty-function: [0] no-empty-pattern: [2] + no-empty-static-block: [2] no-empty: [2, {allowEmptyCatch: true}] no-eq-null: [2] no-eval: [2] @@ -269,6 +270,7 @@ rules: no-negated-condition: [0] no-nested-ternary: [0] no-new-func: [2] + no-new-native-nonconstructor: [2] no-new-object: [2] no-new-symbol: [2] no-new-wrappers: [2] @@ -443,6 +445,7 @@ rules: unicorn/no-invalid-remove-event-listener: [2] unicorn/no-keyword-prefix: [0] unicorn/no-lonely-if: [2] + unicorn/no-negated-condition: [0] unicorn/no-nested-ternary: [0] unicorn/no-new-array: [0] unicorn/no-new-buffer: [0] @@ -453,6 +456,7 @@ rules: unicorn/no-static-only-class: [2] unicorn/no-thenable: [2] unicorn/no-this-assignment: [2] + unicorn/no-typeof-undefined: [2] unicorn/no-unnecessary-await: [2] unicorn/no-unreadable-array-destructuring: [0] unicorn/no-unreadable-iife: [2] @@ -503,6 +507,7 @@ rules: unicorn/prefer-regexp-test: [2] unicorn/prefer-replace-all: [0] unicorn/prefer-set-has: [0] + unicorn/prefer-set-size: [2] unicorn/prefer-spread: [0] unicorn/prefer-starts-ends-with: [2] unicorn/prefer-string-slice: [0] diff --git a/package-lock.json b/package-lock.json index d46d3a15cae58..346dae412df9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,14 @@ "dependencies": { "@citation-js/core": "0.6.1", "@citation-js/plugin-bibtex": "0.6.1", - "@citation-js/plugin-csl": "0.6.3", + "@citation-js/plugin-csl": "0.6.4", "@citation-js/plugin-software-formats": "0.6.0", "@claviska/jquery-minicolors": "2.3.6", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", - "@primer/octicons": "17.7.0", - "@vue/compiler-sfc": "3.2.41", + "@primer/octicons": "17.9.0", + "@vue/compiler-sfc": "3.2.45", "add-asset-webpack-plugin": "2.0.1", - "css-loader": "6.7.1", + "css-loader": "6.7.2", "dropzone": "6.0.0-beta.2", "easymde": "2.18.0", "esbuild-loader": "2.20.0", @@ -29,45 +29,45 @@ "less": "4.1.3", "less-loader": "11.1.0", "license-checker-webpack-plugin": "0.2.1", - "mermaid": "9.1.7", - "mini-css-extract-plugin": "2.6.1", + "mermaid": "9.2.2", + "mini-css-extract-plugin": "2.7.0", "monaco-editor": "0.34.1", "monaco-editor-webpack-plugin": "7.0.1", "pretty-ms": "8.0.0", "sortablejs": "1.15.0", - "swagger-ui-dist": "4.15.0", + "swagger-ui-dist": "4.15.5", "tippy.js": "6.3.7", "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", - "vue": "3.2.41", + "vue": "3.2.45", "vue-bar-graph": "2.0.0", - "vue-loader": "17.0.0", + "vue-loader": "17.0.1", "vue3-calendar-heatmap": "2.0.0", - "webpack": "5.74.0", - "webpack-cli": "4.10.0", + "webpack": "5.75.0", + "webpack-cli": "5.0.0", "workbox-routing": "6.5.4", "workbox-strategies": "6.5.4", "worker-loader": "3.0.8", "wrap-ansi": "8.0.1" }, "devDependencies": { - "@playwright/test": "1.27.1", + "@playwright/test": "1.28.0", "@rollup/pluginutils": "5.0.2", - "@stoplight/spectral-cli": "6.5.1", - "eslint": "8.26.0", + "@stoplight/spectral-cli": "6.6.0", + "eslint": "8.28.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jquery": "1.5.1", "eslint-plugin-sonarjs": "0.16.0", - "eslint-plugin-unicorn": "44.0.2", - "eslint-plugin-vue": "9.6.0", - "jsdom": "20.0.1", + "eslint-plugin-unicorn": "45.0.0", + "eslint-plugin-vue": "9.7.0", + "jsdom": "20.0.3", "markdownlint-cli": "0.32.2", "postcss-less": "6.0.0", - "stylelint": "14.14.0", + "stylelint": "14.15.0", "stylelint-config-standard": "29.0.0", - "svgo": "3.0.0", - "updates": "13.1.10", - "vitest": "0.24.3" + "svgo": "3.0.2", + "updates": "13.2.1", + "vitest": "0.25.2" }, "engines": { "node": ">= 14.0.0" @@ -186,9 +186,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.6.tgz", - "integrity": "sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", + "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -197,9 +197,9 @@ } }, "node_modules/@braintree/sanitize-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.1.tgz", - "integrity": "sha512-zr9Qs9KFQiEvMWdZesjcmRJlUck5NR+eKGS1uyKk+oYTWwlYrsoPEi6VmG6/TzBD1hKCGEimrhTgGS6hvn/xIQ==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", + "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" }, "node_modules/@citation-js/core": { "version": "0.6.1", @@ -248,9 +248,9 @@ } }, "node_modules/@citation-js/plugin-csl": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.6.3.tgz", - "integrity": "sha512-SP1/QyHfhcNufQ6VTJUM04Ti0XEWSWYMUhkDGG2lQtnDJU7pSDeAwtsE1kYUIJ9Np0Gm8IEZAfJ3CslMfsbimg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.6.4.tgz", + "integrity": "sha512-RG4NrFIx0CZTfNeMCC8CL7UGFRiUv5/bNd/Nc6Q/NHx0cS/tYDQcKt0M24dpOI7PAZwVoddbDW4Iakn6nS4QsQ==", "dependencies": { "@citation-js/date": "^0.5.0", "citeproc": "^2.4.6" @@ -309,9 +309,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.12.tgz", - "integrity": "sha512-IC7TqIqiyE0MmvAhWkl/8AEzpOtbhRNDo7aph47We1NbE5w2bt/Q+giAhe0YYeVpYnIhGMcuZY92qDK6dQauvA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.14.tgz", + "integrity": "sha512-+Rb20XXxRGisNu2WmNKk+scpanb7nL5yhuI1KR9wQFiC43ddPj/V1fmNyzlFC9bKiG4mYzxW7egtoHVcynr+OA==", "cpu": [ "arm" ], @@ -324,9 +324,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.12.tgz", - "integrity": "sha512-tZEowDjvU7O7I04GYvWQOS4yyP9E/7YlsB0jjw1Ycukgr2ycEzKyIk5tms5WnLBymaewc6VmRKnn5IJWgK4eFw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz", + "integrity": "sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==", "cpu": [ "loong64" ], @@ -384,14 +384,14 @@ "dev": true }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", - "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" @@ -574,13 +574,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz", - "integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.28.0.tgz", + "integrity": "sha512-vrHs5DFTPwYox5SGKq/7TDn/S4q6RA1zArd7uhO6EyP9hj3XgZBBM12ktMbnDQNxh/fL1IUKsTNLxihmsU38lQ==", "dev": true, "dependencies": { "@types/node": "*", - "playwright-core": "1.27.1" + "playwright-core": "1.28.0" }, "bin": { "playwright": "cli.js" @@ -599,17 +599,17 @@ } }, "node_modules/@primer/octicons": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.7.0.tgz", - "integrity": "sha512-J5cVJDhExmqLGLWu8zHTOqcC8g1rQL7QzQZdbvHxW85u8ya82GtF5F68uHMDI5En3fsMlbkkF8Rz6dCaV3r+KA==", + "version": "17.9.0", + "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.9.0.tgz", + "integrity": "sha512-B6y3VxPrF6U+GUjZR883NsstI7v/Qcup9puDG+fOJvCm8b7UXNl46TbRrctMCZnYlyIzUF3/SgjJhr5od/Y6sw==", "dependencies": { "object-assign": "^4.1.1" } }, "node_modules/@rollup/plugin-commonjs": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-20.0.0.tgz", - "integrity": "sha512-5K0g5W2Ol8hAcTHqcTBHiA7M58tfmYi1o9KxeJuuRNpGaTa5iLjcyemBitCBcKXaHamOBBEH2dGom6v6Unmqjg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", + "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", "dev": true, "dependencies": { "@rollup/pluginutils": "^3.1.0", @@ -621,10 +621,10 @@ "resolve": "^1.17.0" }, "engines": { - "node": ">= 8.0.0" + "node": ">= 12.0.0" }, "peerDependencies": { - "rollup": "^2.38.3" + "rollup": "^2.68.0" } }, "node_modules/@rollup/plugin-commonjs/node_modules/@rollup/pluginutils": { @@ -695,13 +695,14 @@ } }, "node_modules/@stoplight/json": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.17.0.tgz", - "integrity": "sha512-WW0z2bb0D4t8FTl+zNTCu46J8lEOsrUhBPgwEYQ3Ri2Y0MiRE4U1/9ZV8Ki+pIJznZgY9i42bbFwOBxyZn5/6w==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", + "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", "dev": true, "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.2", - "@stoplight/types": "^12.3.0", + "@stoplight/ordered-object-literal": "^1.0.3", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", "jsonc-parser": "~2.2.1", "lodash": "^4.17.21", "safe-stable-stringify": "^1.1" @@ -730,22 +731,21 @@ "dev": true }, "node_modules/@stoplight/json-ref-resolver": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.3.tgz", - "integrity": "sha512-SgoKXwVnlpIZUyAFX4W79eeuTWvXmNlMfICZixL16GZXnkjcW+uZnfmAU0ZIjcnaTgaI4mjfxn8LAP2KR6Cr0A==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.4.tgz", + "integrity": "sha512-842JVmMsi++qpDuIX+JpQvK7YY8FXEZZb+/z4xuRfStOAVEryJT/tbgGOWxniSdxEl9Eni5D/I2afMyy6BuiNw==", "dev": true, "dependencies": { "@stoplight/json": "^3.17.0", "@stoplight/path": "^1.3.2", - "@stoplight/types": "^12.3.0", - "@types/urijs": "^1.19.16", + "@stoplight/types": "^12.3.0 || ^13.0.0", + "@types/urijs": "^1.19.19", "dependency-graph": "~0.11.0", "fast-memoize": "^2.5.2", "immer": "^9.0.6", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", + "lodash": "^4.17.21", "tslib": "^2.3.1", - "urijs": "^1.19.6" + "urijs": "^1.19.11" }, "engines": { "node": ">=8.3.0" @@ -770,22 +770,21 @@ } }, "node_modules/@stoplight/spectral-cli": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-cli/-/spectral-cli-6.5.1.tgz", - "integrity": "sha512-+qpwsDG2jQ4ULQmegBWonI3UnF6tUh351WDnV1GU8acl8eaeKbS+ZUNBgoP2f9tnMTfITdctVRFEGC3D6P7f9g==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-cli/-/spectral-cli-6.6.0.tgz", + "integrity": "sha512-z46fnrvraaWMio8Y9RYYkLO+XdmtxOWpy5qNJF3CsmWua0FZ4iOTryb5Cm3GkB0wEtqxNUCBUHvoo4hS6Noyqg==", "dev": true, "dependencies": { - "@rollup/plugin-commonjs": "^20.0.0", - "@stoplight/json": "3.17.0", + "@stoplight/json": "~3.20.1", "@stoplight/path": "1.3.2", - "@stoplight/spectral-core": "^1.5.1", - "@stoplight/spectral-parsers": "^1.0.1", - "@stoplight/spectral-ref-resolver": "1.0.1", - "@stoplight/spectral-ruleset-bundler": "^1.0.0", - "@stoplight/spectral-ruleset-migrator": "^1.5.0", + "@stoplight/spectral-core": "^1.15.1", + "@stoplight/spectral-parsers": "^1.0.2", + "@stoplight/spectral-ref-resolver": "1.0.2", + "@stoplight/spectral-ruleset-bundler": "^1.4.0", + "@stoplight/spectral-ruleset-migrator": "^1.9.0", "@stoplight/spectral-rulesets": ">=1", - "@stoplight/spectral-runtime": "^1.1.0", - "@stoplight/types": "12.3.0", + "@stoplight/spectral-runtime": "^1.1.2", + "@stoplight/types": "^13.6.0", "chalk": "4.1.2", "cliui": "7.0.4", "eol": "0.9.1", @@ -835,9 +834,9 @@ } }, "node_modules/@stoplight/spectral-core": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.15.0.tgz", - "integrity": "sha512-+DwK8SmnujMZJaxJeNU11vWY+DFOnt4oQM1TzAuvufdd3Y6Lsno88Jl31OaR1M9Fn7l/u3v1anBB/SSl/fI5rQ==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.15.1.tgz", + "integrity": "sha512-IZV8L1Hyz9759KdqJIA90W5uvurHplMmaPPIZjQzG2Bq/39kN/sbLA/Js8uOf3xB9cHBbG599t4AB+uGsI8t0g==", "dev": true, "dependencies": { "@stoplight/better-ajv-errors": "1.0.3", @@ -852,7 +851,6 @@ "ajv": "^8.6.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.0", - "blueimp-md5": "2.18.0", "es-aggregate-error": "^1.0.7", "jsonpath-plus": "7.1.0", "lodash": "~4.17.21", @@ -867,23 +865,6 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/@stoplight/spectral-core/node_modules/@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - }, - "engines": { - "node": ">=8.3.0" - } - }, "node_modules/@stoplight/spectral-core/node_modules/@stoplight/types": { "version": "13.6.0", "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", @@ -934,36 +915,6 @@ "node": ">=12" } }, - "node_modules/@stoplight/spectral-functions/node_modules/@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - }, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/@stoplight/spectral-functions/node_modules/@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - }, - "engines": { - "node": "^12.20 || >=14.13" - } - }, "node_modules/@stoplight/spectral-parsers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@stoplight/spectral-parsers/-/spectral-parsers-1.0.2.tgz", @@ -979,45 +930,15 @@ "node": ">=12" } }, - "node_modules/@stoplight/spectral-parsers/node_modules/@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - }, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/@stoplight/spectral-parsers/node_modules/@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - }, - "engines": { - "node": "^12.20 || >=14.13" - } - }, "node_modules/@stoplight/spectral-ref-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.1.tgz", - "integrity": "sha512-0tY7nTOccvTsa3c4QbSWfJ8wGfPO1RXvmKnmBjuyLfoTMNuhkHPII9gKhCjygsshzsBLxs2IyRHZYhWYVnEbCA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.2.tgz", + "integrity": "sha512-ah6NIB/O1EdEaEu89So3LmtbKRXPVnSElgQ7oBRE9S4/VOedSqyXn+qqMd40tGnO2CsKgZaFUYXdSEHOshpHYw==", "dev": true, "dependencies": { "@stoplight/json-ref-readers": "1.2.2", - "@stoplight/json-ref-resolver": "3.1.3", - "@stoplight/spectral-runtime": "^1.0.0", + "@stoplight/json-ref-resolver": "~3.1.4", + "@stoplight/spectral-runtime": "^1.1.2", "dependency-graph": "0.11.0", "tslib": "^2.3.1" }, @@ -1026,9 +947,9 @@ } }, "node_modules/@stoplight/spectral-ruleset-bundler": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.3.tgz", - "integrity": "sha512-hfHl7XZeF/wWMpSrsLqLnH2GevRHjSIqtBL2aRjO2SjMCTbO9LVz80p4sYaxrCcu4wQ6K71gMZXsG687+3fAeg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.4.0.tgz", + "integrity": "sha512-aYDI4a145IXED+6jvRjj9Ha0fnB+s54cr8KbQbPCEyhCHW1cP8UGVeOuwAfk+9C4ZIg40OuYrugN5EhA35oQtA==", "dev": true, "dependencies": { "@rollup/plugin-commonjs": "~22.0.2", @@ -1052,73 +973,10 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/@stoplight/spectral-ruleset-bundler/node_modules/@rollup/plugin-commonjs": { - "version": "22.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", - "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "rollup": "^2.68.0" - } - }, - "node_modules/@stoplight/spectral-ruleset-bundler/node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@stoplight/spectral-ruleset-bundler/node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "node_modules/@stoplight/spectral-ruleset-bundler/node_modules/@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - }, - "engines": { - "node": "^12.20 || >=14.13" - } - }, - "node_modules/@stoplight/spectral-ruleset-bundler/node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, "node_modules/@stoplight/spectral-ruleset-migrator": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.8.0.tgz", - "integrity": "sha512-zg6RPF+d8uS7zAp5TzUph3hQG4sgGcG5Fsw8Zx24H1REyuSkjiIfyee2Kf13c3BcIlTXvnFc4csz2rNXpZO7Ug==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.9.0.tgz", + "integrity": "sha512-hPSjgXsTxMQ5UV1hfkVVPknhqRjmjSnCZD5jideM4rRU5NS1fj2Pse1CiXBsRChsuAGi/2s0Ke5uuOmFFsHrxQ==", "dev": true, "dependencies": { "@stoplight/json": "~3.20.1", @@ -1140,36 +998,6 @@ "node": ">=12" } }, - "node_modules/@stoplight/spectral-ruleset-migrator/node_modules/@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "dependencies": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - }, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/@stoplight/spectral-ruleset-migrator/node_modules/@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - }, - "engines": { - "node": "^12.20 || >=14.13" - } - }, "node_modules/@stoplight/spectral-rulesets": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.14.1.tgz", @@ -1195,19 +1023,6 @@ "node": ">=12" } }, - "node_modules/@stoplight/spectral-rulesets/node_modules/@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - }, - "engines": { - "node": "^12.20 || >=14.13" - } - }, "node_modules/@stoplight/spectral-runtime": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@stoplight/spectral-runtime/-/spectral-runtime-1.1.2.tgz", @@ -1226,10 +1041,10 @@ "node": ">=12" } }, - "node_modules/@stoplight/types": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-12.3.0.tgz", - "integrity": "sha512-hgzUR1z5BlYvIzUeFK5pjs5JXSvEutA9Pww31+dVicBlunsG1iXopDx/cvfBY7rHOrgtZDuvyeK4seqkwAZ6Cg==", + "node_modules/@stoplight/spectral-runtime/node_modules/@stoplight/types": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-12.5.0.tgz", + "integrity": "sha512-dwqYcDrGmEyUv5TWrDam5TGOxU72ufyQ7hnOIIDdmW5ezOwZaBFoR5XQ9AsH49w7wgvOqB2Bmo799pJPWnpCbg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.4", @@ -1239,6 +1054,19 @@ "node": ">=8" } }, + "node_modules/@stoplight/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.8.0.tgz", + "integrity": "sha512-5glKswz7y9aACh+a+JegID+4xX//4TsIdv7iPl29hWnOoWrnlPbg3Gjc4nYUXXgMSaSlSsA15JU/0+rE89fR4A==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, "node_modules/@stoplight/yaml": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.2.3.tgz", @@ -1260,19 +1088,6 @@ "integrity": "sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==", "dev": true }, - "node_modules/@stoplight/yaml/node_modules/@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - }, - "engines": { - "node": "^12.20 || >=14.13" - } - }, "node_modules/@swc/helpers": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.2.14.tgz", @@ -1297,9 +1112,9 @@ } }, "node_modules/@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "node_modules/@types/chai-subset": { @@ -1329,9 +1144,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz", - "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==", + "version": "8.4.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", + "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -1374,9 +1189,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.4.tgz", - "integrity": "sha512-BxcJpBu8D3kv/GZkx/gSMz6VnTJREBj/4lbzYOQueUOELkt8WrO6zAcSPmp9uRPEW/d+lUO8QK0W2xnS1hEU0A==" + "version": "18.11.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", + "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -1405,36 +1220,36 @@ "dev": true }, "node_modules/@vue/compiler-core": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.41.tgz", - "integrity": "sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.45.tgz", + "integrity": "sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.41", + "@vue/shared": "3.2.45", "estree-walker": "^2.0.2", "source-map": "^0.6.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz", - "integrity": "sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz", + "integrity": "sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==", "dependencies": { - "@vue/compiler-core": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-core": "3.2.45", + "@vue/shared": "3.2.45" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz", - "integrity": "sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz", + "integrity": "sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.41", - "@vue/compiler-dom": "3.2.41", - "@vue/compiler-ssr": "3.2.41", - "@vue/reactivity-transform": "3.2.41", - "@vue/shared": "3.2.41", + "@vue/compiler-core": "3.2.45", + "@vue/compiler-dom": "3.2.45", + "@vue/compiler-ssr": "3.2.45", + "@vue/reactivity-transform": "3.2.45", + "@vue/shared": "3.2.45", "estree-walker": "^2.0.2", "magic-string": "^0.25.7", "postcss": "^8.1.10", @@ -1442,69 +1257,69 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz", - "integrity": "sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz", + "integrity": "sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==", "dependencies": { - "@vue/compiler-dom": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-dom": "3.2.45", + "@vue/shared": "3.2.45" } }, "node_modules/@vue/reactivity": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.41.tgz", - "integrity": "sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz", + "integrity": "sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==", "dependencies": { - "@vue/shared": "3.2.41" + "@vue/shared": "3.2.45" } }, "node_modules/@vue/reactivity-transform": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz", - "integrity": "sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz", + "integrity": "sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.41", - "@vue/shared": "3.2.41", + "@vue/compiler-core": "3.2.45", + "@vue/shared": "3.2.45", "estree-walker": "^2.0.2", "magic-string": "^0.25.7" } }, "node_modules/@vue/runtime-core": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.41.tgz", - "integrity": "sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz", + "integrity": "sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==", "dependencies": { - "@vue/reactivity": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/reactivity": "3.2.45", + "@vue/shared": "3.2.45" } }, "node_modules/@vue/runtime-dom": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.41.tgz", - "integrity": "sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz", + "integrity": "sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==", "dependencies": { - "@vue/runtime-core": "3.2.41", - "@vue/shared": "3.2.41", + "@vue/runtime-core": "3.2.45", + "@vue/shared": "3.2.45", "csstype": "^2.6.8" } }, "node_modules/@vue/server-renderer": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.41.tgz", - "integrity": "sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz", + "integrity": "sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==", "dependencies": { - "@vue/compiler-ssr": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-ssr": "3.2.45", + "@vue/shared": "3.2.45" }, "peerDependencies": { - "vue": "3.2.41" + "vue": "3.2.45" } }, "node_modules/@vue/shared": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz", - "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==" + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz", + "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==" }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", @@ -1638,31 +1453,39 @@ } }, "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.0.0.tgz", + "integrity": "sha512-war4OU8NGjBqU3DP3bx6ciODXIh7dSXcpQq+P4K2Tqyd8L5OjZ7COx9QXx/QdCIwL2qoX09Wr4Cwf7uS4qdEng==", + "engines": { + "node": ">=14.15.0" + }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" + "webpack": "5.x.x", + "webpack-cli": "5.x.x" } }, "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "dependencies": { - "envinfo": "^7.7.3" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.0.tgz", + "integrity": "sha512-NNxDgbo4VOkNhOlTgY0Elhz3vKpOJq4/PKeKg7r8cmYM+GQA9vDofLYyup8jS6EpUvhNmR30cHTCEIyvXpskwA==", + "engines": { + "node": ">=14.15.0" }, "peerDependencies": { - "webpack-cli": "4.x.x" + "webpack": "5.x.x", + "webpack-cli": "5.x.x" } }, "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.0.tgz", + "integrity": "sha512-Rumq5mHvGXamnOh3O8yLk1sjx8dB30qF1OeR6VC00DIR6SLJ4bwwUGKC4pE7qBFoQyyh0H9sAg3fikYgAqVR0w==", + "engines": { + "node": ">=14.15.0" + }, "peerDependencies": { - "webpack-cli": "4.x.x" + "webpack": "5.x.x", + "webpack-cli": "5.x.x" }, "peerDependenciesMeta": { "webpack-dev-server": { @@ -1772,9 +1595,9 @@ } }, "node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -1872,15 +1695,15 @@ } }, "node_modules/array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", "is-string": "^1.0.7" }, "engines": { @@ -1900,14 +1723,14 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -2012,12 +1835,6 @@ "node": "*" } }, - "node_modules/blueimp-md5": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", - "integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==", - "dev": true - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2175,9 +1992,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001423", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz", - "integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==", + "version": "1.0.30001431", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", + "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==", "funding": [ { "type": "opencollective", @@ -2190,14 +2007,14 @@ ] }, "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -2240,10 +2057,13 @@ } }, "node_modules/ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/citeproc": { "version": "2.4.62", @@ -2324,9 +2144,9 @@ } }, "node_modules/codemirror": { - "version": "5.65.9", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz", - "integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw==" + "version": "5.65.10", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.10.tgz", + "integrity": "sha512-IXAG5wlhbgcTJ6rZZcmi4+sjWIbJqIGfeg3tNa3yX84Jb3T4huS5qzQAo/cUisc1l3bI47WZodpyf7cYcocDKg==" }, "node_modules/codemirror-spell-checker": { "version": "1.1.2", @@ -2412,9 +2232,9 @@ "dev": true }, "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", @@ -2450,18 +2270,18 @@ } }, "node_modules/css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.2.tgz", + "integrity": "sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q==", "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.7", + "postcss": "^8.4.18", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" + "semver": "^7.3.8" }, "engines": { "node": ">= 12.13.0" @@ -3308,9 +3128,9 @@ } }, "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "dependencies": { "decamelize": "^1.1.0", @@ -3318,6 +3138,9 @@ }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decamelize-keys/node_modules/map-obj": { @@ -3336,15 +3159,15 @@ "dev": true }, "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.2.tgz", + "integrity": "sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=6" } }, "node_modules/deep-extend": { @@ -3775,17 +3598,17 @@ } }, "node_modules/es-aggregate-error": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.8.tgz", - "integrity": "sha512-AKUb5MKLWMozPlFRHOKqWD7yta5uaEhH21qwtnf6FlKjNjTJOoqFi0/G14+FfSkIQhhu6X68Af4xgRC6y8qG4A==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.9.tgz", + "integrity": "sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg==", "dev": true, "dependencies": { "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", + "es-abstract": "^1.20.4", "function-bind": "^1.1.1", "functions-have-names": "^1.2.3", - "get-intrinsic": "^1.1.1", - "globalthis": "^1.0.2", + "get-intrinsic": "^1.1.3", + "globalthis": "^1.0.3", "has-property-descriptors": "^1.0.0" }, "engines": { @@ -3827,9 +3650,9 @@ } }, "node_modules/esbuild": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.12.tgz", - "integrity": "sha512-PcT+/wyDqJQsRVhaE9uX/Oq4XLrFh0ce/bs2TJh4CSaw9xuvI+xFrH2nAYOADbhQjUgAhNWC5LKoUsakm4dxng==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.14.tgz", + "integrity": "sha512-pJN8j42fvWLFWwSMG4luuupl2Me7mxciUOsMegKvwCmhEbJ2covUdFnihxm0FMIBV+cbwbtMoHgMCCI+pj1btQ==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -3838,34 +3661,34 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.15.12", - "@esbuild/linux-loong64": "0.15.12", - "esbuild-android-64": "0.15.12", - "esbuild-android-arm64": "0.15.12", - "esbuild-darwin-64": "0.15.12", - "esbuild-darwin-arm64": "0.15.12", - "esbuild-freebsd-64": "0.15.12", - "esbuild-freebsd-arm64": "0.15.12", - "esbuild-linux-32": "0.15.12", - "esbuild-linux-64": "0.15.12", - "esbuild-linux-arm": "0.15.12", - "esbuild-linux-arm64": "0.15.12", - "esbuild-linux-mips64le": "0.15.12", - "esbuild-linux-ppc64le": "0.15.12", - "esbuild-linux-riscv64": "0.15.12", - "esbuild-linux-s390x": "0.15.12", - "esbuild-netbsd-64": "0.15.12", - "esbuild-openbsd-64": "0.15.12", - "esbuild-sunos-64": "0.15.12", - "esbuild-windows-32": "0.15.12", - "esbuild-windows-64": "0.15.12", - "esbuild-windows-arm64": "0.15.12" + "@esbuild/android-arm": "0.15.14", + "@esbuild/linux-loong64": "0.15.14", + "esbuild-android-64": "0.15.14", + "esbuild-android-arm64": "0.15.14", + "esbuild-darwin-64": "0.15.14", + "esbuild-darwin-arm64": "0.15.14", + "esbuild-freebsd-64": "0.15.14", + "esbuild-freebsd-arm64": "0.15.14", + "esbuild-linux-32": "0.15.14", + "esbuild-linux-64": "0.15.14", + "esbuild-linux-arm": "0.15.14", + "esbuild-linux-arm64": "0.15.14", + "esbuild-linux-mips64le": "0.15.14", + "esbuild-linux-ppc64le": "0.15.14", + "esbuild-linux-riscv64": "0.15.14", + "esbuild-linux-s390x": "0.15.14", + "esbuild-netbsd-64": "0.15.14", + "esbuild-openbsd-64": "0.15.14", + "esbuild-sunos-64": "0.15.14", + "esbuild-windows-32": "0.15.14", + "esbuild-windows-64": "0.15.14", + "esbuild-windows-arm64": "0.15.14" } }, "node_modules/esbuild-android-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.12.tgz", - "integrity": "sha512-MJKXwvPY9g0rGps0+U65HlTsM1wUs9lbjt5CU19RESqycGFDRijMDQsh68MtbzkqWSRdEtiKS1mtPzKneaAI0Q==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz", + "integrity": "sha512-HuilVIb4rk9abT4U6bcFdU35UHOzcWVGLSjEmC58OVr96q5UiRqzDtWjPlCMugjhgUGKEs8Zf4ueIvYbOStbIg==", "cpu": [ "x64" ], @@ -3878,9 +3701,9 @@ } }, "node_modules/esbuild-android-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.12.tgz", - "integrity": "sha512-Hc9SEcZbIMhhLcvhr1DH+lrrec9SFTiRzfJ7EGSBZiiw994gfkVV6vG0sLWqQQ6DD7V4+OggB+Hn0IRUdDUqvA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.14.tgz", + "integrity": "sha512-/QnxRVxsR2Vtf3XottAHj7hENAMW2wCs6S+OZcAbc/8nlhbAL/bCQRCVD78VtI5mdwqWkVi3wMqM94kScQCgqg==", "cpu": [ "arm64" ], @@ -3893,9 +3716,9 @@ } }, "node_modules/esbuild-darwin-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.12.tgz", - "integrity": "sha512-qkmqrTVYPFiePt5qFjP8w/S+GIUMbt6k8qmiPraECUWfPptaPJUGkCKrWEfYFRWB7bY23FV95rhvPyh/KARP8Q==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.14.tgz", + "integrity": "sha512-ToNuf1uifu8hhwWvoZJGCdLIX/1zpo8cOGnT0XAhDQXiKOKYaotVNx7pOVB1f+wHoWwTLInrOmh3EmA7Fd+8Vg==", "cpu": [ "x64" ], @@ -3908,9 +3731,9 @@ } }, "node_modules/esbuild-darwin-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.12.tgz", - "integrity": "sha512-z4zPX02tQ41kcXMyN3c/GfZpIjKoI/BzHrdKUwhC/Ki5BAhWv59A9M8H+iqaRbwpzYrYidTybBwiZAIWCLJAkw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.14.tgz", + "integrity": "sha512-KgGP+y77GszfYJgceO0Wi/PiRtYo5y2Xo9rhBUpxTPaBgWDJ14gqYN0+NMbu+qC2fykxXaipHxN4Scaj9tUS1A==", "cpu": [ "arm64" ], @@ -3923,9 +3746,9 @@ } }, "node_modules/esbuild-freebsd-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.12.tgz", - "integrity": "sha512-XFL7gKMCKXLDiAiBjhLG0XECliXaRLTZh6hsyzqUqPUf/PY4C6EJDTKIeqqPKXaVJ8+fzNek88285krSz1QECw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.14.tgz", + "integrity": "sha512-xr0E2n5lyWw3uFSwwUXHc0EcaBDtsal/iIfLioflHdhAe10KSctV978Te7YsfnsMKzcoGeS366+tqbCXdqDHQA==", "cpu": [ "x64" ], @@ -3938,9 +3761,9 @@ } }, "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.12.tgz", - "integrity": "sha512-jwEIu5UCUk6TjiG1X+KQnCGISI+ILnXzIzt9yDVrhjug2fkYzlLbl0K43q96Q3KB66v6N1UFF0r5Ks4Xo7i72g==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.14.tgz", + "integrity": "sha512-8XH96sOQ4b1LhMlO10eEWOjEngmZ2oyw3pW4o8kvBcpF6pULr56eeYVP5radtgw54g3T8nKHDHYEI5AItvskZg==", "cpu": [ "arm64" ], @@ -3953,9 +3776,9 @@ } }, "node_modules/esbuild-linux-32": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.12.tgz", - "integrity": "sha512-uSQuSEyF1kVzGzuIr4XM+v7TPKxHjBnLcwv2yPyCz8riV8VUCnO/C4BF3w5dHiVpCd5Z1cebBtZJNlC4anWpwA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.14.tgz", + "integrity": "sha512-6ssnvwaTAi8AzKN8By2V0nS+WF5jTP7SfuK6sStGnDP7MCJo/4zHgM9oE1eQTS2jPmo3D673rckuCzRlig+HMA==", "cpu": [ "ia32" ], @@ -3968,9 +3791,9 @@ } }, "node_modules/esbuild-linux-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.12.tgz", - "integrity": "sha512-QcgCKb7zfJxqT9o5z9ZUeGH1k8N6iX1Y7VNsEi5F9+HzN1OIx7ESxtQXDN9jbeUSPiRH1n9cw6gFT3H4qbdvcA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.14.tgz", + "integrity": "sha512-ONySx3U0wAJOJuxGUlXBWxVKFVpWv88JEv0NZ6NlHknmDd1yCbf4AEdClSgLrqKQDXYywmw4gYDvdLsS6z0hcw==", "cpu": [ "x64" ], @@ -3983,9 +3806,9 @@ } }, "node_modules/esbuild-linux-arm": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.12.tgz", - "integrity": "sha512-Wf7T0aNylGcLu7hBnzMvsTfEXdEdJY/hY3u36Vla21aY66xR0MS5I1Hw8nVquXjTN0A6fk/vnr32tkC/C2lb0A==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.14.tgz", + "integrity": "sha512-D2LImAIV3QzL7lHURyCHBkycVFbKwkDb1XEUWan+2fb4qfW7qAeUtul7ZIcIwFKZgPcl+6gKZmvLgPSj26RQ2Q==", "cpu": [ "arm" ], @@ -3998,9 +3821,9 @@ } }, "node_modules/esbuild-linux-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.12.tgz", - "integrity": "sha512-HtNq5xm8fUpZKwWKS2/YGwSfTF+339L4aIA8yphNKYJckd5hVdhfdl6GM2P3HwLSCORS++++7++//ApEwXEuAQ==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.14.tgz", + "integrity": "sha512-kle2Ov6a1e5AjlHlMQl1e+c4myGTeggrRzArQFmWp6O6JoqqB9hT+B28EW4tjFWgV/NxUq46pWYpgaWXsXRPAg==", "cpu": [ "arm64" ], @@ -4013,9 +3836,9 @@ } }, "node_modules/esbuild-linux-mips64le": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.12.tgz", - "integrity": "sha512-Qol3+AvivngUZkTVFgLpb0H6DT+N5/zM3V1YgTkryPYFeUvuT5JFNDR3ZiS6LxhyF8EE+fiNtzwlPqMDqVcc6A==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.14.tgz", + "integrity": "sha512-FVdMYIzOLXUq+OE7XYKesuEAqZhmAIV6qOoYahvUp93oXy0MOVTP370ECbPfGXXUdlvc0TNgkJa3YhEwyZ6MRA==", "cpu": [ "mips64el" ], @@ -4028,9 +3851,9 @@ } }, "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.12.tgz", - "integrity": "sha512-4D8qUCo+CFKaR0cGXtGyVsOI7w7k93Qxb3KFXWr75An0DHamYzq8lt7TNZKoOq/Gh8c40/aKaxvcZnTgQ0TJNg==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.14.tgz", + "integrity": "sha512-2NzH+iuzMDA+jjtPjuIz/OhRDf8tzbQ1tRZJI//aT25o1HKc0reMMXxKIYq/8nSHXiJSnYV4ODzTiv45s+h73w==", "cpu": [ "ppc64" ], @@ -4043,9 +3866,9 @@ } }, "node_modules/esbuild-linux-riscv64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.12.tgz", - "integrity": "sha512-G9w6NcuuCI6TUUxe6ka0enjZHDnSVK8bO+1qDhMOCtl7Tr78CcZilJj8SGLN00zO5iIlwNRZKHjdMpfFgNn1VA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.14.tgz", + "integrity": "sha512-VqxvutZNlQxmUNS7Ac+aczttLEoHBJ9e3OYGqnULrfipRvG97qLrAv9EUY9iSrRKBqeEbSvS9bSfstZqwz0T4Q==", "cpu": [ "riscv64" ], @@ -4058,9 +3881,9 @@ } }, "node_modules/esbuild-linux-s390x": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.12.tgz", - "integrity": "sha512-Lt6BDnuXbXeqSlVuuUM5z18GkJAZf3ERskGZbAWjrQoi9xbEIsj/hEzVnSAFLtkfLuy2DE4RwTcX02tZFunXww==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.14.tgz", + "integrity": "sha512-+KVHEUshX5n6VP6Vp/AKv9fZIl5kr2ph8EUFmQUJnDpHwcfTSn2AQgYYm0HTBR2Mr4d0Wlr0FxF/Cs5pbFgiOw==", "cpu": [ "s390x" ], @@ -4092,9 +3915,9 @@ } }, "node_modules/esbuild-netbsd-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.12.tgz", - "integrity": "sha512-jlUxCiHO1dsqoURZDQts+HK100o0hXfi4t54MNRMCAqKGAV33JCVvMplLAa2FwviSojT/5ZG5HUfG3gstwAG8w==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.14.tgz", + "integrity": "sha512-6D/dr17piEgevIm1xJfZP2SjB9Z+g8ERhNnBdlZPBWZl+KSPUKLGF13AbvC+nzGh8IxOH2TyTIdRMvKMP0nEzQ==", "cpu": [ "x64" ], @@ -4107,9 +3930,9 @@ } }, "node_modules/esbuild-openbsd-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.12.tgz", - "integrity": "sha512-1o1uAfRTMIWNOmpf8v7iudND0L6zRBYSH45sofCZywrcf7NcZA+c7aFsS1YryU+yN7aRppTqdUK1PgbZVaB1Dw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.14.tgz", + "integrity": "sha512-rREQBIlMibBetgr2E9Lywt2Qxv2ZdpmYahR4IUlAQ1Efv/A5gYdO0/VIN3iowDbCNTLxp0bb57Vf0LFcffD6kA==", "cpu": [ "x64" ], @@ -4122,9 +3945,9 @@ } }, "node_modules/esbuild-sunos-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.12.tgz", - "integrity": "sha512-nkl251DpoWoBO9Eq9aFdoIt2yYmp4I3kvQjba3jFKlMXuqQ9A4q+JaqdkCouG3DHgAGnzshzaGu6xofGcXyPXg==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.14.tgz", + "integrity": "sha512-DNVjSp/BY4IfwtdUAvWGIDaIjJXY5KI4uD82+15v6k/w7px9dnaDaJJ2R6Mu+KCgr5oklmFc0KjBjh311Gxl9Q==", "cpu": [ "x64" ], @@ -4137,9 +3960,9 @@ } }, "node_modules/esbuild-windows-32": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.12.tgz", - "integrity": "sha512-WlGeBZHgPC00O08luIp5B2SP4cNCp/PcS+3Pcg31kdcJPopHxLkdCXtadLU9J82LCfw4TVls21A6lilQ9mzHrw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.14.tgz", + "integrity": "sha512-pHBWrcA+/oLgvViuG9FO3kNPO635gkoVrRQwe6ZY1S0jdET07xe2toUvQoJQ8KT3/OkxqUasIty5hpuKFLD+eg==", "cpu": [ "ia32" ], @@ -4152,9 +3975,9 @@ } }, "node_modules/esbuild-windows-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.12.tgz", - "integrity": "sha512-VActO3WnWZSN//xjSfbiGOSyC+wkZtI8I4KlgrTo5oHJM6z3MZZBCuFaZHd8hzf/W9KPhF0lY8OqlmWC9HO5AA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.14.tgz", + "integrity": "sha512-CszIGQVk/P8FOS5UgAH4hKc9zOaFo69fe+k1rqgBHx3CSK3Opyk5lwYriIamaWOVjBt7IwEP6NALz+tkVWdFog==", "cpu": [ "x64" ], @@ -4167,9 +3990,9 @@ } }, "node_modules/esbuild-windows-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.12.tgz", - "integrity": "sha512-Of3MIacva1OK/m4zCNIvBfz8VVROBmQT+gRX6pFTLPngFYcj6TFH/12VveAqq1k9VB2l28EoVMNMUCcmsfwyuA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.14.tgz", + "integrity": "sha512-KW9W4psdZceaS9A7Jsgl4WialOznSURvqX/oHZk3gOP7KbjtHLSsnmSvNdzagGJfxbAe30UVGXRe8q8nDsOSQw==", "cpu": [ "arm64" ], @@ -4286,9 +4109,9 @@ } }, "node_modules/eslint": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", - "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", + "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.3.3", @@ -4462,24 +4285,26 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "44.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-44.0.2.tgz", - "integrity": "sha512-GLIDX1wmeEqpGaKcnMcqRvMVsoabeF0Ton0EX4Th5u6Kmf7RM9WBl705AXFEsns56ESkEs0uyelLuUTvz9Tr0w==", + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.0.tgz", + "integrity": "sha512-iP8cMRxXKHonKioOhnCoCcqVhoqhAp6rB+nsoLjXFDxTHz3btWMAp8xwzjHA0B1K6YV/U/Yvqn1bUXZt8sJPuQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.19.1", - "ci-info": "^3.4.0", + "ci-info": "^3.6.1", "clean-regexp": "^1.0.0", "eslint-utils": "^3.0.0", "esquery": "^1.4.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.0", + "jsesc": "3.0.2", "lodash": "^4.17.21", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.24", + "regjsparser": "0.9.1", "safe-regex": "^2.1.1", - "semver": "^7.3.7", + "semver": "^7.3.8", "strip-indent": "^3.0.0" }, "engines": { @@ -4489,13 +4314,13 @@ "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" }, "peerDependencies": { - "eslint": ">=8.23.1" + "eslint": ">=8.28.0" } }, "node_modules/eslint-plugin-vue": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.6.0.tgz", - "integrity": "sha512-zzySkJgVbFCylnG2+9MDF7N+2Rjze2y0bF8GyUNpFOnT8mCMfqqtLDJkHBuYu9N/psW1A6DVbQhPkP92E+qakA==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.7.0.tgz", + "integrity": "sha512-DrOO3WZCZEwcLsnd3ohFwqCoipGRSTKTBTnLwdhqAbYZtzWl0o7D+D8ZhlmiZvABKTEl8AFsqH1GHGdybyoQmw==", "dev": true, "dependencies": { "eslint-utils": "^3.0.0", @@ -4585,9 +4410,9 @@ "dev": true }, "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "dependencies": { "acorn": "^8.8.0", @@ -4676,6 +4501,11 @@ "node": ">=0.8.x" } }, + "node_modules/fast-clone": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/fast-clone/-/fast-clone-1.5.13.tgz", + "integrity": "sha512-0ez7coyFBQFjZtId+RJqJ+EQs61w9xARfqjqK0AD9vIUkSxWD4HvPt80+5evebZ1tTnv1GYKrPTipx7kOW5ipA==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5098,9 +4928,9 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz", + "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -5510,11 +5340,11 @@ } }, "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/ip": { @@ -5883,18 +5713,18 @@ } }, "node_modules/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", "dev": true, "dependencies": { "abab": "^2.0.6", - "acorn": "^8.8.0", + "acorn": "^8.8.1", "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", "data-urls": "^3.0.2", - "decimal.js": "^10.4.1", + "decimal.js": "^10.4.2", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", @@ -5907,12 +5737,12 @@ "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^3.0.0", + "w3c-xmlserializer": "^4.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0", - "ws": "^8.9.0", + "ws": "^8.11.0", "xml-name-validator": "^4.0.0" }, "engines": { @@ -5936,6 +5766,18 @@ "node": ">= 10.16.0" } }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -6038,9 +5880,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", - "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.26.0.tgz", + "integrity": "sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==", "dev": true }, "node_modules/less": { @@ -6231,24 +6073,12 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", - "dev": true - }, "node_modules/lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -6279,9 +6109,9 @@ "dev": true }, "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "dependencies": { "get-func-name": "^2.0.0" @@ -6455,9 +6285,9 @@ } }, "node_modules/marked": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", - "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.3.tgz", + "integrity": "sha512-slWRdJkbTZ+PjkyJnE30Uid64eHwbwa1Q25INCAYfZlK4o6ylagBy/Le9eWntqJFoFT93ikUKMv47GZ4gTwHkw==", "bin": { "marked": "bin/marked.js" }, @@ -6584,19 +6414,23 @@ } }, "node_modules/mermaid": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.1.7.tgz", - "integrity": "sha512-MRVHXy5FLjnUQUG7YS3UN9jEN6FXCJbFCXVGJQjVIbiR6Vhw0j/6pLIjqsiah9xoHmQU6DEaKOvB3S1g/1nBPA==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.2.2.tgz", + "integrity": "sha512-6s7eKMqFJGS+0MYjmx8f6ZigqKBJVoSx5ql2gw6a4Aa+WJ49QiEJg7gPwywaBg3DZMs79UP7trESp4+jmaQccw==", "dependencies": { "@braintree/sanitize-url": "^6.0.0", "d3": "^7.0.0", "dagre": "^0.8.5", "dagre-d3": "^0.6.4", "dompurify": "2.4.0", + "fast-clone": "^1.5.13", "graphlib": "^2.1.8", "khroma": "^2.0.0", - "moment-mini": "2.24.0", - "stylis": "^4.0.10" + "lodash": "^4.17.21", + "moment-mini": "^2.24.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "uuid": "^9.0.0" } }, "node_modules/micromatch": { @@ -6652,9 +6486,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", - "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz", + "integrity": "sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw==", "dependencies": { "schema-utils": "^4.0.0" }, @@ -6704,9 +6538,9 @@ } }, "node_modules/moment-mini": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", - "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz", + "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==" }, "node_modules/monaco-editor": { "version": "0.34.1", @@ -6726,9 +6560,9 @@ } }, "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" }, "node_modules/ms": { "version": "2.1.2", @@ -6754,9 +6588,9 @@ "dev": true }, "node_modules/needle": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", - "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", "optional": true, "dependencies": { "debug": "^3.2.6", @@ -6865,6 +6699,11 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -6958,14 +6797,14 @@ } }, "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -7299,9 +7138,9 @@ } }, "node_modules/playwright-core": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz", - "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.28.0.tgz", + "integrity": "sha512-nJLknd28kPBiCNTbqpu6Wmkrh63OEqJSFw9xOfL9qxfNwody7h6/L3O2dZoWQ6Oxcm0VOHjWmGiCUGkc0X3VZA==", "dev": true, "bin": { "playwright": "cli.js" @@ -7329,9 +7168,9 @@ } }, "node_modules/postcss": { - "version": "8.4.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", - "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", + "version": "8.4.19", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", + "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", "funding": [ { "type": "opencollective", @@ -7447,9 +7286,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -7744,14 +7583,14 @@ } }, "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dependencies": { - "resolve": "^1.9.0" + "resolve": "^1.20.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/redent": { @@ -7805,6 +7644,27 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8373,28 +8233,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8463,15 +8323,15 @@ "dev": true }, "node_modules/stylelint": { - "version": "14.14.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz", - "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==", + "version": "14.15.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.15.0.tgz", + "integrity": "sha512-JOgDAo5QRsqiOZPZO+B9rKJvBm64S0xasbuRPAbPs6/vQDgDCnZLIiw6XcAS6GQKk9k1sBWR6rmH3Mfj8OknKg==", "dev": true, "dependencies": { "@csstools/selector-specificity": "^2.0.2", "balanced-match": "^2.0.0", "colord": "^2.9.3", - "cosmiconfig": "^7.0.1", + "cosmiconfig": "^7.1.0", "css-functions-list": "^3.1.0", "debug": "^4.3.4", "fast-glob": "^3.2.12", @@ -8485,13 +8345,13 @@ "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.25.0", + "known-css-properties": "^0.26.0", "mathml-tag-names": "^2.1.3", "meow": "^9.0.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.17", + "postcss": "^8.4.19", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", @@ -8503,7 +8363,7 @@ "style-search": "^0.1.0", "supports-hyperlinks": "^2.3.0", "svg-tags": "^1.0.0", - "table": "^6.8.0", + "table": "^6.8.1", "v8-compile-cache": "^2.3.0", "write-file-atomic": "^4.0.2" }, @@ -8555,9 +8415,9 @@ } }, "node_modules/stylis": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.2.tgz", - "integrity": "sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA==" + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" }, "node_modules/superstruct": { "version": "0.10.13", @@ -8606,9 +8466,9 @@ "dev": true }, "node_modules/svgo": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.0.tgz", - "integrity": "sha512-mSqPn6RDeNqJvCeqHERlfWJjd4crP/2PgFelil9WpTwC4D3okAUopPsH3lnEyl7ONXfDVyISOihDjO0uK8YVAA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", + "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", "dev": true, "dependencies": { "@trysound/sax": "0.2.0", @@ -8639,9 +8499,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.0.tgz", - "integrity": "sha512-vAsIdNHraLuBRm1vrxcMaLk/y/PGBTvHLf4lQGQ3LaEXkORtIxw11sBMpYJL3keOLaFJ1OqNXuURd6eShoFLZQ==" + "version": "4.15.5", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.5.tgz", + "integrity": "sha512-V3eIa28lwB6gg7/wfNvAbjwJYmDXy1Jo1POjyTzlB6wPcHiGlRxq39TSjYGVjQrUSAzpv+a7nzp7mDxgNy57xA==" }, "node_modules/symbol-tree": { "version": "3.2.4", @@ -8662,9 +8522,9 @@ } }, "node_modules/table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", "dev": true, "dependencies": { "ajv": "^8.0.1", @@ -8918,9 +8778,9 @@ } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "node_modules/type-check": { "version": "0.4.0", @@ -9030,9 +8890,9 @@ } }, "node_modules/updates": { - "version": "13.1.10", - "resolved": "https://registry.npmjs.org/updates/-/updates-13.1.10.tgz", - "integrity": "sha512-YSt1ncMoBXAQZndhLwiywvEGHXmA4424SlAf2HMUDuf8qE9Tlqj0s6IANb388HrjkybdZJkaadLSg/hkigwnuQ==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/updates/-/updates-13.2.1.tgz", + "integrity": "sha512-d+nIbU2fl/PDEvUkbQch4uRdkXt9AQoPlH6b/FPTOAzF9voGbXgZNNxgO79Jeish24ZMfOqUl5lJcKSwMO2RJQ==", "dev": true, "bin": { "updates": "bin/updates.js" @@ -9079,6 +8939,14 @@ "node": ">= 4" } }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -9105,15 +8973,15 @@ } }, "node_modules/vite": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz", - "integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.4.tgz", + "integrity": "sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==", "dev": true, "dependencies": { "esbuild": "^0.15.9", - "postcss": "^8.4.16", + "postcss": "^8.4.18", "resolve": "^1.22.1", - "rollup": "~2.78.0" + "rollup": "^2.79.1" }, "bin": { "vite": "bin/vite.js" @@ -9125,12 +8993,17 @@ "fsevents": "~2.3.2" }, "peerDependencies": { + "@types/node": ">= 14", "less": "*", "sass": "*", "stylus": "*", + "sugarss": "*", "terser": "^5.4.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "less": { "optional": true }, @@ -9140,40 +9013,31 @@ "stylus": { "optional": true }, - "terser": { + "sugarss": { "optional": true - } - } - }, - "node_modules/vite/node_modules/rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + }, + "terser": { + "optional": true + } } }, "node_modules/vitest": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", - "integrity": "sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.25.2.tgz", + "integrity": "sha512-qqkzfzglEFbQY7IGkgSJkdOhoqHjwAao/OrphnHboeYHC5JzsVFoLCaB2lnAy8krhj7sbrFTVRApzpkTOeuDWQ==", "dev": true, "dependencies": { "@types/chai": "^4.3.3", "@types/chai-subset": "^1.3.3", "@types/node": "*", + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", "chai": "^4.3.6", "debug": "^4.3.4", "local-pkg": "^0.4.2", + "source-map": "^0.6.1", "strip-literal": "^0.4.2", - "tinybench": "^2.3.0", + "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0" @@ -9229,15 +9093,15 @@ } }, "node_modules/vue": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.41.tgz", - "integrity": "sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.45.tgz", + "integrity": "sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==", "dependencies": { - "@vue/compiler-dom": "3.2.41", - "@vue/compiler-sfc": "3.2.41", - "@vue/runtime-dom": "3.2.41", - "@vue/server-renderer": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-dom": "3.2.45", + "@vue/compiler-sfc": "3.2.45", + "@vue/runtime-dom": "3.2.45", + "@vue/server-renderer": "3.2.45", + "@vue/shared": "3.2.45" } }, "node_modules/vue-bar-graph": { @@ -9274,9 +9138,9 @@ } }, "node_modules/vue-loader": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", - "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.1.tgz", + "integrity": "sha512-/OOyugJnImKCkAKrAvdsWMuwoCqGxWT5USLsjohzWbMgOwpA5wQmzQiLMzZd7DjhIfunzAGIApTOgIylz/kwcg==", "dependencies": { "chalk": "^4.1.0", "hash-sum": "^2.0.0", @@ -9284,6 +9148,14 @@ }, "peerDependencies": { "webpack": "^4.1.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + }, + "vue": { + "optional": true + } } }, "node_modules/vue3-calendar-heatmap": { @@ -9301,15 +9173,15 @@ } }, "node_modules/w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", "dev": true, "dependencies": { "xml-name-validator": "^4.0.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/watchpack": { @@ -9334,9 +9206,9 @@ } }, "node_modules/webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.75.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", + "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -9380,43 +9252,41 @@ } }, "node_modules/webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.0.0.tgz", + "integrity": "sha512-AACDTo20yG+xn6HPW5xjbn2Be4KUzQPebWXsDMHwPPyKh9OnTOJgZN2Nc+g/FZKV3ObRTYsGvibAvc+5jAUrVA==", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", + "@webpack-cli/configtest": "^2.0.0", + "@webpack-cli/info": "^2.0.0", + "@webpack-cli/serve": "^2.0.0", "colorette": "^2.0.14", - "commander": "^7.0.0", + "commander": "^9.4.1", "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", "webpack-merge": "^5.7.3" }, "bin": { "webpack-cli": "bin/cli.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.15.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x" + "webpack": "5.x.x" }, "peerDependenciesMeta": { "@webpack-cli/generators": { "optional": true }, - "@webpack-cli/migrate": { - "optional": true - }, "webpack-bundle-analyzer": { "optional": true }, @@ -9426,11 +9296,11 @@ } }, "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", "engines": { - "node": ">= 10" + "node": "^12.20.0 || >=14" } }, "node_modules/webpack-merge": { @@ -9790,9 +9660,9 @@ } }, "node_modules/ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "dev": true, "engines": { "node": ">=10.0.0" @@ -9999,14 +9869,14 @@ } }, "@babel/parser": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.6.tgz", - "integrity": "sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==" + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", + "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==" }, "@braintree/sanitize-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.1.tgz", - "integrity": "sha512-zr9Qs9KFQiEvMWdZesjcmRJlUck5NR+eKGS1uyKk+oYTWwlYrsoPEi6VmG6/TzBD1hKCGEimrhTgGS6hvn/xIQ==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", + "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" }, "@citation-js/core": { "version": "0.6.1", @@ -10040,9 +9910,9 @@ } }, "@citation-js/plugin-csl": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.6.3.tgz", - "integrity": "sha512-SP1/QyHfhcNufQ6VTJUM04Ti0XEWSWYMUhkDGG2lQtnDJU7pSDeAwtsE1kYUIJ9Np0Gm8IEZAfJ3CslMfsbimg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.6.4.tgz", + "integrity": "sha512-RG4NrFIx0CZTfNeMCC8CL7UGFRiUv5/bNd/Nc6Q/NHx0cS/tYDQcKt0M24dpOI7PAZwVoddbDW4Iakn6nS4QsQ==", "requires": { "@citation-js/date": "^0.5.0", "citeproc": "^2.4.6" @@ -10077,15 +9947,15 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, "@esbuild/android-arm": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.12.tgz", - "integrity": "sha512-IC7TqIqiyE0MmvAhWkl/8AEzpOtbhRNDo7aph47We1NbE5w2bt/Q+giAhe0YYeVpYnIhGMcuZY92qDK6dQauvA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.14.tgz", + "integrity": "sha512-+Rb20XXxRGisNu2WmNKk+scpanb7nL5yhuI1KR9wQFiC43ddPj/V1fmNyzlFC9bKiG4mYzxW7egtoHVcynr+OA==", "optional": true }, "@esbuild/linux-loong64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.12.tgz", - "integrity": "sha512-tZEowDjvU7O7I04GYvWQOS4yyP9E/7YlsB0jjw1Ycukgr2ycEzKyIk5tms5WnLBymaewc6VmRKnn5IJWgK4eFw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz", + "integrity": "sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==", "optional": true }, "@eslint/eslintrc": { @@ -10126,14 +9996,14 @@ } }, "@humanwhocodes/config-array": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", - "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, "@humanwhocodes/module-importer": { @@ -10242,13 +10112,13 @@ } }, "@playwright/test": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz", - "integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.28.0.tgz", + "integrity": "sha512-vrHs5DFTPwYox5SGKq/7TDn/S4q6RA1zArd7uhO6EyP9hj3XgZBBM12ktMbnDQNxh/fL1IUKsTNLxihmsU38lQ==", "dev": true, "requires": { "@types/node": "*", - "playwright-core": "1.27.1" + "playwright-core": "1.28.0" } }, "@popperjs/core": { @@ -10257,17 +10127,17 @@ "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" }, "@primer/octicons": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.7.0.tgz", - "integrity": "sha512-J5cVJDhExmqLGLWu8zHTOqcC8g1rQL7QzQZdbvHxW85u8ya82GtF5F68uHMDI5En3fsMlbkkF8Rz6dCaV3r+KA==", + "version": "17.9.0", + "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.9.0.tgz", + "integrity": "sha512-B6y3VxPrF6U+GUjZR883NsstI7v/Qcup9puDG+fOJvCm8b7UXNl46TbRrctMCZnYlyIzUF3/SgjJhr5od/Y6sw==", "requires": { "object-assign": "^4.1.1" } }, "@rollup/plugin-commonjs": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-20.0.0.tgz", - "integrity": "sha512-5K0g5W2Ol8hAcTHqcTBHiA7M58tfmYi1o9KxeJuuRNpGaTa5iLjcyemBitCBcKXaHamOBBEH2dGom6v6Unmqjg==", + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", + "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", "dev": true, "requires": { "@rollup/pluginutils": "^3.1.0", @@ -10328,13 +10198,14 @@ } }, "@stoplight/json": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.17.0.tgz", - "integrity": "sha512-WW0z2bb0D4t8FTl+zNTCu46J8lEOsrUhBPgwEYQ3Ri2Y0MiRE4U1/9ZV8Ki+pIJznZgY9i42bbFwOBxyZn5/6w==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", + "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", "dev": true, "requires": { - "@stoplight/ordered-object-literal": "^1.0.2", - "@stoplight/types": "^12.3.0", + "@stoplight/ordered-object-literal": "^1.0.3", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", "jsonc-parser": "~2.2.1", "lodash": "^4.17.21", "safe-stable-stringify": "^1.1" @@ -10359,22 +10230,21 @@ } }, "@stoplight/json-ref-resolver": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.3.tgz", - "integrity": "sha512-SgoKXwVnlpIZUyAFX4W79eeuTWvXmNlMfICZixL16GZXnkjcW+uZnfmAU0ZIjcnaTgaI4mjfxn8LAP2KR6Cr0A==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.4.tgz", + "integrity": "sha512-842JVmMsi++qpDuIX+JpQvK7YY8FXEZZb+/z4xuRfStOAVEryJT/tbgGOWxniSdxEl9Eni5D/I2afMyy6BuiNw==", "dev": true, "requires": { "@stoplight/json": "^3.17.0", "@stoplight/path": "^1.3.2", - "@stoplight/types": "^12.3.0", - "@types/urijs": "^1.19.16", + "@stoplight/types": "^12.3.0 || ^13.0.0", + "@types/urijs": "^1.19.19", "dependency-graph": "~0.11.0", "fast-memoize": "^2.5.2", "immer": "^9.0.6", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", + "lodash": "^4.17.21", "tslib": "^2.3.1", - "urijs": "^1.19.6" + "urijs": "^1.19.11" } }, "@stoplight/ordered-object-literal": { @@ -10390,22 +10260,21 @@ "dev": true }, "@stoplight/spectral-cli": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-cli/-/spectral-cli-6.5.1.tgz", - "integrity": "sha512-+qpwsDG2jQ4ULQmegBWonI3UnF6tUh351WDnV1GU8acl8eaeKbS+ZUNBgoP2f9tnMTfITdctVRFEGC3D6P7f9g==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-cli/-/spectral-cli-6.6.0.tgz", + "integrity": "sha512-z46fnrvraaWMio8Y9RYYkLO+XdmtxOWpy5qNJF3CsmWua0FZ4iOTryb5Cm3GkB0wEtqxNUCBUHvoo4hS6Noyqg==", "dev": true, "requires": { - "@rollup/plugin-commonjs": "^20.0.0", - "@stoplight/json": "3.17.0", + "@stoplight/json": "~3.20.1", "@stoplight/path": "1.3.2", - "@stoplight/spectral-core": "^1.5.1", - "@stoplight/spectral-parsers": "^1.0.1", - "@stoplight/spectral-ref-resolver": "1.0.1", - "@stoplight/spectral-ruleset-bundler": "^1.0.0", - "@stoplight/spectral-ruleset-migrator": "^1.5.0", + "@stoplight/spectral-core": "^1.15.1", + "@stoplight/spectral-parsers": "^1.0.2", + "@stoplight/spectral-ref-resolver": "1.0.2", + "@stoplight/spectral-ruleset-bundler": "^1.4.0", + "@stoplight/spectral-ruleset-migrator": "^1.9.0", "@stoplight/spectral-rulesets": ">=1", - "@stoplight/spectral-runtime": "^1.1.0", - "@stoplight/types": "12.3.0", + "@stoplight/spectral-runtime": "^1.1.2", + "@stoplight/types": "^13.6.0", "chalk": "4.1.2", "cliui": "7.0.4", "eol": "0.9.1", @@ -10445,9 +10314,9 @@ } }, "@stoplight/spectral-core": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.15.0.tgz", - "integrity": "sha512-+DwK8SmnujMZJaxJeNU11vWY+DFOnt4oQM1TzAuvufdd3Y6Lsno88Jl31OaR1M9Fn7l/u3v1anBB/SSl/fI5rQ==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.15.1.tgz", + "integrity": "sha512-IZV8L1Hyz9759KdqJIA90W5uvurHplMmaPPIZjQzG2Bq/39kN/sbLA/Js8uOf3xB9cHBbG599t4AB+uGsI8t0g==", "dev": true, "requires": { "@stoplight/better-ajv-errors": "1.0.3", @@ -10462,7 +10331,6 @@ "ajv": "^8.6.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.0", - "blueimp-md5": "2.18.0", "es-aggregate-error": "^1.0.7", "jsonpath-plus": "7.1.0", "lodash": "~4.17.21", @@ -10474,20 +10342,6 @@ "tslib": "^2.3.0" }, "dependencies": { - "@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "requires": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - } - }, "@stoplight/types": { "version": "13.6.0", "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", @@ -10529,32 +10383,6 @@ "ajv-formats": "~2.1.0", "lodash": "~4.17.21", "tslib": "^2.3.0" - }, - "dependencies": { - "@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "requires": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - } - }, - "@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - } - } } }, "@stoplight/spectral-parsers": { @@ -10567,51 +10395,25 @@ "@stoplight/types": "^13.6.0", "@stoplight/yaml": "~4.2.3", "tslib": "^2.3.1" - }, - "dependencies": { - "@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "requires": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - } - }, - "@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - } - } } }, "@stoplight/spectral-ref-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.1.tgz", - "integrity": "sha512-0tY7nTOccvTsa3c4QbSWfJ8wGfPO1RXvmKnmBjuyLfoTMNuhkHPII9gKhCjygsshzsBLxs2IyRHZYhWYVnEbCA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.2.tgz", + "integrity": "sha512-ah6NIB/O1EdEaEu89So3LmtbKRXPVnSElgQ7oBRE9S4/VOedSqyXn+qqMd40tGnO2CsKgZaFUYXdSEHOshpHYw==", "dev": true, "requires": { "@stoplight/json-ref-readers": "1.2.2", - "@stoplight/json-ref-resolver": "3.1.3", - "@stoplight/spectral-runtime": "^1.0.0", + "@stoplight/json-ref-resolver": "~3.1.4", + "@stoplight/spectral-runtime": "^1.1.2", "dependency-graph": "0.11.0", "tslib": "^2.3.1" } }, "@stoplight/spectral-ruleset-bundler": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.3.tgz", - "integrity": "sha512-hfHl7XZeF/wWMpSrsLqLnH2GevRHjSIqtBL2aRjO2SjMCTbO9LVz80p4sYaxrCcu4wQ6K71gMZXsG687+3fAeg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.4.0.tgz", + "integrity": "sha512-aYDI4a145IXED+6jvRjj9Ha0fnB+s54cr8KbQbPCEyhCHW1cP8UGVeOuwAfk+9C4ZIg40OuYrugN5EhA35oQtA==", "dev": true, "requires": { "@rollup/plugin-commonjs": "~22.0.2", @@ -10630,64 +10432,12 @@ "rollup": "~2.79.0", "tslib": "^2.3.1", "validate-npm-package-name": "3.0.0" - }, - "dependencies": { - "@rollup/plugin-commonjs": { - "version": "22.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", - "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - } - }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - } - } - }, - "@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - } - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - } } }, "@stoplight/spectral-ruleset-migrator": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.8.0.tgz", - "integrity": "sha512-zg6RPF+d8uS7zAp5TzUph3hQG4sgGcG5Fsw8Zx24H1REyuSkjiIfyee2Kf13c3BcIlTXvnFc4csz2rNXpZO7Ug==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.9.0.tgz", + "integrity": "sha512-hPSjgXsTxMQ5UV1hfkVVPknhqRjmjSnCZD5jideM4rRU5NS1fj2Pse1CiXBsRChsuAGi/2s0Ke5uuOmFFsHrxQ==", "dev": true, "requires": { "@stoplight/json": "~3.20.1", @@ -10704,32 +10454,6 @@ "reserved": "0.1.2", "tslib": "^2.3.1", "validate-npm-package-name": "3.0.0" - }, - "dependencies": { - "@stoplight/json": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.1.tgz", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", - "dev": true, - "requires": { - "@stoplight/ordered-object-literal": "^1.0.3", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^13.6.0", - "jsonc-parser": "~2.2.1", - "lodash": "^4.17.21", - "safe-stable-stringify": "^1.1" - } - }, - "@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - } - } } }, "@stoplight/spectral-rulesets": { @@ -10752,18 +10476,6 @@ "json-schema-traverse": "^1.0.0", "lodash": "~4.17.21", "tslib": "^2.3.0" - }, - "dependencies": { - "@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - } - } } }, "@stoplight/spectral-runtime": { @@ -10779,12 +10491,24 @@ "lodash": "^4.17.21", "node-fetch": "^2.6.7", "tslib": "^2.3.1" + }, + "dependencies": { + "@stoplight/types": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-12.5.0.tgz", + "integrity": "sha512-dwqYcDrGmEyUv5TWrDam5TGOxU72ufyQ7hnOIIDdmW5ezOwZaBFoR5XQ9AsH49w7wgvOqB2Bmo799pJPWnpCbg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + } + } } }, "@stoplight/types": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-12.3.0.tgz", - "integrity": "sha512-hgzUR1z5BlYvIzUeFK5pjs5JXSvEutA9Pww31+dVicBlunsG1iXopDx/cvfBY7rHOrgtZDuvyeK4seqkwAZ6Cg==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.8.0.tgz", + "integrity": "sha512-5glKswz7y9aACh+a+JegID+4xX//4TsIdv7iPl29hWnOoWrnlPbg3Gjc4nYUXXgMSaSlSsA15JU/0+rE89fR4A==", "dev": true, "requires": { "@types/json-schema": "^7.0.4", @@ -10801,18 +10525,6 @@ "@stoplight/types": "^13.0.0", "@stoplight/yaml-ast-parser": "0.0.48", "tslib": "^2.2.0" - }, - "dependencies": { - "@stoplight/types": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.7.0.tgz", - "integrity": "sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "utility-types": "^3.10.0" - } - } } }, "@stoplight/yaml-ast-parser": { @@ -10839,9 +10551,9 @@ "dev": true }, "@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "@types/chai-subset": { @@ -10871,9 +10583,9 @@ } }, "@types/eslint": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz", - "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==", + "version": "8.4.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", + "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", "requires": { "@types/estree": "*", "@types/json-schema": "*" @@ -10916,9 +10628,9 @@ "dev": true }, "@types/node": { - "version": "18.11.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.4.tgz", - "integrity": "sha512-BxcJpBu8D3kv/GZkx/gSMz6VnTJREBj/4lbzYOQueUOELkt8WrO6zAcSPmp9uRPEW/d+lUO8QK0W2xnS1hEU0A==" + "version": "18.11.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", + "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" }, "@types/normalize-package-data": { "version": "2.4.1", @@ -10947,36 +10659,36 @@ "dev": true }, "@vue/compiler-core": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.41.tgz", - "integrity": "sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.45.tgz", + "integrity": "sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==", "requires": { "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.41", + "@vue/shared": "3.2.45", "estree-walker": "^2.0.2", "source-map": "^0.6.1" } }, "@vue/compiler-dom": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz", - "integrity": "sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz", + "integrity": "sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==", "requires": { - "@vue/compiler-core": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-core": "3.2.45", + "@vue/shared": "3.2.45" } }, "@vue/compiler-sfc": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz", - "integrity": "sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz", + "integrity": "sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==", "requires": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.41", - "@vue/compiler-dom": "3.2.41", - "@vue/compiler-ssr": "3.2.41", - "@vue/reactivity-transform": "3.2.41", - "@vue/shared": "3.2.41", + "@vue/compiler-core": "3.2.45", + "@vue/compiler-dom": "3.2.45", + "@vue/compiler-ssr": "3.2.45", + "@vue/reactivity-transform": "3.2.45", + "@vue/shared": "3.2.45", "estree-walker": "^2.0.2", "magic-string": "^0.25.7", "postcss": "^8.1.10", @@ -10984,66 +10696,66 @@ } }, "@vue/compiler-ssr": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz", - "integrity": "sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz", + "integrity": "sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==", "requires": { - "@vue/compiler-dom": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-dom": "3.2.45", + "@vue/shared": "3.2.45" } }, "@vue/reactivity": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.41.tgz", - "integrity": "sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz", + "integrity": "sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==", "requires": { - "@vue/shared": "3.2.41" + "@vue/shared": "3.2.45" } }, "@vue/reactivity-transform": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz", - "integrity": "sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz", + "integrity": "sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==", "requires": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.41", - "@vue/shared": "3.2.41", + "@vue/compiler-core": "3.2.45", + "@vue/shared": "3.2.45", "estree-walker": "^2.0.2", "magic-string": "^0.25.7" } }, "@vue/runtime-core": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.41.tgz", - "integrity": "sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz", + "integrity": "sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==", "requires": { - "@vue/reactivity": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/reactivity": "3.2.45", + "@vue/shared": "3.2.45" } }, "@vue/runtime-dom": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.41.tgz", - "integrity": "sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz", + "integrity": "sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==", "requires": { - "@vue/runtime-core": "3.2.41", - "@vue/shared": "3.2.41", + "@vue/runtime-core": "3.2.45", + "@vue/shared": "3.2.45", "csstype": "^2.6.8" } }, "@vue/server-renderer": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.41.tgz", - "integrity": "sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz", + "integrity": "sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==", "requires": { - "@vue/compiler-ssr": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-ssr": "3.2.45", + "@vue/shared": "3.2.45" } }, "@vue/shared": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz", - "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==" + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz", + "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==" }, "@webassemblyjs/ast": { "version": "1.11.1", @@ -11177,23 +10889,21 @@ } }, "@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.0.0.tgz", + "integrity": "sha512-war4OU8NGjBqU3DP3bx6ciODXIh7dSXcpQq+P4K2Tqyd8L5OjZ7COx9QXx/QdCIwL2qoX09Wr4Cwf7uS4qdEng==", "requires": {} }, "@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "requires": { - "envinfo": "^7.7.3" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.0.tgz", + "integrity": "sha512-NNxDgbo4VOkNhOlTgY0Elhz3vKpOJq4/PKeKg7r8cmYM+GQA9vDofLYyup8jS6EpUvhNmR30cHTCEIyvXpskwA==", + "requires": {} }, "@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.0.tgz", + "integrity": "sha512-Rumq5mHvGXamnOh3O8yLk1sjx8dB30qF1OeR6VC00DIR6SLJ4bwwUGKC4pE7qBFoQyyh0H9sAg3fikYgAqVR0w==", "requires": {} }, "@xtuc/ieee754": { @@ -11271,9 +10981,9 @@ } }, "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -11335,15 +11045,15 @@ "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==" }, "array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", "is-string": "^1.0.7" } }, @@ -11354,14 +11064,14 @@ "dev": true }, "array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" } }, @@ -11428,12 +11138,6 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, - "blueimp-md5": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", - "integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==", - "dev": true - }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -11534,19 +11238,19 @@ } }, "caniuse-lite": { - "version": "1.0.30001423", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz", - "integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==" + "version": "1.0.30001431", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz", + "integrity": "sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==" }, "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -11574,9 +11278,9 @@ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" }, "ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", "dev": true }, "citeproc": { @@ -11646,9 +11350,9 @@ } }, "codemirror": { - "version": "5.65.9", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz", - "integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw==" + "version": "5.65.10", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.10.tgz", + "integrity": "sha512-IXAG5wlhbgcTJ6rZZcmi4+sjWIbJqIGfeg3tNa3yX84Jb3T4huS5qzQAo/cUisc1l3bI47WZodpyf7cYcocDKg==" }, "codemirror-spell-checker": { "version": "1.1.2", @@ -11722,9 +11426,9 @@ "dev": true }, "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -11751,18 +11455,18 @@ "dev": true }, "css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.2.tgz", + "integrity": "sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q==", "requires": { "icss-utils": "^5.1.0", - "postcss": "^8.4.7", + "postcss": "^8.4.18", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" + "semver": "^7.3.8" } }, "css-select": { @@ -12438,9 +12142,9 @@ "dev": true }, "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "requires": { "decamelize": "^1.1.0", @@ -12462,9 +12166,9 @@ "dev": true }, "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.2.tgz", + "integrity": "sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -12794,17 +12498,17 @@ } }, "es-aggregate-error": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.8.tgz", - "integrity": "sha512-AKUb5MKLWMozPlFRHOKqWD7yta5uaEhH21qwtnf6FlKjNjTJOoqFi0/G14+FfSkIQhhu6X68Af4xgRC6y8qG4A==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.9.tgz", + "integrity": "sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg==", "dev": true, "requires": { "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", + "es-abstract": "^1.20.4", "function-bind": "^1.1.1", "functions-have-names": "^1.2.3", - "get-intrinsic": "^1.1.1", - "globalthis": "^1.0.2", + "get-intrinsic": "^1.1.3", + "globalthis": "^1.0.3", "has-property-descriptors": "^1.0.0" } }, @@ -12834,116 +12538,116 @@ } }, "esbuild": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.12.tgz", - "integrity": "sha512-PcT+/wyDqJQsRVhaE9uX/Oq4XLrFh0ce/bs2TJh4CSaw9xuvI+xFrH2nAYOADbhQjUgAhNWC5LKoUsakm4dxng==", - "requires": { - "@esbuild/android-arm": "0.15.12", - "@esbuild/linux-loong64": "0.15.12", - "esbuild-android-64": "0.15.12", - "esbuild-android-arm64": "0.15.12", - "esbuild-darwin-64": "0.15.12", - "esbuild-darwin-arm64": "0.15.12", - "esbuild-freebsd-64": "0.15.12", - "esbuild-freebsd-arm64": "0.15.12", - "esbuild-linux-32": "0.15.12", - "esbuild-linux-64": "0.15.12", - "esbuild-linux-arm": "0.15.12", - "esbuild-linux-arm64": "0.15.12", - "esbuild-linux-mips64le": "0.15.12", - "esbuild-linux-ppc64le": "0.15.12", - "esbuild-linux-riscv64": "0.15.12", - "esbuild-linux-s390x": "0.15.12", - "esbuild-netbsd-64": "0.15.12", - "esbuild-openbsd-64": "0.15.12", - "esbuild-sunos-64": "0.15.12", - "esbuild-windows-32": "0.15.12", - "esbuild-windows-64": "0.15.12", - "esbuild-windows-arm64": "0.15.12" + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.14.tgz", + "integrity": "sha512-pJN8j42fvWLFWwSMG4luuupl2Me7mxciUOsMegKvwCmhEbJ2covUdFnihxm0FMIBV+cbwbtMoHgMCCI+pj1btQ==", + "requires": { + "@esbuild/android-arm": "0.15.14", + "@esbuild/linux-loong64": "0.15.14", + "esbuild-android-64": "0.15.14", + "esbuild-android-arm64": "0.15.14", + "esbuild-darwin-64": "0.15.14", + "esbuild-darwin-arm64": "0.15.14", + "esbuild-freebsd-64": "0.15.14", + "esbuild-freebsd-arm64": "0.15.14", + "esbuild-linux-32": "0.15.14", + "esbuild-linux-64": "0.15.14", + "esbuild-linux-arm": "0.15.14", + "esbuild-linux-arm64": "0.15.14", + "esbuild-linux-mips64le": "0.15.14", + "esbuild-linux-ppc64le": "0.15.14", + "esbuild-linux-riscv64": "0.15.14", + "esbuild-linux-s390x": "0.15.14", + "esbuild-netbsd-64": "0.15.14", + "esbuild-openbsd-64": "0.15.14", + "esbuild-sunos-64": "0.15.14", + "esbuild-windows-32": "0.15.14", + "esbuild-windows-64": "0.15.14", + "esbuild-windows-arm64": "0.15.14" } }, "esbuild-android-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.12.tgz", - "integrity": "sha512-MJKXwvPY9g0rGps0+U65HlTsM1wUs9lbjt5CU19RESqycGFDRijMDQsh68MtbzkqWSRdEtiKS1mtPzKneaAI0Q==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz", + "integrity": "sha512-HuilVIb4rk9abT4U6bcFdU35UHOzcWVGLSjEmC58OVr96q5UiRqzDtWjPlCMugjhgUGKEs8Zf4ueIvYbOStbIg==", "optional": true }, "esbuild-android-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.12.tgz", - "integrity": "sha512-Hc9SEcZbIMhhLcvhr1DH+lrrec9SFTiRzfJ7EGSBZiiw994gfkVV6vG0sLWqQQ6DD7V4+OggB+Hn0IRUdDUqvA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.14.tgz", + "integrity": "sha512-/QnxRVxsR2Vtf3XottAHj7hENAMW2wCs6S+OZcAbc/8nlhbAL/bCQRCVD78VtI5mdwqWkVi3wMqM94kScQCgqg==", "optional": true }, "esbuild-darwin-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.12.tgz", - "integrity": "sha512-qkmqrTVYPFiePt5qFjP8w/S+GIUMbt6k8qmiPraECUWfPptaPJUGkCKrWEfYFRWB7bY23FV95rhvPyh/KARP8Q==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.14.tgz", + "integrity": "sha512-ToNuf1uifu8hhwWvoZJGCdLIX/1zpo8cOGnT0XAhDQXiKOKYaotVNx7pOVB1f+wHoWwTLInrOmh3EmA7Fd+8Vg==", "optional": true }, "esbuild-darwin-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.12.tgz", - "integrity": "sha512-z4zPX02tQ41kcXMyN3c/GfZpIjKoI/BzHrdKUwhC/Ki5BAhWv59A9M8H+iqaRbwpzYrYidTybBwiZAIWCLJAkw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.14.tgz", + "integrity": "sha512-KgGP+y77GszfYJgceO0Wi/PiRtYo5y2Xo9rhBUpxTPaBgWDJ14gqYN0+NMbu+qC2fykxXaipHxN4Scaj9tUS1A==", "optional": true }, "esbuild-freebsd-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.12.tgz", - "integrity": "sha512-XFL7gKMCKXLDiAiBjhLG0XECliXaRLTZh6hsyzqUqPUf/PY4C6EJDTKIeqqPKXaVJ8+fzNek88285krSz1QECw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.14.tgz", + "integrity": "sha512-xr0E2n5lyWw3uFSwwUXHc0EcaBDtsal/iIfLioflHdhAe10KSctV978Te7YsfnsMKzcoGeS366+tqbCXdqDHQA==", "optional": true }, "esbuild-freebsd-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.12.tgz", - "integrity": "sha512-jwEIu5UCUk6TjiG1X+KQnCGISI+ILnXzIzt9yDVrhjug2fkYzlLbl0K43q96Q3KB66v6N1UFF0r5Ks4Xo7i72g==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.14.tgz", + "integrity": "sha512-8XH96sOQ4b1LhMlO10eEWOjEngmZ2oyw3pW4o8kvBcpF6pULr56eeYVP5radtgw54g3T8nKHDHYEI5AItvskZg==", "optional": true }, "esbuild-linux-32": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.12.tgz", - "integrity": "sha512-uSQuSEyF1kVzGzuIr4XM+v7TPKxHjBnLcwv2yPyCz8riV8VUCnO/C4BF3w5dHiVpCd5Z1cebBtZJNlC4anWpwA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.14.tgz", + "integrity": "sha512-6ssnvwaTAi8AzKN8By2V0nS+WF5jTP7SfuK6sStGnDP7MCJo/4zHgM9oE1eQTS2jPmo3D673rckuCzRlig+HMA==", "optional": true }, "esbuild-linux-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.12.tgz", - "integrity": "sha512-QcgCKb7zfJxqT9o5z9ZUeGH1k8N6iX1Y7VNsEi5F9+HzN1OIx7ESxtQXDN9jbeUSPiRH1n9cw6gFT3H4qbdvcA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.14.tgz", + "integrity": "sha512-ONySx3U0wAJOJuxGUlXBWxVKFVpWv88JEv0NZ6NlHknmDd1yCbf4AEdClSgLrqKQDXYywmw4gYDvdLsS6z0hcw==", "optional": true }, "esbuild-linux-arm": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.12.tgz", - "integrity": "sha512-Wf7T0aNylGcLu7hBnzMvsTfEXdEdJY/hY3u36Vla21aY66xR0MS5I1Hw8nVquXjTN0A6fk/vnr32tkC/C2lb0A==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.14.tgz", + "integrity": "sha512-D2LImAIV3QzL7lHURyCHBkycVFbKwkDb1XEUWan+2fb4qfW7qAeUtul7ZIcIwFKZgPcl+6gKZmvLgPSj26RQ2Q==", "optional": true }, "esbuild-linux-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.12.tgz", - "integrity": "sha512-HtNq5xm8fUpZKwWKS2/YGwSfTF+339L4aIA8yphNKYJckd5hVdhfdl6GM2P3HwLSCORS++++7++//ApEwXEuAQ==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.14.tgz", + "integrity": "sha512-kle2Ov6a1e5AjlHlMQl1e+c4myGTeggrRzArQFmWp6O6JoqqB9hT+B28EW4tjFWgV/NxUq46pWYpgaWXsXRPAg==", "optional": true }, "esbuild-linux-mips64le": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.12.tgz", - "integrity": "sha512-Qol3+AvivngUZkTVFgLpb0H6DT+N5/zM3V1YgTkryPYFeUvuT5JFNDR3ZiS6LxhyF8EE+fiNtzwlPqMDqVcc6A==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.14.tgz", + "integrity": "sha512-FVdMYIzOLXUq+OE7XYKesuEAqZhmAIV6qOoYahvUp93oXy0MOVTP370ECbPfGXXUdlvc0TNgkJa3YhEwyZ6MRA==", "optional": true }, "esbuild-linux-ppc64le": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.12.tgz", - "integrity": "sha512-4D8qUCo+CFKaR0cGXtGyVsOI7w7k93Qxb3KFXWr75An0DHamYzq8lt7TNZKoOq/Gh8c40/aKaxvcZnTgQ0TJNg==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.14.tgz", + "integrity": "sha512-2NzH+iuzMDA+jjtPjuIz/OhRDf8tzbQ1tRZJI//aT25o1HKc0reMMXxKIYq/8nSHXiJSnYV4ODzTiv45s+h73w==", "optional": true }, "esbuild-linux-riscv64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.12.tgz", - "integrity": "sha512-G9w6NcuuCI6TUUxe6ka0enjZHDnSVK8bO+1qDhMOCtl7Tr78CcZilJj8SGLN00zO5iIlwNRZKHjdMpfFgNn1VA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.14.tgz", + "integrity": "sha512-VqxvutZNlQxmUNS7Ac+aczttLEoHBJ9e3OYGqnULrfipRvG97qLrAv9EUY9iSrRKBqeEbSvS9bSfstZqwz0T4Q==", "optional": true }, "esbuild-linux-s390x": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.12.tgz", - "integrity": "sha512-Lt6BDnuXbXeqSlVuuUM5z18GkJAZf3ERskGZbAWjrQoi9xbEIsj/hEzVnSAFLtkfLuy2DE4RwTcX02tZFunXww==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.14.tgz", + "integrity": "sha512-+KVHEUshX5n6VP6Vp/AKv9fZIl5kr2ph8EUFmQUJnDpHwcfTSn2AQgYYm0HTBR2Mr4d0Wlr0FxF/Cs5pbFgiOw==", "optional": true }, "esbuild-loader": { @@ -12960,39 +12664,39 @@ } }, "esbuild-netbsd-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.12.tgz", - "integrity": "sha512-jlUxCiHO1dsqoURZDQts+HK100o0hXfi4t54MNRMCAqKGAV33JCVvMplLAa2FwviSojT/5ZG5HUfG3gstwAG8w==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.14.tgz", + "integrity": "sha512-6D/dr17piEgevIm1xJfZP2SjB9Z+g8ERhNnBdlZPBWZl+KSPUKLGF13AbvC+nzGh8IxOH2TyTIdRMvKMP0nEzQ==", "optional": true }, "esbuild-openbsd-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.12.tgz", - "integrity": "sha512-1o1uAfRTMIWNOmpf8v7iudND0L6zRBYSH45sofCZywrcf7NcZA+c7aFsS1YryU+yN7aRppTqdUK1PgbZVaB1Dw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.14.tgz", + "integrity": "sha512-rREQBIlMibBetgr2E9Lywt2Qxv2ZdpmYahR4IUlAQ1Efv/A5gYdO0/VIN3iowDbCNTLxp0bb57Vf0LFcffD6kA==", "optional": true }, "esbuild-sunos-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.12.tgz", - "integrity": "sha512-nkl251DpoWoBO9Eq9aFdoIt2yYmp4I3kvQjba3jFKlMXuqQ9A4q+JaqdkCouG3DHgAGnzshzaGu6xofGcXyPXg==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.14.tgz", + "integrity": "sha512-DNVjSp/BY4IfwtdUAvWGIDaIjJXY5KI4uD82+15v6k/w7px9dnaDaJJ2R6Mu+KCgr5oklmFc0KjBjh311Gxl9Q==", "optional": true }, "esbuild-windows-32": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.12.tgz", - "integrity": "sha512-WlGeBZHgPC00O08luIp5B2SP4cNCp/PcS+3Pcg31kdcJPopHxLkdCXtadLU9J82LCfw4TVls21A6lilQ9mzHrw==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.14.tgz", + "integrity": "sha512-pHBWrcA+/oLgvViuG9FO3kNPO635gkoVrRQwe6ZY1S0jdET07xe2toUvQoJQ8KT3/OkxqUasIty5hpuKFLD+eg==", "optional": true }, "esbuild-windows-64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.12.tgz", - "integrity": "sha512-VActO3WnWZSN//xjSfbiGOSyC+wkZtI8I4KlgrTo5oHJM6z3MZZBCuFaZHd8hzf/W9KPhF0lY8OqlmWC9HO5AA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.14.tgz", + "integrity": "sha512-CszIGQVk/P8FOS5UgAH4hKc9zOaFo69fe+k1rqgBHx3CSK3Opyk5lwYriIamaWOVjBt7IwEP6NALz+tkVWdFog==", "optional": true }, "esbuild-windows-arm64": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.12.tgz", - "integrity": "sha512-Of3MIacva1OK/m4zCNIvBfz8VVROBmQT+gRX6pFTLPngFYcj6TFH/12VveAqq1k9VB2l28EoVMNMUCcmsfwyuA==", + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.14.tgz", + "integrity": "sha512-KW9W4psdZceaS9A7Jsgl4WialOznSURvqX/oHZk3gOP7KbjtHLSsnmSvNdzagGJfxbAe30UVGXRe8q8nDsOSQw==", "optional": true }, "escalade": { @@ -13066,9 +12770,9 @@ } }, "eslint": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", - "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", + "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", "dev": true, "requires": { "@eslint/eslintrc": "^1.3.3", @@ -13235,31 +12939,33 @@ "requires": {} }, "eslint-plugin-unicorn": { - "version": "44.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-44.0.2.tgz", - "integrity": "sha512-GLIDX1wmeEqpGaKcnMcqRvMVsoabeF0Ton0EX4Th5u6Kmf7RM9WBl705AXFEsns56ESkEs0uyelLuUTvz9Tr0w==", + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.0.tgz", + "integrity": "sha512-iP8cMRxXKHonKioOhnCoCcqVhoqhAp6rB+nsoLjXFDxTHz3btWMAp8xwzjHA0B1K6YV/U/Yvqn1bUXZt8sJPuQ==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.19.1", - "ci-info": "^3.4.0", + "ci-info": "^3.6.1", "clean-regexp": "^1.0.0", "eslint-utils": "^3.0.0", "esquery": "^1.4.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.0", + "jsesc": "3.0.2", "lodash": "^4.17.21", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.24", + "regjsparser": "0.9.1", "safe-regex": "^2.1.1", - "semver": "^7.3.7", + "semver": "^7.3.8", "strip-indent": "^3.0.0" } }, "eslint-plugin-vue": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.6.0.tgz", - "integrity": "sha512-zzySkJgVbFCylnG2+9MDF7N+2Rjze2y0bF8GyUNpFOnT8mCMfqqtLDJkHBuYu9N/psW1A6DVbQhPkP92E+qakA==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.7.0.tgz", + "integrity": "sha512-DrOO3WZCZEwcLsnd3ohFwqCoipGRSTKTBTnLwdhqAbYZtzWl0o7D+D8ZhlmiZvABKTEl8AFsqH1GHGdybyoQmw==", "dev": true, "requires": { "eslint-utils": "^3.0.0", @@ -13305,9 +13011,9 @@ "dev": true }, "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "requires": { "acorn": "^8.8.0", @@ -13365,6 +13071,11 @@ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" }, + "fast-clone": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/fast-clone/-/fast-clone-1.5.13.tgz", + "integrity": "sha512-0ez7coyFBQFjZtId+RJqJ+EQs61w9xARfqjqK0AD9vIUkSxWD4HvPt80+5evebZ1tTnv1GYKrPTipx7kOW5ipA==" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -13695,9 +13406,9 @@ } }, "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz", + "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -13976,9 +13687,9 @@ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" }, "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==" }, "ip": { "version": "1.1.8", @@ -14240,18 +13951,18 @@ } }, "jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", "dev": true, "requires": { "abab": "^2.0.6", - "acorn": "^8.8.0", + "acorn": "^8.8.1", "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", "data-urls": "^3.0.2", - "decimal.js": "^10.4.1", + "decimal.js": "^10.4.2", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", @@ -14264,12 +13975,12 @@ "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^3.0.0", + "w3c-xmlserializer": "^4.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0", - "ws": "^8.9.0", + "ws": "^8.11.0", "xml-name-validator": "^4.0.0" } }, @@ -14279,6 +13990,12 @@ "integrity": "sha512-NFbZTr1t13fPKw53swmZFKwBkEDWDnno7uLJk+a+Rw9tGDTkGgnGdZJ8A/o3gR1+XaAXmSsbpfIBIBgqRBZWDA==", "dev": true }, + "jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -14356,9 +14073,9 @@ "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" }, "known-css-properties": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", - "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.26.0.tgz", + "integrity": "sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==", "dev": true }, "less": { @@ -14499,24 +14216,12 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", - "dev": true - }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -14547,9 +14252,9 @@ "dev": true }, "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "requires": { "get-func-name": "^2.0.0" @@ -14688,9 +14393,9 @@ "dev": true }, "marked": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", - "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.3.tgz", + "integrity": "sha512-slWRdJkbTZ+PjkyJnE30Uid64eHwbwa1Q25INCAYfZlK4o6ylagBy/Le9eWntqJFoFT93ikUKMv47GZ4gTwHkw==" }, "mathml-tag-names": { "version": "2.1.3", @@ -14785,19 +14490,23 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "mermaid": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.1.7.tgz", - "integrity": "sha512-MRVHXy5FLjnUQUG7YS3UN9jEN6FXCJbFCXVGJQjVIbiR6Vhw0j/6pLIjqsiah9xoHmQU6DEaKOvB3S1g/1nBPA==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.2.2.tgz", + "integrity": "sha512-6s7eKMqFJGS+0MYjmx8f6ZigqKBJVoSx5ql2gw6a4Aa+WJ49QiEJg7gPwywaBg3DZMs79UP7trESp4+jmaQccw==", "requires": { "@braintree/sanitize-url": "^6.0.0", "d3": "^7.0.0", "dagre": "^0.8.5", "dagre-d3": "^0.6.4", "dompurify": "2.4.0", + "fast-clone": "^1.5.13", "graphlib": "^2.1.8", "khroma": "^2.0.0", - "moment-mini": "2.24.0", - "stylis": "^4.0.10" + "lodash": "^4.17.21", + "moment-mini": "^2.24.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "uuid": "^9.0.0" } }, "micromatch": { @@ -14835,9 +14544,9 @@ "dev": true }, "mini-css-extract-plugin": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", - "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz", + "integrity": "sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw==", "requires": { "schema-utils": "^4.0.0" } @@ -14868,9 +14577,9 @@ } }, "moment-mini": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", - "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz", + "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==" }, "monaco-editor": { "version": "0.34.1", @@ -14886,9 +14595,9 @@ } }, "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" }, "ms": { "version": "2.1.2", @@ -14908,9 +14617,9 @@ "dev": true }, "needle": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", - "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", "optional": true, "requires": { "debug": "^3.2.6", @@ -14997,6 +14706,11 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, + "non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -15068,14 +14782,14 @@ } }, "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "once": { @@ -15310,9 +15024,9 @@ } }, "playwright-core": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz", - "integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.28.0.tgz", + "integrity": "sha512-nJLknd28kPBiCNTbqpu6Wmkrh63OEqJSFw9xOfL9qxfNwody7h6/L3O2dZoWQ6Oxcm0VOHjWmGiCUGkc0X3VZA==", "dev": true }, "pluralize": { @@ -15328,9 +15042,9 @@ "dev": true }, "postcss": { - "version": "8.4.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", - "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", + "version": "8.4.19", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", + "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -15396,9 +15110,9 @@ "requires": {} }, "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15624,11 +15338,11 @@ } }, "rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "requires": { - "resolve": "^1.9.0" + "resolve": "^1.20.0" } }, "redent": { @@ -15664,6 +15378,23 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -16098,25 +15829,25 @@ } }, "string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" } }, "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" } }, "strip-ansi": { @@ -16164,15 +15895,15 @@ "dev": true }, "stylelint": { - "version": "14.14.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz", - "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==", + "version": "14.15.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.15.0.tgz", + "integrity": "sha512-JOgDAo5QRsqiOZPZO+B9rKJvBm64S0xasbuRPAbPs6/vQDgDCnZLIiw6XcAS6GQKk9k1sBWR6rmH3Mfj8OknKg==", "dev": true, "requires": { "@csstools/selector-specificity": "^2.0.2", "balanced-match": "^2.0.0", "colord": "^2.9.3", - "cosmiconfig": "^7.0.1", + "cosmiconfig": "^7.1.0", "css-functions-list": "^3.1.0", "debug": "^4.3.4", "fast-glob": "^3.2.12", @@ -16186,13 +15917,13 @@ "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.25.0", + "known-css-properties": "^0.26.0", "mathml-tag-names": "^2.1.3", "meow": "^9.0.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.17", + "postcss": "^8.4.19", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", @@ -16204,7 +15935,7 @@ "style-search": "^0.1.0", "supports-hyperlinks": "^2.3.0", "svg-tags": "^1.0.0", - "table": "^6.8.0", + "table": "^6.8.1", "v8-compile-cache": "^2.3.0", "write-file-atomic": "^4.0.2" }, @@ -16240,9 +15971,9 @@ } }, "stylis": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.2.tgz", - "integrity": "sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA==" + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" }, "superstruct": { "version": "0.10.13", @@ -16279,9 +16010,9 @@ "dev": true }, "svgo": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.0.tgz", - "integrity": "sha512-mSqPn6RDeNqJvCeqHERlfWJjd4crP/2PgFelil9WpTwC4D3okAUopPsH3lnEyl7ONXfDVyISOihDjO0uK8YVAA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", + "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", "dev": true, "requires": { "@trysound/sax": "0.2.0", @@ -16301,9 +16032,9 @@ } }, "swagger-ui-dist": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.0.tgz", - "integrity": "sha512-vAsIdNHraLuBRm1vrxcMaLk/y/PGBTvHLf4lQGQ3LaEXkORtIxw11sBMpYJL3keOLaFJ1OqNXuURd6eShoFLZQ==" + "version": "4.15.5", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.5.tgz", + "integrity": "sha512-V3eIa28lwB6gg7/wfNvAbjwJYmDXy1Jo1POjyTzlB6wPcHiGlRxq39TSjYGVjQrUSAzpv+a7nzp7mDxgNy57xA==" }, "symbol-tree": { "version": "3.2.4", @@ -16321,9 +16052,9 @@ } }, "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", "dev": true, "requires": { "ajv": "^8.0.1", @@ -16512,9 +16243,9 @@ } }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "type-check": { "version": "0.4.0", @@ -16587,9 +16318,9 @@ } }, "updates": { - "version": "13.1.10", - "resolved": "https://registry.npmjs.org/updates/-/updates-13.1.10.tgz", - "integrity": "sha512-YSt1ncMoBXAQZndhLwiywvEGHXmA4424SlAf2HMUDuf8qE9Tlqj0s6IANb388HrjkybdZJkaadLSg/hkigwnuQ==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/updates/-/updates-13.2.1.tgz", + "integrity": "sha512-d+nIbU2fl/PDEvUkbQch4uRdkXt9AQoPlH6b/FPTOAzF9voGbXgZNNxgO79Jeish24ZMfOqUl5lJcKSwMO2RJQ==", "dev": true }, "uri-js": { @@ -16627,6 +16358,11 @@ "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", "dev": true }, + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -16653,43 +16389,35 @@ } }, "vite": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz", - "integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.4.tgz", + "integrity": "sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==", "dev": true, "requires": { "esbuild": "^0.15.9", "fsevents": "~2.3.2", - "postcss": "^8.4.16", + "postcss": "^8.4.18", "resolve": "^1.22.1", - "rollup": "~2.78.0" - }, - "dependencies": { - "rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - } + "rollup": "^2.79.1" } }, "vitest": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", - "integrity": "sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.25.2.tgz", + "integrity": "sha512-qqkzfzglEFbQY7IGkgSJkdOhoqHjwAao/OrphnHboeYHC5JzsVFoLCaB2lnAy8krhj7sbrFTVRApzpkTOeuDWQ==", "dev": true, "requires": { "@types/chai": "^4.3.3", "@types/chai-subset": "^1.3.3", "@types/node": "*", + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", "chai": "^4.3.6", "debug": "^4.3.4", "local-pkg": "^0.4.2", + "source-map": "^0.6.1", "strip-literal": "^0.4.2", - "tinybench": "^2.3.0", + "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0" @@ -16706,15 +16434,15 @@ } }, "vue": { - "version": "3.2.41", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.41.tgz", - "integrity": "sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==", + "version": "3.2.45", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.45.tgz", + "integrity": "sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==", "requires": { - "@vue/compiler-dom": "3.2.41", - "@vue/compiler-sfc": "3.2.41", - "@vue/runtime-dom": "3.2.41", - "@vue/server-renderer": "3.2.41", - "@vue/shared": "3.2.41" + "@vue/compiler-dom": "3.2.45", + "@vue/compiler-sfc": "3.2.45", + "@vue/runtime-dom": "3.2.45", + "@vue/server-renderer": "3.2.45", + "@vue/shared": "3.2.45" } }, "vue-bar-graph": { @@ -16742,9 +16470,9 @@ } }, "vue-loader": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", - "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.1.tgz", + "integrity": "sha512-/OOyugJnImKCkAKrAvdsWMuwoCqGxWT5USLsjohzWbMgOwpA5wQmzQiLMzZd7DjhIfunzAGIApTOgIylz/kwcg==", "requires": { "chalk": "^4.1.0", "hash-sum": "^2.0.0", @@ -16760,9 +16488,9 @@ } }, "w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", "dev": true, "requires": { "xml-name-validator": "^4.0.0" @@ -16784,9 +16512,9 @@ "dev": true }, "webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.75.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", + "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -16873,28 +16601,29 @@ } }, "webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.0.0.tgz", + "integrity": "sha512-AACDTo20yG+xn6HPW5xjbn2Be4KUzQPebWXsDMHwPPyKh9OnTOJgZN2Nc+g/FZKV3ObRTYsGvibAvc+5jAUrVA==", "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", + "@webpack-cli/configtest": "^2.0.0", + "@webpack-cli/info": "^2.0.0", + "@webpack-cli/serve": "^2.0.0", "colorette": "^2.0.14", - "commander": "^7.0.0", + "commander": "^9.4.1", "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", "webpack-merge": "^5.7.3" }, "dependencies": { "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==" } } }, @@ -17098,9 +16827,9 @@ } }, "ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index d221a1379a5e9..a90c1618fafd9 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,14 @@ "dependencies": { "@citation-js/core": "0.6.1", "@citation-js/plugin-bibtex": "0.6.1", - "@citation-js/plugin-csl": "0.6.3", + "@citation-js/plugin-csl": "0.6.4", "@citation-js/plugin-software-formats": "0.6.0", "@claviska/jquery-minicolors": "2.3.6", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", - "@primer/octicons": "17.7.0", - "@vue/compiler-sfc": "3.2.41", + "@primer/octicons": "17.9.0", + "@vue/compiler-sfc": "3.2.45", "add-asset-webpack-plugin": "2.0.1", - "css-loader": "6.7.1", + "css-loader": "6.7.2", "dropzone": "6.0.0-beta.2", "easymde": "2.18.0", "esbuild-loader": "2.20.0", @@ -29,45 +29,45 @@ "less": "4.1.3", "less-loader": "11.1.0", "license-checker-webpack-plugin": "0.2.1", - "mermaid": "9.1.7", - "mini-css-extract-plugin": "2.6.1", + "mermaid": "9.2.2", + "mini-css-extract-plugin": "2.7.0", "monaco-editor": "0.34.1", "monaco-editor-webpack-plugin": "7.0.1", "pretty-ms": "8.0.0", "sortablejs": "1.15.0", - "swagger-ui-dist": "4.15.0", + "swagger-ui-dist": "4.15.5", "tippy.js": "6.3.7", "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", - "vue": "3.2.41", + "vue": "3.2.45", "vue-bar-graph": "2.0.0", - "vue-loader": "17.0.0", + "vue-loader": "17.0.1", "vue3-calendar-heatmap": "2.0.0", - "webpack": "5.74.0", - "webpack-cli": "4.10.0", + "webpack": "5.75.0", + "webpack-cli": "5.0.0", "workbox-routing": "6.5.4", "workbox-strategies": "6.5.4", "worker-loader": "3.0.8", "wrap-ansi": "8.0.1" }, "devDependencies": { - "@playwright/test": "1.27.1", + "@playwright/test": "1.28.0", "@rollup/pluginutils": "5.0.2", - "@stoplight/spectral-cli": "6.5.1", - "eslint": "8.26.0", + "@stoplight/spectral-cli": "6.6.0", + "eslint": "8.28.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jquery": "1.5.1", "eslint-plugin-sonarjs": "0.16.0", - "eslint-plugin-unicorn": "44.0.2", - "eslint-plugin-vue": "9.6.0", - "jsdom": "20.0.1", + "eslint-plugin-unicorn": "45.0.0", + "eslint-plugin-vue": "9.7.0", + "jsdom": "20.0.3", "markdownlint-cli": "0.32.2", "postcss-less": "6.0.0", - "stylelint": "14.14.0", + "stylelint": "14.15.0", "stylelint-config-standard": "29.0.0", - "svgo": "3.0.0", - "updates": "13.1.10", - "vitest": "0.24.3" + "svgo": "3.0.2", + "updates": "13.2.1", + "vitest": "0.25.2" }, "browserslist": [ "defaults", diff --git a/public/img/svg/octicon-arrow-down-left.svg b/public/img/svg/octicon-arrow-down-left.svg new file mode 100644 index 0000000000000..f02bd330c9948 --- /dev/null +++ b/public/img/svg/octicon-arrow-down-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-arrow-down-right.svg b/public/img/svg/octicon-arrow-down-right.svg new file mode 100644 index 0000000000000..dff9d36c1b4a3 --- /dev/null +++ b/public/img/svg/octicon-arrow-down-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-arrow-up-left.svg b/public/img/svg/octicon-arrow-up-left.svg new file mode 100644 index 0000000000000..0f5a452b8a209 --- /dev/null +++ b/public/img/svg/octicon-arrow-up-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-arrow-up-right.svg b/public/img/svg/octicon-arrow-up-right.svg new file mode 100644 index 0000000000000..896c9b60b46b4 --- /dev/null +++ b/public/img/svg/octicon-arrow-up-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-clock-fill.svg b/public/img/svg/octicon-clock-fill.svg new file mode 100644 index 0000000000000..5fcfb477c4294 --- /dev/null +++ b/public/img/svg/octicon-clock-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-issue-tracked-by.svg b/public/img/svg/octicon-issue-tracked-by.svg new file mode 100644 index 0000000000000..d4352a943007c --- /dev/null +++ b/public/img/svg/octicon-issue-tracked-by.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-issue-tracked-in.svg b/public/img/svg/octicon-issue-tracked-in.svg new file mode 100644 index 0000000000000..8910bd7a24a51 --- /dev/null +++ b/public/img/svg/octicon-issue-tracked-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-project-roadmap.svg b/public/img/svg/octicon-project-roadmap.svg new file mode 100644 index 0000000000000..afc3b223bd5db --- /dev/null +++ b/public/img/svg/octicon-project-roadmap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-project-symlink.svg b/public/img/svg/octicon-project-symlink.svg new file mode 100644 index 0000000000000..2c889a090cf16 --- /dev/null +++ b/public/img/svg/octicon-project-symlink.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/octicon-skip-fill.svg b/public/img/svg/octicon-skip-fill.svg new file mode 100644 index 0000000000000..6606a56df9230 --- /dev/null +++ b/public/img/svg/octicon-skip-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web_src/js/features/clipboard.js b/web_src/js/features/clipboard.js index f266d4f64d11e..75b96cb7811c4 100644 --- a/web_src/js/features/clipboard.js +++ b/web_src/js/features/clipboard.js @@ -4,7 +4,7 @@ const {copy_success, copy_error} = window.config.i18n; export async function copyToClipboard(content) { if (content instanceof Blob) { - const item = new window.ClipboardItem({[content.type]: content}); + const item = new ClipboardItem({[content.type]: content}); await navigator.clipboard.write([item]); } else { // text try { diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index e6a7c6dcd1774..d438186c5f5ae 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -463,10 +463,10 @@ export function initRepository() { $('.enable-system-radio').on('change', function () { if (this.value === 'false') { $($(this).data('target')).addClass('disabled'); - if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).removeClass('disabled'); + if ($(this).data('context') !== undefined) $($(this).data('context')).removeClass('disabled'); } else if (this.value === 'true') { $($(this).data('target')).removeClass('disabled'); - if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).addClass('disabled'); + if ($(this).data('context') !== undefined) $($(this).data('context')).addClass('disabled'); } }); const $trackerIssueStyleRadios = $('.js-tracker-issue-style'); diff --git a/web_src/js/features/repo-migrate.js b/web_src/js/features/repo-migrate.js index 5d61eb410e839..d44f540c46b3b 100644 --- a/web_src/js/features/repo-migrate.js +++ b/web_src/js/features/repo-migrate.js @@ -9,7 +9,7 @@ export function initRepoMigrationStatusChecker() { $('#repo_migrating_progress_message').hide(); if (migrating) { const task = migrating.attr('task'); - if (typeof task === 'undefined') { + if (task === undefined) { return; } $.ajax({ diff --git a/web_src/js/features/tribute.js b/web_src/js/features/tribute.js index 5678acdf47e1e..dcee7aa4a3ba3 100644 --- a/web_src/js/features/tribute.js +++ b/web_src/js/features/tribute.js @@ -21,7 +21,7 @@ function makeCollections({mentions, emoji}) { }, lookup: (item) => item, selectTemplate: (item) => { - if (typeof item === 'undefined') return null; + if (item === undefined) return null; return emojiString(item.original); }, menuItemTemplate: (item) => { diff --git a/webpack.config.js b/webpack.config.js index a8363051dfa2a..cdd8071d27159 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -227,10 +227,11 @@ export default { }).join('\n'); }, override: { - 'jquery.are-you-sure@*': {licenseName: 'MIT'}, + 'jquery.are-you-sure@*': {licenseName: 'MIT'}, // https://github.com/codedance/jquery.AreYouSure/pull/147 + 'khroma@*': {licenseName: 'MIT'}, // https://github.com/fabiospampinato/khroma/pull/33 }, emitError: true, - allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0)', + allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense)', ignore: [ 'font-awesome', ], From 05b73aae29e860f92d0efb13da8245496d79f831 Mon Sep 17 00:00:00 2001 From: mpeter50 <83356418+mpeter50@users.noreply.github.com> Date: Tue, 22 Nov 2022 01:04:29 +0000 Subject: [PATCH 45/49] Clarify logging documentation (#21665) My pull request changes the logging documentation that is visible here: https://docs.gitea.io/en-us/logging-configuration/ The reason behind the changes is that for some time I've found the logging documentation confusing, and wanted to give a try at making it more clear. --- If you find the existing changes to be ok, please don't merge yet, as I have further ideas which I want to discuss with you before making the changes. ### Swap the "Log Groups" and "Log outputs" sections. I want to move the "Log outputs" section before the "Log Groups" section. The reason is that the "Log Groups" section refers to ini sections that are only later explained, and to concepts that are general and should be documented in "Log outputs" or a different section. This change is essentially a swap of the "Log Groups" and "Log outputs" sections. That way the doumentation would follow the structure in which the ini file is built: first explaining the outer sections, and then the inner ones ([log], [log.name], [log.name.default], ...) ### Explain the workings of ambigous settings below the settings listing Right now the basics of a setting is shown later than the explanation of its special workings, for example with `FILE_NAME` at [the file output mode](https://docs.gitea.io/en-us/logging-configuration/#file-mode) (well, if the first changes are taken into account). Currently I have `TODO` witten at 2 settings, which I have to figure out how do they exactly work before I can document them. ### New section about [log] New section after "Collecting Logs for Help" about how the top level [log] itself works and what can go there. Currently, variables that directly go into [log] are noted throughout the whole document. --- Please let me know what you think about the changes. A counterargument that I myself see is that some of this is already present in the cheatsheet, but I think it would be better to have [this document](https://docs.gitea.io/en-us/logging-configuration/) as a throrough explanation of how logging is configured, and the cheatsheet would only have a short outline of the possible sections and variables. Co-authored-by: Lunny Xiao --- .../advanced/logging-documentation.en-us.md | 268 +++++++++++------- 1 file changed, 168 insertions(+), 100 deletions(-) diff --git a/docs/content/doc/advanced/logging-documentation.en-us.md b/docs/content/doc/advanced/logging-documentation.en-us.md index 4e8cbb32825d0..145c8c320c78d 100644 --- a/docs/content/doc/advanced/logging-documentation.en-us.md +++ b/docs/content/doc/advanced/logging-documentation.en-us.md @@ -15,6 +15,14 @@ menu: # Logging Configuration +The logging configuration of Gitea mainly consists of 3 types of components: + +- The `[log]` section for general configuration +- `[log.]` sections for the configuration of different log outputs +- `[log..]` sections for output specific configuration of a log group + +As mentioned below, there is a fully functional log output by default, so it is not necessary to define one. + **Table of Contents** {{< toc >}} @@ -23,6 +31,166 @@ menu: To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}}). +## The `[log]` section + +Configuration of logging facilities in Gitea happen in the `[log]` section and it's subsections. + +In the top level `[log]` section the following configurations can be placed: + +- `ROOT_PATH`: (Default: **%(GITEA_WORK_DIR)/log**): Base path for log files +- `MODE`: (Default: **console**) List of log outputs to use for the Default logger. +- `ROUTER`: (Default: **console**): List of log outputs to use for the Router logger. +- `ACCESS`: List of log outputs to use for the Access logger. +- `XORM`: (Default: **,**) List of log outputs to use for the XORM logger. +- `ENABLE_ACCESS_LOG`: (Default: **false**): whether the Access logger is allowed to emit logs +- `ENABLE_XORM_LOG`: (Default: **true**): whether the XORM logger is allowed to emit logs + +For details on the loggers check the "Log Groups" section. +Important: log outputs won't be used if you don't enable them for the desired loggers in the corresponding list value. + +Lists are specified as comma separated values. This format also works in subsection. + +This section may be used for defining default values for subsections. +Examples: + +- `LEVEL`: (Default: **Info**) Least severe log events to persist. Case insensitive. The full list of levels as of v1.17.3 can be read [here](https://github.com/go-gitea/gitea/blob/v1.17.3/custom/conf/app.example.ini#L507). +- `STACKTRACE_LEVEL`: (Default: **None**) For this and more severe events the stacktrace will be printed upon getting logged. + +Some values are not inherited by subsections. For details see the "Non-inherited default values" section. + +## Log outputs + +Log outputs are the targets to which log messages will be sent. +The content and the format of the log messages to be saved can be configured in these. + +Log outputs are also called subloggers. + +Gitea provides 4 possible log outputs: + +- `console` - Log to `os.Stdout` or `os.Stderr` +- `file` - Log to a file +- `conn` - Log to a socket (network or unix) +- `smtp` - Log via email + +By default, Gitea has a `console` output configured, which is used by the loggers as seen in the section "The log section" above. + +### Common configuration + +Certain configuration is common to all modes of log output: + +- `MODE` is the mode of the log output. It will default to the sublogger + name, thus `[log.console.router]` will default to `MODE = console`. + For mode specific confgurations read further. +- `LEVEL` is the lowest level that this output will log. This value + is inherited from `[log]` and in the case of the non-default loggers + from `[log.sublogger]`. +- `STACKTRACE_LEVEL` is the lowest level that this output will print + a stacktrace. This value is inherited. +- `COLORIZE` will default to `true` for `console` as + described, otherwise it will default to `false`. + +### Non-inherited default values + +There are several values which are not inherited as described above but +rather default to those specific to type of logger, these are: +`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`. + +#### `EXPRESSION` + +`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match. + +Please note this expression will be run in the sublogger's goroutine +not the logging event subroutine. Therefore it can be complicated. + +#### `FLAGS` + +`FLAGS` represents the preceding logging context information that is +printed before each message. It is a comma-separated string set. The order of values does not matter. + +Possible values are: + +- `none` or `,` - No flags. +- `date` - the date in the local time zone: `2009/01/23`. +- `time` - the time in the local time zone: `01:23:23`. +- `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes + time. +- `longfile` - full file name and line number: `/a/b/c/d.go:23`. +- `shortfile` - final file name element and line number: `d.go:23`. +- `funcname` - function name of the caller: `runtime.Caller()`. +- `shortfuncname` - last part of the function name. Overrides + `funcname`. +- `utc` - if date or time is set, use UTC rather than the local time + zone. +- `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info. +- `level` - Provided level in brackets `[INFO]` +- `medfile` - Last 20 characters of the filename - equivalent to + `shortfile,longfile`. +- `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial` + +### Console mode + +In this mode the logger will forward log messages to the stdout and +stderr streams attached to the Gitea process. + +For loggers in console mode, `COLORIZE` will default to `true` if not +on windows, or the windows terminal can be set into ANSI mode or is a +cygwin or Msys pipe. + +Settings: + +- `STDERR`: **false**: Whether the logger should print to `stderr` instead of `stdout`. + +### File mode + +In this mode the logger will save log messages to a file. + +Settings: + +- `FILE_NAME`: The file to write the log events to. For details see below. +- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file. 28 represents 256Mb. For details see below. +- `LOG_ROTATE` **true**: Whether to rotate the log files. TODO: if false, will it delete instead on daily rotate, or do nothing?. +- `DAILY_ROTATE`: **true**: Whether to rotate logs daily. +- `MAX_DAYS`: **7**: Delete rotated log files after this number of days. +- `COMPRESS`: **true**: Whether to compress old log files by default with gzip. +- `COMPRESSION_LEVEL`: **-1**: Compression level. For details see below. + +The default value of `FILE_NAME` depends on the respective logger facility. +If unset, their own default will be used. +If set it will be relative to the provided `ROOT_PATH` in the master `[log]` section. + +`MAX_SIZE_SHIFT` defines the maximum size of a file by left shifting 1 the given number of times (`1 << x`). +The exact behavior at the time of v1.17.3 can be seen [here](https://github.com/go-gitea/gitea/blob/v1.17.3/modules/setting/log.go#L185). + +The useful values of `COMPRESSION_LEVEL` are from 1 to (and including) 9, where higher numbers mean better compression. +Beware that better compression might come with higher resource usage. +Must be preceded with a `-` sign. + +### Conn mode + +In this mode the logger will send log messages over a network socket. + +Settings: + +- `ADDR`: **:7020**: Sets the address to connect to. +- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp". +- `RECONNECT`: **false**: Try to reconnect when connection is lost. +- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message. + +### SMTP mode + +In this mode the logger will send log messages in email. + +It is not recommended to use this logger to send general logging +messages. However, you could perhaps set this logger to work on `FATAL` messages only. + +Settings: + +- `HOST`: **127.0.0.1:25**: The SMTP host to connect to. +- `USER`: User email address to send from. +- `PASSWD`: Password for the smtp server. +- `RECEIVERS`: Email addresses to send to. +- `SUBJECT`: **Diagnostic message from Gitea**. The content of the email's subject field. + ## Log Groups The fundamental thing to be aware of in Gitea is that there are several @@ -172,106 +340,6 @@ which will not be inherited from the `[log]` or relevant - `EXPRESSION` will default to `""` - `PREFIX` will default to `""` -## Log outputs - -Gitea provides 4 possible log outputs: - -- `console` - Log to `os.Stdout` or `os.Stderr` -- `file` - Log to a file -- `conn` - Log to a keep-alive TCP connection -- `smtp` - Log via email - -Certain configuration is common to all modes of log output: - -- `LEVEL` is the lowest level that this output will log. This value - is inherited from `[log]` and in the case of the non-default loggers - from `[log.sublogger]`. -- `STACKTRACE_LEVEL` is the lowest level that this output will print - a stacktrace. This value is inherited. -- `MODE` is the mode of the log output. It will default to the sublogger - name. Thus `[log.console.router]` will default to `MODE = console`. -- `COLORIZE` will default to `true` for `console` as - described, otherwise it will default to `false`. - -### Non-inherited default values - -There are several values which are not inherited as described above but -rather default to those specific to type of logger, these are: -`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`. - -#### `EXPRESSION` - -`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match. - -Please note this expression will be run in the sublogger's goroutine -not the logging event subroutine. Therefore it can be complicated. - -#### `FLAGS` - -`FLAGS` represents the preceding logging context information that is -printed before each message. It is a comma-separated string set. The order of values does not matter. - -Possible values are: - -- `none` or `,` - No flags. -- `date` - the date in the local time zone: `2009/01/23`. -- `time` - the time in the local time zone: `01:23:23`. -- `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes - time. -- `longfile` - full file name and line number: `/a/b/c/d.go:23`. -- `shortfile` - final file name element and line number: `d.go:23`. -- `funcname` - function name of the caller: `runtime.Caller()`. -- `shortfuncname` - last part of the function name. Overrides - `funcname`. -- `utc` - if date or time is set, use UTC rather than the local time - zone. -- `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info. -- `level` - Provided level in brackets `[INFO]` -- `medfile` - Last 20 characters of the filename - equivalent to - `shortfile,longfile`. -- `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial` - -### Console mode - -For loggers in console mode, `COLORIZE` will default to `true` if not -on windows, or the windows terminal can be set into ANSI mode or is a -cygwin or Msys pipe. - -If `STDERR` is set to `true` the logger will use `os.Stderr` instead of -`os.Stdout`. - -### File mode - -The `FILE_NAME` defaults as described above. If set it will be relative -to the provided `ROOT_PATH` in the master `[log]` section. - -Other values: - -- `LOG_ROTATE`: **true**: Rotate the log files. -- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb. -- `DAILY_ROTATE`: **true**: Rotate logs daily. -- `MAX_DAYS`: **7**: Delete the log file after n days -- `COMPRESS`: **true**: Compress old log files by default with gzip -- `COMPRESSION_LEVEL`: **-1**: Compression level - -### Conn mode - -- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message. -- `RECONNECT`: **false**: Try to reconnect when connection is lost. -- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp". -- `ADDR`: **:7020**: Sets the address to connect to. - -### SMTP mode - -It is not recommended to use this logger to send general logging -messages. However, you could perhaps set this logger to work on `FATAL`. - -- `USER`: User email address to send from. -- `PASSWD`: Password for the smtp server. -- `HOST`: **127.0.0.1:25**: The SMTP host to connect to. -- `RECEIVERS`: Email addresses to send to. -- `SUBJECT`: **Diagnostic message from Gitea** - ## Debugging problems When submitting logs in Gitea issues it is often helpful to submit From 4a5afa178da10a36e0dac0576e78ad0181065383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Leopoldo=20Sologuren=20Guti=C3=A9rrez?= Date: Tue, 22 Nov 2022 05:46:29 -0300 Subject: [PATCH 46/49] Fixes #21895: standardize UTC tz for util tests (#21897) Standardize UTC timezone for `translateMonth` and `translateDay` tests. --- web_src/js/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_src/js/utils.js b/web_src/js/utils.js index 62ee11c2eb789..01c076aebac21 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -78,12 +78,12 @@ function getCurrentLocale() { // given a month (0-11), returns it in the documents language export function translateMonth(month) { - return new Date(Date.UTC(2022, month, 12)).toLocaleString(getCurrentLocale(), {month: 'short'}); + return new Date(Date.UTC(2022, month, 12)).toLocaleString(getCurrentLocale(), {month: 'short', timeZone: 'UTC'}); } // given a weekday (0-6, Sunday to Saturday), returns it in the documents language export function translateDay(day) { - return new Date(Date.UTC(2022, 7, day)).toLocaleString(getCurrentLocale(), {weekday: 'short'}); + return new Date(Date.UTC(2022, 7, day)).toLocaleString(getCurrentLocale(), {weekday: 'short', timeZone: 'UTC'}); } // convert a Blob to a DataURI From e0467a7010b25570d7f5cc4663e95c905725f5bf Mon Sep 17 00:00:00 2001 From: zeripath Date: Tue, 22 Nov 2022 12:58:49 +0000 Subject: [PATCH 47/49] Prepend refs/heads/ to issue template refs (#20461) Fix #20456 At some point during the 1.17 cycle abbreviated refishs to issue branches started breaking. This is likely due serious inconsistencies in our management of refs throughout Gitea - which is a bug needing to be addressed in a different PR. (Likely more than one) We should try to use non-abbreviated `fullref`s as much as possible. That is where a user has inputted a abbreviated `refish` we should add `refs/heads/` if it is `branch` etc. I know people keep writing and merging PRs that remove prefixes from stored content but it is just wrong and it keeps causing problems like this. We should only remove the prefix at the time of presentation as the prefix is the only way of knowing umambiguously and permanently if the `ref` is referring to a `branch`, `tag` or `commit` / `SHA`. We need to make it so that every ref has the appropriate prefix, and probably also need to come up with some definitely unambiguous way of storing `SHA`s if they're used in a `ref` or `refish` field. We must not store a potentially ambiguous `refish` as a `ref`. (Especially when referring a `tag` - there is no reason why users cannot create a `branch` with the same short name as a `tag` and vice versa and any attempt to prevent this will fail. You can even create a `branch` and a `tag` that matches the `SHA` pattern.) To that end in order to fix this bug, when parsing issue templates check the provided `Ref` (here a `refish` because almost all users do not know or understand the subtly), if it does not start with `refs/` add the `BranchPrefix` to it. This allows people to make their templates refer to a `tag` but not to a `SHA` directly. (I don't think that is particularly unreasonable but if people disagree I can make the `refish` be checked to see if it matches the `SHA` pattern.) Next we need to handle the issue links that are already written. The links here are created with `git.RefURL` Here we see there is a bug introduced in #17551 whereby the provided `ref` argument can be double-escaped so we remove the incorrect external escape. (The escape added in #17551 is in the right place - unfortunately I missed that the calling function was doing the wrong thing.) Then within `RefURL()` we check if an unprefixed `ref` (therefore potentially a `refish`) matches the `SHA` pattern before assuming that is actually a `commit` - otherwise is assumed to be a `branch`. This will handle most of the problem cases excepting the very unusual cases where someone has deliberately written a `branch` to look like a `SHA1`. But please if something is called a `ref` or interpreted as a `ref` make it a full-ref before storing or using it. By all means if something is a `branch` assume the prefix is removed but always add it back in if you are using it as a `ref`. Stop storing abbreviated `branch` names and `tag` names - which are `refish` as a `ref`. It will keep on causing problems like this. Fix #20456 Signed-off-by: Andrew Thornton Co-authored-by: Lauris BH Co-authored-by: wxiaoguang Co-authored-by: Lunny Xiao --- modules/context/repo.go | 3 +++ modules/git/utils.go | 3 +++ routers/web/repo/issue.go | 4 ++++ services/issue/issue.go | 3 +-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/context/repo.go b/modules/context/repo.go index c363c36994736..1a83c49e95a26 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -1089,6 +1089,9 @@ func (ctx *Context) IssueTemplatesErrorsFromDefaultBranch() ([]*api.IssueTemplat if it, err := template.UnmarshalFromEntry(entry, dirName); err != nil { invalidFiles[fullName] = err } else { + if !strings.HasPrefix(it.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/ + it.Ref = git.BranchPrefix + it.Ref + } issueTemplates = append(issueTemplates, it) } } diff --git a/modules/git/utils.go b/modules/git/utils.go index d6bf9f4413cd5..a439dabae18ef 100644 --- a/modules/git/utils.go +++ b/modules/git/utils.go @@ -100,6 +100,9 @@ func RefURL(repoURL, ref string) string { return repoURL + "/src/branch/" + refName case strings.HasPrefix(ref, TagPrefix): return repoURL + "/src/tag/" + refName + case !IsValidSHAPattern(ref): + // assume they mean a branch + return repoURL + "/src/branch/" + refName default: return repoURL + "/src/commit/" + refName } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 3cfddffc10c7b..d890d4fb03e16 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -784,6 +784,10 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles } } } + + } + if !strings.HasPrefix(template.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/ + template.Ref = git.BranchPrefix + template.Ref } ctx.Data["HasSelectedLabel"] = len(labelIDs) > 0 ctx.Data["label_ids"] = strings.Join(labelIDs, ",") diff --git a/services/issue/issue.go b/services/issue/issue.go index ba9b17a0c8ab1..9ec43f8264694 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -18,7 +18,6 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/modules/util" ) // NewIssue creates new issue with labels for repository. @@ -201,7 +200,7 @@ func GetRefEndNamesAndURLs(issues []*issues_model.Issue, repoLink string) (map[i for _, issue := range issues { if issue.Ref != "" { issueRefEndNames[issue.ID] = git.RefEndName(issue.Ref) - issueRefURLs[issue.ID] = git.RefURL(repoLink, util.PathEscapeSegments(issue.Ref)) + issueRefURLs[issue.ID] = git.RefURL(repoLink, issue.Ref) } } return issueRefEndNames, issueRefURLs From f3b3149fad3ea50f878069459fd746104d930280 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 21 Nov 2022 10:59:42 +0100 Subject: [PATCH 48/49] Improvements for Content Copy (#21842) It now supports copying Markdown, SVG and Images (not in Firefox currently because of lacking [`ClipboardItem`](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem) support, but can be enabled in `about:config` and works). It will fetch the data if in a rendered view or when it's an image. Followup to https://github.com/go-gitea/gitea/pull/21629. --- web_src/js/utils.js | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/web_src/js/utils.js b/web_src/js/utils.js index 01c076aebac21..d345e6419466d 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -133,3 +133,51 @@ export function convertImage(blob, mime) { } }); } + +// convert a Blob to a DataURI +export function blobToDataURI(blob) { + return new Promise((resolve, reject) => { + try { + const reader = new FileReader(); + reader.addEventListener('load', (e) => { + resolve(e.target.result); + }); + reader.addEventListener('error', () => { + reject(new Error('FileReader failed')); + }); + reader.readAsDataURL(blob); + } catch (err) { + reject(err); + } + }); +} + +// convert image Blob to another mime-type format. +export function convertImage(blob, mime) { + return new Promise(async (resolve, reject) => { + try { + const img = new Image(); + const canvas = document.createElement('canvas'); + img.addEventListener('load', () => { + try { + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + const context = canvas.getContext('2d'); + context.drawImage(img, 0, 0); + canvas.toBlob((blob) => { + if (!(blob instanceof Blob)) return reject(new Error('imageBlobToPng failed')); + resolve(blob); + }, mime); + } catch (err) { + reject(err); + } + }); + img.addEventListener('error', () => { + reject(new Error('imageBlobToPng failed')); + }); + img.src = await blobToDataURI(blob); + } catch (err) { + reject(err); + } + }); +} From 40cdd3ce9107ea4104aaae5092974cafd05ee244 Mon Sep 17 00:00:00 2001 From: fsologureng Date: Tue, 22 Nov 2022 13:40:52 -0300 Subject: [PATCH 49/49] Revert failed merge "Improvements for Content Copy (#21842)" This reverts commit f3b3149fad3ea50f878069459fd746104d930280. --- web_src/js/utils.js | 48 --------------------------------------------- 1 file changed, 48 deletions(-) diff --git a/web_src/js/utils.js b/web_src/js/utils.js index d345e6419466d..01c076aebac21 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -133,51 +133,3 @@ export function convertImage(blob, mime) { } }); } - -// convert a Blob to a DataURI -export function blobToDataURI(blob) { - return new Promise((resolve, reject) => { - try { - const reader = new FileReader(); - reader.addEventListener('load', (e) => { - resolve(e.target.result); - }); - reader.addEventListener('error', () => { - reject(new Error('FileReader failed')); - }); - reader.readAsDataURL(blob); - } catch (err) { - reject(err); - } - }); -} - -// convert image Blob to another mime-type format. -export function convertImage(blob, mime) { - return new Promise(async (resolve, reject) => { - try { - const img = new Image(); - const canvas = document.createElement('canvas'); - img.addEventListener('load', () => { - try { - canvas.width = img.naturalWidth; - canvas.height = img.naturalHeight; - const context = canvas.getContext('2d'); - context.drawImage(img, 0, 0); - canvas.toBlob((blob) => { - if (!(blob instanceof Blob)) return reject(new Error('imageBlobToPng failed')); - resolve(blob); - }, mime); - } catch (err) { - reject(err); - } - }); - img.addEventListener('error', () => { - reject(new Error('imageBlobToPng failed')); - }); - img.src = await blobToDataURI(blob); - } catch (err) { - reject(err); - } - }); -}