{{template "repo/header" .}} -
-
-
- {{template "repo/issue/navbar" .}} -
-
- {{if and .CanWriteProjects (not .Repository.IsArchived)}} - {{.locale.Tr "repo.issues.new"}} - {{.locale.Tr "new_project_column"}} - {{end}} - -
-
-
-
-
-

{{$.Project.Title}}

-
{{$.Project.RenderedContent|Str2html}}
-
- {{if and $.CanWriteProjects (not $.Repository.IsArchived)}} - - {{end}} +
+
+ {{template "repo/issue/navbar" .}} + {{ctx.Locale.Tr "repo.issues.new"}}
-
+ {{template "projects/view" .}}
-
- -
- {{range $board := .Boards}} - -
-
-
-
- {{.NumIssues}} -
- {{.Title}} -
- {{if and $.CanWriteProjects (not $.Repository.IsArchived) (ne .ID 0)}} - - {{end}} -
-
- -
- - {{range (index $.IssuesMap .ID)}} - - -
- {{if eq $.Project.CardType 1}}{{/* Images and Text*/}} -
- {{range (index $.issuesAttachmentMap .ID)}} - {{.Name}} - {{end}} -
- {{end}} -
-
- - {{template "shared/issueicon" .}} - - - {{.Title}} - -
-
- - #{{.Index}} - {{$timeStr := TimeSinceUnix .GetLastEventTimestamp $.locale}} - {{if .OriginalAuthor}} - {{$.locale.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}} - {{else if gt .Poster.ID 0}} - {{$.locale.Tr .GetLastEventLabel $timeStr (.Poster.HomeLink|Escape) (.Poster.GetDisplayName | Escape) | Safe}} - {{else}} - {{$.locale.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}} - {{end}} - -
- {{- if .MilestoneID}} - - {{- end}} - {{- range index $.LinkedPRs .ID}} - - {{- end}} -
- - {{if or .Labels .Assignees}} -
- {{range .Labels}} - {{RenderLabel $.Context .}} - {{end}} -
- {{range .Assignees}} - {{ctx.AvatarUtils.Avatar . 28 "mini gt-mr-3"}} - {{end}} -
-
- {{end}} -
- - - {{end}} -
-
- {{end}} -
- -
-
-{{if .CanWriteProjects}} - -{{end}} - {{template "base/footer" .}} diff --git a/web_src/css/features/projects.css b/web_src/css/features/projects.css index bd48429fa6c2c..f85430a2a80ed 100644 --- a/web_src/css/features/projects.css +++ b/web_src/css/features/projects.css @@ -6,11 +6,7 @@ margin: 0 0.5em; } -.board.sortable .board-card { - cursor: move; -} - -.board-column { +.project-column { background-color: var(--color-project-board-bg) !important; border: 1px solid var(--color-secondary) !important; margin: 0 0.5rem !important; @@ -25,33 +21,34 @@ flex-direction: column; } -.board-column-header { +.project-column-header { display: flex; + align-items: center; justify-content: space-between; } -.board-column-header.dark-label { +.project-column-header.dark-label { color: var(--color-project-board-dark-label) !important; } -.board-column-header.dark-label .board-label { +.project-column-header.dark-label .project-column-title { color: var(--color-project-board-dark-label) !important; } -.board-column-header.light-label { +.project-column-header.light-label { color: var(--color-project-board-light-label) !important; } -.board-column-header.light-label .board-label { +.project-column-header.light-label .project-column-title { color: var(--color-project-board-light-label) !important; } -.board-label { +.project-column-title { background: none !important; line-height: 1.25 !important; } -.board-column > .cards { +.project-column > .cards { flex: 1; display: flex; align-content: baseline; @@ -59,60 +56,37 @@ padding: 0 !important; flex-wrap: nowrap !important; flex-direction: column; + overflow-x: auto; + gap: .25rem; } -.project-board-title { - word-break: break-word; -} - -.board-column > .divider { +.project-column > .divider { margin: 5px 0; } -.board-column:first-child { +.project-column:first-child { margin-left: auto !important; } -.board-column:last-child { +.project-column:last-child { margin-right: auto !important; } -.board-column .ui.cards > .card > .content { - border: none; -} - -.board-card { - margin: 4px 2px !important; - border-radius: 5px !important; - width: calc(100% - 4px) !important; - padding: 0.5rem !important; - min-height: auto !important; -} - -.board-card .meta * { - margin-right: 0 !important; -} - -.board-card .header { - margin-top: 0 !important; - font-size: 16px !important; -} - -.board-card .card-attachment-images { +.card-attachment-images { display: inline-block; white-space: nowrap; overflow: hidden; text-align: center; } -.board-card .card-attachment-images img { +.card-attachment-images img { display: inline-block; max-height: 50px; border-radius: var(--border-radius); margin-right: 2px; } -.board-card .card-attachment-images img:only-child { +.card-attachment-images img:only-child { max-height: 90px; margin: auto; } @@ -139,12 +113,12 @@ top: 10px; } -.edit-project-board .color.picker.column, -.new-board-modal .color.picker.column { +.edit-project-column-modal .color.picker.column, +.new-project-column-modal .color.picker.column { display: flex; } -.edit-project-board .color.picker.column .minicolors, -.new-board-modal .color.picker.column .minicolors { +.edit-project-column-modal .color.picker.column .minicolors, +.new-project-column-modal .color.picker.column .minicolors { flex: 1; } diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css index 8a6c2c6539074..35b5d3c97e52e 100644 --- a/web_src/css/helpers.css +++ b/web_src/css/helpers.css @@ -60,6 +60,7 @@ Gitea's private styles use `g-` prefix. .gt-content-center { align-content: center !important; } .gt-cursor-default { cursor: default !important; } .gt-cursor-pointer { cursor: pointer !important; } +.gt-cursor-grab { cursor: grab !important; } .gt-invisible { visibility: hidden !important; } .gt-items-start { align-items: flex-start !important; } .gt-pointer-events-none { pointer-events: none !important; } diff --git a/web_src/css/index.css b/web_src/css/index.css index 55ea67453b6ea..d399f073d557f 100644 --- a/web_src/css/index.css +++ b/web_src/css/index.css @@ -45,6 +45,7 @@ @import "./repo.css"; @import "./repo/release-tag.css"; +@import "./repo/issue-card.css"; @import "./repo/issue-label.css"; @import "./repo/issue-list.css"; @import "./repo/list-header.css"; diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 2b3f4e1efb3d2..34fa2a0052fc7 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -3302,25 +3302,6 @@ tbody.commit-list { } } -.pinned-issue-card { - border-radius: var(--border-radius); - padding: 8px 10px; - border: 1px solid var(--color-secondary); - background: var(--color-card); -} - -.pinned-issue-icon, -.pinned-issue-unpin { - margin-top: 1px; - flex-shrink: 0; -} - -.pinned-issue-title { - flex: 1; - font-size: 18px; - margin-left: 4px; -} - #cherry-pick-modal .scrolling.menu { max-height: 200px; } diff --git a/web_src/css/repo/issue-card.css b/web_src/css/repo/issue-card.css new file mode 100644 index 0000000000000..31d3a2375b99f --- /dev/null +++ b/web_src/css/repo/issue-card.css @@ -0,0 +1,21 @@ +.issue-card { + display: flex; + flex-direction: column; + align-items: start; + border-radius: var(--border-radius); + padding: 8px 10px; + border: 1px solid var(--color-secondary); + background: var(--color-card); +} + +.issue-card-icon, +.issue-card-unpin { + margin-top: 1px; + flex-shrink: 0; +} + +.issue-card-title { + flex: 1; + font-size: 18px; + margin-left: 4px; +} diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js index 3dc523e709d99..64343a8d22aba 100644 --- a/web_src/js/features/repo-issue-list.js +++ b/web_src/js/features/repo-issue-list.js @@ -140,7 +140,7 @@ function initRepoIssueListAuthorDropdown() { } function initPinRemoveButton() { - for (const button of document.getElementsByClassName('pinned-issue-unpin')) { + for (const button of document.getElementsByClassName('issue-card-unpin')) { button.addEventListener('click', async (event) => { const el = event.currentTarget; const id = Number(el.getAttribute('data-issue-id')); @@ -157,7 +157,7 @@ function initPinRemoveButton() { // Delete the tooltip el._tippy.destroy(); // Remove the Card - el.closest(`div.pinned-issue-card[data-issue-id="${id}"]`).remove(); + el.closest(`div.issue-card[data-issue-id="${id}"]`).remove(); } }); } diff --git a/web_src/js/features/repo-projects.js b/web_src/js/features/repo-projects.js index 1b8807d243c71..f12d4f234f8cd 100644 --- a/web_src/js/features/repo-projects.js +++ b/web_src/js/features/repo-projects.js @@ -7,27 +7,27 @@ const {csrfToken} = window.config; function updateIssueCount(cards) { const parent = cards.parentElement; - const cnt = parent.getElementsByClassName('board-card').length; - parent.getElementsByClassName('board-card-cnt')[0].textContent = cnt; + const cnt = parent.getElementsByClassName('issue-card').length; + parent.getElementsByClassName('project-column-issue-count')[0].textContent = cnt; } -function createNewBoard(url, boardTitle, projectColorInput) { +function createNewColumn(url, columnTitle, projectColorInput) { $.ajax({ url, - data: JSON.stringify({title: boardTitle.val(), color: projectColorInput.val()}), + data: JSON.stringify({title: columnTitle.val(), color: projectColorInput.val()}), headers: { 'X-Csrf-Token': csrfToken, }, contentType: 'application/json', method: 'POST', }).done(() => { - boardTitle.closest('form').removeClass('dirty'); + columnTitle.closest('form').removeClass('dirty'); window.location.reload(); }); } function moveIssue({item, from, to, oldIndex}) { - const columnCards = to.getElementsByClassName('board-card'); + const columnCards = to.getElementsByClassName('issue-card'); updateIssueCount(from); updateIssueCount(to); @@ -56,19 +56,19 @@ async function initRepoProjectSortable() { const els = document.querySelectorAll('#project-board > .board.sortable'); if (!els.length) return; - // the HTML layout is: #project-board > .board > .board-column .board.cards > .board-card.card .content + // the HTML layout is: #project-board > .board > .project-column .cards > .issue-card const mainBoard = els[0]; - let boardColumns = mainBoard.getElementsByClassName('board-column'); + let boardColumns = mainBoard.getElementsByClassName('project-column'); createSortable(mainBoard, { - group: 'board-column', - draggable: '.board-column', + group: 'project-column', + draggable: '.project-column', filter: '[data-id="0"]', animation: 150, ghostClass: 'card-ghost', delayOnTouchOnly: true, delay: 500, onSort: () => { - boardColumns = mainBoard.getElementsByClassName('board-column'); + boardColumns = mainBoard.getElementsByClassName('project-column'); for (let i = 0; i < boardColumns.length; i++) { const column = boardColumns[i]; if (parseInt($(column).data('sorting')) !== i) { @@ -87,7 +87,7 @@ async function initRepoProjectSortable() { }); for (const boardColumn of boardColumns) { - const boardCardList = boardColumn.getElementsByClassName('board')[0]; + const boardCardList = boardColumn.getElementsByClassName('cards')[0]; createSortable(boardCardList, { group: 'shared', animation: 150, @@ -107,18 +107,18 @@ export function initRepoProject() { const _promise = initRepoProjectSortable(); - $('.edit-project-board').each(function () { - const projectHeader = $(this).closest('.board-column-header'); - const projectTitleLabel = projectHeader.find('.board-label'); - const projectTitleInput = $(this).find('.project-board-title'); - const projectColorInput = $(this).find('#new_board_color'); - const boardColumn = $(this).closest('.board-column'); + $('.edit-project-column-modal').each(function () { + const projectHeader = $(this).closest('.project-column-header'); + const projectTitleLabel = projectHeader.find('.project-column-title'); + const projectTitleInput = $(this).find('.project-column-title-input'); + const projectColorInput = $(this).find('#new_project_column_color'); + const boardColumn = $(this).closest('.project-column'); if (boardColumn.css('backgroundColor')) { setLabelColor(projectHeader, rgbToHex(boardColumn.css('backgroundColor'))); } - $(this).find('.edit-column-button').on('click', function (e) { + $(this).find('.edit-project-column-button').on('click', function (e) { e.preventDefault(); $.ajax({ @@ -141,9 +141,9 @@ export function initRepoProject() { }); }); - $('.default-project-board-modal').each(function () { - const boardColumn = $(this).closest('.board-column'); - const showButton = $(boardColumn).find('.default-project-board-show'); + $('.default-project-column-modal').each(function () { + const boardColumn = $(this).closest('.project-column'); + const showButton = $(boardColumn).find('.default-project-column-show'); const commitButton = $(this).find('.actions > .ok.button'); $(commitButton).on('click', (e) => { @@ -162,7 +162,7 @@ export function initRepoProject() { }); }); - $('.show-delete-column-modal').each(function () { + $('.show-delete-project-column-modal').each(function () { const deleteColumnModal = $(`${$(this).attr('data-modal')}`); const deleteColumnButton = deleteColumnModal.find('.actions > .ok.button'); const deleteUrl = $(this).attr('data-url'); @@ -183,28 +183,28 @@ export function initRepoProject() { }); }); - $('#new_board_submit').on('click', (e) => { + $('#new_project_column_submit').on('click', (e) => { e.preventDefault(); - const boardTitle = $('#new_board'); - const projectColorInput = $('#new_board_color_picker'); - if (!boardTitle.val()) { + const columnTitle = $('#new_project_column'); + const projectColorInput = $('#new_project_column_color_picker'); + if (!columnTitle.val()) { return; } const url = $(this).data('url'); - createNewBoard(url, boardTitle, projectColorInput); + createNewColumn(url, columnTitle, projectColorInput); }); - $('.new-board').on('input keyup', (e) => { - const boardTitle = $('#new_board'); - const projectColorInput = $('#new_board_color_picker'); - if (!boardTitle.val()) { - $('#new_board_submit').addClass('disabled'); + $('.new-project-column').on('input keyup', (e) => { + const columnTitle = $('#new_project_column'); + const projectColorInput = $('#new_project_column_color_picker'); + if (!columnTitle.val()) { + $('#new_project_column_submit').addClass('disabled'); return; } - $('#new_board_submit').removeClass('disabled'); + $('#new_project_column_submit').removeClass('disabled'); if (e.key === 'Enter') { const url = $(this).data('url'); - createNewBoard(url, boardTitle, projectColorInput); + createNewColumn(url, columnTitle, projectColorInput); } }); } From 2eb456dde21b51be4cfeb185193cdcfd2a66f315 Mon Sep 17 00:00:00 2001 From: John Olheiser Date: Sat, 12 Aug 2023 09:54:50 -0500 Subject: [PATCH 12/24] Add matrix to support (#26382) This PR adds our matrix space to the support options and alphabetizes the list. I also considered adding our Mastodon, however that isn't as suitable as the other options because it's just whoever has access to the account vs a community chat/forum. --------- Signed-off-by: jolheiser Co-authored-by: Giteabot --- docs/content/help/support.en-us.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/content/help/support.en-us.md b/docs/content/help/support.en-us.md index 144072299a1c7..24afe67bb86cf 100644 --- a/docs/content/help/support.en-us.md +++ b/docs/content/help/support.en-us.md @@ -20,6 +20,8 @@ menu: - [Paid Commercial Support](https://about.gitea.com/) - [Discord](https://discord.gg/Gitea) - [Discourse Forum](https://discourse.gitea.io/) +- [Matrix](https://matrix.to/#/#gitea-space:matrix.org) + - NOTE: Most of the Matrix channels are bridged with their counterpart in Discord and may experience some degree of flakiness with the bridge process. **NOTE:** When asking for support, it may be a good idea to have the following available so that the person helping has all the info they need: From bcccf4c0d6149e5e7382226a191abd54848f9416 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sat, 12 Aug 2023 23:28:35 +0800 Subject: [PATCH 13/24] Remove last newline from config file (#26468) When users put the secrets into a file (GITEA__sec__KEY__FILE), the newline sometimes is different to avoid (eg: echo/vim/...) So the last newline could be removed when reading, it makes the users easier to maintain the secret files. Co-authored-by: Giteabot --- modules/setting/config_env.go | 6 ++++++ modules/setting/config_env_test.go | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/modules/setting/config_env.go b/modules/setting/config_env.go index bd479253dc304..b30e44de30a0d 100644 --- a/modules/setting/config_env.go +++ b/modules/setting/config_env.go @@ -4,6 +4,7 @@ package setting import ( + "bytes" "os" "regexp" "strconv" @@ -131,6 +132,11 @@ func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) { log.Error("Error reading file for %s : %v", envKey, envValue, err) continue } + if bytes.HasSuffix(fileContent, []byte("\r\n")) { + fileContent = fileContent[:len(fileContent)-2] + } else if bytes.HasSuffix(fileContent, []byte("\n")) { + fileContent = fileContent[:len(fileContent)-1] + } keyValue = string(fileContent) } diff --git a/modules/setting/config_env_test.go b/modules/setting/config_env_test.go index edd23a24aa056..e14d5ecb414f1 100644 --- a/modules/setting/config_env_test.go +++ b/modules/setting/config_env_test.go @@ -99,4 +99,19 @@ key = old changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile}) assert.True(t, changed) assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String()) + + cfg, _ = NewConfigProviderFromData("") + _ = os.WriteFile(tmpFile, []byte("value-from-file\n"), 0o644) + EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile}) + assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String()) + + cfg, _ = NewConfigProviderFromData("") + _ = os.WriteFile(tmpFile, []byte("value-from-file\r\n"), 0o644) + EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile}) + assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String()) + + cfg, _ = NewConfigProviderFromData("") + _ = os.WriteFile(tmpFile, []byte("value-from-file\n\n"), 0o644) + EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile}) + assert.Equal(t, "value-from-file\n", cfg.Section("sec").Key("key").String()) } From c28e29fd94032aa2804b57512115cd9c5fe76398 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 13 Aug 2023 00:30:16 +0800 Subject: [PATCH 14/24] Refactor tests (#26464) 1. Give the global variable clear names 2. Use generic parameter for `onGiteaRun` --- cmd/web.go | 4 +- tests/e2e/e2e_test.go | 4 +- tests/e2e/utils_e2e_test.go | 2 +- .../api_activitypub_person_test.go | 14 +-- tests/integration/api_nodeinfo_test.go | 4 +- .../integration/api_repo_file_create_test.go | 19 ++- tests/integration/benchmarks_test.go | 4 +- tests/integration/create_no_session_test.go | 4 +- .../git_helper_for_declarative_test.go | 14 +-- tests/integration/gpg_git_test.go | 111 +++++------------- tests/integration/integration_test.go | 10 +- tests/test_utils.go | 2 +- 12 files changed, 65 insertions(+), 127 deletions(-) diff --git a/cmd/web.go b/cmd/web.go index b69769ec433bf..01386251becfa 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -208,8 +208,8 @@ func serveInstalled(ctx *cli.Context) error { } // Set up Chi routes - c := routers.NormalRoutes() - err := listen(c, true) + webRoutes := routers.NormalRoutes() + err := listen(webRoutes, true) <-graceful.GetManager().Done() log.Info("PID: %d Gitea Web Finished", os.Getpid()) log.GetManager().Close() diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index c4b0b621998cc..df4fe95fdb18f 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -28,7 +28,7 @@ import ( "code.gitea.io/gitea/tests" ) -var c *web.Route +var testE2eWebRoutes *web.Route func TestMain(m *testing.M) { defer log.GetManager().Close() @@ -38,7 +38,7 @@ func TestMain(m *testing.M) { defer cancel() tests.InitTest(false) - c = routers.NormalRoutes() + testE2eWebRoutes = routers.NormalRoutes() os.Unsetenv("GIT_AUTHOR_NAME") os.Unsetenv("GIT_AUTHOR_EMAIL") diff --git a/tests/e2e/utils_e2e_test.go b/tests/e2e/utils_e2e_test.go index e6e35c47466e7..efb4a6ba88176 100644 --- a/tests/e2e/utils_e2e_test.go +++ b/tests/e2e/utils_e2e_test.go @@ -22,7 +22,7 @@ func onGiteaRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare ... defer tests.PrepareTestEnv(t, 1)() } s := http.Server{ - Handler: c, + Handler: testE2eWebRoutes, } u, err := url.Parse(setting.AppURL) diff --git a/tests/integration/api_activitypub_person_test.go b/tests/integration/api_activitypub_person_test.go index a1ce802709cac..1a8a38ce56208 100644 --- a/tests/integration/api_activitypub_person_test.go +++ b/tests/integration/api_activitypub_person_test.go @@ -22,10 +22,10 @@ import ( func TestActivityPubPerson(t *testing.T) { setting.Federation.Enabled = true - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() defer func() { setting.Federation.Enabled = false - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() }() onGiteaRun(t, func(*testing.T, *url.URL) { @@ -60,10 +60,10 @@ func TestActivityPubPerson(t *testing.T) { func TestActivityPubMissingPerson(t *testing.T) { setting.Federation.Enabled = true - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() defer func() { setting.Federation.Enabled = false - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() }() onGiteaRun(t, func(*testing.T, *url.URL) { @@ -75,13 +75,13 @@ func TestActivityPubMissingPerson(t *testing.T) { func TestActivityPubPersonInbox(t *testing.T) { setting.Federation.Enabled = true - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() defer func() { setting.Federation.Enabled = false - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() }() - srv := httptest.NewServer(c) + srv := httptest.NewServer(testWebRoutes) defer srv.Close() onGiteaRun(t, func(*testing.T, *url.URL) { diff --git a/tests/integration/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go index f8f50bf073862..a347ec5b3b1f9 100644 --- a/tests/integration/api_nodeinfo_test.go +++ b/tests/integration/api_nodeinfo_test.go @@ -17,10 +17,10 @@ import ( func TestNodeinfo(t *testing.T) { setting.Federation.Enabled = true - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() defer func() { setting.Federation.Enabled = false - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() }() onGiteaRun(t, func(*testing.T, *url.URL) { diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go index 2433a68c312f7..c48abe7f0f19e 100644 --- a/tests/integration/api_repo_file_create_test.go +++ b/tests/integration/api_repo_file_create_test.go @@ -110,14 +110,14 @@ func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCo } func BenchmarkAPICreateFileSmall(b *testing.B) { - onGiteaRunTB(b, func(t testing.TB, u *url.URL) { - b := t.(*testing.B) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 - repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo + onGiteaRun(b, func(b *testing.B, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(b, &user_model.User{ID: 2}) // owner of the repo1 & repo16 + repo1 := unittest.AssertExistsAndLoadBean(b, &repo_model.Repository{ID: 1}) // public repo + b.ResetTimer() for n := 0; n < b.N; n++ { treePath := fmt.Sprintf("update/file%d.txt", n) - createFileInBranch(user2, repo1, treePath, repo1.DefaultBranch, treePath) + _, _ = createFileInBranch(user2, repo1, treePath, repo1.DefaultBranch, treePath) } }) } @@ -125,16 +125,15 @@ func BenchmarkAPICreateFileSmall(b *testing.B) { func BenchmarkAPICreateFileMedium(b *testing.B) { data := make([]byte, 10*1024*1024) - onGiteaRunTB(b, func(t testing.TB, u *url.URL) { - b := t.(*testing.B) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 - repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo + onGiteaRun(b, func(b *testing.B, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(b, &user_model.User{ID: 2}) // owner of the repo1 & repo16 + repo1 := unittest.AssertExistsAndLoadBean(b, &repo_model.Repository{ID: 1}) // public repo b.ResetTimer() for n := 0; n < b.N; n++ { treePath := fmt.Sprintf("update/file%d.txt", n) copy(data, treePath) - createFileInBranch(user2, repo1, treePath, repo1.DefaultBranch, treePath) + _, _ = createFileInBranch(user2, repo1, treePath, repo1.DefaultBranch, treePath) } }) } diff --git a/tests/integration/benchmarks_test.go b/tests/integration/benchmarks_test.go index 2f91f8273ea53..7a882fe836135 100644 --- a/tests/integration/benchmarks_test.go +++ b/tests/integration/benchmarks_test.go @@ -24,9 +24,7 @@ func StringWithCharset(length int, charset string) string { } func BenchmarkRepoBranchCommit(b *testing.B) { - onGiteaRunTB(b, func(t testing.TB, u *url.URL) { - b := t.(*testing.B) - + onGiteaRun(b, func(b *testing.B, u *url.URL) { samples := []int64{1, 2, 3} b.ResetTimer() diff --git a/tests/integration/create_no_session_test.go b/tests/integration/create_no_session_test.go index 535d0d4955a5c..601f5e1733408 100644 --- a/tests/integration/create_no_session_test.go +++ b/tests/integration/create_no_session_test.go @@ -56,7 +56,7 @@ func TestSessionFileCreation(t *testing.T) { oldSessionConfig := setting.SessionConfig.ProviderConfig defer func() { setting.SessionConfig.ProviderConfig = oldSessionConfig - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() }() var config session.Options @@ -75,7 +75,7 @@ func TestSessionFileCreation(t *testing.T) { setting.SessionConfig.ProviderConfig = string(newConfigBytes) - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() t.Run("NoSessionOnViewIssue", func(t *testing.T) { defer tests.PrintCurrentTest(t)() diff --git a/tests/integration/git_helper_for_declarative_test.go b/tests/integration/git_helper_for_declarative_test.go index 1e99783096ee6..10cf79b9fd8b2 100644 --- a/tests/integration/git_helper_for_declarative_test.go +++ b/tests/integration/git_helper_for_declarative_test.go @@ -57,12 +57,10 @@ func createSSHUrl(gitPath string, u *url.URL) *url.URL { return &u2 } -func onGiteaRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare ...bool) { - if len(prepare) == 0 || prepare[0] { - defer tests.PrepareTestEnv(t, 1)() - } +func onGiteaRun[T testing.TB](t T, callback func(T, *url.URL)) { + defer tests.PrepareTestEnv(t, 1)() s := http.Server{ - Handler: c, + Handler: testWebRoutes, } u, err := url.Parse(setting.AppURL) @@ -89,12 +87,6 @@ func onGiteaRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare ... callback(t, u) } -func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL), prepare ...bool) { - onGiteaRunTB(t, func(t testing.TB, u *url.URL) { - callback(t.(*testing.T), u) - }, prepare...) -} - func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) { return func(t *testing.T) { assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{})) diff --git a/tests/integration/gpg_git_test.go b/tests/integration/gpg_git_test.go index 10174b99fe037..6d67bec09b67e 100644 --- a/tests/integration/gpg_git_test.go +++ b/tests/integration/gpg_git_test.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" @@ -24,12 +25,7 @@ import ( ) func TestGPGGit(t *testing.T) { - defer tests.PrepareTestEnv(t)() - username := "user2" - - // OK Set a new GPG home - tmpDir := t.TempDir() - + tmpDir := t.TempDir() // use a temp dir to avoid messing with the user's GPG keyring err := os.Chmod(tmpDir, 0o700) assert.NoError(t, err) @@ -40,31 +36,20 @@ func TestGPGGit(t *testing.T) { // Need to create a root key rootKeyPair, err := importTestingKey(tmpDir, "gitea", "gitea@fake.local") - assert.NoError(t, err) - if err != nil { - assert.FailNow(t, "Unable to import rootKeyPair") + if !assert.NoError(t, err, "importTestingKey") { + return } - rootKeyID := rootKeyPair.PrimaryKey.KeyIdShortString() + defer test.MockVariableValue(&setting.Repository.Signing.SigningKey, rootKeyPair.PrimaryKey.KeyIdShortString())() + defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")() + defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})() + defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})() - oldKeyID := setting.Repository.Signing.SigningKey - oldName := setting.Repository.Signing.SigningName - oldEmail := setting.Repository.Signing.SigningEmail - defer func() { - setting.Repository.Signing.SigningKey = oldKeyID - setting.Repository.Signing.SigningName = oldName - setting.Repository.Signing.SigningEmail = oldEmail - }() - - setting.Repository.Signing.SigningKey = rootKeyID - setting.Repository.Signing.SigningName = "gitea" - setting.Repository.Signing.SigningEmail = "gitea@fake.local" + username := "user2" user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: username}) - - setting.Repository.Signing.InitialCommit = []string{"never"} - setting.Repository.Signing.CRUDActions = []string{"never"} - baseAPITestContext := NewAPITestContext(t, username, "repo1") + onGiteaRun(t, func(t *testing.T, u *url.URL) { u.Path = baseAPITestContext.GitPath() @@ -87,11 +72,8 @@ func TestGPGGit(t *testing.T) { assert.False(t, response.Verification.Verified) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"parentsigned"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.CRUDActions = []string{"parentsigned"} t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -104,11 +86,8 @@ func TestGPGGit(t *testing.T) { assert.False(t, response.Verification.Verified) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"never"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.CRUDActions = []string{"never"} t.Run("Unsigned-Initial-CRUD-Never", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -117,11 +96,8 @@ func TestGPGGit(t *testing.T) { assert.False(t, response.Verification.Verified) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"always"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.CRUDActions = []string{"always"} t.Run("Unsigned-Initial-CRUD-Always", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -154,11 +130,8 @@ func TestGPGGit(t *testing.T) { assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"parentsigned"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.CRUDActions = []string{"parentsigned"} t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -177,11 +150,8 @@ func TestGPGGit(t *testing.T) { assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email) })) }) - }, false) - setting.Repository.Signing.InitialCommit = []string{"always"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.InitialCommit = []string{"always"} t.Run("AlwaysSign-Initial", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-always", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -205,11 +175,8 @@ func TestGPGGit(t *testing.T) { assert.Equal(t, "gitea@fake.local", branch.Commit.Verification.Signer.Email) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"never"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.CRUDActions = []string{"never"} t.Run("AlwaysSign-Initial-CRUD-Never", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-always-never", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -219,10 +186,8 @@ func TestGPGGit(t *testing.T) { assert.False(t, response.Verification.Verified) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"parentsigned"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + + setting.Repository.Signing.CRUDActions = []string{"parentsigned"} t.Run("AlwaysSign-Initial-CRUD-ParentSigned-On-Always", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-always-parent", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -237,11 +202,8 @@ func TestGPGGit(t *testing.T) { assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email) })) }) - }, false) - setting.Repository.Signing.CRUDActions = []string{"always"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.CRUDActions = []string{"always"} t.Run("AlwaysSign-Initial-CRUD-Always", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-always-always", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) @@ -256,21 +218,16 @@ func TestGPGGit(t *testing.T) { assert.Equal(t, "gitea@fake.local", response.Verification.Signer.Email) })) }) - }, false) - var pr api.PullRequest - setting.Repository.Signing.Merges = []string{"commitssigned"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.Merges = []string{"commitssigned"} t.Run("UnsignedMerging", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) - var err error t.Run("CreatePullRequest", func(t *testing.T) { - pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "never2")(t) + pr, err := doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "never2")(t) assert.NoError(t, err) + t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index)) }) - t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index)) t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) { assert.NotNil(t, branch.Commit) assert.NotNil(t, branch.Commit.Verification) @@ -278,20 +235,16 @@ func TestGPGGit(t *testing.T) { assert.Empty(t, branch.Commit.Verification.Signature) })) }) - }, false) - setting.Repository.Signing.Merges = []string{"basesigned"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.Merges = []string{"basesigned"} t.Run("BaseSignedMerging", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) - var err error t.Run("CreatePullRequest", func(t *testing.T) { - pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "parentsigned2")(t) + pr, err := doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "parentsigned2")(t) assert.NoError(t, err) + t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index)) }) - t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index)) t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) { assert.NotNil(t, branch.Commit) assert.NotNil(t, branch.Commit.Verification) @@ -299,27 +252,23 @@ func TestGPGGit(t *testing.T) { assert.Empty(t, branch.Commit.Verification.Signature) })) }) - }, false) - setting.Repository.Signing.Merges = []string{"commitssigned"} - onGiteaRun(t, func(t *testing.T, u *url.URL) { - u.Path = baseAPITestContext.GitPath() + setting.Repository.Signing.Merges = []string{"commitssigned"} t.Run("CommitsSignedMerging", func(t *testing.T) { defer tests.PrintCurrentTest(t)() testCtx := NewAPITestContext(t, username, "initial-unsigned", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) - var err error t.Run("CreatePullRequest", func(t *testing.T) { - pr, err = doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "always-parentsigned")(t) + pr, err := doAPICreatePullRequest(testCtx, testCtx.Username, testCtx.Reponame, "master", "always-parentsigned")(t) assert.NoError(t, err) + t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index)) }) - t.Run("MergePR", doAPIMergePullRequest(testCtx, testCtx.Username, testCtx.Reponame, pr.Index)) t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) { assert.NotNil(t, branch.Commit) assert.NotNil(t, branch.Commit.Verification) assert.True(t, branch.Commit.Verification.Verified) })) }) - }, false) + }) } func crudActionCreateFile(t *testing.T, ctx APITestContext, user *user_model.User, from, to, path string, callback ...func(*testing.T, api.FileResponse)) func(*testing.T) { diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index c904d32ffa08e..76a65e3f03727 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -40,7 +40,7 @@ import ( "github.com/xeipuuv/gojsonschema" ) -var c *web.Route +var testWebRoutes *web.Route type NilResponseRecorder struct { httptest.ResponseRecorder @@ -87,7 +87,7 @@ func TestMain(m *testing.M) { defer cancel() tests.InitTest(true) - c = routers.NormalRoutes() + testWebRoutes = routers.NormalRoutes() // integration test settings... if setting.CfgProvider != nil { @@ -374,7 +374,7 @@ func MakeRequest(t testing.TB, req *http.Request, expectedStatus int) *httptest. if req.RemoteAddr == "" { req.RemoteAddr = "test-mock:12345" } - c.ServeHTTP(recorder, req) + testWebRoutes.ServeHTTP(recorder, req) if expectedStatus != NoExpectedStatus { if !assert.EqualValues(t, expectedStatus, recorder.Code, "Request: %s %s", req.Method, req.URL.String()) { logUnexpectedResponse(t, recorder) @@ -386,7 +386,7 @@ func MakeRequest(t testing.TB, req *http.Request, expectedStatus int) *httptest. func MakeRequestNilResponseRecorder(t testing.TB, req *http.Request, expectedStatus int) *NilResponseRecorder { t.Helper() recorder := NewNilResponseRecorder() - c.ServeHTTP(recorder, req) + testWebRoutes.ServeHTTP(recorder, req) if expectedStatus != NoExpectedStatus { if !assert.EqualValues(t, expectedStatus, recorder.Code, "Request: %s %s", req.Method, req.URL.String()) { @@ -399,7 +399,7 @@ func MakeRequestNilResponseRecorder(t testing.TB, req *http.Request, expectedSta func MakeRequestNilResponseHashSumRecorder(t testing.TB, req *http.Request, expectedStatus int) *NilResponseHashSumRecorder { t.Helper() recorder := NewNilResponseHashSumRecorder() - c.ServeHTTP(recorder, req) + testWebRoutes.ServeHTTP(recorder, req) if expectedStatus != NoExpectedStatus { if !assert.EqualValues(t, expectedStatus, recorder.Code, "Request: %s %s", req.Method, req.URL.String()) { diff --git a/tests/test_utils.go b/tests/test_utils.go index 6ac61db63e054..089b4dce1cc1d 100644 --- a/tests/test_utils.go +++ b/tests/test_utils.go @@ -181,7 +181,7 @@ func InitTest(requireGitea bool) { func PrepareTestEnv(t testing.TB, skip ...int) func() { t.Helper() - ourSkip := 2 + ourSkip := 1 if len(skip) > 0 { ourSkip += skip[0] } From 7018659a1d7ef2ec1303ae26a8925fff92898327 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 13 Aug 2023 10:11:20 +0800 Subject: [PATCH 15/24] Close stdout correctly for "git blame" (#26470) Close stdout correctly for "git blame", otherwise the failed "git blame" would case the request hanging forever. And "os.Stderr" should never (seldom) be used as git command's stderr --- modules/git/blame.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/git/blame.go b/modules/git/blame.go index ec88accb106c8..4bd13dc32d27e 100644 --- a/modules/git/blame.go +++ b/modules/git/blame.go @@ -5,11 +5,14 @@ package git import ( "bufio" + "bytes" "context" "fmt" "io" "os" "regexp" + + "code.gitea.io/gitea/modules/log" ) // BlamePart represents block of blame - continuous lines with one sha @@ -115,15 +118,19 @@ func CreateBlameReader(ctx context.Context, repoPath, commitID, file string) (*B done := make(chan error, 1) go func(cmd *Command, dir string, stdout io.WriteCloser, done chan error) { - if err := cmd.Run(&RunOpts{ + stderr := bytes.Buffer{} + // TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close" + err := cmd.Run(&RunOpts{ UseContextTimeout: true, Dir: dir, Stdout: stdout, - Stderr: os.Stderr, - }); err == nil { - stdout.Close() - } + Stderr: &stderr, + }) done <- err + _ = stdout.Close() + if err != nil { + log.Error("Error running git blame (dir: %v): %v, stderr: %v", repoPath, err, stderr.String()) + } }(cmd, repoPath, stdout, done) bufferedReader := bufio.NewReader(reader) From ca74b074ea84dea1c37f7bd04b299de602e57e8c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 13 Aug 2023 17:04:42 +0800 Subject: [PATCH 16/24] Use correct pull request commit link instead of a generic commit link (#26434) Replace #26197 Since #25528 merged, the links of pull request commits should be redirect to pull file changes UI but not the generic one. --------- Co-authored-by: Giteabot --- templates/repo/commits_list.tmpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl index 9f1d182158dcd..b9b42ebb235da 100644 --- a/templates/repo/commits_list.tmpl +++ b/templates/repo/commits_list.tmpl @@ -43,6 +43,8 @@ {{end}} {{if $.PageIsWiki}} + {{else if $.PageIsPullCommits}} + {{else if $.Reponame}} {{else}} @@ -54,6 +56,8 @@ {{end}} {{if $.PageIsWiki}} + {{else if $.PageIsPullCommits}} + {{else if $.Reponame}} {{else}} From 82ea557dd37312af02b991069e2debb71721882b Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 13 Aug 2023 20:49:30 +0800 Subject: [PATCH 17/24] Fix stderr usages (#26477) --- cmd/admin_user_create.go | 3 +-- models/migrations/migrations.go | 4 +--- services/gitdiff/gitdiff.go | 6 +++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cmd/admin_user_create.go b/cmd/admin_user_create.go index 260d729544e45..52ce46c353bf1 100644 --- a/cmd/admin_user_create.go +++ b/cmd/admin_user_create.go @@ -6,7 +6,6 @@ package cmd import ( "errors" "fmt" - "os" auth_model "code.gitea.io/gitea/models/auth" user_model "code.gitea.io/gitea/models/user" @@ -87,7 +86,7 @@ func runCreateUser(c *cli.Context) error { username = c.String("username") } else { username = c.String("name") - fmt.Fprintf(os.Stderr, "--name flag is deprecated. Use --username instead.\n") + _, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n") } ctx, cancel := installSignals() diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index b2140a1eb1327..55107439b0484 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -7,7 +7,6 @@ package migrations import ( "context" "fmt" - "os" "code.gitea.io/gitea/models/migrations/v1_10" "code.gitea.io/gitea/models/migrations/v1_11" @@ -608,8 +607,7 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t if !setting.IsProd { msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", minDBVersion+len(migrations)) } - _, _ = fmt.Fprintln(os.Stderr, msg) - log.Fatal(msg) + log.Fatal("Migration Error: %s", msg) return nil } diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 4cb2b1303df4b..4cc093e65debd 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -13,7 +13,6 @@ import ( "html/template" "io" "net/url" - "os" "sort" "strings" "time" @@ -1152,14 +1151,15 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff }() go func() { + stderr := &bytes.Buffer{} cmdDiff.SetDescription(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath)) if err := cmdDiff.Run(&git.RunOpts{ Timeout: time.Duration(setting.Git.Timeout.Default) * time.Second, Dir: repoPath, - Stderr: os.Stderr, Stdout: writer, + Stderr: stderr, }); err != nil { - log.Error("error during RunWithContext: %w", err) + log.Error("error during GetDiff(git diff dir: %s): %v, stderr: %s", repoPath, err, stderr.String()) } _ = writer.Close() From 50fc22eecfd9d96f4b15d75e1b9f85d83715db87 Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Sun, 13 Aug 2023 16:00:06 +0200 Subject: [PATCH 18/24] Add ThreadID parameter for Telegram webhooks (#25996) Telegram has recently implemented threads (channels) for group chats. Co-authored-by: neveraskedtoexist --- options/locale/locale_en-US.ini | 1 + routers/web/repo/setting/webhook.go | 3 ++- services/forms/repo_form.go | 1 + services/webhook/telegram.go | 1 + templates/repo/settings/webhook/telegram.tmpl | 4 ++++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 2023dade3fa46..30fa899c9d85b 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2314,6 +2314,7 @@ settings.tags.protection.none = There are no protected tags. settings.tags.protection.pattern.description = You can use a single name or a glob pattern or regular expression to match multiple tags. Read more in the protected tags guide. settings.bot_token = Bot Token settings.chat_id = Chat ID +settings.thread_id = Thread ID settings.matrix.homeserver_url = Homeserver URL settings.matrix.room_id = Room ID settings.matrix.message_type = Message Type diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index 5c4e1d47d09ad..bbcc36ee60a51 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -425,12 +425,13 @@ func telegramHookParams(ctx *context.Context) webhookParams { return webhookParams{ Type: webhook_module.TELEGRAM, - URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", url.PathEscape(form.BotToken), url.QueryEscape(form.ChatID)), + URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s&message_thread_id=%s", url.PathEscape(form.BotToken), url.QueryEscape(form.ChatID), url.QueryEscape(form.ThreadID)), ContentType: webhook.ContentTypeJSON, WebhookForm: form.WebhookForm, Meta: &webhook_service.TelegramMeta{ BotToken: form.BotToken, ChatID: form.ChatID, + ThreadID: form.ThreadID, }, } } diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index a26a2d89c5d65..8c763e17cbb5d 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -353,6 +353,7 @@ func (f *NewDingtalkHookForm) Validate(req *http.Request, errs binding.Errors) b type NewTelegramHookForm struct { BotToken string `binding:"Required"` ChatID string `binding:"Required"` + ThreadID string WebhookForm } diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go index 2d0484648bb8e..ea7e8185defdd 100644 --- a/services/webhook/telegram.go +++ b/services/webhook/telegram.go @@ -28,6 +28,7 @@ type ( TelegramMeta struct { BotToken string `json:"bot_token"` ChatID string `json:"chat_id"` + ThreadID string `json:"thread_id"` } ) diff --git a/templates/repo/settings/webhook/telegram.tmpl b/templates/repo/settings/webhook/telegram.tmpl index 4313980bf17bd..f618fea140038 100644 --- a/templates/repo/settings/webhook/telegram.tmpl +++ b/templates/repo/settings/webhook/telegram.tmpl @@ -10,6 +10,10 @@
+
+ + +
{{template "repo/settings/webhook/settings" .}} {{end}} From e10ba5e5e0b5de2cedff2f180cc17245158aee25 Mon Sep 17 00:00:00 2001 From: delvh Date: Sun, 13 Aug 2023 21:17:21 +0200 Subject: [PATCH 19/24] Rename `Sync2` -> `Sync` (#26479) The xorm `Sync2` has already been deprecated in favor of `Sync`, so let's do the same inside the Gitea codebase. Command used to replace everything: ```sh for i in $(ag Sync2 --files-with-matches); do vim $i -c ':%sno/Sync2/Sync/g' -c ':wq'; done ``` --- docs/content/administration/command-line.en-us.md | 2 +- docs/content/administration/command-line.zh-cn.md | 2 +- docs/content/help/faq.en-us.md | 2 +- docs/content/help/faq.zh-cn.md | 2 +- models/db/engine.go | 4 ++-- models/db/engine_test.go | 2 +- models/issues/content_history_test.go | 2 +- models/migrations/base/db_test.go | 4 ++-- models/migrations/base/tests.go | 2 +- models/migrations/v1_10/v100.go | 4 ++-- models/migrations/v1_10/v101.go | 2 +- models/migrations/v1_10/v88.go | 2 +- models/migrations/v1_10/v89.go | 6 +++--- models/migrations/v1_10/v90.go | 2 +- models/migrations/v1_10/v91.go | 4 ++-- models/migrations/v1_10/v93.go | 2 +- models/migrations/v1_10/v94.go | 2 +- models/migrations/v1_10/v95.go | 2 +- models/migrations/v1_10/v97.go | 2 +- models/migrations/v1_10/v98.go | 2 +- models/migrations/v1_10/v99.go | 2 +- models/migrations/v1_11/v103.go | 2 +- models/migrations/v1_11/v104.go | 2 +- models/migrations/v1_11/v105.go | 2 +- models/migrations/v1_11/v106.go | 2 +- models/migrations/v1_11/v107.go | 2 +- models/migrations/v1_11/v108.go | 2 +- models/migrations/v1_11/v109.go | 2 +- models/migrations/v1_11/v111.go | 4 ++-- models/migrations/v1_11/v113.go | 4 ++-- models/migrations/v1_11/v116.go | 2 +- models/migrations/v1_12/v117.go | 2 +- models/migrations/v1_12/v118.go | 4 ++-- models/migrations/v1_12/v120.go | 2 +- models/migrations/v1_12/v121.go | 2 +- models/migrations/v1_12/v122.go | 2 +- models/migrations/v1_12/v123.go | 2 +- models/migrations/v1_12/v124.go | 2 +- models/migrations/v1_12/v125.go | 4 ++-- models/migrations/v1_12/v127.go | 8 ++++---- models/migrations/v1_12/v131.go | 4 ++-- models/migrations/v1_12/v132.go | 4 ++-- models/migrations/v1_12/v133.go | 2 +- models/migrations/v1_12/v135.go | 4 ++-- models/migrations/v1_12/v136.go | 4 ++-- models/migrations/v1_12/v137.go | 2 +- models/migrations/v1_12/v138.go | 4 ++-- models/migrations/v1_13/v140.go | 4 ++-- models/migrations/v1_13/v141.go | 4 ++-- models/migrations/v1_13/v145.go | 2 +- models/migrations/v1_13/v146.go | 10 +++++----- models/migrations/v1_13/v147.go | 2 +- models/migrations/v1_13/v149.go | 4 ++-- models/migrations/v1_13/v151.go | 4 ++-- models/migrations/v1_13/v152.go | 2 +- models/migrations/v1_13/v153.go | 4 ++-- models/migrations/v1_13/v154.go | 10 +++++----- models/migrations/v1_14/v155.go | 4 ++-- models/migrations/v1_14/v158.go | 2 +- models/migrations/v1_14/v160.go | 2 +- models/migrations/v1_14/v161.go | 2 +- models/migrations/v1_14/v162.go | 2 +- models/migrations/v1_14/v163.go | 2 +- models/migrations/v1_14/v164.go | 4 ++-- models/migrations/v1_14/v167.go | 4 ++-- models/migrations/v1_14/v170.go | 4 ++-- models/migrations/v1_14/v171.go | 4 ++-- models/migrations/v1_14/v172.go | 2 +- models/migrations/v1_14/v173.go | 4 ++-- models/migrations/v1_14/v174.go | 4 ++-- models/migrations/v1_14/v176.go | 2 +- models/migrations/v1_14/v177.go | 4 ++-- models/migrations/v1_15/v178.go | 2 +- models/migrations/v1_15/v181.go | 4 ++-- models/migrations/v1_15/v182.go | 2 +- models/migrations/v1_15/v183.go | 4 ++-- models/migrations/v1_15/v184.go | 4 ++-- models/migrations/v1_15/v185.go | 2 +- models/migrations/v1_15/v186.go | 2 +- models/migrations/v1_15/v187.go | 4 ++-- models/migrations/v1_16/v189.go | 2 +- models/migrations/v1_16/v190.go | 2 +- models/migrations/v1_16/v193.go | 2 +- models/migrations/v1_16/v194.go | 4 ++-- models/migrations/v1_16/v195.go | 4 ++-- models/migrations/v1_16/v196.go | 4 ++-- models/migrations/v1_16/v197.go | 2 +- models/migrations/v1_16/v198.go | 4 ++-- models/migrations/v1_16/v200.go | 4 ++-- models/migrations/v1_16/v202.go | 2 +- models/migrations/v1_16/v203.go | 2 +- models/migrations/v1_16/v204.go | 2 +- models/migrations/v1_16/v206.go | 2 +- models/migrations/v1_16/v210.go | 2 +- models/migrations/v1_17/v212.go | 12 ++++++------ models/migrations/v1_17/v213.go | 2 +- models/migrations/v1_17/v214.go | 2 +- models/migrations/v1_17/v215.go | 2 +- models/migrations/v1_17/v218.go | 2 +- models/migrations/v1_17/v219.go | 2 +- models/migrations/v1_17/v221.go | 2 +- models/migrations/v1_17/v222.go | 2 +- models/migrations/v1_17/v223.go | 6 +++--- models/migrations/v1_18/v224.go | 4 ++-- models/migrations/v1_18/v227.go | 2 +- models/migrations/v1_18/v228.go | 2 +- models/migrations/v1_19/v234.go | 2 +- models/migrations/v1_20/v245.go | 2 +- models/migrations/v1_21/v263.go | 4 ++-- models/migrations/v1_6/v71.go | 4 ++-- models/migrations/v1_6/v72.go | 4 ++-- models/migrations/v1_7/v73.go | 2 +- models/migrations/v1_7/v74.go | 2 +- models/migrations/v1_8/v77.go | 2 +- models/migrations/v1_8/v78.go | 2 +- models/migrations/v1_8/v79.go | 2 +- models/migrations/v1_8/v80.go | 2 +- models/migrations/v1_9/v83.go | 2 +- models/migrations/v1_9/v84.go | 2 +- models/migrations/v1_9/v85.go | 8 ++++---- models/migrations/v1_9/v86.go | 2 +- models/migrations/v1_9/v87.go | 2 +- 122 files changed, 184 insertions(+), 184 deletions(-) diff --git a/docs/content/administration/command-line.en-us.md b/docs/content/administration/command-line.en-us.md index 400d9dd877af7..91c6c1e626271 100644 --- a/docs/content/administration/command-line.en-us.md +++ b/docs/content/administration/command-line.en-us.md @@ -403,7 +403,7 @@ Sometimes when there are migrations the old columns and default values may be le unchanged in the database schema. This may lead to warning such as: ``` -2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync2() [W] Table user Column keep_activity_private db default is , struct default is 0 +2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync() [W] Table user Column keep_activity_private db default is , struct default is 0 ``` You can cause Gitea to recreate these tables and copy the old data into the new table diff --git a/docs/content/administration/command-line.zh-cn.md b/docs/content/administration/command-line.zh-cn.md index 4b8176322dd19..bd3d0c72bcf89 100644 --- a/docs/content/administration/command-line.zh-cn.md +++ b/docs/content/administration/command-line.zh-cn.md @@ -375,7 +375,7 @@ AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k 有时,在迁移时,旧的列和默认值可能会在数据库模式中保持不变。这可能会导致警告,如下所示: ``` -2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync2() [W] Table user Column keep_activity_private db default is , struct default is 0 +2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync() [W] Table user Column keep_activity_private db default is , struct default is 0 ``` 您可以通过以下方式让 Gitea 重新创建这些表,并将旧数据复制到新表中,并适当设置默认值: diff --git a/docs/content/help/faq.en-us.md b/docs/content/help/faq.en-us.md index 3d03dd23ba32c..c83f8549e20d1 100644 --- a/docs/content/help/faq.en-us.md +++ b/docs/content/help/faq.en-us.md @@ -410,7 +410,7 @@ Sometimes when there are migrations the old columns and default values may be le unchanged in the database schema. This may lead to warning such as: ``` -2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync2() [W] Table user Column keep_activity_private db default is , struct default is 0 +2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync() [W] Table user Column keep_activity_private db default is , struct default is 0 ``` These can safely be ignored, but you are able to stop these warnings by getting Gitea to recreate these tables using: diff --git a/docs/content/help/faq.zh-cn.md b/docs/content/help/faq.zh-cn.md index a11e074a24775..36610db8e0b8e 100644 --- a/docs/content/help/faq.zh-cn.md +++ b/docs/content/help/faq.zh-cn.md @@ -424,7 +424,7 @@ SystemD 上的标准输出默认会写入日志记录中。您可以尝试使用 这可能会导致警告,例如: ``` -2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync2() [W] Table user Column keep_activity_private db default is , struct default is 0 +2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync() [W] Table user Column keep_activity_private db default is , struct default is 0 ``` 可以安全地忽略这些警告,但您可以通过让 Gitea 重新创建这些表来停止这些警告,使用以下命令: diff --git a/models/db/engine.go b/models/db/engine.go index 07e4d00270bf2..182d8cd993696 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -55,7 +55,7 @@ type Engine interface { Limit(limit int, start ...int) *xorm.Session NoAutoTime() *xorm.Session SumInt(bean any, columnName string) (res int64, err error) - Sync2(...any) error + Sync(...any) error Select(string) *xorm.Session NotIn(string, ...any) *xorm.Session OrderBy(any, ...any) *xorm.Session @@ -172,7 +172,7 @@ func UnsetDefaultEngine() { } // InitEngineWithMigration initializes a new xorm.Engine and sets it as the db.DefaultContext -// This function must never call .Sync2() if the provided migration function fails. +// This function must never call .Sync() if the provided migration function fails. // When called from the "doctor" command, the migration function is a version check // that prevents the doctor from fixing anything in the database if the migration level // is different from the expected value. diff --git a/models/db/engine_test.go b/models/db/engine_test.go index 551436677782a..e3dbfbdc24205 100644 --- a/models/db/engine_test.go +++ b/models/db/engine_test.go @@ -26,7 +26,7 @@ func TestDumpDatabase(t *testing.T) { ID int64 `xorm:"pk autoincr"` Version int64 } - assert.NoError(t, db.GetEngine(db.DefaultContext).Sync2(new(Version))) + assert.NoError(t, db.GetEngine(db.DefaultContext).Sync(new(Version))) for _, dbType := range setting.SupportedDatabaseTypes { assert.NoError(t, db.DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType)) diff --git a/models/issues/content_history_test.go b/models/issues/content_history_test.go index 7d52f1bcc6450..53638e967f200 100644 --- a/models/issues/content_history_test.go +++ b/models/issues/content_history_test.go @@ -46,7 +46,7 @@ func TestContentHistory(t *testing.T) { Name string FullName string } - _ = db.GetEngine(dbCtx).Sync2(&User{}) + _ = db.GetEngine(dbCtx).Sync(&User{}) list1, _ := issues_model.FetchIssueContentHistoryList(dbCtx, 10, 0) assert.Len(t, list1, 3) diff --git a/models/migrations/base/db_test.go b/models/migrations/base/db_test.go index 5145e19e8661b..4d61b758cf505 100644 --- a/models/migrations/base/db_test.go +++ b/models/migrations/base/db_test.go @@ -38,7 +38,7 @@ func Test_DropTableColumns(t *testing.T) { for i := range columns { x.SetMapper(names.GonicMapper{}) - if err := x.Sync2(new(DropTest)); err != nil { + if err := x.Sync(new(DropTest)); err != nil { t.Errorf("unable to create DropTest table: %v", err) return } @@ -65,7 +65,7 @@ func Test_DropTableColumns(t *testing.T) { } for j := range columns[i+1:] { x.SetMapper(names.GonicMapper{}) - if err := x.Sync2(new(DropTest)); err != nil { + if err := x.Sync(new(DropTest)); err != nil { t.Errorf("unable to create DropTest table: %v", err) return } diff --git a/models/migrations/base/tests.go b/models/migrations/base/tests.go index e7ff5241447a7..85cafc1ab915e 100644 --- a/models/migrations/base/tests.go +++ b/models/migrations/base/tests.go @@ -81,7 +81,7 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, fu } if len(syncModels) > 0 { - if err := x.Sync2(syncModels...); err != nil { + if err := x.Sync(syncModels...); err != nil { t.Errorf("error during sync: %v", err) return x, deferFn } diff --git a/models/migrations/v1_10/v100.go b/models/migrations/v1_10/v100.go index e94024f4df43b..5d2fd8e244942 100644 --- a/models/migrations/v1_10/v100.go +++ b/models/migrations/v1_10/v100.go @@ -18,7 +18,7 @@ func UpdateMigrationServiceTypes(x *xorm.Engine) error { OriginalURL string `xorm:"VARCHAR(2048)"` } - if err := x.Sync2(new(Repository)); err != nil { + if err := x.Sync(new(Repository)); err != nil { return err } @@ -78,5 +78,5 @@ func UpdateMigrationServiceTypes(x *xorm.Engine) error { ExpiresAt time.Time } - return x.Sync2(new(ExternalLoginUser)) + return x.Sync(new(ExternalLoginUser)) } diff --git a/models/migrations/v1_10/v101.go b/models/migrations/v1_10/v101.go index 79b419e9d97cc..f023a2a0e779e 100644 --- a/models/migrations/v1_10/v101.go +++ b/models/migrations/v1_10/v101.go @@ -14,5 +14,5 @@ func ChangeSomeColumnsLengthOfExternalLoginUser(x *xorm.Engine) error { RefreshToken string `xorm:"TEXT"` } - return x.Sync2(new(ExternalLoginUser)) + return x.Sync(new(ExternalLoginUser)) } diff --git a/models/migrations/v1_10/v88.go b/models/migrations/v1_10/v88.go index e6376af62e49d..7e86ac364f61a 100644 --- a/models/migrations/v1_10/v88.go +++ b/models/migrations/v1_10/v88.go @@ -21,7 +21,7 @@ func AddCommitStatusContext(x *xorm.Engine) error { Context string `xorm:"TEXT"` } - if err := x.Sync2(new(CommitStatus)); err != nil { + if err := x.Sync(new(CommitStatus)); err != nil { return err } diff --git a/models/migrations/v1_10/v89.go b/models/migrations/v1_10/v89.go index 937068292c221..d5f27ffdc65db 100644 --- a/models/migrations/v1_10/v89.go +++ b/models/migrations/v1_10/v89.go @@ -12,7 +12,7 @@ func AddOriginalMigrationInfo(x *xorm.Engine) error { OriginalAuthorID int64 } - if err := x.Sync2(new(Issue)); err != nil { + if err := x.Sync(new(Issue)); err != nil { return err } @@ -22,7 +22,7 @@ func AddOriginalMigrationInfo(x *xorm.Engine) error { OriginalAuthorID int64 } - if err := x.Sync2(new(Comment)); err != nil { + if err := x.Sync(new(Comment)); err != nil { return err } @@ -31,5 +31,5 @@ func AddOriginalMigrationInfo(x *xorm.Engine) error { OriginalURL string } - return x.Sync2(new(Repository)) + return x.Sync(new(Repository)) } diff --git a/models/migrations/v1_10/v90.go b/models/migrations/v1_10/v90.go index c9a69a6dfe30e..295d4b1c1bab8 100644 --- a/models/migrations/v1_10/v90.go +++ b/models/migrations/v1_10/v90.go @@ -13,5 +13,5 @@ func ChangeSomeColumnsLengthOfRepo(x *xorm.Engine) error { OriginalURL string `xorm:"VARCHAR(2048)"` } - return x.Sync2(new(Repository)) + return x.Sync(new(Repository)) } diff --git a/models/migrations/v1_10/v91.go b/models/migrations/v1_10/v91.go index 9b5fefb1d02a8..48cac2de7071f 100644 --- a/models/migrations/v1_10/v91.go +++ b/models/migrations/v1_10/v91.go @@ -11,7 +11,7 @@ func AddIndexOnRepositoryAndComment(x *xorm.Engine) error { OwnerID int64 `xorm:"index"` } - if err := x.Sync2(new(Repository)); err != nil { + if err := x.Sync(new(Repository)); err != nil { return err } @@ -21,5 +21,5 @@ func AddIndexOnRepositoryAndComment(x *xorm.Engine) error { ReviewID int64 `xorm:"index"` } - return x.Sync2(new(Comment)) + return x.Sync(new(Comment)) } diff --git a/models/migrations/v1_10/v93.go b/models/migrations/v1_10/v93.go index 5b59065171e56..ee59a8db394f4 100644 --- a/models/migrations/v1_10/v93.go +++ b/models/migrations/v1_10/v93.go @@ -11,5 +11,5 @@ func AddEmailNotificationEnabledToUser(x *xorm.Engine) error { EmailNotificationsPreference string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'enabled'"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } diff --git a/models/migrations/v1_10/v94.go b/models/migrations/v1_10/v94.go index fe3804aee428f..c131af162b3cf 100644 --- a/models/migrations/v1_10/v94.go +++ b/models/migrations/v1_10/v94.go @@ -11,7 +11,7 @@ func AddStatusCheckColumnsForProtectedBranches(x *xorm.Engine) error { StatusCheckContexts []string `xorm:"JSON TEXT"` } - if err := x.Sync2(new(ProtectedBranch)); err != nil { + if err := x.Sync(new(ProtectedBranch)); err != nil { return err } diff --git a/models/migrations/v1_10/v95.go b/models/migrations/v1_10/v95.go index 1b60eefb4272e..3b1f67fd9c964 100644 --- a/models/migrations/v1_10/v95.go +++ b/models/migrations/v1_10/v95.go @@ -15,5 +15,5 @@ func AddCrossReferenceColumns(x *xorm.Engine) error { RefIsPull bool } - return x.Sync2(new(Comment)) + return x.Sync(new(Comment)) } diff --git a/models/migrations/v1_10/v97.go b/models/migrations/v1_10/v97.go index 8a1a4426ab2c1..dee45b32e35ea 100644 --- a/models/migrations/v1_10/v97.go +++ b/models/migrations/v1_10/v97.go @@ -10,5 +10,5 @@ func AddRepoAdminChangeTeamAccessColumnForUser(x *xorm.Engine) error { RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } diff --git a/models/migrations/v1_10/v98.go b/models/migrations/v1_10/v98.go index cab9a6306503d..bdd9aed0891ad 100644 --- a/models/migrations/v1_10/v98.go +++ b/models/migrations/v1_10/v98.go @@ -12,5 +12,5 @@ func AddOriginalAuthorOnMigratedReleases(x *xorm.Engine) error { OriginalAuthorID int64 `xorm:"index"` } - return x.Sync2(new(Release)) + return x.Sync(new(Release)) } diff --git a/models/migrations/v1_10/v99.go b/models/migrations/v1_10/v99.go index 170a30631f888..ebe6597f7c99b 100644 --- a/models/migrations/v1_10/v99.go +++ b/models/migrations/v1_10/v99.go @@ -34,5 +34,5 @@ func AddTaskTable(x *xorm.Engine) error { Status int `xorm:"NOT NULL DEFAULT 0"` } - return x.Sync2(new(Task), new(Repository)) + return x.Sync(new(Task), new(Repository)) } diff --git a/models/migrations/v1_11/v103.go b/models/migrations/v1_11/v103.go index e4e16a054e827..53527dac586ff 100644 --- a/models/migrations/v1_11/v103.go +++ b/models/migrations/v1_11/v103.go @@ -13,5 +13,5 @@ func AddWhitelistDeployKeysToBranches(x *xorm.Engine) error { WhitelistDeployKeys bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_11/v104.go b/models/migrations/v1_11/v104.go index c76554cf59f7a..3e8ee64bc1112 100644 --- a/models/migrations/v1_11/v104.go +++ b/models/migrations/v1_11/v104.go @@ -15,7 +15,7 @@ func RemoveLabelUneededCols(x *xorm.Engine) error { QueryString string IsSelected bool } - if err := x.Sync2(new(Label)); err != nil { + if err := x.Sync(new(Label)); err != nil { return err } diff --git a/models/migrations/v1_11/v105.go b/models/migrations/v1_11/v105.go index df261c992c8e3..b91340c30a944 100644 --- a/models/migrations/v1_11/v105.go +++ b/models/migrations/v1_11/v105.go @@ -13,7 +13,7 @@ func AddTeamIncludesAllRepositories(x *xorm.Engine) error { IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"` } - if err := x.Sync2(new(Team)); err != nil { + if err := x.Sync(new(Team)); err != nil { return err } diff --git a/models/migrations/v1_11/v106.go b/models/migrations/v1_11/v106.go index 18d436ae20cf0..ecb11cdd1e34c 100644 --- a/models/migrations/v1_11/v106.go +++ b/models/migrations/v1_11/v106.go @@ -17,7 +17,7 @@ type Watch struct { } func AddModeColumnToWatch(x *xorm.Engine) error { - if err := x.Sync2(new(Watch)); err != nil { + if err := x.Sync(new(Watch)); err != nil { return err } _, err := x.Exec("UPDATE `watch` SET `mode` = 1") diff --git a/models/migrations/v1_11/v107.go b/models/migrations/v1_11/v107.go index 1ffbd35dd714e..f0bfe5862c9f0 100644 --- a/models/migrations/v1_11/v107.go +++ b/models/migrations/v1_11/v107.go @@ -13,5 +13,5 @@ func AddTemplateToRepo(x *xorm.Engine) error { TemplateID int64 `xorm:"INDEX"` } - return x.Sync2(new(Repository)) + return x.Sync(new(Repository)) } diff --git a/models/migrations/v1_11/v108.go b/models/migrations/v1_11/v108.go index 28132c377d9fe..a85096234d262 100644 --- a/models/migrations/v1_11/v108.go +++ b/models/migrations/v1_11/v108.go @@ -13,5 +13,5 @@ func AddCommentIDOnNotification(x *xorm.Engine) error { CommentID int64 } - return x.Sync2(new(Notification)) + return x.Sync(new(Notification)) } diff --git a/models/migrations/v1_11/v109.go b/models/migrations/v1_11/v109.go index d2ee9a6aaa21d..ea565ccda37e4 100644 --- a/models/migrations/v1_11/v109.go +++ b/models/migrations/v1_11/v109.go @@ -12,5 +12,5 @@ func AddCanCreateOrgRepoColumnForTeam(x *xorm.Engine) error { CanCreateOrgRepo bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(Team)) + return x.Sync(new(Team)) } diff --git a/models/migrations/v1_11/v111.go b/models/migrations/v1_11/v111.go index 5b15c32163680..d757acb7d2328 100644 --- a/models/migrations/v1_11/v111.go +++ b/models/migrations/v1_11/v111.go @@ -36,11 +36,11 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { IssueID int64 `xorm:"index"` } - if err := x.Sync2(new(ProtectedBranch)); err != nil { + if err := x.Sync(new(ProtectedBranch)); err != nil { return err } - if err := x.Sync2(new(Review)); err != nil { + if err := x.Sync(new(Review)); err != nil { return err } diff --git a/models/migrations/v1_11/v113.go b/models/migrations/v1_11/v113.go index dc9adb60b05d6..dea344a44f268 100644 --- a/models/migrations/v1_11/v113.go +++ b/models/migrations/v1_11/v113.go @@ -15,8 +15,8 @@ func FeatureChangeTargetBranch(x *xorm.Engine) error { NewRef string } - if err := x.Sync2(new(Comment)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Comment)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_11/v116.go b/models/migrations/v1_11/v116.go index 73fddd1039510..85aa76c1e0217 100644 --- a/models/migrations/v1_11/v116.go +++ b/models/migrations/v1_11/v116.go @@ -24,7 +24,7 @@ func ExtendTrackedTimes(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(TrackedTime)); err != nil { + if err := sess.Sync(new(TrackedTime)); err != nil { return err } diff --git a/models/migrations/v1_12/v117.go b/models/migrations/v1_12/v117.go index bc768f3f0bb1d..8eadcdef2b331 100644 --- a/models/migrations/v1_12/v117.go +++ b/models/migrations/v1_12/v117.go @@ -12,5 +12,5 @@ func AddBlockOnRejectedReviews(x *xorm.Engine) error { BlockOnRejectedReviews bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_12/v118.go b/models/migrations/v1_12/v118.go index 9b893e2992bb4..eb022dc5e487e 100644 --- a/models/migrations/v1_12/v118.go +++ b/models/migrations/v1_12/v118.go @@ -18,8 +18,8 @@ func AddReviewCommitAndStale(x *xorm.Engine) error { } // Old reviews will have commit ID set to "" and not stale - if err := x.Sync2(new(Review)); err != nil { + if err := x.Sync(new(Review)); err != nil { return err } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_12/v120.go b/models/migrations/v1_12/v120.go index f4e61215eb019..3f7ed8d373153 100644 --- a/models/migrations/v1_12/v120.go +++ b/models/migrations/v1_12/v120.go @@ -11,7 +11,7 @@ func AddOwnerNameOnRepository(x *xorm.Engine) error { type Repository struct { OwnerName string } - if err := x.Sync2(new(Repository)); err != nil { + if err := x.Sync(new(Repository)); err != nil { return err } _, err := x.Exec("UPDATE repository SET owner_name = (SELECT name FROM `user` WHERE `user`.id = repository.owner_id)") diff --git a/models/migrations/v1_12/v121.go b/models/migrations/v1_12/v121.go index ac656b2d4225c..175ec9164dddb 100644 --- a/models/migrations/v1_12/v121.go +++ b/models/migrations/v1_12/v121.go @@ -12,5 +12,5 @@ func AddIsRestricted(x *xorm.Engine) error { IsRestricted bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } diff --git a/models/migrations/v1_12/v122.go b/models/migrations/v1_12/v122.go index 67ac9411faab5..6e31d863a1259 100644 --- a/models/migrations/v1_12/v122.go +++ b/models/migrations/v1_12/v122.go @@ -12,5 +12,5 @@ func AddRequireSignedCommits(x *xorm.Engine) error { RequireSignedCommits bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_12/v123.go b/models/migrations/v1_12/v123.go index ec56161afa6d0..b0c3af07a3a4e 100644 --- a/models/migrations/v1_12/v123.go +++ b/models/migrations/v1_12/v123.go @@ -13,5 +13,5 @@ func AddReactionOriginals(x *xorm.Engine) error { OriginalAuthor string } - return x.Sync2(new(Reaction)) + return x.Sync(new(Reaction)) } diff --git a/models/migrations/v1_12/v124.go b/models/migrations/v1_12/v124.go index 311690c039b3c..d2ba03ffe03d7 100644 --- a/models/migrations/v1_12/v124.go +++ b/models/migrations/v1_12/v124.go @@ -19,5 +19,5 @@ func AddUserRepoMissingColumns(x *xorm.Engine) error { Topics []string `xorm:"TEXT JSON"` } - return x.Sync2(new(User), new(Repository)) + return x.Sync(new(User), new(Repository)) } diff --git a/models/migrations/v1_12/v125.go b/models/migrations/v1_12/v125.go index 5540dfd626fb9..ec4ffaab254be 100644 --- a/models/migrations/v1_12/v125.go +++ b/models/migrations/v1_12/v125.go @@ -15,8 +15,8 @@ func AddReviewMigrateInfo(x *xorm.Engine) error { OriginalAuthorID int64 } - if err := x.Sync2(new(Review)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Review)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_12/v127.go b/models/migrations/v1_12/v127.go index b248eb4c06cbd..00e391dc875b8 100644 --- a/models/migrations/v1_12/v127.go +++ b/models/migrations/v1_12/v127.go @@ -34,11 +34,11 @@ func AddLanguageStats(x *xorm.Engine) error { IndexerType RepoIndexerType `xorm:"INDEX(s) NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(LanguageStat)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(LanguageStat)); err != nil { + return fmt.Errorf("Sync: %w", err) } - if err := x.Sync2(new(RepoIndexerStatus)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(RepoIndexerStatus)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_12/v131.go b/models/migrations/v1_12/v131.go index a734d9fbf8f97..5184bc3590323 100644 --- a/models/migrations/v1_12/v131.go +++ b/models/migrations/v1_12/v131.go @@ -14,8 +14,8 @@ func AddSystemWebhookColumn(x *xorm.Engine) error { IsSystemWebhook bool `xorm:"NOT NULL DEFAULT false"` } - if err := x.Sync2(new(Webhook)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Webhook)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_12/v132.go b/models/migrations/v1_12/v132.go index 1708a57a7e4cf..3b2b28f7abb4e 100644 --- a/models/migrations/v1_12/v132.go +++ b/models/migrations/v1_12/v132.go @@ -14,8 +14,8 @@ func AddBranchProtectionProtectedFilesColumn(x *xorm.Engine) error { ProtectedFilePatterns string `xorm:"TEXT"` } - if err := x.Sync2(new(ProtectedBranch)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(ProtectedBranch)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_12/v133.go b/models/migrations/v1_12/v133.go index e1c392459b8e6..c9087fc8c143e 100644 --- a/models/migrations/v1_12/v133.go +++ b/models/migrations/v1_12/v133.go @@ -11,5 +11,5 @@ func AddEmailHashTable(x *xorm.Engine) error { Hash string `xorm:"pk varchar(32)"` Email string `xorm:"UNIQUE NOT NULL"` } - return x.Sync2(new(EmailHash)) + return x.Sync(new(EmailHash)) } diff --git a/models/migrations/v1_12/v135.go b/models/migrations/v1_12/v135.go index 5a87d9911b38f..8898011df56c8 100644 --- a/models/migrations/v1_12/v135.go +++ b/models/migrations/v1_12/v135.go @@ -14,8 +14,8 @@ func AddOrgIDLabelColumn(x *xorm.Engine) error { OrgID int64 `xorm:"INDEX"` } - if err := x.Sync2(new(Label)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Label)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_12/v136.go b/models/migrations/v1_12/v136.go index 0cecba7be9395..d91ff92feb00a 100644 --- a/models/migrations/v1_12/v136.go +++ b/models/migrations/v1_12/v136.go @@ -42,8 +42,8 @@ func AddCommitDivergenceToPulls(x *xorm.Engine) error { MergedCommitID string `xorm:"VARCHAR(40)"` } - if err := x.Sync2(new(PullRequest)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(PullRequest)); err != nil { + return fmt.Errorf("Sync: %w", err) } last := 0 diff --git a/models/migrations/v1_12/v137.go b/models/migrations/v1_12/v137.go index 371b1a3fdb85d..0d86b72010923 100644 --- a/models/migrations/v1_12/v137.go +++ b/models/migrations/v1_12/v137.go @@ -11,5 +11,5 @@ func AddBlockOnOutdatedBranch(x *xorm.Engine) error { type ProtectedBranch struct { BlockOnOutdatedBranch bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_12/v138.go b/models/migrations/v1_12/v138.go index a2bfdb59a85cb..8c8d353f405c8 100644 --- a/models/migrations/v1_12/v138.go +++ b/models/migrations/v1_12/v138.go @@ -14,8 +14,8 @@ func AddResolveDoerIDCommentColumn(x *xorm.Engine) error { ResolveDoerID int64 } - if err := x.Sync2(new(Comment)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Comment)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_13/v140.go b/models/migrations/v1_13/v140.go index 30c1bc07d22fc..2d3337012dd54 100644 --- a/models/migrations/v1_13/v140.go +++ b/models/migrations/v1_13/v140.go @@ -33,8 +33,8 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error { IndexerType RepoIndexerType `xorm:"INDEX(s) NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(LanguageStat)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(LanguageStat)); err != nil { + return fmt.Errorf("Sync: %w", err) } x.Delete(&RepoIndexerStatus{IndexerType: RepoIndexerTypeStats}) diff --git a/models/migrations/v1_13/v141.go b/models/migrations/v1_13/v141.go index 80796e6db9319..ae211e0e44b7f 100644 --- a/models/migrations/v1_13/v141.go +++ b/models/migrations/v1_13/v141.go @@ -14,8 +14,8 @@ func AddKeepActivityPrivateUserColumn(x *xorm.Engine) error { KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` } - if err := x.Sync2(new(User)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(User)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_13/v145.go b/models/migrations/v1_13/v145.go index ee40bfc77f862..8acb29bf33722 100644 --- a/models/migrations/v1_13/v145.go +++ b/models/migrations/v1_13/v145.go @@ -17,7 +17,7 @@ func IncreaseLanguageField(x *xorm.Engine) error { Language string `xorm:"VARCHAR(50) UNIQUE(s) INDEX NOT NULL"` } - if err := x.Sync2(new(LanguageStat)); err != nil { + if err := x.Sync(new(LanguageStat)); err != nil { return err } diff --git a/models/migrations/v1_13/v146.go b/models/migrations/v1_13/v146.go index 5db8b0a4374ac..7d9a87870478c 100644 --- a/models/migrations/v1_13/v146.go +++ b/models/migrations/v1_13/v146.go @@ -32,7 +32,7 @@ func AddProjectsInfo(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(new(Project)); err != nil { + if err := x.Sync(new(Project)); err != nil { return err } @@ -41,7 +41,7 @@ func AddProjectsInfo(x *xorm.Engine) error { ProjectID int64 } - if err := x.Sync2(new(Comment)); err != nil { + if err := x.Sync(new(Comment)); err != nil { return err } @@ -51,7 +51,7 @@ func AddProjectsInfo(x *xorm.Engine) error { NumClosedProjects int `xorm:"NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(Repository)); err != nil { + if err := x.Sync(new(Repository)); err != nil { return err } @@ -63,7 +63,7 @@ func AddProjectsInfo(x *xorm.Engine) error { ProjectBoardID int64 `xorm:"INDEX"` } - if err := x.Sync2(new(ProjectIssue)); err != nil { + if err := x.Sync(new(ProjectIssue)); err != nil { return err } @@ -79,5 +79,5 @@ func AddProjectsInfo(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - return x.Sync2(new(ProjectBoard)) + return x.Sync(new(ProjectBoard)) } diff --git a/models/migrations/v1_13/v147.go b/models/migrations/v1_13/v147.go index d9c51145c4183..510ef39b286b9 100644 --- a/models/migrations/v1_13/v147.go +++ b/models/migrations/v1_13/v147.go @@ -78,7 +78,7 @@ func CreateReviewsForCodeComments(x *xorm.Engine) error { RefIsPull bool } - if err := x.Sync2(new(Review), new(Comment)); err != nil { + if err := x.Sync(new(Review), new(Comment)); err != nil { return err } diff --git a/models/migrations/v1_13/v149.go b/models/migrations/v1_13/v149.go index e093b4f9db8d6..2a1db04cbb496 100644 --- a/models/migrations/v1_13/v149.go +++ b/models/migrations/v1_13/v149.go @@ -17,8 +17,8 @@ func AddCreatedAndUpdatedToMilestones(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(new(Milestone)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Milestone)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_13/v151.go b/models/migrations/v1_13/v151.go index 9aa71ec29f13f..25af1d03ec925 100644 --- a/models/migrations/v1_13/v151.go +++ b/models/migrations/v1_13/v151.go @@ -77,14 +77,14 @@ func SetDefaultPasswordToArgon2(x *xorm.Engine) error { type User struct { PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'argon2'"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } column := table.GetColumn("passwd_hash_algo") if column == nil { type User struct { PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'argon2'"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } tempTableName := "tmp_recreate__user" diff --git a/models/migrations/v1_13/v152.go b/models/migrations/v1_13/v152.go index 7f7c414de8a97..502c82a40de59 100644 --- a/models/migrations/v1_13/v152.go +++ b/models/migrations/v1_13/v152.go @@ -9,5 +9,5 @@ func AddTrustModelToRepository(x *xorm.Engine) error { type Repository struct { TrustModel int } - return x.Sync2(new(Repository)) + return x.Sync(new(Repository)) } diff --git a/models/migrations/v1_13/v153.go b/models/migrations/v1_13/v153.go index 4146d83387845..0b2dd3eb62eac 100644 --- a/models/migrations/v1_13/v153.go +++ b/models/migrations/v1_13/v153.go @@ -16,9 +16,9 @@ func AddTeamReviewRequestSupport(x *xorm.Engine) error { AssigneeTeamID int64 `xorm:"NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(Review)); err != nil { + if err := x.Sync(new(Review)); err != nil { return err } - return x.Sync2(new(Comment)) + return x.Sync(new(Comment)) } diff --git a/models/migrations/v1_13/v154.go b/models/migrations/v1_13/v154.go index 8b4498be847ad..60cc56713e5e4 100644 --- a/models/migrations/v1_13/v154.go +++ b/models/migrations/v1_13/v154.go @@ -16,7 +16,7 @@ func AddTimeStamps(x *xorm.Engine) error { type Star struct { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` } - if err := x.Sync2(new(Star)); err != nil { + if err := x.Sync(new(Star)); err != nil { return err } @@ -25,7 +25,7 @@ func AddTimeStamps(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(new(Label)); err != nil { + if err := x.Sync(new(Label)); err != nil { return err } @@ -33,7 +33,7 @@ func AddTimeStamps(x *xorm.Engine) error { type Follow struct { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` } - if err := x.Sync2(new(Follow)); err != nil { + if err := x.Sync(new(Follow)); err != nil { return err } @@ -42,7 +42,7 @@ func AddTimeStamps(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(new(Watch)); err != nil { + if err := x.Sync(new(Watch)); err != nil { return err } @@ -51,5 +51,5 @@ func AddTimeStamps(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - return x.Sync2(new(Collaboration)) + return x.Sync(new(Collaboration)) } diff --git a/models/migrations/v1_14/v155.go b/models/migrations/v1_14/v155.go index 7c5dc5fbe278d..e814f59938d5b 100644 --- a/models/migrations/v1_14/v155.go +++ b/models/migrations/v1_14/v155.go @@ -14,8 +14,8 @@ func AddChangedProtectedFilesPullRequestColumn(x *xorm.Engine) error { ChangedProtectedFiles []string `xorm:"TEXT JSON"` } - if err := x.Sync2(new(PullRequest)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(PullRequest)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_14/v158.go b/models/migrations/v1_14/v158.go index 2029829ff9901..1094d8abf79ce 100644 --- a/models/migrations/v1_14/v158.go +++ b/models/migrations/v1_14/v158.go @@ -27,7 +27,7 @@ func UpdateCodeCommentReplies(x *xorm.Engine) error { ReviewID int64 `xorm:"index"` } - if err := x.Sync2(new(Comment)); err != nil { + if err := x.Sync(new(Comment)); err != nil { return err } diff --git a/models/migrations/v1_14/v160.go b/models/migrations/v1_14/v160.go index b9b7e7fbdd5d4..4dea91b5148c1 100644 --- a/models/migrations/v1_14/v160.go +++ b/models/migrations/v1_14/v160.go @@ -12,5 +12,5 @@ func AddBlockOnOfficialReviewRequests(x *xorm.Engine) error { BlockOnOfficialReviewRequests bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_14/v161.go b/models/migrations/v1_14/v161.go index ef3c14d595017..ac7e821a804b2 100644 --- a/models/migrations/v1_14/v161.go +++ b/models/migrations/v1_14/v161.go @@ -41,7 +41,7 @@ func ConvertTaskTypeToString(x *xorm.Engine) error { type HookTask struct { Typ string `xorm:"VARCHAR(16) index"` } - if err := x.Sync2(new(HookTask)); err != nil { + if err := x.Sync(new(HookTask)); err != nil { return err } diff --git a/models/migrations/v1_14/v162.go b/models/migrations/v1_14/v162.go index 972f771fd7b3a..2e4e0b8eb0547 100644 --- a/models/migrations/v1_14/v162.go +++ b/models/migrations/v1_14/v162.go @@ -39,7 +39,7 @@ func ConvertWebhookTaskTypeToString(x *xorm.Engine) error { type Webhook struct { Type string `xorm:"char(16) index"` } - if err := x.Sync2(new(Webhook)); err != nil { + if err := x.Sync(new(Webhook)); err != nil { return err } diff --git a/models/migrations/v1_14/v163.go b/models/migrations/v1_14/v163.go index 22f55f48d1691..0cd8ba68c8ec1 100644 --- a/models/migrations/v1_14/v163.go +++ b/models/migrations/v1_14/v163.go @@ -18,7 +18,7 @@ func ConvertTopicNameFrom25To50(x *xorm.Engine) error { UpdatedUnix int64 `xorm:"INDEX updated"` } - if err := x.Sync2(new(Topic)); err != nil { + if err := x.Sync(new(Topic)); err != nil { return err } diff --git a/models/migrations/v1_14/v164.go b/models/migrations/v1_14/v164.go index a6791b16e03d5..54f6951427ea2 100644 --- a/models/migrations/v1_14/v164.go +++ b/models/migrations/v1_14/v164.go @@ -30,8 +30,8 @@ func (grant *OAuth2Grant) TableName() string { } func AddScopeAndNonceColumnsToOAuth2Grant(x *xorm.Engine) error { - if err := x.Sync2(new(OAuth2Grant)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(OAuth2Grant)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_14/v167.go b/models/migrations/v1_14/v167.go index fb6b3b474af92..9d416f6a32d47 100644 --- a/models/migrations/v1_14/v167.go +++ b/models/migrations/v1_14/v167.go @@ -16,8 +16,8 @@ func AddUserRedirect(x *xorm.Engine) (err error) { RedirectUserID int64 } - if err := x.Sync2(new(UserRedirect)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(UserRedirect)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_14/v170.go b/models/migrations/v1_14/v170.go index adb28cae5e6c4..7b6498a3e9b4a 100644 --- a/models/migrations/v1_14/v170.go +++ b/models/migrations/v1_14/v170.go @@ -14,8 +14,8 @@ func AddDismissedReviewColumn(x *xorm.Engine) error { Dismissed bool `xorm:"NOT NULL DEFAULT false"` } - if err := x.Sync2(new(Review)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Review)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_14/v171.go b/models/migrations/v1_14/v171.go index 35769342e8755..51a35a02add16 100644 --- a/models/migrations/v1_14/v171.go +++ b/models/migrations/v1_14/v171.go @@ -14,8 +14,8 @@ func AddSortingColToProjectBoard(x *xorm.Engine) error { Sorting int8 `xorm:"NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(ProjectBoard)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(ProjectBoard)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_14/v172.go b/models/migrations/v1_14/v172.go index 76519b94579ae..0f9bef902a361 100644 --- a/models/migrations/v1_14/v172.go +++ b/models/migrations/v1_14/v172.go @@ -15,5 +15,5 @@ func AddSessionTable(x *xorm.Engine) error { Data []byte `xorm:"BLOB"` Expiry timeutil.TimeStamp } - return x.Sync2(new(Session)) + return x.Sync(new(Session)) } diff --git a/models/migrations/v1_14/v173.go b/models/migrations/v1_14/v173.go index 3b7ecb8f9d8fd..2d9eee9197ff4 100644 --- a/models/migrations/v1_14/v173.go +++ b/models/migrations/v1_14/v173.go @@ -14,8 +14,8 @@ func AddTimeIDCommentColumn(x *xorm.Engine) error { TimeID int64 } - if err := x.Sync2(new(Comment)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Comment)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_14/v174.go b/models/migrations/v1_14/v174.go index 766d3a4208e4b..c839e15db85d2 100644 --- a/models/migrations/v1_14/v174.go +++ b/models/migrations/v1_14/v174.go @@ -26,8 +26,8 @@ func AddRepoTransfer(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(RepoTransfer)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(RepoTransfer)); err != nil { + return fmt.Errorf("Sync: %w", err) } return sess.Commit() diff --git a/models/migrations/v1_14/v176.go b/models/migrations/v1_14/v176.go index bd2484e49d7b7..1ed49f75fac97 100644 --- a/models/migrations/v1_14/v176.go +++ b/models/migrations/v1_14/v176.go @@ -42,7 +42,7 @@ func RemoveInvalidLabels(x *xorm.Engine) error { LabelID int64 `xorm:"UNIQUE(s)"` } - if err := x.Sync2(new(Comment), new(Issue), new(Repository), new(Label), new(IssueLabel)); err != nil { + if err := x.Sync(new(Comment), new(Issue), new(Repository), new(Label), new(IssueLabel)); err != nil { return err } diff --git a/models/migrations/v1_14/v177.go b/models/migrations/v1_14/v177.go index e72a9e53a95bd..6e1838f3696a5 100644 --- a/models/migrations/v1_14/v177.go +++ b/models/migrations/v1_14/v177.go @@ -23,8 +23,8 @@ func DeleteOrphanedIssueLabels(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(IssueLabel)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(IssueLabel)); err != nil { + return fmt.Errorf("Sync: %w", err) } if _, err := sess.Exec(`DELETE FROM issue_label WHERE issue_label.id IN ( diff --git a/models/migrations/v1_15/v178.go b/models/migrations/v1_15/v178.go index 9bb6ed7f8df76..6d236eb049831 100644 --- a/models/migrations/v1_15/v178.go +++ b/models/migrations/v1_15/v178.go @@ -13,5 +13,5 @@ func AddLFSMirrorColumns(x *xorm.Engine) error { LFSEndpoint string `xorm:"lfs_endpoint TEXT"` } - return x.Sync2(new(Mirror)) + return x.Sync(new(Mirror)) } diff --git a/models/migrations/v1_15/v181.go b/models/migrations/v1_15/v181.go index f4dd1d6016cd7..2185ed02134aa 100644 --- a/models/migrations/v1_15/v181.go +++ b/models/migrations/v1_15/v181.go @@ -26,7 +26,7 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) error { } // Add lower_email and is_primary columns - if err := x.Table("email_address").Sync2(new(EmailAddress1)); err != nil { + if err := x.Table("email_address").Sync(new(EmailAddress1)); err != nil { return err } @@ -44,7 +44,7 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) error { } // change lower_email as unique - if err := x.Sync2(new(EmailAddress)); err != nil { + if err := x.Sync(new(EmailAddress)); err != nil { return err } diff --git a/models/migrations/v1_15/v182.go b/models/migrations/v1_15/v182.go index c584ef851df37..9ca500c0f9637 100644 --- a/models/migrations/v1_15/v182.go +++ b/models/migrations/v1_15/v182.go @@ -20,7 +20,7 @@ func AddIssueResourceIndexTable(x *xorm.Engine) error { return err } - if err := sess.Table("issue_index").Sync2(new(ResourceIndex)); err != nil { + if err := sess.Table("issue_index").Sync(new(ResourceIndex)); err != nil { return err } diff --git a/models/migrations/v1_15/v183.go b/models/migrations/v1_15/v183.go index 4cc98f9efcb36..effad1b467c39 100644 --- a/models/migrations/v1_15/v183.go +++ b/models/migrations/v1_15/v183.go @@ -30,8 +30,8 @@ func CreatePushMirrorTable(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(PushMirror)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(PushMirror)); err != nil { + return fmt.Errorf("Sync: %w", err) } return sess.Commit() diff --git a/models/migrations/v1_15/v184.go b/models/migrations/v1_15/v184.go index caf41b6048ed4..4b3dd1467a839 100644 --- a/models/migrations/v1_15/v184.go +++ b/models/migrations/v1_15/v184.go @@ -42,8 +42,8 @@ func RenameTaskErrorsToMessage(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(Task)); err != nil { - return fmt.Errorf("error on Sync2: %w", err) + if err := sess.Sync(new(Task)); err != nil { + return fmt.Errorf("error on Sync: %w", err) } if messageExist { diff --git a/models/migrations/v1_15/v185.go b/models/migrations/v1_15/v185.go index 382cb621477fd..e5878ec193879 100644 --- a/models/migrations/v1_15/v185.go +++ b/models/migrations/v1_15/v185.go @@ -17,5 +17,5 @@ func AddRepoArchiver(x *xorm.Engine) error { CommitID string `xorm:"VARCHAR(40) unique(s)"` CreatedUnix int64 `xorm:"INDEX NOT NULL created"` } - return x.Sync2(new(RepoArchiver)) + return x.Sync(new(RepoArchiver)) } diff --git a/models/migrations/v1_15/v186.go b/models/migrations/v1_15/v186.go index 310ac85f4cf9d..01aab3add5c40 100644 --- a/models/migrations/v1_15/v186.go +++ b/models/migrations/v1_15/v186.go @@ -21,5 +21,5 @@ func CreateProtectedTagTable(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"updated"` } - return x.Sync2(new(ProtectedTag)) + return x.Sync(new(ProtectedTag)) } diff --git a/models/migrations/v1_15/v187.go b/models/migrations/v1_15/v187.go index afd86bac45e37..21cd6772b7e92 100644 --- a/models/migrations/v1_15/v187.go +++ b/models/migrations/v1_15/v187.go @@ -15,7 +15,7 @@ func DropWebhookColumns(x *xorm.Engine) error { Signature string `xorm:"TEXT"` IsSSL bool `xorm:"is_ssl"` } - if err := x.Sync2(new(Webhook)); err != nil { + if err := x.Sync(new(Webhook)); err != nil { return err } @@ -27,7 +27,7 @@ func DropWebhookColumns(x *xorm.Engine) error { ContentType int IsSSL bool } - if err := x.Sync2(new(HookTask)); err != nil { + if err := x.Sync(new(HookTask)); err != nil { return err } diff --git a/models/migrations/v1_16/v189.go b/models/migrations/v1_16/v189.go index 79e3289ba7f51..afd93b0eac1e3 100644 --- a/models/migrations/v1_16/v189.go +++ b/models/migrations/v1_16/v189.go @@ -58,7 +58,7 @@ func UnwrapLDAPSourceCfg(x *xorm.Engine) error { } // change lower_email as unique - if err := x.Sync2(new(LoginSource)); err != nil { + if err := x.Sync(new(LoginSource)); err != nil { return err } diff --git a/models/migrations/v1_16/v190.go b/models/migrations/v1_16/v190.go index 1853729ae99dc..5953802849a7b 100644 --- a/models/migrations/v1_16/v190.go +++ b/models/migrations/v1_16/v190.go @@ -16,7 +16,7 @@ func AddAgitFlowPullRequest(x *xorm.Engine) error { Flow PullRequestFlow `xorm:"NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(PullRequest)); err != nil { + if err := x.Sync(new(PullRequest)); err != nil { return fmt.Errorf("sync2: %w", err) } return nil diff --git a/models/migrations/v1_16/v193.go b/models/migrations/v1_16/v193.go index dd50e353e3713..8d3ce7a5587c3 100644 --- a/models/migrations/v1_16/v193.go +++ b/models/migrations/v1_16/v193.go @@ -16,7 +16,7 @@ func AddRepoIDForAttachment(x *xorm.Engine) error { ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating UploaderID int64 `xorm:"INDEX DEFAULT 0"` } - if err := x.Sync2(new(Attachment)); err != nil { + if err := x.Sync(new(Attachment)); err != nil { return err } diff --git a/models/migrations/v1_16/v194.go b/models/migrations/v1_16/v194.go index ae7fe10bfc56f..6aa13c50cf833 100644 --- a/models/migrations/v1_16/v194.go +++ b/models/migrations/v1_16/v194.go @@ -14,8 +14,8 @@ func AddBranchProtectionUnprotectedFilesColumn(x *xorm.Engine) error { UnprotectedFilePatterns string `xorm:"TEXT"` } - if err := x.Sync2(new(ProtectedBranch)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(ProtectedBranch)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_16/v195.go b/models/migrations/v1_16/v195.go index 9e390a971e471..6d7e94141e446 100644 --- a/models/migrations/v1_16/v195.go +++ b/models/migrations/v1_16/v195.go @@ -18,8 +18,8 @@ func AddTableCommitStatusIndex(x *xorm.Engine) error { MaxIndex int64 `xorm:"index"` } - if err := x.Sync2(new(CommitStatusIndex)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(CommitStatusIndex)); err != nil { + return fmt.Errorf("Sync: %w", err) } sess := x.NewSession() diff --git a/models/migrations/v1_16/v196.go b/models/migrations/v1_16/v196.go index ed7f4185a1bfc..7cbafc61e56e0 100644 --- a/models/migrations/v1_16/v196.go +++ b/models/migrations/v1_16/v196.go @@ -14,8 +14,8 @@ func AddColorColToProjectBoard(x *xorm.Engine) error { Color string `xorm:"VARCHAR(7)"` } - if err := x.Sync2(new(ProjectBoard)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(ProjectBoard)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_16/v197.go b/models/migrations/v1_16/v197.go index ef9d57a79e5bb..97888b284797b 100644 --- a/models/migrations/v1_16/v197.go +++ b/models/migrations/v1_16/v197.go @@ -15,5 +15,5 @@ func AddRenamedBranchTable(x *xorm.Engine) error { To string CreatedUnix int64 `xorm:"created"` } - return x.Sync2(new(RenamedBranch)) + return x.Sync(new(RenamedBranch)) } diff --git a/models/migrations/v1_16/v198.go b/models/migrations/v1_16/v198.go index ed792de793c19..115bb313a0643 100644 --- a/models/migrations/v1_16/v198.go +++ b/models/migrations/v1_16/v198.go @@ -25,8 +25,8 @@ func AddTableIssueContentHistory(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() - if err := sess.Sync2(new(IssueContentHistory)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(IssueContentHistory)); err != nil { + return fmt.Errorf("Sync: %w", err) } return sess.Commit() } diff --git a/models/migrations/v1_16/v200.go b/models/migrations/v1_16/v200.go index e39f4af9e86fb..c08c20e51de44 100644 --- a/models/migrations/v1_16/v200.go +++ b/models/migrations/v1_16/v200.go @@ -15,8 +15,8 @@ func AddTableAppState(x *xorm.Engine) error { Revision int64 Content string `xorm:"LONGTEXT"` } - if err := x.Sync2(new(AppState)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(AppState)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_16/v202.go b/models/migrations/v1_16/v202.go index 79676f3fab2d2..6ba36152f1f2f 100644 --- a/models/migrations/v1_16/v202.go +++ b/models/migrations/v1_16/v202.go @@ -16,7 +16,7 @@ func CreateUserSettingsTable(x *xorm.Engine) error { SettingKey string `xorm:"varchar(255) index unique(key_userid)"` // ensure key is always lowercase SettingValue string `xorm:"text"` } - if err := x.Sync2(new(UserSetting)); err != nil { + if err := x.Sync(new(UserSetting)); err != nil { return fmt.Errorf("sync2: %w", err) } return nil diff --git a/models/migrations/v1_16/v203.go b/models/migrations/v1_16/v203.go index 26ec135a07cd2..e8e6b52453848 100644 --- a/models/migrations/v1_16/v203.go +++ b/models/migrations/v1_16/v203.go @@ -13,5 +13,5 @@ func AddProjectIssueSorting(x *xorm.Engine) error { Sorting int64 `xorm:"NOT NULL DEFAULT 0"` } - return x.Sync2(new(ProjectIssue)) + return x.Sync(new(ProjectIssue)) } diff --git a/models/migrations/v1_16/v204.go b/models/migrations/v1_16/v204.go index e7577c8da49ca..ece03e1305262 100644 --- a/models/migrations/v1_16/v204.go +++ b/models/migrations/v1_16/v204.go @@ -10,5 +10,5 @@ func AddSSHKeyIsVerified(x *xorm.Engine) error { Verified bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(PublicKey)) + return x.Sync(new(PublicKey)) } diff --git a/models/migrations/v1_16/v206.go b/models/migrations/v1_16/v206.go index 64c794a2d0f21..581a7d76e9e30 100644 --- a/models/migrations/v1_16/v206.go +++ b/models/migrations/v1_16/v206.go @@ -18,7 +18,7 @@ func AddAuthorizeColForTeamUnit(x *xorm.Engine) error { AccessMode int } - if err := x.Sync2(new(TeamUnit)); err != nil { + if err := x.Sync(new(TeamUnit)); err != nil { return fmt.Errorf("sync2: %w", err) } diff --git a/models/migrations/v1_16/v210.go b/models/migrations/v1_16/v210.go index 974e77fb8421c..4e55afccc1302 100644 --- a/models/migrations/v1_16/v210.go +++ b/models/migrations/v1_16/v210.go @@ -34,7 +34,7 @@ func RemigrateU2FCredentials(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(&webauthnCredential{}); err != nil { + if err := x.Sync(&webauthnCredential{}); err != nil { return err } diff --git a/models/migrations/v1_17/v212.go b/models/migrations/v1_17/v212.go index 536ba0a2c42d4..e3f94371212c0 100644 --- a/models/migrations/v1_17/v212.go +++ b/models/migrations/v1_17/v212.go @@ -20,7 +20,7 @@ func AddPackageTables(x *xorm.Engine) error { SemverCompatible bool `xorm:"NOT NULL DEFAULT false"` } - if err := x.Sync2(new(Package)); err != nil { + if err := x.Sync(new(Package)); err != nil { return err } @@ -36,7 +36,7 @@ func AddPackageTables(x *xorm.Engine) error { DownloadCount int64 `xorm:"NOT NULL DEFAULT 0"` } - if err := x.Sync2(new(PackageVersion)); err != nil { + if err := x.Sync(new(PackageVersion)); err != nil { return err } @@ -48,7 +48,7 @@ func AddPackageTables(x *xorm.Engine) error { Value string `xorm:"TEXT NOT NULL"` } - if err := x.Sync2(new(PackageProperty)); err != nil { + if err := x.Sync(new(PackageProperty)); err != nil { return err } @@ -63,7 +63,7 @@ func AddPackageTables(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"` } - if err := x.Sync2(new(PackageFile)); err != nil { + if err := x.Sync(new(PackageFile)); err != nil { return err } @@ -77,7 +77,7 @@ func AddPackageTables(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"` } - if err := x.Sync2(new(PackageBlob)); err != nil { + if err := x.Sync(new(PackageBlob)); err != nil { return err } @@ -89,5 +89,5 @@ func AddPackageTables(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"updated INDEX NOT NULL"` } - return x.Sync2(new(PackageBlobUpload)) + return x.Sync(new(PackageBlobUpload)) } diff --git a/models/migrations/v1_17/v213.go b/models/migrations/v1_17/v213.go index 8607fdba47f24..bb3f466e5283f 100644 --- a/models/migrations/v1_17/v213.go +++ b/models/migrations/v1_17/v213.go @@ -13,5 +13,5 @@ func AddAllowMaintainerEdit(x *xorm.Engine) error { AllowMaintainerEdit bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(PullRequest)) + return x.Sync(new(PullRequest)) } diff --git a/models/migrations/v1_17/v214.go b/models/migrations/v1_17/v214.go index 3b2351d160407..2268164919d41 100644 --- a/models/migrations/v1_17/v214.go +++ b/models/migrations/v1_17/v214.go @@ -18,5 +18,5 @@ func AddAutoMergeTable(x *xorm.Engine) error { CreatedUnix int64 `xorm:"created"` } - return x.Sync2(&PullAutoMerge{}) + return x.Sync(&PullAutoMerge{}) } diff --git a/models/migrations/v1_17/v215.go b/models/migrations/v1_17/v215.go index 0244be216c446..b338f854178ba 100644 --- a/models/migrations/v1_17/v215.go +++ b/models/migrations/v1_17/v215.go @@ -20,5 +20,5 @@ func AddReviewViewedFiles(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"updated"` } - return x.Sync2(new(ReviewState)) + return x.Sync(new(ReviewState)) } diff --git a/models/migrations/v1_17/v218.go b/models/migrations/v1_17/v218.go index ae91ba0c494bc..4c05a9b5392b3 100644 --- a/models/migrations/v1_17/v218.go +++ b/models/migrations/v1_17/v218.go @@ -48,5 +48,5 @@ func (*improveActionTableIndicesAction) TableIndices() []*schemas.Index { } func ImproveActionTableIndices(x *xorm.Engine) error { - return x.Sync2(&improveActionTableIndicesAction{}) + return x.Sync(&improveActionTableIndicesAction{}) } diff --git a/models/migrations/v1_17/v219.go b/models/migrations/v1_17/v219.go index a2165212cc9b2..d266029fd9f28 100644 --- a/models/migrations/v1_17/v219.go +++ b/models/migrations/v1_17/v219.go @@ -26,5 +26,5 @@ func AddSyncOnCommitColForPushMirror(x *xorm.Engine) error { LastError string `xorm:"text"` } - return x.Sync2(new(PushMirror)) + return x.Sync(new(PushMirror)) } diff --git a/models/migrations/v1_17/v221.go b/models/migrations/v1_17/v221.go index 8a58b0f1056d3..9e159388bdc7a 100644 --- a/models/migrations/v1_17/v221.go +++ b/models/migrations/v1_17/v221.go @@ -30,7 +30,7 @@ func StoreWebauthnCredentialIDAsBytes(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(&webauthnCredential{}); err != nil { + if err := x.Sync(&webauthnCredential{}); err != nil { return err } diff --git a/models/migrations/v1_17/v222.go b/models/migrations/v1_17/v222.go index d1b77d845d164..2ffb94eb1cacd 100644 --- a/models/migrations/v1_17/v222.go +++ b/models/migrations/v1_17/v222.go @@ -49,7 +49,7 @@ func DropOldCredentialIDColumn(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(&webauthnCredential{}); err != nil { + if err := x.Sync(&webauthnCredential{}); err != nil { return err } diff --git a/models/migrations/v1_17/v223.go b/models/migrations/v1_17/v223.go index 6c61dbc53ae48..018451ee4c3b1 100644 --- a/models/migrations/v1_17/v223.go +++ b/models/migrations/v1_17/v223.go @@ -53,8 +53,8 @@ func RenameCredentialIDBytes(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(webauthnCredential)); err != nil { - return fmt.Errorf("error on Sync2: %w", err) + if err := sess.Sync(new(webauthnCredential)); err != nil { + return fmt.Errorf("error on Sync: %w", err) } if credentialIDExist { @@ -99,5 +99,5 @@ func RenameCredentialIDBytes(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - return x.Sync2(&webauthnCredential{}) + return x.Sync(&webauthnCredential{}) } diff --git a/models/migrations/v1_18/v224.go b/models/migrations/v1_18/v224.go index afd34a5db09cc..f3d522b91a17a 100644 --- a/models/migrations/v1_18/v224.go +++ b/models/migrations/v1_18/v224.go @@ -20,8 +20,8 @@ func CreateUserBadgesTable(x *xorm.Engine) error { UserID int64 `xorm:"INDEX"` } - if err := x.Sync2(new(Badge)); err != nil { + if err := x.Sync(new(Badge)); err != nil { return err } - return x.Sync2(new(userBadge)) + return x.Sync(new(userBadge)) } diff --git a/models/migrations/v1_18/v227.go b/models/migrations/v1_18/v227.go index c938028323fd7..78c80f74ece34 100644 --- a/models/migrations/v1_18/v227.go +++ b/models/migrations/v1_18/v227.go @@ -43,7 +43,7 @@ func insertSettingsIfNotExist(x *xorm.Engine, sysSettings []*SystemSetting) erro } func CreateSystemSettingsTable(x *xorm.Engine) error { - if err := x.Sync2(new(SystemSetting)); err != nil { + if err := x.Sync(new(SystemSetting)); err != nil { return fmt.Errorf("sync2: %w", err) } diff --git a/models/migrations/v1_18/v228.go b/models/migrations/v1_18/v228.go index 58d3257528ae9..3e7a36de15e7e 100644 --- a/models/migrations/v1_18/v228.go +++ b/models/migrations/v1_18/v228.go @@ -21,5 +21,5 @@ func AddTeamInviteTable(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - return x.Sync2(new(TeamInvite)) + return x.Sync(new(TeamInvite)) } diff --git a/models/migrations/v1_19/v234.go b/models/migrations/v1_19/v234.go index 4e98a2b7a9fdc..728a580807b25 100644 --- a/models/migrations/v1_19/v234.go +++ b/models/migrations/v1_19/v234.go @@ -24,5 +24,5 @@ func CreatePackageCleanupRuleTable(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"` } - return x.Sync2(new(PackageCleanupRule)) + return x.Sync(new(PackageCleanupRule)) } diff --git a/models/migrations/v1_20/v245.go b/models/migrations/v1_20/v245.go index 466f21c239d09..ab58d128806aa 100644 --- a/models/migrations/v1_20/v245.go +++ b/models/migrations/v1_20/v245.go @@ -40,7 +40,7 @@ func RenameWebhookOrgToOwner(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(Webhook)); err != nil { + if err := sess.Sync(new(Webhook)); err != nil { return err } diff --git a/models/migrations/v1_21/v263.go b/models/migrations/v1_21/v263.go index 88a5cb92b49fb..5dccd8bfa0d9e 100644 --- a/models/migrations/v1_21/v263.go +++ b/models/migrations/v1_21/v263.go @@ -23,8 +23,8 @@ func AddGitSizeAndLFSSizeToRepositoryTable(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(Repository)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(Repository)); err != nil { + return fmt.Errorf("Sync: %w", err) } _, err := sess.Exec(`UPDATE repository SET lfs_size=(SELECT SUM(size) FROM lfs_meta_object WHERE lfs_meta_object.repository_id=repository.ID) WHERE EXISTS (SELECT 1 FROM lfs_meta_object WHERE lfs_meta_object.repository_id=repository.ID)`) diff --git a/models/migrations/v1_6/v71.go b/models/migrations/v1_6/v71.go index effd2ebf99595..4e50ca9219bba 100644 --- a/models/migrations/v1_6/v71.go +++ b/models/migrations/v1_6/v71.go @@ -27,8 +27,8 @@ func AddScratchHash(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(new(TwoFactor)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(TwoFactor)); err != nil { + return fmt.Errorf("Sync: %w", err) } sess := x.NewSession() diff --git a/models/migrations/v1_6/v72.go b/models/migrations/v1_6/v72.go index ce963eb371480..04cef9a1707c7 100644 --- a/models/migrations/v1_6/v72.go +++ b/models/migrations/v1_6/v72.go @@ -23,8 +23,8 @@ func AddReview(x *xorm.Engine) error { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` } - if err := x.Sync2(new(Review)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := x.Sync(new(Review)); err != nil { + return fmt.Errorf("Sync: %w", err) } return nil } diff --git a/models/migrations/v1_7/v73.go b/models/migrations/v1_7/v73.go index 1013daedbd635..b5a748aae3a67 100644 --- a/models/migrations/v1_7/v73.go +++ b/models/migrations/v1_7/v73.go @@ -14,5 +14,5 @@ func AddMustChangePassword(x *xorm.Engine) error { MustChangePassword bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } diff --git a/models/migrations/v1_7/v74.go b/models/migrations/v1_7/v74.go index bdd89d1f342a4..f0567e3c9b9c3 100644 --- a/models/migrations/v1_7/v74.go +++ b/models/migrations/v1_7/v74.go @@ -11,5 +11,5 @@ func AddApprovalWhitelistsToProtectedBranches(x *xorm.Engine) error { ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` } - return x.Sync2(new(ProtectedBranch)) + return x.Sync(new(ProtectedBranch)) } diff --git a/models/migrations/v1_8/v77.go b/models/migrations/v1_8/v77.go index 2305984c129ed..8b199939245ff 100644 --- a/models/migrations/v1_8/v77.go +++ b/models/migrations/v1_8/v77.go @@ -12,5 +12,5 @@ func AddUserDefaultTheme(x *xorm.Engine) error { Theme string `xorm:"VARCHAR(30) NOT NULL DEFAULT ''"` } - return x.Sync2(new(User)) + return x.Sync(new(User)) } diff --git a/models/migrations/v1_8/v78.go b/models/migrations/v1_8/v78.go index 637db451f5b8f..8f041c14849d7 100644 --- a/models/migrations/v1_8/v78.go +++ b/models/migrations/v1_8/v78.go @@ -22,7 +22,7 @@ func RenameRepoIsBareToIsEmpty(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(Repository)); err != nil { + if err := sess.Sync(new(Repository)); err != nil { return err } if _, err := sess.Exec("UPDATE repository SET is_empty = is_bare;"); err != nil { diff --git a/models/migrations/v1_8/v79.go b/models/migrations/v1_8/v79.go index e708d7229464e..eb3a9ed0f4df3 100644 --- a/models/migrations/v1_8/v79.go +++ b/models/migrations/v1_8/v79.go @@ -15,7 +15,7 @@ func AddCanCloseIssuesViaCommitInAnyBranch(x *xorm.Engine) error { CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"` } - if err := x.Sync2(new(Repository)); err != nil { + if err := x.Sync(new(Repository)); err != nil { return err } diff --git a/models/migrations/v1_8/v80.go b/models/migrations/v1_8/v80.go index 7f2e0ff72bf09..cebbbead28b78 100644 --- a/models/migrations/v1_8/v80.go +++ b/models/migrations/v1_8/v80.go @@ -12,5 +12,5 @@ func AddIsLockedToIssues(x *xorm.Engine) error { IsLocked bool `xorm:"NOT NULL DEFAULT false"` } - return x.Sync2(new(Issue)) + return x.Sync(new(Issue)) } diff --git a/models/migrations/v1_9/v83.go b/models/migrations/v1_9/v83.go index afe504e9c5f96..10e6c45875785 100644 --- a/models/migrations/v1_9/v83.go +++ b/models/migrations/v1_9/v83.go @@ -23,5 +23,5 @@ func AddUploaderIDForAttachment(x *xorm.Engine) error { CreatedUnix timeutil.TimeStamp `xorm:"created"` } - return x.Sync2(new(Attachment)) + return x.Sync(new(Attachment)) } diff --git a/models/migrations/v1_9/v84.go b/models/migrations/v1_9/v84.go index 13fc238d4801c..c7155fe9cff8d 100644 --- a/models/migrations/v1_9/v84.go +++ b/models/migrations/v1_9/v84.go @@ -13,5 +13,5 @@ func AddGPGKeyImport(x *xorm.Engine) error { Content string `xorm:"TEXT NOT NULL"` } - return x.Sync2(new(GPGKeyImport)) + return x.Sync(new(GPGKeyImport)) } diff --git a/models/migrations/v1_9/v85.go b/models/migrations/v1_9/v85.go index 6cf7faaad6392..9419ee1aae1db 100644 --- a/models/migrations/v1_9/v85.go +++ b/models/migrations/v1_9/v85.go @@ -40,8 +40,8 @@ func HashAppToken(x *xorm.Engine) error { return err } - if err := sess.Sync2(new(AccessToken)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(AccessToken)); err != nil { + return fmt.Errorf("Sync: %w", err) } if err := sess.Commit(); err != nil { @@ -112,8 +112,8 @@ func resyncHashAppTokenWithUniqueHash(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return err } - if err := sess.Sync2(new(AccessToken)); err != nil { - return fmt.Errorf("Sync2: %w", err) + if err := sess.Sync(new(AccessToken)); err != nil { + return fmt.Errorf("Sync: %w", err) } return sess.Commit() } diff --git a/models/migrations/v1_9/v86.go b/models/migrations/v1_9/v86.go index a2a2c042c0bac..cf2725d15854d 100644 --- a/models/migrations/v1_9/v86.go +++ b/models/migrations/v1_9/v86.go @@ -12,5 +12,5 @@ func AddHTTPMethodToWebhook(x *xorm.Engine) error { HTTPMethod string `xorm:"http_method DEFAULT 'POST'"` } - return x.Sync2(new(Webhook)) + return x.Sync(new(Webhook)) } diff --git a/models/migrations/v1_9/v87.go b/models/migrations/v1_9/v87.go index b373a40bc07fb..fa01b6e5e3694 100644 --- a/models/migrations/v1_9/v87.go +++ b/models/migrations/v1_9/v87.go @@ -13,5 +13,5 @@ func AddAvatarFieldToRepository(x *xorm.Engine) error { Avatar string `xorm:"VARCHAR(64)"` } - return x.Sync2(new(Repository)) + return x.Sync(new(Repository)) } From 389fb754a24948cbe90b09104f341f5fc5d7e3d5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 14 Aug 2023 04:09:25 +0800 Subject: [PATCH 20/24] Fix storage path logic especially for relative paths (#26441) This PR rewrites the function `getStorage` and make it more clear. Include tests from #26435, thanks @earl-warren --------- Co-authored-by: Earl Warren --- modules/setting/storage.go | 224 +++++++++++++++++++------------- modules/setting/storage_test.go | 163 +++++++++++++++++++++++ 2 files changed, 294 insertions(+), 93 deletions(-) diff --git a/modules/setting/storage.go b/modules/setting/storage.go index c28f2be4ed714..cc3a2899d76ed 100644 --- a/modules/setting/storage.go +++ b/modules/setting/storage.go @@ -91,134 +91,172 @@ func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*S return nil, errors.New("no name for storage") } - var targetSec ConfigSection - // check typ first - if typ != "" { - var err error - targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ) - if err != nil { - if !IsValidStorageType(StorageType(typ)) { - return nil, fmt.Errorf("get section via storage type %q failed: %v", typ, err) - } + targetSec, tp, err := getStorageTargetSection(rootCfg, name, typ, sec) + if err != nil { + return nil, err + } + + overrideSec := getStorageOverrideSection(rootCfg, targetSec, sec, tp, name) + + targetType := targetSec.Key("STORAGE_TYPE").String() + switch targetType { + case string(LocalStorageType): + return getStorageForLocal(targetSec, overrideSec, tp, name) + case string(MinioStorageType): + return getStorageForMinio(targetSec, overrideSec, tp, name) + default: + return nil, fmt.Errorf("unsupported storage type %q", targetType) + } +} + +type targetSecType int + +const ( + targetSecIsTyp targetSecType = iota // target section is [storage.type] which the type from parameter + targetSecIsStorage // target section is [storage] + targetSecIsDefault // target section is the default value + targetSecIsStorageWithName // target section is [storage.name] + targetSecIsSec // target section is from the name seciont [name] +) + +func getStorageSectionByType(rootCfg ConfigProvider, typ string) (ConfigSection, targetSecType, error) { + targetSec, err := rootCfg.GetSection(storageSectionName + "." + typ) + if err != nil { + if !IsValidStorageType(StorageType(typ)) { + return nil, 0, fmt.Errorf("get section via storage type %q failed: %v", typ, err) } - if targetSec != nil { - targetType := targetSec.Key("STORAGE_TYPE").String() - if targetType == "" { - if !IsValidStorageType(StorageType(typ)) { - return nil, fmt.Errorf("unknow storage type %q", typ) - } - targetSec.Key("STORAGE_TYPE").SetValue(typ) - } else if !IsValidStorageType(StorageType(targetType)) { - return nil, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ) - } + // if typ is a valid storage type, but there is no [storage.local] or [storage.minio] section + // it's not an error + return nil, 0, nil + } + + targetType := targetSec.Key("STORAGE_TYPE").String() + if targetType == "" { + if !IsValidStorageType(StorageType(typ)) { + return nil, 0, fmt.Errorf("unknow storage type %q", typ) } + targetSec.Key("STORAGE_TYPE").SetValue(typ) + } else if !IsValidStorageType(StorageType(targetType)) { + return nil, 0, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ) } - if targetSec == nil && sec != nil { - secTyp := sec.Key("STORAGE_TYPE").String() - if IsValidStorageType(StorageType(secTyp)) { - targetSec = sec - } else if secTyp != "" { - targetSec, _ = rootCfg.GetSection(storageSectionName + "." + secTyp) + return targetSec, targetSecIsTyp, nil +} + +func getStorageTargetSection(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (ConfigSection, targetSecType, error) { + // check typ first + if typ == "" { + if sec != nil { // check sec's type secondly + typ = sec.Key("STORAGE_TYPE").String() + if IsValidStorageType(StorageType(typ)) { + if targetSec, _ := rootCfg.GetSection(storageSectionName + "." + typ); targetSec == nil { + return sec, targetSecIsSec, nil + } + } } } - targetSecIsStoragename := false - storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name) - if targetSec == nil { - targetSec = storageNameSec - targetSecIsStoragename = storageNameSec != nil + if typ != "" { + targetSec, tp, err := getStorageSectionByType(rootCfg, typ) + if targetSec != nil || err != nil { + return targetSec, tp, err + } } - if targetSec == nil { - targetSec = getDefaultStorageSection(rootCfg) - } else { + // check stoarge name thirdly + targetSec, _ := rootCfg.GetSection(storageSectionName + "." + name) + if targetSec != nil { targetType := targetSec.Key("STORAGE_TYPE").String() switch { case targetType == "": - if targetSec != storageNameSec && storageNameSec != nil { - targetSec = storageNameSec - targetSecIsStoragename = true - if targetSec.Key("STORAGE_TYPE").String() == "" { - return nil, fmt.Errorf("storage section %s.%s has no STORAGE_TYPE", storageSectionName, name) - } - } else { - if targetSec.Key("PATH").String() == "" { - targetSec = getDefaultStorageSection(rootCfg) - } else { - targetSec.Key("STORAGE_TYPE").SetValue("local") - } + if targetSec.Key("PATH").String() == "" { // both storage type and path are empty, use default + return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil } + + targetSec.Key("STORAGE_TYPE").SetValue("local") default: - newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType) - if newTargetSec == nil { - if !IsValidStorageType(StorageType(targetType)) { - return nil, fmt.Errorf("invalid storage section %s.%q", storageSectionName, targetType) - } - } else { - targetSec = newTargetSec - if IsValidStorageType(StorageType(targetType)) { - tp := targetSec.Key("STORAGE_TYPE").String() - if tp == "" { - targetSec.Key("STORAGE_TYPE").SetValue(targetType) - } - } + targetSec, tp, err := getStorageSectionByType(rootCfg, targetType) + if targetSec != nil || err != nil { + return targetSec, tp, err } } + + return targetSec, targetSecIsStorageWithName, nil } - targetType := targetSec.Key("STORAGE_TYPE").String() - if !IsValidStorageType(StorageType(targetType)) { - return nil, fmt.Errorf("invalid storage type %q", targetType) + return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil +} + +// getStorageOverrideSection override section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible +func getStorageOverrideSection(rootConfig ConfigProvider, targetSec, sec ConfigSection, targetSecType targetSecType, name string) ConfigSection { + if targetSecType == targetSecIsSec { + return nil } - // extra config section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible - extraConfigSec := sec - if extraConfigSec == nil { - extraConfigSec = storageNameSec + if sec != nil { + return sec } - var storage Storage - storage.Type = StorageType(targetType) + if targetSecType != targetSecIsStorageWithName { + nameSec, _ := rootConfig.GetSection(storageSectionName + "." + name) + return nameSec + } + return nil +} - switch targetType { - case string(LocalStorageType): - targetPath := ConfigSectionKeyString(targetSec, "PATH", "") - if targetPath == "" { - targetPath = AppDataPath - } else if !filepath.IsAbs(targetPath) { - targetPath = filepath.Join(AppDataPath, targetPath) - } +func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) { + storage := Storage{ + Type: StorageType(targetSec.Key("STORAGE_TYPE").String()), + } - var fallbackPath string - if targetSecIsStoragename { - fallbackPath = targetPath - } else { + targetPath := ConfigSectionKeyString(targetSec, "PATH", "") + var fallbackPath string + if targetPath == "" { // no path + fallbackPath = filepath.Join(AppDataPath, name) + } else { + if tp == targetSecIsStorage || tp == targetSecIsDefault { fallbackPath = filepath.Join(targetPath, name) + } else { + fallbackPath = targetPath + } + if !filepath.IsAbs(fallbackPath) { + fallbackPath = filepath.Join(AppDataPath, fallbackPath) } + } - if extraConfigSec == nil { + if overrideSec == nil { // no override section + storage.Path = fallbackPath + } else { + storage.Path = ConfigSectionKeyString(overrideSec, "PATH", "") + if storage.Path == "" { // overrideSec has no path storage.Path = fallbackPath - } else { - storage.Path = ConfigSectionKeyString(extraConfigSec, "PATH", fallbackPath) - if !filepath.IsAbs(storage.Path) { + } else if !filepath.IsAbs(storage.Path) { + if targetPath == "" { + storage.Path = filepath.Join(AppDataPath, storage.Path) + } else { storage.Path = filepath.Join(targetPath, storage.Path) } } + } - case string(MinioStorageType): - if err := targetSec.MapTo(&storage.MinioConfig); err != nil { - return nil, fmt.Errorf("map minio config failed: %v", err) - } + return &storage, nil +} - storage.MinioConfig.BasePath = name + "/" +func getStorageForMinio(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) { + var storage Storage + storage.Type = StorageType(targetSec.Key("STORAGE_TYPE").String()) + if err := targetSec.MapTo(&storage.MinioConfig); err != nil { + return nil, fmt.Errorf("map minio config failed: %v", err) + } - if extraConfigSec != nil { - storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect) - storage.MinioConfig.BasePath = ConfigSectionKeyString(extraConfigSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath) - storage.MinioConfig.Bucket = ConfigSectionKeyString(extraConfigSec, "MINIO_BUCKET", storage.MinioConfig.Bucket) - } + if storage.MinioConfig.BasePath == "" { + storage.MinioConfig.BasePath = name + "/" } + if overrideSec != nil { + storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(overrideSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect) + storage.MinioConfig.BasePath = ConfigSectionKeyString(overrideSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath) + storage.MinioConfig.Bucket = ConfigSectionKeyString(overrideSec, "MINIO_BUCKET", storage.MinioConfig.Bucket) + } return &storage, nil } diff --git a/modules/setting/storage_test.go b/modules/setting/storage_test.go index 9a83f31d918b4..20886d4c4e959 100644 --- a/modules/setting/storage_test.go +++ b/modules/setting/storage_test.go @@ -27,12 +27,15 @@ MINIO_BUCKET = gitea-storage assert.NoError(t, loadAttachmentFrom(cfg)) assert.EqualValues(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket) + assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath) assert.NoError(t, loadLFSFrom(cfg)) assert.EqualValues(t, "gitea-lfs", LFS.Storage.MinioConfig.Bucket) + assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath) assert.NoError(t, loadAvatarsFrom(cfg)) assert.EqualValues(t, "gitea-storage", Avatar.Storage.MinioConfig.Bucket) + assert.EqualValues(t, "avatars/", Avatar.Storage.MinioConfig.BasePath) } func Test_getStorageUseOtherNameAsType(t *testing.T) { @@ -49,9 +52,11 @@ MINIO_BUCKET = gitea-storage assert.NoError(t, loadAttachmentFrom(cfg)) assert.EqualValues(t, "gitea-storage", Attachment.Storage.MinioConfig.Bucket) + assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath) assert.NoError(t, loadLFSFrom(cfg)) assert.EqualValues(t, "gitea-storage", LFS.Storage.MinioConfig.Bucket) + assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath) } func Test_getStorageInheritStorageType(t *testing.T) { @@ -117,6 +122,9 @@ func Test_getStorageInheritStorageTypeLocal(t *testing.T) { [storage] STORAGE_TYPE = local `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"}, + {loadLFSFrom, &LFS.Storage, "/appdata/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/appdata/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/repo-archive"}, {loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"}, @@ -131,6 +139,9 @@ func Test_getStorageInheritStorageTypeLocalPath(t *testing.T) { STORAGE_TYPE = local PATH = /data/gitea `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"}, + {loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"}, {loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"}, @@ -145,6 +156,9 @@ func Test_getStorageInheritStorageTypeLocalRelativePath(t *testing.T) { STORAGE_TYPE = local PATH = storages `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/appdata/storages/attachments"}, + {loadLFSFrom, &LFS.Storage, "/appdata/storages/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/appdata/storages/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/appdata/storages/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/storages/repo-archive"}, {loadActionsFrom, &Actions.LogStorage, "/appdata/storages/actions_log"}, @@ -162,6 +176,9 @@ PATH = /data/gitea [repo-archive] PATH = /data/gitea/the-archives-dir `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"}, + {loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"}, {loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"}, @@ -178,6 +195,9 @@ PATH = /data/gitea [repo-archive] `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"}, + {loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"}, {loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"}, @@ -195,6 +215,9 @@ PATH = /data/gitea [repo-archive] PATH = the-archives-dir `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"}, + {loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"}, {loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"}, @@ -209,6 +232,9 @@ func Test_getStorageInheritStorageTypeLocalPathOverride3(t *testing.T) { STORAGE_TYPE = local PATH = /data/gitea/archives `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"}, + {loadLFSFrom, &LFS.Storage, "/appdata/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/appdata/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"}, {loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"}, @@ -217,6 +243,23 @@ PATH = /data/gitea/archives }) } +func Test_getStorageInheritStorageTypeLocalPathOverride3_5(t *testing.T) { + testLocalStoragePath(t, "/appdata", ` +[storage.repo-archive] +STORAGE_TYPE = local +PATH = a-relative-path +`, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"}, + {loadLFSFrom, &LFS.Storage, "/appdata/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"}, + {loadPackagesFrom, &Packages.Storage, "/appdata/packages"}, + {loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/a-relative-path"}, + {loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"}, + {loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"}, + {loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"}, + }) +} + func Test_getStorageInheritStorageTypeLocalPathOverride4(t *testing.T) { testLocalStoragePath(t, "/appdata", ` [storage.repo-archive] @@ -226,6 +269,9 @@ PATH = /data/gitea/archives [repo-archive] PATH = /tmp/gitea/archives `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"}, + {loadLFSFrom, &LFS.Storage, "/appdata/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/appdata/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/tmp/gitea/archives"}, {loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"}, @@ -242,6 +288,9 @@ PATH = /data/gitea/archives [repo-archive] `, []testLocalStoragePathCase{ + {loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"}, + {loadLFSFrom, &LFS.Storage, "/appdata/lfs"}, + {loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"}, {loadPackagesFrom, &Packages.Storage, "/appdata/packages"}, {loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"}, {loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"}, @@ -249,3 +298,117 @@ PATH = /data/gitea/archives {loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"}, }) } + +func Test_getStorageInheritStorageTypeLocalPathOverride72(t *testing.T) { + testLocalStoragePath(t, "/appdata", ` +[repo-archive] +STORAGE_TYPE = local +PATH = archives +`, []testLocalStoragePathCase{ + {loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/archives"}, + }) +} + +func Test_getStorageConfiguration20(t *testing.T) { + cfg, err := NewConfigProviderFromData(` +[repo-archive] +STORAGE_TYPE = my_storage +PATH = archives +`) + assert.NoError(t, err) + + assert.Error(t, loadRepoArchiveFrom(cfg)) +} + +func Test_getStorageConfiguration21(t *testing.T) { + testLocalStoragePath(t, "/appdata", ` +[storage.repo-archive] +`, []testLocalStoragePathCase{ + {loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/repo-archive"}, + }) +} + +func Test_getStorageConfiguration22(t *testing.T) { + testLocalStoragePath(t, "/appdata", ` +[storage.repo-archive] +PATH = archives +`, []testLocalStoragePathCase{ + {loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/archives"}, + }) +} + +func Test_getStorageConfiguration23(t *testing.T) { + cfg, err := NewConfigProviderFromData(` +[repo-archive] +STORAGE_TYPE = minio +MINIO_ACCESS_KEY_ID = my_access_key +MINIO_SECRET_ACCESS_KEY = my_secret_key +`) + assert.NoError(t, err) + + _, err = getStorage(cfg, "", "", nil) + assert.Error(t, err) + + assert.NoError(t, loadRepoArchiveFrom(cfg)) + cp := RepoArchive.Storage.ToShadowCopy() + assert.EqualValues(t, "******", cp.MinioConfig.AccessKeyID) + assert.EqualValues(t, "******", cp.MinioConfig.SecretAccessKey) +} + +func Test_getStorageConfiguration24(t *testing.T) { + cfg, err := NewConfigProviderFromData(` +[repo-archive] +STORAGE_TYPE = my_archive + +[storage.my_archive] +; unsupported, storage type should be defined explicitly +PATH = archives +`) + assert.NoError(t, err) + assert.Error(t, loadRepoArchiveFrom(cfg)) +} + +func Test_getStorageConfiguration25(t *testing.T) { + cfg, err := NewConfigProviderFromData(` +[repo-archive] +STORAGE_TYPE = my_archive + +[storage.my_archive] +; unsupported, storage type should be known type +STORAGE_TYPE = unknown // should be local or minio +PATH = archives +`) + assert.NoError(t, err) + assert.Error(t, loadRepoArchiveFrom(cfg)) +} + +func Test_getStorageConfiguration26(t *testing.T) { + cfg, err := NewConfigProviderFromData(` +[repo-archive] +STORAGE_TYPE = minio +MINIO_ACCESS_KEY_ID = my_access_key +MINIO_SECRET_ACCESS_KEY = my_secret_key +; wrong configuration +MINIO_USE_SSL = abc +`) + assert.NoError(t, err) + // assert.Error(t, loadRepoArchiveFrom(cfg)) + // FIXME: this should return error but now ini package's MapTo() doesn't check type + assert.NoError(t, loadRepoArchiveFrom(cfg)) +} + +func Test_getStorageConfiguration27(t *testing.T) { + cfg, err := NewConfigProviderFromData(` +[storage.repo-archive] +STORAGE_TYPE = minio +MINIO_ACCESS_KEY_ID = my_access_key +MINIO_SECRET_ACCESS_KEY = my_secret_key +MINIO_USE_SSL = true +`) + assert.NoError(t, err) + assert.NoError(t, loadRepoArchiveFrom(cfg)) + assert.EqualValues(t, "my_access_key", RepoArchive.Storage.MinioConfig.AccessKeyID) + assert.EqualValues(t, "my_secret_key", RepoArchive.Storage.MinioConfig.SecretAccessKey) + assert.EqualValues(t, true, RepoArchive.Storage.MinioConfig.UseSSL) + assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath) +} From 7456573541c0c01314690e4a40bc4b5ec6faf79e Mon Sep 17 00:00:00 2001 From: Denys Konovalov Date: Mon, 14 Aug 2023 03:15:16 +0200 Subject: [PATCH 21/24] fix grab cursor on default column (#26476) Fix https://github.com/go-gitea/gitea/pull/26448#issuecomment-1676194200 I accidentally set grab cursor for project columns instead of issue cards, which actually turned out not to be a problem - with proper check for the default column, which can't be moved. --------- Co-authored-by: delvh Co-authored-by: Giteabot --- templates/projects/view.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 97869ca262991..700b40c39b9fb 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -167,9 +167,9 @@
-
+
{{range (index $.IssuesMap .ID)}} -
+
{{template "repo/issue/card" (dict "Issue" . "Page" $)}}
{{end}} From 56b6b2b88ef175cc18d2ccdb86c220e885a24262 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 14 Aug 2023 04:16:40 +0200 Subject: [PATCH 22/24] Fix tooltip of commit select button (#26472) Previously, the tooltip for this button was only shown after opening and closing it once because it was only set after the server response, now it shows before opening it. --- routers/web/repo/pull.go | 1 - templates/repo/diff/box.tmpl | 2 +- web_src/js/components/DiffCommitSelector.vue | 5 ++++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index be4e9711e74db..e3854779fe258 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -718,7 +718,6 @@ func GetPullCommits(ctx *context.Context) { // Get the needed locale resp.Locale = map[string]string{ "lang": ctx.Locale.Language(), - "filter_changes_by_commit": ctx.Tr("repo.pulls.filter_changes_by_commit"), "show_all_commits": ctx.Tr("repo.pulls.show_all_commits"), "stats_num_commits": ctx.TrN(len(commits), "repo.activity.git_stats_commit_1", "repo.activity.git_stats_commit_n", len(commits)), "show_changes_since_your_last_review": ctx.Tr("repo.pulls.show_changes_since_your_last_review"), diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index 324166b03c1da..7b936cb8174e3 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -32,7 +32,7 @@ {{template "repo/diff/whitespace_dropdown" .}} {{template "repo/diff/options_dropdown" .}} {{if .PageIsPullFiles}} -
+
{{/* the following will be replaced by vue component but this avoids any loading artifacts till the vue component is initialized diff --git a/web_src/js/components/DiffCommitSelector.vue b/web_src/js/components/DiffCommitSelector.vue index a0fc4b2a9183d..e24619dc081a4 100644 --- a/web_src/js/components/DiffCommitSelector.vue +++ b/web_src/js/components/DiffCommitSelector.vue @@ -77,10 +77,13 @@ import {SvgIcon} from '../svg.js'; export default { components: {SvgIcon}, data: () => { + const el = document.getElementById('diff-commit-select'); return { menuVisible: false, isLoading: false, - locale: {}, + locale: { + filter_changes_by_commit: el.getAttribute('data-filter_changes_by_commit'), + }, commits: [], hoverActivated: false, lastReviewCommitSha: null From ecd51f710b7b08eddc952d518f0d097367221388 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Mon, 14 Aug 2023 04:50:55 +0200 Subject: [PATCH 23/24] Fix NuGet search endpoints (#25613) Fixes #25564 Fixes #23191 - Api v2 search endpoint should return only the latest version matching the query - Api v3 search endpoint should return `take` packages not package versions --- models/db/common.go | 16 +++++ models/packages/nuget/search.go | 70 ++++++++++++++++++++ models/packages/package_version.go | 10 +-- routers/api/packages/nuget/api_v3.go | 13 +++- routers/api/packages/nuget/nuget.go | 9 ++- tests/integration/api_packages_nuget_test.go | 18 ++--- 6 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 models/packages/nuget/search.go diff --git a/models/db/common.go b/models/db/common.go index 2a5043a8e7849..ea628bf2a0a96 100644 --- a/models/db/common.go +++ b/models/db/common.go @@ -37,3 +37,19 @@ func BuildCaseInsensitiveIn(key string, values []string) builder.Cond { return builder.In("UPPER("+key+")", uppers) } + +// BuilderDialect returns the xorm.Builder dialect of the engine +func BuilderDialect() string { + switch { + case setting.Database.Type.IsMySQL(): + return builder.MYSQL + case setting.Database.Type.IsSQLite3(): + return builder.SQLITE + case setting.Database.Type.IsPostgreSQL(): + return builder.POSTGRES + case setting.Database.Type.IsMSSQL(): + return builder.MSSQL + default: + return "" + } +} diff --git a/models/packages/nuget/search.go b/models/packages/nuget/search.go new file mode 100644 index 0000000000000..53cdf2d4ad89e --- /dev/null +++ b/models/packages/nuget/search.go @@ -0,0 +1,70 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package nuget + +import ( + "context" + "strings" + + "code.gitea.io/gitea/models/db" + packages_model "code.gitea.io/gitea/models/packages" + + "xorm.io/builder" +) + +// SearchVersions gets all versions of packages matching the search options +func SearchVersions(ctx context.Context, opts *packages_model.PackageSearchOptions) ([]*packages_model.PackageVersion, int64, error) { + cond := toConds(opts) + + e := db.GetEngine(ctx) + + total, err := e. + Where(cond). + Count(&packages_model.Package{}) + if err != nil { + return nil, 0, err + } + + inner := builder. + Dialect(db.BuilderDialect()). // builder needs the sql dialect to build the Limit() below + Select("*"). + From("package"). + Where(cond). + OrderBy("package.name ASC") + if opts.Paginator != nil { + skip, take := opts.GetSkipTake() + inner = inner.Limit(take, skip) + } + + sess := e. + Where(opts.ToConds()). + Table("package_version"). + Join("INNER", inner, "package.id = package_version.package_id") + + pvs := make([]*packages_model.PackageVersion, 0, 10) + return pvs, total, sess.Find(&pvs) +} + +// CountPackages counts all packages matching the search options +func CountPackages(ctx context.Context, opts *packages_model.PackageSearchOptions) (int64, error) { + return db.GetEngine(ctx). + Where(toConds(opts)). + Count(&packages_model.Package{}) +} + +func toConds(opts *packages_model.PackageSearchOptions) builder.Cond { + var cond builder.Cond = builder.Eq{ + "package.is_internal": opts.IsInternal.IsTrue(), + "package.owner_id": opts.OwnerID, + "package.type": packages_model.TypeNuGet, + } + if opts.Name.Value != "" { + if opts.Name.ExactMatch { + cond = cond.And(builder.Eq{"package.lower_name": strings.ToLower(opts.Name.Value)}) + } else { + cond = cond.And(builder.Like{"package.lower_name", strings.ToLower(opts.Name.Value)}) + } + } + return cond +} diff --git a/models/packages/package_version.go b/models/packages/package_version.go index ab1bcddae5818..4392c70f79bca 100644 --- a/models/packages/package_version.go +++ b/models/packages/package_version.go @@ -189,7 +189,7 @@ type PackageSearchOptions struct { db.Paginator } -func (opts *PackageSearchOptions) toConds() builder.Cond { +func (opts *PackageSearchOptions) ToConds() builder.Cond { cond := builder.NewCond() if !opts.IsInternal.IsNone() { cond = builder.Eq{ @@ -283,7 +283,7 @@ func (opts *PackageSearchOptions) configureOrderBy(e db.Engine) { // SearchVersions gets all versions of packages matching the search options func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) { sess := db.GetEngine(ctx). - Where(opts.toConds()). + Where(opts.ToConds()). Table("package_version"). Join("INNER", "package", "package.id = package_version.package_id") @@ -300,7 +300,7 @@ func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*Package // SearchLatestVersions gets the latest version of every package matching the search options func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) { - cond := opts.toConds(). + cond := opts.ToConds(). And(builder.Expr("pv2.id IS NULL")) joinCond := builder.Expr("package_version.package_id = pv2.package_id AND (package_version.created_unix < pv2.created_unix OR (package_version.created_unix = pv2.created_unix AND package_version.id < pv2.id))") @@ -328,7 +328,7 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P // 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()). + Where(opts.ToConds()). Table("package_version"). Join("INNER", "package", "package.id = package_version.package_id"). Exist(new(PackageVersion)) @@ -337,7 +337,7 @@ func ExistVersion(ctx context.Context, opts *PackageSearchOptions) (bool, error) // CountVersions counts all versions of packages matching the search options func CountVersions(ctx context.Context, opts *PackageSearchOptions) (int64, error) { return db.GetEngine(ctx). - Where(opts.toConds()). + Where(opts.ToConds()). Table("package_version"). Join("INNER", "package", "package.id = package_version.package_id"). Count(new(PackageVersion)) diff --git a/routers/api/packages/nuget/api_v3.go b/routers/api/packages/nuget/api_v3.go index af52125e2e4dc..2fe25dc0f805d 100644 --- a/routers/api/packages/nuget/api_v3.go +++ b/routers/api/packages/nuget/api_v3.go @@ -9,6 +9,9 @@ import ( packages_model "code.gitea.io/gitea/models/packages" nuget_module "code.gitea.io/gitea/modules/packages/nuget" + + "golang.org/x/text/collate" + "golang.org/x/text/language" ) // https://docs.microsoft.com/en-us/nuget/api/service-index#resources @@ -207,9 +210,15 @@ func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages grouped[pd.Package.Name] = append(grouped[pd.Package.Name], pd) } + keys := make([]string, 0, len(grouped)) + for key := range grouped { + keys = append(keys, key) + } + collate.New(language.English, collate.IgnoreCase).SortStrings(keys) + data := make([]*SearchResult, 0, len(pds)) - for _, group := range grouped { - data = append(data, createSearchResult(l, group)) + for _, key := range keys { + data = append(data, createSearchResult(l, grouped[key])) } return &SearchResultResponse{ diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go index 9c97ba8e776f7..6f63c1d4c21f9 100644 --- a/routers/api/packages/nuget/nuget.go +++ b/routers/api/packages/nuget/nuget.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/db" packages_model "code.gitea.io/gitea/models/packages" + nuget_model "code.gitea.io/gitea/models/packages/nuget" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" packages_module "code.gitea.io/gitea/modules/packages" @@ -115,7 +116,7 @@ func SearchServiceV2(ctx *context.Context) { skip, take := ctx.FormInt("$skip"), ctx.FormInt("$top") paginator := db.NewAbsoluteListOptions(skip, take) - pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ + pvs, total, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{ OwnerID: ctx.Package.Owner.ID, Type: packages_model.TypeNuGet, Name: packages_model.SearchValue{ @@ -166,9 +167,8 @@ func SearchServiceV2(ctx *context.Context) { // http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351 func SearchServiceV2Count(ctx *context.Context) { - count, err := packages_model.CountVersions(ctx, &packages_model.PackageSearchOptions{ + count, err := nuget_model.CountPackages(ctx, &packages_model.PackageSearchOptions{ OwnerID: ctx.Package.Owner.ID, - Type: packages_model.TypeNuGet, Name: packages_model.SearchValue{ Value: getSearchTerm(ctx), }, @@ -184,9 +184,8 @@ func SearchServiceV2Count(ctx *context.Context) { // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-for-packages func SearchServiceV3(ctx *context.Context) { - pvs, count, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ + pvs, count, err := nuget_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ OwnerID: ctx.Package.Owner.ID, - Type: packages_model.TypeNuGet, Name: packages_model.SearchValue{Value: ctx.FormTrim("q")}, IsInternal: util.OptionalBoolFalse, Paginator: db.NewAbsoluteListOptions( diff --git a/tests/integration/api_packages_nuget_test.go b/tests/integration/api_packages_nuget_test.go index e4ea92ee11112..520d1dd0a70d9 100644 --- a/tests/integration/api_packages_nuget_test.go +++ b/tests/integration/api_packages_nuget_test.go @@ -414,6 +414,10 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) {"test", 1, 10, 1, 0}, } + req := NewRequestWithBody(t, "PUT", url, createPackage(packageName, "1.0.99")) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusCreated) + t.Run("v2", func(t *testing.T) { t.Run("Search()", func(t *testing.T) { defer tests.PrintCurrentTest(t)() @@ -493,10 +497,6 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusCreated) - req = NewRequestWithBody(t, "PUT", url, createPackage(packageName, "1.0.99")) - req = AddBasicAuthHeader(req, user.Name) - MakeRequest(t, req, http.StatusCreated) - req = NewRequest(t, "GET", fmt.Sprintf("%s/query?q=%s", url, packageName)) req = AddBasicAuthHeader(req, user.Name) resp := MakeRequest(t, req, http.StatusOK) @@ -504,7 +504,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) var result nuget.SearchResultResponse DecodeJSON(t, resp, &result) - assert.EqualValues(t, 3, result.TotalHits) + assert.EqualValues(t, 2, result.TotalHits) assert.Len(t, result.Data, 2) for _, sr := range result.Data { if sr.ID == packageName { @@ -517,12 +517,12 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName+".dummy", "1.0.0")) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusNoContent) - - req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, "1.0.99")) - req = AddBasicAuthHeader(req, user.Name) - MakeRequest(t, req, http.StatusNoContent) }) }) + + req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, "1.0.99")) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusNoContent) }) t.Run("RegistrationService", func(t *testing.T) { From db7b0a1a4ef2222ca6209c190b2283f27061db55 Mon Sep 17 00:00:00 2001 From: CaiCandong <50507092+CaiCandong@users.noreply.github.com> Date: Mon, 14 Aug 2023 13:35:49 +0800 Subject: [PATCH 24/24] Update zh-cn documentation (#26406) --- .../config-cheat-sheet.zh-cn.md | 1546 +++++++++++++---- docs/content/index.zh-cn.md | 55 +- docs/content/installation/comparison.zh-cn.md | 91 +- .../content/installation/from-binary.zh-cn.md | 40 + .../installation/from-package.zh-cn.md | 8 + .../installation/upgrade-from-gogs.zh-cn.md | 87 +- .../installation/windows-service.zh-cn.md | 35 +- docs/content/usage/permissions.zh-cn.md | 39 +- docs/content/usage/pull-request.zh-cn.md | 40 +- docs/content/usage/repo-mirror.zh-cn.md | 13 + .../usage/template-repositories.zh-cn.md | 2 + 11 files changed, 1513 insertions(+), 443 deletions(-) diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index a2fa25df92968..87e45aa6934d0 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -17,344 +17,1086 @@ menu: # 配置说明 -这是针对Gitea配置文件的说明,你可以了解Gitea的强大配置。需要说明的是,你的所有改变请修改 `custom/conf/app.ini` 文件而不是源文件。 +这是针对Gitea配置文件的说明, +你可以了解Gitea的强大配置。 + +需要说明的是,你的所有改变请修改 `custom/conf/app.ini` 文件而不是源文件。 +如果是从发行版本完成的安装, +配置文件的路径为`/etc/gitea/conf/app.ini`。 + 所有默认值可以通过 [app.example.ini](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini) 查看到。 -如果你发现 `%(X)s` 这样的内容,请查看 [ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。 +如果你发现 `%(X)s` 这样的内容,请查看 +[ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。 标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。 -## ⚠️时效性警告⚠️ - -此文档的内容可能过于陈旧或者错误,请参考英文文档。 +在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`enviroment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。 + +包含`#`或者`;`的变量必须使用引号(`` ` ``或者`""""`)包裹,否则会被解析为注释。 + +**注意:** 修改完配置文件后,需要重启 Gitea 服务才能生效。 + +## 默认配置 (非`app.ini`配置文件) + +这些值取决于环境,但构成了许多值的基础。当运行 `gitea help`或启动时,它们将 +作为默认配置的一部分进行报告。它们在那里发出的顺序略有不同,但我们将按照设置的顺序在这里列出。 + +- _`AppPath`_: Gitea二进制可执行文件的绝对路径 +- _`AppWorkPath`_: Gitea可执行文件的工作目录。 该配置可以通过以下几种方式设置,优先级依次递减: + - `app.ini`中的`WORK_PATH`配置项 + - 启动Gitea时的`--work-path`命令行参数 + - `$GITEA_WORK_DIR`环境变量 + - 在编译时设置的内置值(参见从源代码编译) + - 默认为 _`AppPath`_ 的目录 + - 如果上述任何路径为相对路径,将自动解析为相对于 _`AppPath`_ 目录的绝对路径 +- _`CustomPath`_: 这是用于自定义模板和其他选项的基础目录。 +它是通过使用以下层次结构中的第一个设置的内容来确定的: + - 通过传递给二进制文件的`--custom-path`标志 + - 环境变量 `$GITEA_CUSTOM` + - 在构建时设置的内置值(参见从源代码构建) + - 否则,默认为 _`AppWorkPath`_`/custom` + - 如果上述任何路径是相对路径,则会相对于 _`AppWorkPath`_ 目录进行处理, + 使其变为绝对路径。 +- _`CustomConf`_: 这是指向`app.ini`文件的路径。 + - 这是指向`app.ini`文件的路径。 + - 在构建时设置的内置值(参见从源代码构建) + - 否则,默认为 _`CustomPath`_`/conf/app.ini` + - 如果上述任何路径是相对路径,则会相对于_`CustomPath`_目录进行处理。 + +此外,还有_`StaticRootPath`_,可以在构建时设置为内置值,否则将默认为 _`AppWorkPath`_。 ## Overall (`DEFAULT`) -- `APP_NAME`: 应用名称,改成你希望的名字。 -- `RUN_USER`: 运行Gitea的用户,推荐使用 `git`;如果在你自己的个人电脑使用改成你自己的用户名。如果设置不正确,Gitea可能崩溃。 -- `RUN_MODE`: 从性能考虑,如果在产品级的服务上改成 `prod`。如果您使用安装向导安装的那么会自动设置为 `prod`。 +- `APP_NAME`: **Gitea: Git with a cup of tea** 应用名称,在网页的标题中显示。 +- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: 运行Gitea的用户, + 应当是一个专用的系统账户(非用户使用,推荐创建一个专用的`git`用户). 如果在你自己的个人电脑使用改成你自己的用户名。 + 该配置如果设置不正确,Gitea可能崩溃。 +- `RUN_MODE`: **prod**: 应用的运行模式,对运行性能和问题排除有影响: `dev` 或者 `prod`,默认为 `prod`。 `dev`模式有助于开发和问题排查, 除设置为`dev` 外,均被视为 `prod`. +- `WORK_PATH`: **_the-work-path_**: 工作目录, 前文有提及. + +## 仓库 (`repository`) + +- `ROOT`: **%(APP_DATA_PATH)s/gitea-repositories**: 存放git工程的根目录,建议填绝对路径。 + 相对路径将被解析为**_`AppWorkPath`_/%(ROOT)s**. +- `SCRIPT_TYPE`: **bash**: 服务器支持的Shell类型,通常是`bash`, + 但有些服务器也有可能是`sh`。 +- `DETECTED_CHARSETS_ORDER`: **UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, ISO-8859, windows-1252, ISO-8859, windows-1250, ISO-8859, ISO-8859, ISO-8859, windows-1253, ISO-8859, windows-1255, ISO-8859, windows-1251, windows-1256, KOI8-R, ISO-8859, windows-1254, Shift_JIS, GB18030, EUC-JP, EUC-KR, Big5, ISO-2022, ISO-2022, ISO-2022, IBM424_rtl, IBM424_ltr, IBM420_rtl, IBM420_ltr**: 检测到的字符集的决定性顺序 - 如果检测到的字符集具有相等的置信度,则优先选择列表中较早出现的字符集,而不是较晚出现的字符集。添加“defaults”将会将未命名的字符集放置在该点。 +- `ANSI_CHARSET`: **_empty_**: 默认的ANSI字符集,用于覆盖非UTF-8字符集。 +- `FORCE_PRIVATE`: **false**: 强制使每个新仓库变为私有。 +- `DEFAULT_PRIVATE`: **last**: 创建新仓库时默认为私有。 + \[last, private, public\] +- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 使用推送创建新仓库时默认为私有。 +- `MAX_CREATION_LIMIT`: **-1**: 每个用户的全局仓库创建上限, + `-1` 代表无限制. +- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: 要放置在列表顶部的指定许可证。 + 名称必须与 options/license 或 custom/options/license 中的文件名匹配。 +- `DISABLE_HTTP_GIT`: **false**: 禁用HTTP协议与仓库进行 + 交互的能力。 +- `USE_COMPAT_SSH_URI`: **false**: 当使用默认的SSH端口时,强制使用ssh://克隆URL, + 而不是scp-style uri。 +- `GO_GET_CLONE_URL_PROTOCOL`: **https**: 用于 "go get" 请求的值,返回仓库的URL作为https或ssh, + 默认为https。 +- `ACCESS_CONTROL_ALLOW_ORIGIN`: **_empty_**:用于 Access-Control-Allow-Origin 标头的值, +默认不提供。 +警告:如果您不提供正确的值,这可能对您的网站造成危害。 +- `DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH`: **false**: 如果非默认分支上的提交将问题标记为已关闭,则关闭该问题。 +- `ENABLE_PUSH_CREATE_USER`: **false**: 允许用户将本地存储库推送到Gitea,并为用户自动创建它们。 +- `ENABLE_PUSH_CREATE_ORG`: **false**: 允许用户将本地存储库推送到Gitea,并为组织自动创建它们。 +- `DISABLED_REPO_UNITS`: **_empty_**: 逗号分隔的全局禁用的仓库单元列表。允许的值是:: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions\] +- `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages**: 逗号分隔的默认新仓库单元列表。允许的值是:: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions\]. 注意:目前无法停用代码和发布。如果您指定了默认的仓库单元,您仍应将它们列出以保持未来的兼容性。外部wiki和问题跟踪器不能默认启用,因为它需要额外的设置。禁用的仓库单元将不会添加到新的仓库中,无论它是否在默认列表中。 +- `DEFAULT_FORK_REPO_UNITS`: **repo.code,repo.pulls**: 逗号分隔的默认分叉仓库单元列表。允许的值和规则与`DEFAULT_REPO_UNITS`相同。 +- `PREFIX_ARCHIVE_FILES`: **true**: 通过将存档文件放置在以仓库命名的目录中来添加前缀。 +- `DISABLE_MIGRATIONS`: **false**: 禁用迁移功能。 +- `DISABLE_STARS`: **false**: 禁用点赞功能。 +- `DEFAULT_BRANCH`: **main**: 所有仓库的默认分支名称。 +- `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: 允许非管理员用户认领未被认领的仓库。 +- `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: 允许非管理员用户删除未被认领的仓库。 +- `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: 不允许从用户界面下载源代码存档文件。 +- `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: 允许无限制得派生仓库。 + +### 仓库 - 编辑器 (`repository.editor`) + +- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,.livemd,**: 在 Monaco 编辑器中应该换行的文件扩展名列表。用逗号分隔扩展名。要对没有扩展名的文件进行换行,只需放置一个逗号。 +- `PREVIEWABLE_FILE_MODES`: **markdown**: 具有预览API的有效文件模式,例如 `api/v1/markdown`。用逗号分隔各个值。如果文件扩展名不匹配,编辑模式下的预览选项卡将不会显示。 + +### 仓库 - 合并请求 (`repository.pull-request`) + +- `WORK_IN_PROGRESS_PREFIXES`: **WIP:,\[WIP\]**: 在拉取请求标题中用于标记工作正在进行中的前缀列表。 +这些前缀在不区分大小写的情况下进行匹配。 +- `CLOSE_KEYWORDS`: **close**, **closes**, **closed**, **fix**, **fixes**, **fixed**, **resolve**, **resolves**, **resolved**: 在拉取请求评论中用于自动关闭相关问题的关键词列表。 +- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: 在拉取请求评论中用于自动重新打开相关问题的 +关键词列表。 +- `DEFAULT_MERGE_STYLE`: **merge**: 设置创建仓库的默认合并方式,可选: `merge`, `rebase`, `rebase-merge`, `squash` +- `DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT`: **50**: 在默认合并消息中,对于`squash`提交,最多包括此数量的提交。设置为 -1 以包括所有提交。 +- `DEFAULT_MERGE_MESSAGE_SIZE`: **5120**: 在默认的合并消息中,对于`squash`提交,限制提交消息的大小。设置为 `-1`以取消限制。仅在`POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`为`true`时使用。 +- `DEFAULT_MERGE_MESSAGE_ALL_AUTHORS`: **false**: 在默认合并消息中,对于`squash`提交,遍历所有提交以包括所有作者的`Co-authored-by`,否则仅使用限定列表中的作者。 +- `DEFAULT_MERGE_MESSAGE_MAX_APPROVERS`: **10**:在默认合并消息中,限制列出的审批者数量为`Reviewed-by`:。设置为 `-1` 以包括所有审批者。 +- `DEFAULT_MERGE_MESSAGE_OFFICIAL_APPROVERS_ONLY`: **true**: 在默认合并消息中,仅包括官方允许审查的审批者。 +- `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`: **false**: 在默认的 squash 合并消息中,包括构成拉取请求的所有提交的提交消息。 +- `ADD_CO_COMMITTER_TRAILERS`: **true**: 如果提交者与作者不匹配,在合并提交消息中添加`co-authored-by`和`co-committed-by`标记。 +- `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY`:使用三方合并方法测试`PR Patch`以发现是否存在冲突。如果此设置`true`,将使用`git apply`重新测试冲突的`PR Pathch` - 这是1.18(和之前版本)中的先前行为,但效率相对较低。如果发现需要此设置,请报告。 + +### 仓库 - 工单 (`repository.issue`) + +- `LOCK_REASONS`: **Too heated,Off-topic,Resolved,Spam**: 合并请求或工单被锁定的原因列表。 +- `MAX_PINNED`: **3**: 每个仓库的最大可固定工单数量。设置为0禁用固定工单。 + +### 仓库 - 文件上传 (`repository.upload`) + +- `ENABLED`: **true**: 是否启用仓库文件上传。 +- `TEMP_PATH`: **data/tmp/uploads**: 文件上传的临时保存路径(在Gitea重启的时候该目录会被清空)。 +- `ALLOWED_TYPES`: **_empty_**: 以逗号分割的列表,代表支持上传的文件类型。(`.zip`), mime类型 (`text/plain`) or 通配符类型 (`image/*`, `audio/*`, `video/*`). 为空或者 `*/*`代表允许所有类型文件。 +- `FILE_MAX_SIZE`: **3**: 每个文件的最大大小(MB)。 +- `MAX_FILES`: **5**: 每次上传的最大文件数。 + +### 仓库 - 版本发布 (`repository.release`) + +- `ALLOWED_TYPES`: **_empty_**: 允许发布的文件类型列表,用逗号分隔 。如压缩包类型(`.zip`), mime 类型 (`text/plain`) ,也支持通配符 (`image/*`, `audio/*`, `video/*`)。 空值或者 `*/*` 代表允许所有类型。 +- `DEFAULT_PAGING_NUM`: **10**: 默认的发布版本页面分页大小 +- 关于版本发布相关的附件设置,详见`附件`部分。 + +### 仓库 - Signing (`repository.signing`) + +- `SIGNING_KEY`: **default**: \[none, KEYID, default \]: 用于签名的密钥 +- `SIGNING_NAME` & `SIGNING_EMAIL`: 如果`SIGNING_KEY`提供了一个 KEYID,将使用这些作为签名者的姓名和电子邮件地址。这些应与密钥的公开姓名和电子邮件地址相匹配。 +- `INITIAL_COMMIT`: **always**: \[never, pubkey, twofa, always\]: 签名初始提交。 + - `never`: 永不签名 + - `pubkey`: 仅在用户具有公钥时签名 + - `twofa`: 仅在用户使用双因素身份验证登录时签名 + - `always`: 始终签名 + - 除了 never 和 always 之外的选项可以组合为逗号分隔的列表。 +- `DEFAULT_TRUST_MODEL`: **collaborator**: \[collaborator, committer, collaboratorcommitter\]: 用于验证提交的默认信任模型。 + - `collaborator`: 信任协作者密钥签名的签名。 + - `committer`: 信任与提交者匹配的签名(这与GitHub匹配,并会强制Gitea签名的提交具有Gitea作为提交者)。 + - `collaboratorcommitter`: 信任与提交者匹配的协作者密钥签名的签名。 +- `WIKI`: **never**: \[never, pubkey, twofa, always, parentsigned\]: 对wiki提交进行签名。 +- `CRUD_ACTIONS`: **pubkey, twofa, parentsigned**: \[never, pubkey, twofa, parentsigned, always\]: 对CRUD操作进行签名。 + - 与上面相同的选项,增加了: + - `parentsigned`: 仅在父提交进行了签名时才进行签名。 +- `MERGES`: **pubkey, twofa, basesigned, commitssigned**: \[never, pubkey, twofa, approved, basesigned, commitssigned, always\]: 对合并操作进行签名。 + - `approved`: 仅对已批准的合并操作进行签名,适用于受保护的分支。 + - `basesigned`: 仅在基础仓库的父提交进行了签名时才进行签名。 + - `headsigned`: 仅在头分支的头提交进行了签名时才进行签名。 + - `commitssigned`: 仅在头分支中的所有提交到合并点都进行了签名时才进行签名。 + +### 仓库 - Local (`repository.local`) + +- `LOCAL_COPY_PATH`: **tmp/local-repo**:临时本地仓库副本的路径。默认为 tmp/local-repo(内容在 Gitea 重新启动时被删除) + +### 仓库 - MIME type mapping (`repository.mimetype_mapping`) + +配置用于根据可下载文件的文件扩展名设置预期的 MIME 类型。配置以键值对的形式呈现,文件扩展名以`.`开头。 + +以下配置在下载具有`.apk`文件扩展名的文件时设置`Content-Type: application/vnd.android.package-archive`头部。 -## Repository (`repository`) - -- `ROOT`: 存放git工程的根目录。这里必须填绝对路径,默认值是 `~//gitea-repositories`。 -- `SCRIPT_TYPE`: 服务器支持的Shell类型,通常是 `bash`,但有些服务器也有可能是 `sh`。 -- `ANSI_CHARSET`: 默认字符编码。 -- `FORCE_PRIVATE`: 强制所有git工程必须私有。 -- `DEFAULT_PRIVATE`: 默认创建的git工程为私有。 可以是`last`, `private` 或 `public`。默认值是 `last`表示用户最后创建的Repo的选择。 -- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 通过 ``push-to-create`` 方式创建的仓库是否默认为私有仓库. -- `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。 +```ini +.apk=application/vnd.android.package-archive +``` -### Repository - Release (`repository.release`) +## 跨域 (`cors`) -- `ALLOWED_TYPES`: **_empty_**: 允许扩展名的列表,用逗号分隔 (`.zip`), mime 类型 (`text/plain`) 或者匹配符号 (`image/*`, `audio/*`, `video/*`). 空值或者 `*/*` 允许所有类型。 -- `DEFAULT_PAGING_NUM`: **10**: 默认的发布版本页面分页。 +- `ENABLED`: **false**: 启用 CORS 头部(默认禁用) +- `SCHEME`: **http**: 允许请求的协议 +- `ALLOW_DOMAIN`: **\***: 允许请求的域名列表 +- `ALLOW_SUBDOMAIN`: **false**: 允许上述列出的头部的子域名发出请求。 +- `METHODS`: **GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS**: 允许发起的请求方式列表 +- `MAX_AGE`: **10m**: 缓存响应的最大时间 +- `ALLOW_CREDENTIALS`: **false**: 允许带有凭据的请求 +- `HEADERS`: **Content-Type,User-Agent**: 允许请求携带的头部 +- `X_FRAME_OPTIONS`: **SAMEORIGIN**: 详见 `X-Frame-Options`HTTP头部. -## UI (`ui`) +## 界面 (`ui`) -- `EXPLORE_PAGING_NUM`: 探索页面每页显示的仓库数量。 -- `ISSUE_PAGING_NUM`: 工单页面每页显示的工单数量。 +- `EXPLORE_PAGING_NUM`: **20**: 探索页面每页显示的仓库数量。 +- `ISSUE_PAGING_NUM`: **20**: 工单页面每页显示的工单数量。 - `MEMBERS_PAGING_NUM`: **20**: 组织成员页面每页显示的成员数量。 -- `FEED_MAX_COMMIT_NUM`: 活动流页面显示的最大提交数量。 +- `FEED_MAX_COMMIT_NUM`: **5**: 活动流页面显示的最大提交数量。 +- `FEED_PAGING_NUM`: **20**: 活动流页面显示的最大活动数量。 +- `SITEMAP_PAGING_NUM`: **20**: 在单个子SiteMap中显示的项数。 +- `GRAPH_MAX_COMMIT_NUM`: **100**: 提交图中显示的最大commit数量。 +- `CODE_COMMENT_LINES`: **4**: 在代码评论中能够显示的最大代码行数。 +- `DEFAULT_THEME`: **auto**: \[auto, gitea, arc-green\]: 在Gitea安装时候设置的默认主题。 +- `SHOW_USER_EMAIL`: **true**: 用户的电子邮件是否应该显示在`Explore Users`页面中。 +- `THEMES`: **auto,gitea,arc-green**: 所有可用的主题。允许用户选择个性化的主题, + 而不受DEFAULT_THEME 值的影响。 +- `MAX_DISPLAY_FILE_SIZE`: **8388608**: 能够显示文件的最大大小(默认为8MiB)。 +- `REACTIONS`: 用户可以在问题(Issue)、Pull Request(PR)以及评论中选择的所有可选的反应。 + 这些值可以是表情符号别名(例如::smile:)或Unicode表情符号。 + 对于自定义的反应,在 public/assets/img/emoji/ 目录下添加一个紧密裁剪的正方形图像,文件名为 reaction_name.png。 +- `CUSTOM_EMOJIS`: **gitea, codeberg, gitlab, git, github, gogs**: 不在utf8标准中定义的额外表情符号。 + 默认情况下,我们支持 Gitea 表情符号(:gitea:)。要添加更多表情符号,请将它们复制到 public/assets/img/emoji/ 目录下, + 并将其添加到此配置中。 +- `DEFAULT_SHOW_FULL_NAME`: **false**: 是否在可能的情况下显示用户的全名。如果没有设置全名,则将使用用户名。 +- `SEARCH_REPO_DESCRIPTION`: **true**: 是否在探索页面上的仓库搜索中搜索描述。 +- `ONLY_SHOW_RELEVANT_REPOS`: **false** 在没有指定关键字并使用默认排序时,是否仅在探索页面上显示相关的仓库。 + 如果一个仓库是分叉或者没有元数据(没有描述、图标、主题),则被视为不相关的仓库。 + +### 界面 - 管理员 (`ui.admin`) + +- `USER_PAGING_NUM`: **50**: 单页显示的用户数量。 +- `REPO_PAGING_NUM`: **50**: 单页显示的仓库数量。 +- `NOTICE_PAGING_NUM`: **25**: 单页显示的通知数量。 +- `ORG_PAGING_NUM`: **50**: 单页显示的组织数量。 + +### 界面 - 用户 (`ui.user`) -### UI - Admin (`ui.admin`) +- `REPO_PAGING_NUM`: **15**: 单页显示的仓库数量。 -- `USER_PAGING_NUM`: 用户管理页面每页显示的用户数量。 -- `REPO_PAGING_NUM`: 仓库管理页面每页显示的仓库数量。 -- `NOTICE_PAGING_NUM`: 系统提示页面每页显示的提示数量。 -- `ORG_PAGING_NUM`: 组织管理页面每页显示的组织数量。 +### 界面 - 元信息 (`ui.meta`) + +- `AUTHOR`: **Gitea - Git with a cup of tea**: 主页的作者元标签。 +- `DESCRIPTION`: **Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go**: 主页的描述元标签。 +- `KEYWORDS`: **go,git,self-hosted,gitea**: 首页关键词元标签。 + +### 界面 - 通知 (`ui.notification`) + +- `MIN_TIMEOUT`: **10s**: 这些选项控制通知端点定期轮询以更新通知计数。在页面加载后,通知计数将在` MIN_TIMEOUT`之后进行检查。如果通知计数未更改,超时时间将按照`TIMEOUT_STEP`增加到`MAX_TIMEOUT`。将 `MIN_TIMEOUT`设置为 -1 以关闭该功能。 +- `MAX_TIMEOUT`: **60s**. +- `TIMEOUT_STEP`: **10s**. +- `EVENT_SOURCE_UPDATE_TIME`: **10s**: 该设置确定了查询数据库以更新通知计数的频率。如果浏览器客户端支持`EventSource`和`SharedWorker`,则优先使用`SharedWorker`而不是轮询通知端点。将其设置为 -1 可以禁用 `EventSource`。 + +### 界面 - SVG Images (`ui.svg`) + +- `ENABLE_RENDER`: **true**: 是否将SVG文件呈现为图像。如果禁用了SVG渲染,SVG文件将显示为文本,无法作为图像嵌入到Markdown文件中。 + +### 界面 - CSV Files (`ui.csv`) + +- `MAX_FILE_SIZE`: **524288** (512kb): 以字节为单位允许将CSV文件呈现为表格的最大文件大小(将其设置为0表示没有限制)。 ## Markdown (`markdown`) -- `ENABLE_HARD_LINE_BREAK`: 是否启用硬换行扩展。 - -## Server (`server`) - -- `PROTOCOL`: 可选 `http` 或 `https`。 -- `DOMAIN`: 服务器域名。 -- `ROOT_URL`: Gitea服务器的对外 URL。 -- `HTTP_ADDR`: HTTP 监听地址。 -- `HTTP_PORT`: HTTP 监听端口。 -- `DISABLE_SSH`: 是否禁用SSH。 -- `START_SSH_SERVER`: 是否启用内部SSH服务器。 -- `SSH_PORT`: SSH端口,默认为 `22`。 -- `OFFLINE_MODE`: 针对静态和头像文件禁用 CDN。 -- `DISABLE_ROUTER_LOG`: 关闭日志中的路由日志。 -- `CERT_FILE`: 启用HTTPS的证书文件。 -- `KEY_FILE`: 启用HTTPS的密钥文件。 -- `STATIC_ROOT_PATH`: 存放模板和静态文件的根目录,默认是 Gitea 的根目录。 -- `STATIC_CACHE_TIME`: **6h**: 静态资源文件,包括 `custom/`, `public/` 和所有上传的头像的浏览器缓存时间。 -- `ENABLE_GZIP`: 启用实时生成的数据启用 GZIP 压缩,不包括静态资源。 -- `LANDING_PAGE`: 未登录用户的默认页面,可选 `home` 或 `explore`。 - -- `LFS_START_SERVER`: 是否启用 git-lfs 支持. 可以为 `true` 或 `false`, 默认是 `false`。 -- `LFS_JWT_SECRET`: LFS 认证密钥,改成自己的。 -- `LFS_CONTENT_PATH`: **已废弃**, 存放 lfs 命令上传的文件的地方,默认是 `data/lfs`。**废弃** 请使用 `[lfs]` 的设置。 - -## Database (`database`) - -- `DB_TYPE`: 数据库类型,可选 `mysql`, `postgres`, `mssql` 或 `sqlite3`。 -- `HOST`: 数据库服务器地址和端口。 -- `NAME`: 数据库名称。 -- `USER`: 数据库用户名。 -- `PASSWD`: 数据库用户密码。 -- `SSL_MODE`: MySQL 或 PostgreSQL数据库是否启用SSL模式。 -- `CHARSET`: **utf8mb4**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。 -- `PATH`: SQLite3 数据文件存放路径。 -- `LOG_SQL`: **true**: 显示生成的SQL,默认为真。 -- `MAX_IDLE_CONNS` **0**: 最大空闲数据库连接 -- `CONN_MAX_LIFETIME` **3s**: 数据库连接最大存活时间 - -## Indexer (`indexer`) - -- `ISSUE_INDEXER_TYPE`: **bleve**: 工单索引类型,当前支持 `bleve`, `db` 和 `elasticsearch`,当为 `db` 时其它工单索引项可不用设置。 -- `ISSUE_INDEXER_CONN_STR`: ****: 工单索引连接字符串,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200 -- `ISSUE_INDEXER_NAME`: **gitea_issues**: 工单索引名称,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。 -- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: 工单索引文件存放路径,当索引类型为 `bleve` 时有效。 - -- `REPO_INDEXER_ENABLED`: **false**: 是否启用代码搜索(启用后会占用比较大的磁盘空间,如果是bleve可能需要占用约6倍存储空间)。 -- `REPO_INDEXER_TYPE`: **bleve**: 代码搜索引擎类型,可以为 `bleve` 或者 `elasticsearch`。 -- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: 用于代码搜索的索引文件路径。 -- `REPO_INDEXER_CONN_STR`: ****: 代码搜索引擎连接字符串,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200 -- `REPO_INDEXER_NAME`: **gitea_codes**: 代码搜索引擎的名字,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。 - -- `MAX_FILE_SIZE`: **1048576**: 进行解析的源代码文件的最大长度,小于该值时才会索引。 - -## Security (`security`) - -- `INSTALL_LOCK`: 是否允许运行安装向导,(跟管理员账号有关,十分重要)。 -- `SECRET_KEY`: 全局服务器安全密钥 **最好改成你自己的** (当你运行安装向导的时候会被设置为一个随机值)。 -- `LOGIN_REMEMBER_DAYS`: Cookie 保存时间,单位天。 -- `COOKIE_USERNAME`: 保存用户名的 cookie 名称。 -- `COOKIE_REMEMBER_NAME`: 保存自动登录信息的 cookie 名称。 -- `REVERSE_PROXY_AUTHENTICATION_USER`: 反向代理认证的 HTTP 头名称。 +- `ENABLE_HARD_LINE_BREAK_IN_COMMENTS`: **true**: 在评论中将软换行符呈现为硬换行符, + 这意味着段落之间的单个换行符将导致换行, + 并且不需要在段落后添加尾随空格来强制换行。 +- `ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS`: **false**: 在文档中将软换行符呈现为硬换行符, + 这意味着段落之间的单个换行符将导致换行, + 并且不需要在段落后添加尾随空格来强制换行。 +- `CUSTOM_URL_SCHEMES`: 使用逗号分隔的列表(ftp、git、svn)来指示要在Markdown中呈现的附加URL超链接。 + 以http和https开头的URL始终显示。 + 如果此条目为空,则允许所有URL方案。 +- `FILE_EXTENSIONS`: **.md,.markdown,.mdown,.mkd,.livemd**: 应呈现/编辑为Markdown的文件扩展名列表。使用逗号分隔扩展名。要将没有任何扩展名的文件呈现为Markdown,请只需放置一个逗号。 +- `ENABLE_MATH`: **true**: 启用对`\(...\)`, `\[...\]`, `$...$`和`$$...$$` 作为数学块的检测。 + +## 服务器 (`server`) + +- `APP_DATA_PATH`: **_`AppWorkPath`_/data**: 这是存储数据的默认根路径。 +- `PROTOCOL`: **http**: \[http, https, fcgi, http+unix, fcgi+unix\] +- `USE_PROXY_PROTOCOL`: **false**: 在连接中预期`PROXY`协议头。 +- `PROXY_PROTOCOL_TLS_BRIDGING`: **false**: 协议为 https 时,在`TLS`协商后预期`PROXY`协议头。 +- `PROXY_PROTOCOL_HEADER_TIMEOUT`: **5s**: 等待`PROXY`协议头的超时时间(设置为`0`表示没有超时)。 +- `PROXY_PROTOCOL_ACCEPT_UNKNOWN`: **false**:接受带有未知类型的`PROXY`协议头。 +- `DOMAIN`: **localhost**: 此服务器的域名。 +- `ROOT_URL`: **%(PROTOCOL)s://%(DOMAIN)s:%(HTTP\_PORT)s/**: + 覆盖自动生成的公共URL。 + 如果内部URL和外部URL不匹配(例如在Docker中),这很有用。 +- `STATIC_URL_PREFIX`: **_empty_**: + 覆盖此选项以从不同的URL请求静态资源。 + 这包括CSS文件、图片、JS文件和Web字体。 + 头像图片是动态资源,仍由Gitea提供。 + 选项可以是不同的路径,例如`/static`, 也可以是另一个域,例如`https://cdn.example.com`. + 请求会变成 `%(ROOT_URL)s/static/assets/css/index.css` 或 `https://cdn.example.com/assets/css/index.css` + 静态文件位于Gitea源代码仓库的`public/`目录中。 + 您可以将`STATIC_URL_PREFIX`请求代理到 Gitea 服务器以提供静态资源,或者将手动构建的 Gitea 资源从 `$GITEA_BUILD/public`复制到静态位置,例如`/var/www/assets`。确保`$STATIC_URL_PREFIX/assets/css/index.css`指向`/var/www/assets/css/index.css`。 + +- `HTTP_ADDR`: **0.0.0.0**:HTTP 监听地址。 + - 如果 `PROTOCOL` 设置为 `fcgi`,Gitea 将在由 + `HTTP_ADDR` 和 `HTTP_PORT` 配置设置定义的 TCP 套接字上监听 FastCGI 请求。 + - 如果 `PROTOCOL` 设置为 `http+unix` 或 `fcgi+unix`,则应该是要使用的 Unix 套接字文件的名称。相对路径将相对于 _`AppWorkPath`_ 被转换为绝对路径。 +- `HTTP_PORT`: **3000**:HTTP 监听端口。 + - 如果 `PROTOCOL` 设置为 `fcgi`,Gitea 将在由 `HTTP_ADDR` 和 `HTTP_PORT` + 配置设置定义的 TCP 套接字上监听 FastCGI 请求。 +- `UNIX_SOCKET_PERMISSION`: **666**:Unix 套接字的权限。 +- `LOCAL_ROOT_URL`: **%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/**: + 用于访问网络服务的 Gitea 工作器(例如 SSH 更新)的本地(DMZ)URL。 + 在大多数情况下,您不需要更改默认值。 + 仅在您的 SSH 服务器节点与 HTTP 节点不同的情况下才修改它。对于不同的协议,默认值不同。如果 `PROTOCOL` + 是 `http+unix`,则默认值为 `http://unix/`。如果 `PROTOCOL` 是 `fcgi` 或 `fcgi+unix`,则默认值为 + `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`。如果监听在 `0.0.0.0`,则默认值为 + `%(PROTOCOL)s://localhost:%(HTTP_PORT)s/`, + 否则默认值为 `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`。 +- `LOCAL_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)s**:在进行本地连接时传递 PROXY 协议头。 + 如果本地连接将经过代理,请将其设置为 false。 +- `PER_WRITE_TIMEOUT`: **30s**:连接的任何写操作的超时时间。(将其设置为 -1 + 以禁用所有超时。) +- `PER_WRITE_PER_KB_TIMEOUT`: **10s**:连接每写入 1 KB 的超时时间。 +- `DISABLE_SSH`: **false**:当SSH不可用时禁用SSH功能。 +- `START_SSH_SERVER`: **false**:启用时,使用内置的SSH服务器。 +- `SSH_SERVER_USE_PROXY_PROTOCOL`: **false**:在与内置SSH服务器建立连接时,期望PROXY协议头。 +- `BUILTIN_SSH_SERVER_USER`: **%(RUN_USER)s**:用于内置SSH服务器的用户名。 +- `SSH_USER`: **%(BUILTIN_SSH_SERVER_USER)s**:在克隆URL中显示的SSH用户名。这仅适用于自行配置SSH服务器的人;在大多数情况下,您希望将其留空并修改`BUILTIN_SSH_SERVER_USER`。 +- `SSH_DOMAIN`: **%(DOMAIN)s**:此服务器的域名,用于显示的克隆 URL。 +- `SSH_PORT`: **22**:显示在克隆 URL 中的 SSH 端口。 +- `SSH_LISTEN_HOST`: **0.0.0.0**:内置 SSH 服务器的监听地址。 +- `SSH_LISTEN_PORT`: **%(SSH_PORT)s**:内置 SSH 服务器的端口。 +- `SSH_ROOT_PATH`: **~/.ssh**:SSH 目录的根路径。 +- `SSH_CREATE_AUTHORIZED_KEYS_FILE`: **true**:当 Gitea 不使用内置 SSH 服务器时,默认情况下 Gitea 会创建一个 authorized_keys 文件。如果您打算使用 AuthorizedKeysCommand 功能,您应该关闭此选项。 +- `SSH_AUTHORIZED_KEYS_BACKUP`: **false**:在重写所有密钥时启用 SSH 授权密钥备份,默认值为 false。 +- `SSH_TRUSTED_USER_CA_KEYS`: **_empty_**:指定信任的证书颁发机构的公钥,用于对用户证书进行身份验证。多个密钥应以逗号分隔。例如 `ssh- ` 或 `ssh- , ssh- `。有关详细信息,请参阅 `sshd` 配置手册中的 `TrustedUserCAKeys` 部分。当为空时,不会创建文件,并且 `SSH_AUTHORIZED_PRINCIPALS_ALLOW` 默认为 `off`。 +- `SSH_TRUSTED_USER_CA_KEYS_FILENAME`: **`RUN_USER`/.ssh/gitea-trusted-user-ca-keys.pem**:Gitea 将管理的 `TrustedUserCaKeys` 文件的绝对路径。如果您正在运行自己的 SSH 服务器,并且想要使用 Gitea 管理的文件,您还需要修改您的 `sshd_config` 来指向此文件。官方的 Docker 映像将自动工作,无需进一步配置。 +- `SSH_AUTHORIZED_PRINCIPALS_ALLOW`: **off** 或 **username, email**:\[off, username, email, anything\]:指定允许用户用作 principal 的值。当设置为 `anything` 时,对 principal 字符串不执行任何检查。当设置为 `off` 时,不允许设置授权的 principal。 +- `SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE`: **false/true**:当 Gitea 不使用内置 SSH 服务器且 `SSH_AUTHORIZED_PRINCIPALS_ALLOW` 不为 `off` 时,默认情况下 Gitea 会创建一个 authorized_principals 文件。 +- `SSH_AUTHORIZED_PRINCIPALS_BACKUP`: **false/true**:在重写所有密钥时启用 SSH 授权 principal 备份,默认值为 true(如果 `SSH_AUTHORIZED_PRINCIPALS_ALLOW` 不为 `off`)。 +- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}**:设置用于传递授权密钥的命令模板。可能的密钥是:AppPath、AppWorkPath、CustomConf、CustomPath、Key,其中 Key 是 `models/asymkey.PublicKey`,其他是 shellquoted 字符串。 +- `SSH_SERVER_CIPHERS`: **chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com**:对于内置的 SSH 服务器,选择支持的 SSH 连接的加密方法,对于系统 SSH,此设置无效。 +- `SSH_SERVER_KEY_EXCHANGES`: **curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1**:对于内置 SSH 服务器,选择支持的 SSH 连接的密钥交换算法,对于系统 SSH,此设置无效。 +- `SSH_SERVER_MACS`: **hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1**:对于内置 SSH 服务器,选择支持的 SSH 连接的 MAC 算法,对于系统 SSH,此设置无效。 +- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**:对于内置 SSH 服务器,选择要提供为主机密钥的密钥对。私钥应在 `SSH_SERVER_HOST_KEY` 中,公钥在 `SSH_SERVER_HOST_KEY.pub` 中。相对路径会相对于 `APP_DATA_PATH` 转为绝对路径。如果不存在密钥,将为您创建一个 4096 位的 RSA 密钥。 +- `SSH_KEY_TEST_PATH`: **/tmp**:在使用 `ssh-keygen` 测试公共 SSH 密钥时要在其中创建临时文件的目录,默认为系统临时目录。 +- `SSH_KEYGEN_PATH`: **_empty_**:使用 `ssh-keygen` 解析公共 SSH 密钥。该值将传递给 shell。默认情况下,Gitea 会自行进行解析。 +- `SSH_EXPOSE_ANONYMOUS`: **false**:启用将 SSH 克隆 URL 暴露给匿名访问者,默认为 false。 +- `SSH_PER_WRITE_TIMEOUT`: **30s**:对 SSH 连接的任何写入设置超时。(将其设置为 -1 可以禁用所有超时。) +- `SSH_PER_WRITE_PER_KB_TIMEOUT`: **10s**:对写入 SSH 连接的每 KB 设置超时。 +- `MINIMUM_KEY_SIZE_CHECK`: **true**:指示是否检查最小密钥大小与相应类型。 +- `OFFLINE_MODE`: **false**:禁用 CDN 用于静态文件和 Gravatar 用于个人资料图片。 +- `CERT_FILE`: **https/cert.pem**:用于 HTTPS 的证书文件路径。在链接时,服务器证书必须首先出现,然后是中间 CA 证书(如果有)。如果 `ENABLE_ACME=true`,则此设置会被忽略。路径相对于 `CUSTOM_PATH`。 +- `KEY_FILE`: **https/key.pem**:用于 HTTPS 的密钥文件路径。如果 `ENABLE_ACME=true`,则此设置会被忽略。路径相对于 `CUSTOM_PATH`。 +- `STATIC_ROOT_PATH`: **_`StaticRootPath`_**:模板和静态文件路径的上一级。 +- `APP_DATA_PATH`: **data**(在 Docker 上为 **/data/gitea**):应用程序数据的默认路径。相对路径会相对于 _`AppWorkPath`_ 转为绝对路径。 +- `STATIC_CACHE_TIME`: **6h**:对 `custom/`、`public/` 和所有上传的头像的静态资源的 Web 浏览器缓存时间。请注意,在 `RUN_MODE` 为 "dev" 时,此缓存会被禁用。 +- `ENABLE_GZIP`: **false**:为运行时生成的内容启用 gzip 压缩,静态资源除外。 +- `ENABLE_PPROF`: **false**:应用程序分析(内存和 CPU)。对于 "web" 命令,它会在 `localhost:6060` 上监听。对于 "serv" 命令,它会将数据转储到磁盘上的 `PPROF_DATA_PATH` 中,文件名为 `(cpuprofile|memprofile)__`。 +- `PPROF_DATA_PATH`: **_`AppWorkPath`_/data/tmp/pprof**:`PPROF_DATA_PATH`,当您将 Gitea 作为服务启动时,请使用绝对路径。 +- `LANDING_PAGE`: **home**:未经身份验证用户的登录页面 \[home, explore, organizations, login, **custom**]。其中 custom 可以是任何 URL,例如 "/org/repo" 或甚至是 `https://anotherwebsite.com`。 +- `LFS_START_SERVER`: **false**:启用 Git LFS 支持。 +- `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)s/lfs**:默认的 LFS 内容路径(如果它在本地存储中)。**已弃用**,请使用 `[lfs]` 中的设置。 +- `LFS_JWT_SECRET`: **_empty_**:LFS 身份验证密钥,将其更改为唯一的字符串。 +- `LFS_JWT_SECRET_URI`: **_empty_**:代替在配置中定义 LFS_JWT_SECRET,可以使用此配置选项为 Gitea 提供包含密钥的文件的路径(示例值:`file:/etc/gitea/lfs_jwt_secret`)。 +- `LFS_HTTP_AUTH_EXPIRY`: **24h**:LFS 身份验证的有效期,以 time.Duration 表示,超过此期限的推送可能会失败。 +- `LFS_MAX_FILE_SIZE`: **0**:允许的最大 LFS 文件大小(以字节为单位,设置为 0 为无限制)。 +- `LFS_LOCKS_PAGING_NUM`: **50**:每页返回的最大 LFS 锁定数。 +- `REDIRECT_OTHER_PORT`: **false**:如果为 true 并且 `PROTOCOL` 为 https,则允许将 http 请求重定向到 Gitea 监听的 https 端口的 `PORT_TO_REDIRECT`。 +- `REDIRECTOR_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)s**:在连接到 https 重定向器时,需要 PROXY 协议头。 +- `PORT_TO_REDIRECT`: **80**:http 重定向服务监听的端口。当 `REDIRECT_OTHER_PORT` 为 true 时使用。 +- `SSL_MIN_VERSION`: **TLSv1.2**:设置最低支持的 SSL 版本。 +- `SSL_MAX_VERSION`: **_empty_**:设置最大支持的 SSL 版本。 +- `SSL_CURVE_PREFERENCES`: **X25519,P256**:设置首选的曲线。 +- `SSL_CIPHER_SUITES`: **ecdhe_ecdsa_with_aes_256_gcm_sha384,ecdhe_rsa_with_aes_256_gcm_sha384,ecdhe_ecdsa_with_aes_128_gcm_sha256,ecdhe_rsa_with_aes_128_gcm_sha256,ecdhe_ecdsa_with_chacha20_poly1305,ecdhe_rsa_with_chacha20_poly1305**:设置首选的密码套件。 + - 如果没有对 AES 套件的硬件支持,默认情况下,ChaCha 套件将优先于 AES 套件。 + - 根据 Go 1.18 的支持的套件有: + - TLS 1.0 - 1.2 套件 + - "rsa_with_rc4_128_sha" + - "rsa_with_3des_ede_cbc_sha" + - "rsa_with_aes_128_cbc_sha" + - "rsa_with_aes_256_cbc_sha" + - "rsa_with_aes_128_cbc_sha256" + - "rsa_with_aes_128_gcm_sha256" + - "rsa_with_aes_256_gcm_sha384" + - "ecdhe_ecdsa_with_rc4_128_sha" + - "ecdhe_ecdsa_with_aes_128_cbc_sha" + - "ecdhe_ecdsa_with_aes_256_cbc_sha" + - "ecdhe_rsa_with_rc4_128_sha" + - "ecdhe_rsa_with_3des_ede_cbc_sha" + - "ecdhe_rsa_with_aes_128_cbc_sha" + - "ecdhe_rsa_with_aes_256_cbc_sha" + - "ecdhe_ecdsa_with_aes_128_cbc_sha256" + - "ecdhe_rsa_with_aes_128_cbc_sha256" + - "ecdhe_rsa_with_aes_128_gcm_sha256" + - "ecdhe_ecdsa_with_aes_128_gcm_sha256" + - "ecdhe_rsa_with_aes_256_gcm_sha384" + - "ecdhe_ecdsa_with_aes_256_gcm_sha384" + - "ecdhe_rsa_with_chacha20_poly1305_sha256" + - "ecdhe_ecdsa_with_chacha20_poly1305_sha256" + - TLS 1.3 套件 + - "aes_128_gcm_sha256" + - "aes_256_gcm_sha384" + - "chacha20_poly1305_sha256" + - 别名 + - "ecdhe_rsa_with_chacha20_poly1305" 是 "ecdhe_rsa_with_chacha20_poly1305_sha256" 的别名 + - "ecdhe_ecdsa_with_chacha20_poly1305" 是 "ecdhe_ecdsa_with_chacha20_poly1305_sha256" 的别名 +- `ENABLE_ACME`: **false**:通过 ACME 能力的证书颁发机构(CA)服务器(默认为 Let's Encrypt)启用自动证书管理的标志。如果启用,将忽略 `CERT_FILE` 和 `KEY_FILE`,并且 CA 必须将 `DOMAIN` 解析为此 Gitea 服务器。确保设置了 DNS 记录,并且端口 `80` 或端口 `443` 可以被 CA 服务器访问(默认情况下是公共互联网),并重定向到相应的端口 `PORT_TO_REDIRECT` 或 `HTTP_PORT`。 +- `ACME_URL`: **_empty_**:CA 的 ACME 目录 URL,例如自托管的 [smallstep CA 服务器](https://github.com/smallstep/certificates),它可以是 `https://ca.example.com/acme/acme/directory`。如果留空,默认使用 Let's Encrypt 的生产 CA(还要检查 `LETSENCRYPT_ACCEPTTOS`)。 +- `ACME_ACCEPTTOS`: **false**:这是一个明确的检查,您是否接受 ACME 提供者的服务条款。默认为 Let's Encrypt 的 [服务条款](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)。 +- `ACME_DIRECTORY`: **https**:证书管理器用于缓存证书和私钥等信息的目录。 +- `ACME_EMAIL`: **_empty_**:用于 ACME 注册的电子邮件。通常用于通知有关已颁发的证书的问题。 +- `ACME_CA_ROOT`: **_empty_**:CA 的根证书。如果留空,默认使用系统的信任链。 +- `ALLOW_GRACEFUL_RESTARTS`: **true**:在 SIGHUP 时执行优雅重启。 +- `GRACEFUL_HAMMER_TIME`: **60s**:在重新启动后,父进程将停止接受新连接,并允许请求在停止之前完成。如果耗时超过此时间,则会强制关闭关闭。 +- `STARTUP_TIMEOUT`: **0**:如果启动超过提供的时间,将关闭服务器。在 Windows 上设置这将向 SVC 主机发送一个等待提示,告诉 SVC 主机启动可能需要一些时间。请注意,启动由监听器(HTTP/HTTPS/SSH)的打开来确定。索引程序可能需要更长时间启动,可能具有自己的超时时间。 + +## 数据库 (`database`) + +- `DB_TYPE`: **mysql**:数据库类型 \[mysql, postgres, mssql, sqlite3\]。 +- `HOST`: **127.0.0.1:3306**:数据库主机地址和端口或unix套接字的绝对路径 \[mysql, postgres\](例如:/var/run/mysqld/mysqld.sock)。 +- `NAME`: **gitea**:数据库名称。 +- `USER`: **root**:数据库用户名。 +- `PASSWD`: **_empty_**:数据库密码。如果密码包含特殊字符,请使用 \`your password\` 或 """your password"""。 +- `SCHEMA`: **_empty_**:对于 PostgreSQL,如果与 "public" 不同的模式。模式必须事先存在,用户必须对其具有创建特权,并且用户搜索路径必须设置为首先查找模式(例如 `ALTER USER user SET SEARCH_PATH = schema_name,"$user",public;`)。 +- `SSL_MODE`: **disable**:MySQL 或 PostgreSQL 数据库是否启用 SSL 模式,仅适用于 MySQL 和 PostgreSQL。 + - MySQL 的有效值: + - `true`:启用 TLS,并针对数据库服务器证书根证书进行验证。选择此选项时,请确保用于验证数据库服务器证书的根证书(例如 CA 证书)位于数据库服务器和 Gitea 服务器的系统证书存储中。有关如何将 CA 证书添加到证书存储的说明,请参阅系统文档。 + - `false`:禁用 TLS。 + - `disable`:`false` 的别名,与 PostgreSQL 兼容。 + - `skip-verify`:启用 TLS,但不进行数据库服务器证书验证。如果数据库服务器上有自签名或无效证书,请使用此选项。 + - `prefer`:启用 TLS,并回退到非 TLS 连接。 + - PostgreSQL 的有效值: + - `disable`:禁用 TLS。 + - `require`:启用 TLS,但不进行任何验证。 + - `verify-ca`:启用 TLS,并对数据库服务器证书进行根证书验证。 + - `verify-full`:启用 TLS,并验证数据库服务器名称是否与给定的证书的 "Common Name" 或 "Subject Alternative Name" 字段匹配。 +- `SQLITE_TIMEOUT`:**500**:仅适用于 SQLite3 的查询超时。 +- `SQLITE_JOURNAL_MODE`:**""**:更改 SQlite3 的日志模式。可以用于在高负载导致写入拥塞时启用 [WAL 模式](https://www.sqlite.org/wal.html)。有关可能的值,请参阅 [SQlite3 文档](https://www.sqlite.org/pragma.html#pragma_journal_mode)。默认为数据库文件的默认值,通常为 DELETE。 +- `ITERATE_BUFFER_SIZE`:**50**:用于迭代的内部缓冲区大小。 +- `PATH`:**data/gitea.db**:仅适用于 SQLite3 的数据库文件路径。 +- `LOG_SQL`:**true**:记录已执行的 SQL。 +- `DB_RETRIES`:**10**:允许多少次 ORM 初始化 / DB 连接尝试。 +- `DB_RETRY_BACKOFF`:**3s**:如果发生故障,等待另一个 ORM 初始化 / DB 连接尝试的 time.Duration。 +- `MAX_OPEN_CONNS`:**0**:数据库最大打开连接数 - 默认为 0,表示没有限制。 +- `MAX_IDLE_CONNS`:**2**:连接池上的最大空闲数据库连接数,默认为 2 - 这将限制为 `MAX_OPEN_CONNS`。 +- `CONN_MAX_LIFETIME`:**0 或 3s**:设置 DB 连接可以重用的最长时间 - 默认为 0,表示没有限制(除了 MySQL,其中为 3s - 请参见 #6804 和 #7071)。 +- `AUTO_MIGRATION`:**true**:是否自动执行数据库模型迁移。 + +请参见 #8540 和 #8273 以获取有关 `MAX_OPEN_CONNS`、`MAX_IDLE_CONNS` 和 `CONN_MAX_LIFETIME` 的适当值及其与端口耗尽的关系的进一步讨论。 + +## 索引 (`indexer`) + +- `ISSUE_INDEXER_TYPE`: **bleve**:工单索引类型,当前支持:`bleve`、`db`、`elasticsearch` 或 `meilisearch`。 +- `ISSUE_INDEXER_CONN_STR`:****:工单索引连接字符串,仅适用于 elasticsearch 和 meilisearch(例如:http://elastic:password@localhost:9200)或者(例如:http://:apikey@localhost:7700)。 +- `ISSUE_INDEXER_NAME`:**gitea_issues**:工单索引器名称,在 ISSUE_INDEXER_TYPE 为 elasticsearch 或 meilisearch 时可用。 +- `ISSUE_INDEXER_PATH`:**indexers/issues.bleve**:用于工单搜索的索引文件;在 ISSUE_INDEXER_TYPE 为 bleve 和 elasticsearch 时可用。相对路径将相对于 _`AppWorkPath`_ 进行绝对路径化。 + +- `REPO_INDEXER_ENABLED`:**false**:启用代码搜索(占用大量磁盘空间,约为存储库大小的 6 倍)。 +- `REPO_INDEXER_REPO_TYPES`:**sources,forks,mirrors,templates**:存储库索引器单元。要索引的项目可以是 `sources`、`forks`、`mirrors`、`templates` 或它们的任何组合,用逗号分隔。如果为空,则默认为仅 `sources`,如果要完全禁用,请参见 `REPO_INDEXER_ENABLED`。 +- `REPO_INDEXER_TYPE`:**bleve**:代码搜索引擎类型,可以为 `bleve` 或者 `elasticsearch`。 +- `REPO_INDEXER_PATH`:**indexers/repos.bleve**:用于代码搜索的索引文件。 +- `REPO_INDEXER_CONN_STR`:****:代码索引器连接字符串,在 `REPO_INDEXER_TYPE` 为 elasticsearch 时可用。例如:http://elastic:password@localhost:9200 +- `REPO_INDEXER_NAME`:**gitea_codes**:代码索引器名称,在 `REPO_INDEXER_TYPE` 为 elasticsearch 时可用。 + +- `REPO_INDEXER_INCLUDE`:**empty**:逗号分隔的 glob 模式列表(参见 https://github.com/gobwas/glob)以用于**包括**在索引中。使用 `**.txt` 匹配任何具有 .txt 扩展名的文件。空列表表示包括所有文件。 +- `REPO_INDEXER_EXCLUDE`:**empty**:逗号分隔的 glob 模式列表(参见 https://github.com/gobwas/glob)以用于**排除**在索引中。即使在 `REPO_INDEXER_INCLUDE` 中匹配,也不会索引与此列表匹配的文件。 +- `REPO_INDEXER_EXCLUDE_VENDORED`:**true**:从索引中排除 vendored 文件。 +- `MAX_FILE_SIZE`:**1048576**:要索引的文件的最大字节数。 +- `STARTUP_TIMEOUT`:**30s**:如果索引器启动时间超过此超时时间 - 则失败。(此超时时间将添加到上面的锤子时间中,用于子进程 - 因为 bleve 不会在上一个父进程关闭之前启动)。设置为 -1 表示永不超时。 + +## 队列 (`queue` and `queue.*`) + +[queue] 配置在 `[queue.*]` 下为各个队列设置默认值,并允许为各个队列设置单独的配置覆盖。(不过请参见下文。) + +- `TYPE`:**level**:通用队列类型,当前支持:`level`(在内部使用 LevelDB)、`channel`、`redis`、`dummy`。无效的类型将视为 `level`。 +- `DATADIR`:**queues/common**:用于存储 level 队列的基本 DataDir。单独的队列的 `DATADIR` 可以在 `queue.name` 部分进行设置。相对路径将根据 `%(APP_DATA_PATH)s` 变为绝对路径。 +- `LENGTH`:**100**:通道队列阻塞之前的最大队列大小 +- `BATCH_LENGTH`:**20**:在传递给处理程序之前批处理数据 +- `CONN_STR`:**redis://127.0.0.1:6379/0**:redis 队列类型的连接字符串。对于 `redis-cluster`,使用 `redis+cluster://127.0.0.1:6379/0`。可以使用查询参数来设置选项。类似地,LevelDB 选项也可以使用:**leveldb://relative/path?option=value** 或 **leveldb:///absolute/path?option=value** 进行设置,并将覆盖 `DATADIR`。 +- `QUEUE_NAME`:**_queue**:默认的 redis 和磁盘队列名称的后缀。单独的队列将默认为 **`name`**`QUEUE_NAME`,但可以在特定的 `queue.name` 部分中进行覆盖。 +- `SET_NAME`:**_unique**:将添加到默认的 redis 和磁盘队列 `set` 名称中以用于唯一队列的后缀。单独的队列将默认为 **`name`**`QUEUE_NAME`_`SET_NAME`_,但可以在特定的 `queue.name` 部分中进行覆盖。 +- `MAX_WORKERS`:**(dynamic)**:队列的最大工作协程数。默认值为 "CpuNum/2",限制在 1 到 10 之间。 + +Gitea 创建以下非唯一队列: + +- `code_indexer` +- `issue_indexer` +- `notification-service` +- `task` +- `mail` +- `push_update` + +以及以下唯一队列: + +- `repo_stats_update` +- `repo-archive` +- `mirror` +- `pr_patch_checker` + +## Admin (`admin`) + +- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**:用户电子邮件通知的默认配置(用户可配置)。选项:enabled、onmention、disabled +- `DISABLE_REGULAR_ORG_CREATION`: **false**:禁止普通(非管理员)用户创建组织。 + +## 安全性 (`security`) + +- `INSTALL_LOCK`: **false**:控制是否能够访问安装向导页面,设置为 `true` 则禁止访问安装向导页面。 +- `SECRET_KEY`: **\<每次安装时随机生成\>**:全局服务器安全密钥。这个密钥非常重要,如果丢失将无法解密加密的数据(例如 2FA)。 +- `SECRET_KEY_URI`: **_empty_**:与定义 `SECRET_KEY` 不同,此选项可用于使用存储在文件中的密钥(示例值:`file:/etc/gitea/secret_key`)。它不应该像 `SECRET_KEY` 一样容易丢失。 +- `LOGIN_REMEMBER_DAYS`: **7**:Cookie 保存时间,单位为天。 +- `COOKIE_USERNAME`: **gitea\_awesome**:保存用户名的 Cookie 名称。 +- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**:保存自动登录信息的 Cookie 名称。 +- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**:反向代理认证的 HTTP 头部名称,用于提供用户信息。 +- `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**:反向代理认证的 HTTP 头部名称,用于提供邮箱信息。 +- `REVERSE_PROXY_AUTHENTICATION_FULL_NAME`: **X-WEBAUTH-FULLNAME**:反向代理认证的 HTTP 头部名称,用于提供全名信息。 +- `REVERSE_PROXY_LIMIT`: **1**:解释 X-Forwarded-For 标头或 X-Real-IP 标头,并将其设置为请求的远程 IP。 + 可信代理计数。设置为零以不使用这些标头。 +- `REVERSE_PROXY_TRUSTED_PROXIES`: **127.0.0.0/8,::1/128**:逗号分隔的受信任代理服务器的 IP 地址和网络列表。使用 `*` 来信任全部。 +- `DISABLE_GIT_HOOKS`: **true**:设置为 `false` 以允许具有 Git 钩子权限的用户创建自定义 Git 钩子。 + 警告:自定义 Git 钩子可用于在主机操作系统上执行任意代码。这允许用户访问和修改此配置文件和 Gitea 数据库,并中断 Gitea 服务。 + 通过修改 Gitea 数据库,用户可以获得 Gitea 管理员权限。 + 它还使他们可以访问正在运行 Gitea 实例的操作系统上用户可用的其他资源,并以 Gitea 操作系统用户的名义执行任意操作。 + 这可能对您的网站或操作系统造成危害。 + 在必要之前,请在更改现有 git 存储库中的钩子之前进行调整。 +- `DISABLE_WEBHOOKS`: **false**:设置为 `true` 以禁用 Webhooks 功能。 +- `ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET`: **true**:设置为 `false` 以允许本地用户在未设置 Gitea 环境的情况下推送到 Gitea 存储库。不建议这样做,如果您希望本地用户推送到 Gitea 存储库,应该适当地设置环境。 +- `IMPORT_LOCAL_PATHS`: **false**:设置为 `false` 以防止所有用户(包括管理员)从服务器上导入本地路径。 +- `INTERNAL_TOKEN`: **\<每次安装时随机生成,如果未设置 URI\>**:用于验证 Gitea 二进制文件内部通信的密钥。 +- `INTERNAL_TOKEN_URI`: **_empty_**:与在配置中定义 `INTERNAL_TOKEN` 不同,此配置选项可用于将包含内部令牌的文件的路径提供给 Gitea(示例值:`file:/etc/gitea/internal_token`)。 +- `PASSWORD_HASH_ALGO`: **pbkdf2**:要使用的哈希算法 \[argon2、pbkdf2、pbkdf2_v1、pbkdf2_hi、scrypt、bcrypt\],argon2 和 scrypt 将消耗大量内存。 + - 注意:`pbkdf2` 哈希的默认参数已更改 - 先前的设置可作为 `pbkdf2_v1` 使用,但不建议使用。 + - 可以通过在算法后使用 `$` 进行调整: + - `argon2$