summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEarl Warren <earl-warren@noreply.codeberg.org>2024-03-06 09:59:04 +0100
committerEarl Warren <earl-warren@noreply.codeberg.org>2024-03-06 09:59:04 +0100
commit025798d0f6ffe2492eb0f38f04898515b9cf9a61 (patch)
treebf692d3a3bcbadd3b7ba2a587c794263b5870f63
parent[I18N] Translations update from Weblate (#2556) (diff)
parentAdd an trailing slash to dashboard links (#29555) (diff)
downloadforgejo-025798d0f6ffe2492eb0f38f04898515b9cf9a61.tar.xz
forgejo-025798d0f6ffe2492eb0f38f04898515b9cf9a61.zip
Merge pull request '[gitea] cherry-pick' (#2545) from earl-warren/forgejo:wip-gitea-cherry-pick into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2545 Reviewed-by: Otto <otto@codeberg.org>
-rw-r--r--.deadcode-out7
-rw-r--r--.gitignore2
-rw-r--r--.stylelintrc.yaml1
-rw-r--r--custom/conf/app.example.ini9
-rw-r--r--docs/content/administration/config-cheat-sheet.en-us.md4
-rw-r--r--docs/content/administration/config-cheat-sheet.zh-cn.md3
-rw-r--r--docs/content/administration/mail-templates.en-us.md26
-rw-r--r--docs/content/administration/mail-templates.zh-cn.md24
-rw-r--r--docs/content/usage/issue-pull-request-templates.en-us.md52
-rw-r--r--models/actions/runner.go13
-rw-r--r--models/activities/action.go8
-rw-r--r--models/auth/source.go9
-rw-r--r--models/fixtures/action_run.yml19
-rw-r--r--models/fixtures/action_run_job.yml14
-rw-r--r--models/fixtures/action_task.yml20
-rw-r--r--models/issues/comment.go20
-rw-r--r--models/issues/issue.go3
-rw-r--r--models/issues/issue_search.go25
-rw-r--r--models/issues/issue_stats.go8
-rw-r--r--models/issues/label.go3
-rw-r--r--models/issues/milestone.go8
-rw-r--r--models/issues/milestone_list.go8
-rw-r--r--models/issues/milestone_test.go24
-rw-r--r--models/issues/review_list.go8
-rw-r--r--models/issues/tracked_time.go9
-rw-r--r--models/issues/tracked_time_test.go8
-rw-r--r--models/packages/descriptor.go16
-rw-r--r--models/packages/nuget/search.go2
-rw-r--r--models/packages/package_version.go25
-rw-r--r--models/project/project.go13
-rw-r--r--models/repo/release.go24
-rw-r--r--models/repo/repo.go7
-rw-r--r--models/repo/repo_list.go52
-rw-r--r--models/repo/repo_list_test.go83
-rw-r--r--models/repo/repo_test.go6
-rw-r--r--models/user/email_address.go19
-rw-r--r--models/user/email_address_test.go6
-rw-r--r--models/user/search.go37
-rw-r--r--models/user/user.go8
-rw-r--r--models/user/user_test.go18
-rw-r--r--models/webhook/webhook.go7
-rw-r--r--models/webhook/webhook_system.go8
-rw-r--r--models/webhook/webhook_test.go6
-rw-r--r--modules/actions/task_state.go3
-rw-r--r--modules/actions/workflows.go3
-rw-r--r--modules/git/command.go12
-rw-r--r--modules/indexer/issues/bleve/bleve.go8
-rw-r--r--modules/indexer/issues/db/options.go3
-rw-r--r--modules/indexer/issues/elasticsearch/elasticsearch.go8
-rw-r--r--modules/indexer/issues/indexer.go4
-rw-r--r--modules/indexer/issues/indexer_test.go10
-rw-r--r--modules/indexer/issues/internal/model.go6
-rw-r--r--modules/indexer/issues/internal/tests/tests.go10
-rw-r--r--modules/indexer/issues/meilisearch/meilisearch.go8
-rw-r--r--modules/issue/template/template.go69
-rw-r--r--modules/issue/template/template_test.go109
-rw-r--r--modules/issue/template/unmarshal.go9
-rw-r--r--modules/markup/html_test.go8
-rw-r--r--modules/markup/markdown/markdown.go5
-rw-r--r--modules/markup/markdown/markdown_test.go34
-rw-r--r--modules/optional/option_test.go10
-rw-r--r--modules/queue/workergroup.go20
-rw-r--r--modules/queue/workerqueue.go2
-rw-r--r--modules/queue/workerqueue_test.go29
-rw-r--r--modules/references/references.go4
-rw-r--r--modules/references/references_test.go4
-rw-r--r--modules/repository/init.go68
-rw-r--r--modules/setting/admin.go3
-rw-r--r--modules/setting/session.go7
-rw-r--r--modules/structs/issue.go34
-rw-r--r--modules/templates/helper.go24
-rw-r--r--modules/templates/helper_test.go5
-rw-r--r--modules/templates/mailer.go22
-rw-r--r--modules/templates/util_render.go2
-rw-r--r--modules/templates/util_string.go14
-rw-r--r--modules/translation/mock.go4
-rw-r--r--modules/translation/translation.go2
-rw-r--r--modules/util/util.go61
-rw-r--r--modules/util/util_test.go20
-rw-r--r--options/license/MIT-Khronos-old23
-rw-r--r--options/locale/locale_cs-CZ.ini32
-rw-r--r--options/locale/locale_en-US.ini17
-rw-r--r--options/locale/locale_fr-FR.ini37
-rw-r--r--options/locale/locale_ja-JP.ini7
-rw-r--r--options/locale/locale_lv-LV.ini8
-rw-r--r--options/locale/locale_zh-CN.ini4
-rw-r--r--package-lock.json1026
-rw-r--r--package.json32
-rw-r--r--poetry.lock39
-rw-r--r--pyproject.toml4
-rw-r--r--routers/api/actions/artifact.pb.go1058
-rw-r--r--routers/api/actions/artifact.proto73
-rw-r--r--routers/api/actions/artifacts.go2
-rw-r--r--routers/api/actions/artifacts_chunks.go95
-rw-r--r--routers/api/actions/artifacts_utils.go11
-rw-r--r--routers/api/actions/artifactsv4.go512
-rw-r--r--routers/api/packages/alpine/alpine.go2
-rw-r--r--routers/api/packages/api.go7
-rw-r--r--routers/api/packages/cargo/cargo.go5
-rw-r--r--routers/api/packages/chef/chef.go7
-rw-r--r--routers/api/packages/composer/composer.go5
-rw-r--r--routers/api/packages/conan/conan.go2
-rw-r--r--routers/api/packages/conan/search.go2
-rw-r--r--routers/api/packages/conda/conda.go2
-rw-r--r--routers/api/packages/container/container.go2
-rw-r--r--routers/api/packages/cran/cran.go2
-rw-r--r--routers/api/packages/debian/debian.go2
-rw-r--r--routers/api/packages/generic/generic.go2
-rw-r--r--routers/api/packages/goproxy/goproxy.go5
-rw-r--r--routers/api/packages/helm/helm.go7
-rw-r--r--routers/api/packages/helper/helper.go2
-rw-r--r--routers/api/packages/maven/maven.go2
-rw-r--r--routers/api/packages/npm/api.go3
-rw-r--r--routers/api/packages/npm/npm.go9
-rw-r--r--routers/api/packages/nuget/nuget.go13
-rw-r--r--routers/api/packages/pub/pub.go2
-rw-r--r--routers/api/packages/pypi/pypi.go2
-rw-r--r--routers/api/packages/rpm/rpm.go2
-rw-r--r--routers/api/packages/rubygems/rubygems.go7
-rw-r--r--routers/api/packages/swift/swift.go5
-rw-r--r--routers/api/packages/vagrant/vagrant.go2
-rw-r--r--routers/api/v1/activitypub/person.go2
-rw-r--r--routers/api/v1/activitypub/reqsignature.go2
-rw-r--r--routers/api/v1/admin/adopt.go2
-rw-r--r--routers/api/v1/admin/cron.go2
-rw-r--r--routers/api/v1/admin/email.go2
-rw-r--r--routers/api/v1/admin/hooks.go5
-rw-r--r--routers/api/v1/admin/org.go2
-rw-r--r--routers/api/v1/admin/repo.go2
-rw-r--r--routers/api/v1/admin/runners.go2
-rw-r--r--routers/api/v1/admin/user.go2
-rw-r--r--routers/api/v1/api.go23
-rw-r--r--routers/api/v1/misc/gitignore.go2
-rw-r--r--routers/api/v1/misc/label_templates.go2
-rw-r--r--routers/api/v1/misc/licenses.go2
-rw-r--r--routers/api/v1/misc/markup.go2
-rw-r--r--routers/api/v1/misc/markup_test.go2
-rw-r--r--routers/api/v1/misc/nodeinfo.go2
-rw-r--r--routers/api/v1/misc/signing.go2
-rw-r--r--routers/api/v1/misc/version.go2
-rw-r--r--routers/api/v1/notify/notifications.go2
-rw-r--r--routers/api/v1/notify/repo.go2
-rw-r--r--routers/api/v1/notify/threads.go2
-rw-r--r--routers/api/v1/notify/user.go2
-rw-r--r--routers/api/v1/org/avatar.go2
-rw-r--r--routers/api/v1/org/hook.go2
-rw-r--r--routers/api/v1/org/label.go2
-rw-r--r--routers/api/v1/org/member.go2
-rw-r--r--routers/api/v1/org/org.go2
-rw-r--r--routers/api/v1/org/runners.go2
-rw-r--r--routers/api/v1/org/secrets.go2
-rw-r--r--routers/api/v1/org/team.go2
-rw-r--r--routers/api/v1/packages/package.go6
-rw-r--r--routers/api/v1/repo/action.go2
-rw-r--r--routers/api/v1/repo/avatar.go2
-rw-r--r--routers/api/v1/repo/blob.go2
-rw-r--r--routers/api/v1/repo/branch.go2
-rw-r--r--routers/api/v1/repo/collaborators.go2
-rw-r--r--routers/api/v1/repo/commits.go2
-rw-r--r--routers/api/v1/repo/file.go3
-rw-r--r--routers/api/v1/repo/flags.go2
-rw-r--r--routers/api/v1/repo/fork.go2
-rw-r--r--routers/api/v1/repo/git_hook.go2
-rw-r--r--routers/api/v1/repo/git_ref.go2
-rw-r--r--routers/api/v1/repo/hook.go2
-rw-r--r--routers/api/v1/repo/hook_test.go2
-rw-r--r--routers/api/v1/repo/issue.go48
-rw-r--r--routers/api/v1/repo/issue_attachment.go2
-rw-r--r--routers/api/v1/repo/issue_comment.go12
-rw-r--r--routers/api/v1/repo/issue_comment_attachment.go2
-rw-r--r--routers/api/v1/repo/issue_dependency.go2
-rw-r--r--routers/api/v1/repo/issue_label.go2
-rw-r--r--routers/api/v1/repo/issue_pin.go2
-rw-r--r--routers/api/v1/repo/issue_reaction.go2
-rw-r--r--routers/api/v1/repo/issue_stopwatch.go2
-rw-r--r--routers/api/v1/repo/issue_subscription.go2
-rw-r--r--routers/api/v1/repo/issue_tracked_time.go2
-rw-r--r--routers/api/v1/repo/key.go2
-rw-r--r--routers/api/v1/repo/label.go2
-rw-r--r--routers/api/v1/repo/language.go2
-rw-r--r--routers/api/v1/repo/migrate.go2
-rw-r--r--routers/api/v1/repo/milestone.go8
-rw-r--r--routers/api/v1/repo/mirror.go2
-rw-r--r--routers/api/v1/repo/notes.go2
-rw-r--r--routers/api/v1/repo/patch.go2
-rw-r--r--routers/api/v1/repo/pull.go2
-rw-r--r--routers/api/v1/repo/pull_review.go2
-rw-r--r--routers/api/v1/repo/release.go7
-rw-r--r--routers/api/v1/repo/release_attachment.go43
-rw-r--r--routers/api/v1/repo/release_tags.go2
-rw-r--r--routers/api/v1/repo/repo.go30
-rw-r--r--routers/api/v1/repo/repo_test.go2
-rw-r--r--routers/api/v1/repo/runners.go2
-rw-r--r--routers/api/v1/repo/star.go2
-rw-r--r--routers/api/v1/repo/status.go2
-rw-r--r--routers/api/v1/repo/subscriber.go2
-rw-r--r--routers/api/v1/repo/tag.go2
-rw-r--r--routers/api/v1/repo/teams.go2
-rw-r--r--routers/api/v1/repo/topic.go2
-rw-r--r--routers/api/v1/repo/transfer.go2
-rw-r--r--routers/api/v1/repo/tree.go2
-rw-r--r--routers/api/v1/repo/wiki.go2
-rw-r--r--routers/api/v1/settings/settings.go2
-rw-r--r--routers/api/v1/shared/runners.go2
-rw-r--r--routers/api/v1/user/action.go2
-rw-r--r--routers/api/v1/user/app.go2
-rw-r--r--routers/api/v1/user/avatar.go2
-rw-r--r--routers/api/v1/user/email.go2
-rw-r--r--routers/api/v1/user/follower.go2
-rw-r--r--routers/api/v1/user/gpg_key.go13
-rw-r--r--routers/api/v1/user/helper.go2
-rw-r--r--routers/api/v1/user/hook.go2
-rw-r--r--routers/api/v1/user/key.go2
-rw-r--r--routers/api/v1/user/repo.go2
-rw-r--r--routers/api/v1/user/runners.go2
-rw-r--r--routers/api/v1/user/settings.go2
-rw-r--r--routers/api/v1/user/star.go2
-rw-r--r--routers/api/v1/user/user.go2
-rw-r--r--routers/api/v1/user/watch.go2
-rw-r--r--routers/api/v1/utils/block.go2
-rw-r--r--routers/api/v1/utils/git.go2
-rw-r--r--routers/api/v1/utils/hook.go2
-rw-r--r--routers/api/v1/utils/page.go2
-rw-r--r--routers/common/auth.go2
-rw-r--r--routers/common/errpage.go2
-rw-r--r--routers/common/markup.go2
-rw-r--r--routers/common/middleware.go3
-rw-r--r--routers/common/serve.go2
-rw-r--r--routers/init.go2
-rw-r--r--routers/install/install.go2
-rw-r--r--routers/private/actions.go2
-rw-r--r--routers/private/default_branch.go2
-rw-r--r--routers/private/hook_post_receive.go4
-rw-r--r--routers/private/hook_pre_receive.go2
-rw-r--r--routers/private/hook_proc_receive.go2
-rw-r--r--routers/private/internal.go2
-rw-r--r--routers/private/internal_repo.go2
-rw-r--r--routers/private/key.go2
-rw-r--r--routers/private/mail.go2
-rw-r--r--routers/private/manager.go2
-rw-r--r--routers/private/manager_process.go2
-rw-r--r--routers/private/manager_unix.go2
-rw-r--r--routers/private/manager_windows.go2
-rw-r--r--routers/private/restore_repo.go2
-rw-r--r--routers/private/serv.go2
-rw-r--r--routers/private/ssh_log.go2
-rw-r--r--routers/web/admin/admin.go2
-rw-r--r--routers/web/admin/admin_test.go2
-rw-r--r--routers/web/admin/applications.go2
-rw-r--r--routers/web/admin/auths.go2
-rw-r--r--routers/web/admin/config.go2
-rw-r--r--routers/web/admin/diagnosis.go2
-rw-r--r--routers/web/admin/emails.go8
-rw-r--r--routers/web/admin/hooks.go6
-rw-r--r--routers/web/admin/notice.go2
-rw-r--r--routers/web/admin/orgs.go2
-rw-r--r--routers/web/admin/packages.go6
-rw-r--r--routers/web/admin/queue.go2
-rw-r--r--routers/web/admin/repos.go2
-rw-r--r--routers/web/admin/runners.go2
-rw-r--r--routers/web/admin/stacktrace.go2
-rw-r--r--routers/web/admin/users.go9
-rw-r--r--routers/web/admin/users_test.go2
-rw-r--r--routers/web/auth/2fa.go2
-rw-r--r--routers/web/auth/auth.go10
-rw-r--r--routers/web/auth/linkaccount.go2
-rw-r--r--routers/web/auth/oauth.go2
-rw-r--r--routers/web/auth/openid.go2
-rw-r--r--routers/web/auth/password.go2
-rw-r--r--routers/web/auth/webauthn.go2
-rw-r--r--routers/web/devtest/devtest.go2
-rw-r--r--routers/web/events/events.go2
-rw-r--r--routers/web/explore/code.go2
-rw-r--r--routers/web/explore/org.go17
-rw-r--r--routers/web/explore/repo.go22
-rw-r--r--routers/web/explore/topic.go2
-rw-r--r--routers/web/explore/user.go27
-rw-r--r--routers/web/feed/branch.go2
-rw-r--r--routers/web/feed/convert.go23
-rw-r--r--routers/web/feed/file.go2
-rw-r--r--routers/web/feed/profile.go4
-rw-r--r--routers/web/feed/release.go2
-rw-r--r--routers/web/feed/render.go2
-rw-r--r--routers/web/feed/repo.go2
-rw-r--r--routers/web/githttp.go5
-rw-r--r--routers/web/goget.go2
-rw-r--r--routers/web/home.go6
-rw-r--r--routers/web/misc/markup.go2
-rw-r--r--routers/web/misc/swagger-forgejo.go2
-rw-r--r--routers/web/misc/swagger.go2
-rw-r--r--routers/web/nodeinfo.go2
-rw-r--r--routers/web/org/home.go22
-rw-r--r--routers/web/org/members.go2
-rw-r--r--routers/web/org/org.go2
-rw-r--r--routers/web/org/org_labels.go2
-rw-r--r--routers/web/org/projects.go15
-rw-r--r--routers/web/org/projects_test.go2
-rw-r--r--routers/web/org/setting.go2
-rw-r--r--routers/web/org/setting/blocked_users.go2
-rw-r--r--routers/web/org/setting/runners.go2
-rw-r--r--routers/web/org/setting_oauth2.go2
-rw-r--r--routers/web/org/setting_packages.go2
-rw-r--r--routers/web/org/teams.go2
-rw-r--r--routers/web/repo/actions/actions.go6
-rw-r--r--routers/web/repo/actions/view.go36
-rw-r--r--routers/web/repo/activity.go2
-rw-r--r--routers/web/repo/attachment.go4
-rw-r--r--routers/web/repo/badges/badges.go2
-rw-r--r--routers/web/repo/blame.go2
-rw-r--r--routers/web/repo/branch.go7
-rw-r--r--routers/web/repo/cherry_pick.go2
-rw-r--r--routers/web/repo/code_frequency.go2
-rw-r--r--routers/web/repo/commit.go2
-rw-r--r--routers/web/repo/compare.go4
-rw-r--r--routers/web/repo/contributors.go2
-rw-r--r--routers/web/repo/download.go2
-rw-r--r--routers/web/repo/editor.go12
-rw-r--r--routers/web/repo/editor_test.go2
-rw-r--r--routers/web/repo/find.go2
-rw-r--r--routers/web/repo/flags/manage.go2
-rw-r--r--routers/web/repo/githttp.go2
-rw-r--r--routers/web/repo/helper.go2
-rw-r--r--routers/web/repo/issue.go99
-rw-r--r--routers/web/repo/issue_content_history.go2
-rw-r--r--routers/web/repo/issue_dependency.go2
-rw-r--r--routers/web/repo/issue_label.go2
-rw-r--r--routers/web/repo/issue_label_test.go2
-rw-r--r--routers/web/repo/issue_lock.go2
-rw-r--r--routers/web/repo/issue_pin.go2
-rw-r--r--routers/web/repo/issue_stopwatch.go2
-rw-r--r--routers/web/repo/issue_timetrack.go2
-rw-r--r--routers/web/repo/issue_watch.go2
-rw-r--r--routers/web/repo/middlewares.go2
-rw-r--r--routers/web/repo/migrate.go2
-rw-r--r--routers/web/repo/milestone.go8
-rw-r--r--routers/web/repo/packages.go6
-rw-r--r--routers/web/repo/patch.go2
-rw-r--r--routers/web/repo/projects.go8
-rw-r--r--routers/web/repo/projects_test.go2
-rw-r--r--routers/web/repo/pull.go19
-rw-r--r--routers/web/repo/pull_review.go4
-rw-r--r--routers/web/repo/pull_review_test.go4
-rw-r--r--routers/web/repo/recent_commits.go2
-rw-r--r--routers/web/repo/release.go9
-rw-r--r--routers/web/repo/release_test.go2
-rw-r--r--routers/web/repo/render.go2
-rw-r--r--routers/web/repo/repo.go28
-rw-r--r--routers/web/repo/search.go2
-rw-r--r--routers/web/repo/setting/avatar.go2
-rw-r--r--routers/web/repo/setting/collaboration.go2
-rw-r--r--routers/web/repo/setting/default_branch.go2
-rw-r--r--routers/web/repo/setting/deploy_key.go2
-rw-r--r--routers/web/repo/setting/git_hooks.go2
-rw-r--r--routers/web/repo/setting/lfs.go2
-rw-r--r--routers/web/repo/setting/protected_branch.go2
-rw-r--r--routers/web/repo/setting/protected_tag.go2
-rw-r--r--routers/web/repo/setting/runners.go2
-rw-r--r--routers/web/repo/setting/secrets.go2
-rw-r--r--routers/web/repo/setting/setting.go2
-rw-r--r--routers/web/repo/setting/settings_test.go4
-rw-r--r--routers/web/repo/setting/variables.go2
-rw-r--r--routers/web/repo/setting/webhook.go2
-rw-r--r--routers/web/repo/topic.go2
-rw-r--r--routers/web/repo/treelist.go2
-rw-r--r--routers/web/repo/view.go26
-rw-r--r--routers/web/repo/wiki.go2
-rw-r--r--routers/web/repo/wiki_test.go2
-rw-r--r--routers/web/shared/actions/runners.go2
-rw-r--r--routers/web/shared/actions/variables.go2
-rw-r--r--routers/web/shared/packages/packages.go6
-rw-r--r--routers/web/shared/secrets/secrets.go2
-rw-r--r--routers/web/shared/user/header.go13
-rw-r--r--routers/web/swagger_json.go2
-rw-r--r--routers/web/user/avatar.go2
-rw-r--r--routers/web/user/code.go2
-rw-r--r--routers/web/user/home.go33
-rw-r--r--routers/web/user/home_test.go19
-rw-r--r--routers/web/user/notification.go44
-rw-r--r--routers/web/user/package.go15
-rw-r--r--routers/web/user/profile.go39
-rw-r--r--routers/web/user/search.go2
-rw-r--r--routers/web/user/setting/account.go2
-rw-r--r--routers/web/user/setting/account_test.go2
-rw-r--r--routers/web/user/setting/adopt.go2
-rw-r--r--routers/web/user/setting/applications.go2
-rw-r--r--routers/web/user/setting/blocked_users.go2
-rw-r--r--routers/web/user/setting/keys.go12
-rw-r--r--routers/web/user/setting/oauth2.go2
-rw-r--r--routers/web/user/setting/oauth2_common.go2
-rw-r--r--routers/web/user/setting/packages.go2
-rw-r--r--routers/web/user/setting/profile.go2
-rw-r--r--routers/web/user/setting/runner.go2
-rw-r--r--routers/web/user/setting/security/2fa.go2
-rw-r--r--routers/web/user/setting/security/openid.go2
-rw-r--r--routers/web/user/setting/security/security.go6
-rw-r--r--routers/web/user/setting/security/webauthn.go2
-rw-r--r--routers/web/user/setting/webhooks.go2
-rw-r--r--routers/web/user/stop_watch.go2
-rw-r--r--routers/web/user/task.go2
-rw-r--r--routers/web/web.go7
-rw-r--r--routers/web/webfinger.go2
-rw-r--r--services/actions/job_emitter.go21
-rw-r--r--services/actions/job_emitter_test.go56
-rw-r--r--services/actions/notifier.go24
-rw-r--r--services/actions/notifier_helper.go3
-rw-r--r--services/attachment/attachment.go8
-rw-r--r--services/auth/auth.go2
-rw-r--r--services/auth/signin.go4
-rw-r--r--services/auth/source/oauth2/init.go4
-rw-r--r--services/auth/source/oauth2/providers.go4
-rw-r--r--services/auth/sspi.go5
-rw-r--r--services/context/access_log.go (renamed from modules/context/access_log.go)0
-rw-r--r--services/context/api.go (renamed from modules/context/api.go)0
-rw-r--r--services/context/api_org.go (renamed from modules/context/api_org.go)0
-rw-r--r--services/context/api_test.go (renamed from modules/context/api_test.go)0
-rw-r--r--services/context/base.go (renamed from modules/context/base.go)20
-rw-r--r--services/context/captcha.go (renamed from modules/context/captcha.go)0
-rw-r--r--services/context/context.go (renamed from modules/context/context.go)0
-rw-r--r--services/context/context_cookie.go (renamed from modules/context/context_cookie.go)0
-rw-r--r--services/context/context_model.go (renamed from modules/context/context_model.go)0
-rw-r--r--services/context/context_request.go (renamed from modules/context/context_request.go)0
-rw-r--r--services/context/context_response.go (renamed from modules/context/context_response.go)9
-rw-r--r--services/context/context_template.go (renamed from modules/context/context_template.go)0
-rw-r--r--services/context/context_test.go (renamed from modules/context/context_test.go)0
-rw-r--r--services/context/csrf.go (renamed from modules/context/csrf.go)0
-rw-r--r--services/context/org.go (renamed from modules/context/org.go)0
-rw-r--r--services/context/package.go (renamed from modules/context/package.go)0
-rw-r--r--services/context/pagination.go (renamed from modules/context/pagination.go)0
-rw-r--r--services/context/permission.go (renamed from modules/context/permission.go)0
-rw-r--r--services/context/private.go (renamed from modules/context/private.go)0
-rw-r--r--services/context/repo.go (renamed from modules/context/repo.go)2
-rw-r--r--services/context/response.go (renamed from modules/context/response.go)0
-rw-r--r--services/context/upload/upload.go (renamed from modules/upload/upload.go)2
-rw-r--r--services/context/upload/upload_test.go (renamed from modules/upload/upload_test.go)0
-rw-r--r--services/context/user.go17
-rw-r--r--services/context/utils.go (renamed from modules/context/utils.go)0
-rw-r--r--services/context/xsrf.go (renamed from modules/context/xsrf.go)0
-rw-r--r--services/context/xsrf_test.go (renamed from modules/context/xsrf_test.go)0
-rw-r--r--services/contexttest/context_tests.go (renamed from modules/contexttest/context_tests.go)21
-rw-r--r--services/convert/git_commit.go2
-rw-r--r--services/convert/package.go2
-rw-r--r--services/forms/admin.go3
-rw-r--r--services/forms/auth_form.go2
-rw-r--r--services/forms/org.go2
-rw-r--r--services/forms/package_form.go2
-rw-r--r--services/forms/repo_branch_form.go2
-rw-r--r--services/forms/repo_form.go2
-rw-r--r--services/forms/repo_tag_form.go2
-rw-r--r--services/forms/runner.go2
-rw-r--r--services/forms/user_form.go2
-rw-r--r--services/forms/user_form_auth_openid.go2
-rw-r--r--services/forms/user_form_hidden_comments.go2
-rw-r--r--services/gitdiff/gitdiff.go2
-rw-r--r--services/lfs/locks.go2
-rw-r--r--services/lfs/server.go2
-rw-r--r--services/mailer/incoming/incoming_handler.go2
-rw-r--r--services/mailer/mail_admin_new_user.go14
-rw-r--r--services/markup/processorhelper.go2
-rw-r--r--services/markup/processorhelper_test.go4
-rw-r--r--services/migrations/gitea_uploader.go6
-rw-r--r--services/migrations/gitea_uploader_test.go8
-rw-r--r--services/migrations/gitlab.go54
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_1557802629
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues!page=1&per_page=2&sort=asc&state=all37
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=1&per_page=237
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=2&per_page=237
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=1&per_page=233
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=2&per_page=237
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=3&per_page=237
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=4&per_page=239
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_discussions!page=1&per_page=10033
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_resource_state_events!page=1&per_page=10026
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_labels!page=1&per_page=10037
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests!page=1&per_page=1&view=simple39
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_1_approvals27
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_223
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_approvals27
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=1&per_page=139
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=2&per_page=139
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=3&per_page=141
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_milestones!page=1&per_page=100&state=all35
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_releases!page=1&per_page=10039
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_projects_gitea%2Ftest_repo29
-rw-r--r--services/migrations/testdata/gitlab/full_download/_api_v4_version29
-rw-r--r--services/packages/cleanup/cleanup.go4
-rw-r--r--services/packages/container/cleanup.go6
-rw-r--r--services/packages/packages.go6
-rw-r--r--services/pull/pull.go2
-rw-r--r--services/pull/review.go8
-rw-r--r--services/repository/archiver/archiver_test.go2
-rw-r--r--services/repository/branch.go5
-rw-r--r--services/repository/commit.go2
-rw-r--r--services/repository/create.go2
-rw-r--r--services/repository/files/content_test.go2
-rw-r--r--services/repository/files/diff_test.go2
-rw-r--r--services/repository/files/file_test.go2
-rw-r--r--services/repository/files/search_test.go2
-rw-r--r--services/repository/files/tree_test.go2
-rw-r--r--services/repository/generate.go (renamed from modules/repository/generate.go)15
-rw-r--r--services/repository/generate_test.go (renamed from modules/repository/generate_test.go)0
-rw-r--r--services/repository/init.go83
-rw-r--r--services/repository/template.go7
-rw-r--r--services/webhook/webhook.go7
-rw-r--r--tailwind.config.js1
-rw-r--r--templates/admin/dashboard.tmpl2
-rw-r--r--templates/admin/repo/list.tmpl2
-rw-r--r--templates/admin/repo/search.tmpl29
-rw-r--r--templates/admin/self_check.tmpl2
-rw-r--r--templates/admin/user/edit.tmpl15
-rw-r--r--templates/admin/user/view_details.tmpl8
-rw-r--r--templates/base/alert.tmpl8
-rw-r--r--templates/base/alert_details.tmpl2
-rw-r--r--templates/base/head_navbar.tmpl4
-rw-r--r--templates/base/paginate.tmpl14
-rw-r--r--templates/devtest/fomantic-modal.tmpl8
-rw-r--r--templates/explore/repo_search.tmpl45
-rw-r--r--templates/explore/repos.tmpl2
-rw-r--r--templates/explore/search.tmpl2
-rw-r--r--templates/home.tmpl8
-rw-r--r--templates/mail/auth/activate.tmpl4
-rw-r--r--templates/mail/auth/activate_email.tmpl4
-rw-r--r--templates/mail/auth/register_notify.tmpl2
-rw-r--r--templates/mail/auth/reset_passwd.tmpl4
-rw-r--r--templates/mail/issue/default.tmpl8
-rw-r--r--templates/mail/notify/admin_new_user.tmpl6
-rw-r--r--templates/mail/notify/repo_transfer.tmpl2
-rw-r--r--templates/mail/release.tmpl2
-rw-r--r--templates/mail/team_invite.tmpl2
-rw-r--r--templates/org/header.tmpl2
-rw-r--r--templates/org/home.tmpl4
-rw-r--r--templates/org/settings/delete.tmpl2
-rw-r--r--templates/org/settings/labels.tmpl2
-rw-r--r--templates/org/team/invite.tmpl2
-rw-r--r--templates/org/team/new.tmpl4
-rw-r--r--templates/org/team/sidebar.tmpl10
-rw-r--r--templates/package/content/nuget.tmpl2
-rw-r--r--templates/projects/list.tmpl2
-rw-r--r--templates/projects/view.tmpl2
-rw-r--r--templates/repo/blame.tmpl4
-rw-r--r--templates/repo/branch/list.tmpl2
-rw-r--r--templates/repo/clone_script.tmpl22
-rw-r--r--templates/repo/commit_page.tmpl2
-rw-r--r--templates/repo/create.tmpl2
-rw-r--r--templates/repo/diff/box.tmpl4
-rw-r--r--templates/repo/diff/comments.tmpl4
-rw-r--r--templates/repo/diff/compare.tmpl8
-rw-r--r--templates/repo/diff/stats.tmpl2
-rw-r--r--templates/repo/empty.tmpl2
-rw-r--r--templates/repo/issue/card.tmpl2
-rw-r--r--templates/repo/issue/fields/checkboxes.tmpl4
-rw-r--r--templates/repo/issue/fields/dropdown.tmpl2
-rw-r--r--templates/repo/issue/fields/input.tmpl2
-rw-r--r--templates/repo/issue/fields/markdown.tmpl2
-rw-r--r--templates/repo/issue/fields/textarea.tmpl2
-rw-r--r--templates/repo/issue/labels/label_list.tmpl2
-rw-r--r--templates/repo/issue/milestone_issues.tmpl2
-rw-r--r--templates/repo/issue/milestones.tmpl2
-rw-r--r--templates/repo/issue/new.tmpl8
-rw-r--r--templates/repo/issue/new_form.tmpl8
-rw-r--r--templates/repo/issue/view_content.tmpl6
-rw-r--r--templates/repo/issue/view_content/attachments.tmpl4
-rw-r--r--templates/repo/issue/view_content/comments.tmpl67
-rw-r--r--templates/repo/issue/view_content/comments_authorlink.tmpl11
-rw-r--r--templates/repo/issue/view_content/conversation.tmpl4
-rw-r--r--templates/repo/migrate/options.tmpl2
-rw-r--r--templates/repo/release/list.tmpl4
-rw-r--r--templates/repo/release_tag_header.tmpl2
-rw-r--r--templates/repo/settings/deploy_keys.tmpl2
-rw-r--r--templates/repo/settings/githooks.tmpl2
-rw-r--r--templates/repo/settings/options.tmpl2
-rw-r--r--templates/repo/settings/units/issues.tmpl4
-rw-r--r--templates/repo/settings/webhook/base_list.tmpl2
-rw-r--r--templates/repo/settings/webhook/dingtalk.tmpl2
-rw-r--r--templates/repo/settings/webhook/discord.tmpl2
-rw-r--r--templates/repo/settings/webhook/feishu.tmpl4
-rw-r--r--templates/repo/settings/webhook/forgejo.tmpl2
-rw-r--r--templates/repo/settings/webhook/gitea.tmpl2
-rw-r--r--templates/repo/settings/webhook/gogs.tmpl2
-rw-r--r--templates/repo/settings/webhook/matrix.tmpl2
-rw-r--r--templates/repo/settings/webhook/msteams.tmpl2
-rw-r--r--templates/repo/settings/webhook/packagist.tmpl2
-rw-r--r--templates/repo/settings/webhook/settings.tmpl8
-rw-r--r--templates/repo/settings/webhook/slack.tmpl2
-rw-r--r--templates/repo/settings/webhook/telegram.tmpl2
-rw-r--r--templates/repo/settings/webhook/wechatwork.tmpl2
-rw-r--r--templates/repo/unicode_escape_prompt.tmpl6
-rw-r--r--templates/repo/view_list.tmpl6
-rw-r--r--templates/shared/repo_search.tmpl67
-rw-r--r--templates/shared/user/profile_big_avatar.tmpl2
-rw-r--r--templates/status/404.tmpl2
-rw-r--r--templates/status/500.tmpl4
-rw-r--r--templates/swagger/v1_json.tmpl18
-rw-r--r--templates/user/auth/finalize_openid.tmpl2
-rw-r--r--templates/user/auth/grant.tmpl4
-rw-r--r--templates/user/auth/reset_passwd.tmpl6
-rw-r--r--templates/user/auth/signin_inner.tmpl2
-rw-r--r--templates/user/auth/twofa.tmpl2
-rw-r--r--templates/user/dashboard/feeds.tmpl2
-rw-r--r--templates/user/dashboard/milestones.tmpl2
-rw-r--r--templates/user/notification/notification_subscriptions.tmpl2
-rw-r--r--templates/user/profile.tmpl6
-rw-r--r--templates/user/settings/account.tmpl4
-rw-r--r--templates/user/settings/keys.tmpl2
-rw-r--r--templates/user/settings/keys_gpg.tmpl2
-rw-r--r--templates/user/settings/keys_ssh.tmpl2
-rw-r--r--templates/user/settings/security/twofa.tmpl2
-rw-r--r--templates/user/settings/security/webauthn.tmpl2
-rw-r--r--tests/integration/api_actions_artifact_v4_test.go224
-rw-r--r--tests/integration/api_releases_test.go68
-rw-r--r--tests/integration/api_repo_file_create_test.go2
-rw-r--r--tests/integration/api_repo_file_update_test.go2
-rw-r--r--tests/integration/api_repo_files_change_test.go2
-rw-r--r--tests/integration/block_test.go2
-rw-r--r--tests/integration/branches_test.go2
-rw-r--r--tests/integration/editor_test.go2
-rw-r--r--tests/integration/explore_repos_test.go13
-rw-r--r--tests/integration/explore_user_test.go44
-rw-r--r--tests/integration/forgejo_confirmation_repo_test.go2
-rw-r--r--tests/integration/git_test.go2
-rw-r--r--tests/integration/integration_test.go2
-rw-r--r--tests/integration/mirror_push_test.go2
-rw-r--r--tests/integration/pull_reopen_test.go2
-rw-r--r--tests/integration/repo_settings_test.go2
-rw-r--r--tests/integration/repofiles_change_test.go2
-rw-r--r--web_src/css/base.css6
-rw-r--r--web_src/css/helpers.css6
-rw-r--r--web_src/css/modules/button.css7
-rw-r--r--web_src/css/themes/theme-gitea-dark.css190
-rw-r--r--web_src/css/themes/theme-gitea-light.css8
-rw-r--r--web_src/js/bootstrap.js57
-rw-r--r--web_src/js/features/common-global.js37
-rw-r--r--web_src/js/features/pull-view-file.js2
-rw-r--r--web_src/js/features/repo-commit.js43
-rw-r--r--web_src/js/features/repo-findfile.js60
-rw-r--r--web_src/js/features/repo-home.js59
-rw-r--r--web_src/js/features/repo-search.js22
-rw-r--r--web_src/js/index.js9
-rw-r--r--web_src/js/modules/toast.js5
-rw-r--r--web_src/js/webcomponents/GiteaOriginUrl.js5
639 files changed, 5639 insertions, 2796 deletions
diff --git a/.deadcode-out b/.deadcode-out
index 8fca0d96bb..cf5f7c479b 100644
--- a/.deadcode-out
+++ b/.deadcode-out
@@ -162,9 +162,6 @@ package "code.gitea.io/gitea/modules/cache"
package "code.gitea.io/gitea/modules/charset"
func (*BreakWriter).Write
-package "code.gitea.io/gitea/modules/context"
- func GetPrivateContext
-
package "code.gitea.io/gitea/modules/emoji"
func ReplaceCodes
@@ -296,7 +293,6 @@ package "code.gitea.io/gitea/modules/translation"
package "code.gitea.io/gitea/modules/util"
func UnsafeStringToBytes
- func OptionalBoolFromGeneric
package "code.gitea.io/gitea/modules/util/filebuffer"
func CreateFromReader
@@ -316,6 +312,9 @@ package "code.gitea.io/gitea/routers/web/org"
func getActionIssues
func UpdateIssueProject
+package "code.gitea.io/gitea/services/context"
+ func GetPrivateContext
+
package "code.gitea.io/gitea/services/convert"
func ToSecret
diff --git a/.gitignore b/.gitignore
index 12014d405b..34c71b6973 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,7 +18,7 @@ _test
# MS VSCode
.vscode
-__debug_bin
+__debug_bin*
*.cgo1.go
*.cgo2.c
diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml
index 7dd0a566f2..c7725159f1 100644
--- a/.stylelintrc.yaml
+++ b/.stylelintrc.yaml
@@ -64,6 +64,7 @@ rules:
"@stylistic/media-query-list-comma-newline-before": null
"@stylistic/media-query-list-comma-space-after": null
"@stylistic/media-query-list-comma-space-before": null
+ "@stylistic/named-grid-areas-alignment": null
"@stylistic/no-empty-first-line": null
"@stylistic/no-eol-whitespace": true
"@stylistic/no-extra-semicolons": true
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 04714e5502..4d077643f5 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -969,6 +969,12 @@ LEVEL = Info
;GO_GET_CLONE_URL_PROTOCOL = https
;;
;; Close issues as long as a commit on any branch marks it as fixed
+;DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
+;;
+;; Allow users to push local repositories to Gitea and have them automatically created for a user or an org
+;ENABLE_PUSH_CREATE_USER = false
+;ENABLE_PUSH_CREATE_ORG = false
+;;
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions.
;DISABLED_REPO_UNITS =
;;
@@ -1490,10 +1496,11 @@ LEVEL = Info
;;
;; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
;DEFAULT_EMAIL_NOTIFICATIONS = enabled
-;; Send an email to all admins when a new user signs up to inform the admins about this act. Options: true, false
+;; Disabled features for users, could be "deletion","manage_gpg_keys" more features can be disabled in future
;SEND_NOTIFICATION_EMAIL_ON_NEW_USER = false
;; Disabled features for users, could be "deletion", more features can be disabled in future
;; - deletion: a user cannot delete their own account
+;; - manage_gpg_keys: a user cannot configure gpg keys
;USER_DISABLED_FEATURES =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md
index aa2cbcee5d..ea6e1eb1a4 100644
--- a/docs/content/administration/config-cheat-sheet.en-us.md
+++ b/docs/content/administration/config-cheat-sheet.en-us.md
@@ -518,7 +518,9 @@ And the following unique queues:
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
- `DISABLE_REGULAR_ORG_CREATION`: **false**: Disallow regular (non-admin) users from creating organizations.
-- `SEND_NOTIFICATION_EMAIL_ON_NEW_USER`: **false**: Send an email to all admins when a new user signs up to inform the admins about this act.
+- `USER_DISABLED_FEATURES`: **_empty_** Disabled features for users, could be `deletion`, `manage_gpg_keys` and more features can be added in future.
+ - `deletion`: User cannot delete their own account.
+ - `manage_gpg_keys`: User cannot configure gpg keys
## Security (`security`)
diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md
index 01906930cb..5cc5734359 100644
--- a/docs/content/administration/config-cheat-sheet.zh-cn.md
+++ b/docs/content/administration/config-cheat-sheet.zh-cn.md
@@ -497,6 +497,9 @@ Gitea 创建以下éžå”¯ä¸€é˜Ÿåˆ—:
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**:用户电å­é‚®ä»¶é€šçŸ¥çš„默认é…置(用户å¯é…置)。选项:enabledã€onmentionã€disabled
- `DISABLE_REGULAR_ORG_CREATION`: **false**:ç¦æ­¢æ™®é€šï¼ˆéžç®¡ç†å‘˜ï¼‰ç”¨æˆ·åˆ›å»ºç»„织。
+- `USER_DISABLED_FEATURES`:**_empty_** ç¦ç”¨çš„用户特性,当å‰å…许为空或者 `deletion`,`manage_gpg_keys` 未æ¥å¯ä»¥å¢žåŠ æ›´å¤šè®¾ç½®ã€‚
+ - `deletion`: 用户ä¸èƒ½é€šè¿‡ç•Œé¢æˆ–者API删除他自己。
+ - `manage_gpg_keys`: 用户ä¸èƒ½é…ç½® GPG 密钥
## 安全性 (`security`)
diff --git a/docs/content/administration/mail-templates.en-us.md b/docs/content/administration/mail-templates.en-us.md
index 32b352da4b..0154fe55d0 100644
--- a/docs/content/administration/mail-templates.en-us.md
+++ b/docs/content/administration/mail-templates.en-us.md
@@ -222,9 +222,9 @@ Please check [Gitea's logs](administration/logging-config.md) for error messages
<a href="{{.Link}}">{{.Repo}}#{{.Issue.Index}}</a>.
</p>
{{if not (eq .Body "")}}
- <h3>Message content:</h3>
+ <h3>Message content</h3>
<hr>
- {{.Body | Str2html}}
+ {{.Body | SanitizeHTML}}
{{end}}
</p>
<hr>
@@ -245,7 +245,7 @@ This template produces something along these lines:
> [@rhonda](#) (Rhonda Myers) updated [mike/stuff#38](#).
>
-> #### Message content:
+> #### Message content
>
> \_********************************\_********************************
>
@@ -259,20 +259,20 @@ This template produces something along these lines:
The template system contains several functions that can be used to further process and format
the messages. Here's a list of some of them:
-| Name | Parameters | Available | Usage |
-| ---------------- | ----------- | --------- | --------------------------------------------------------------------------- |
-| `AppUrl` | - | Any | Gitea's URL |
-| `AppName` | - | Any | Set from `app.ini`, usually "Gitea" |
-| `AppDomain` | - | Any | Gitea's host name |
-| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed |
-| `Str2html` | string | Body only | Sanitizes text by removing any HTML tags from it. |
-| `Safe` | string | Body only | Takes the input as HTML; can be used for `.ReviewComments.RenderedContent`. |
+| Name | Parameters | Available | Usage |
+| ---------------- | ----------- | --------- | ------------------------------------------------------------------- |
+| `AppUrl` | - | Any | Gitea's URL |
+| `AppName` | - | Any | Set from `app.ini`, usually "Gitea" |
+| `AppDomain` | - | Any | Gitea's host name |
+| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed |
+| `SanitizeHTML` | string | Body only | Sanitizes text by removing any dangerous HTML tags from it |
+| `SafeHTML` | string | Body only | Takes the input as HTML, can be used for outputing raw HTML content |
These are _functions_, not metadata, so they have to be used:
```html
-Like this: {{Str2html "Escape<my>text"}}
-Or this: {{"Escape<my>text" | Str2html}}
+Like this: {{SanitizeHTML "Escape<my>text"}}
+Or this: {{"Escape<my>text" | SanitizeHTML}}
Or this: {{AppUrl}}
But not like this: {{.AppUrl}}
```
diff --git a/docs/content/administration/mail-templates.zh-cn.md b/docs/content/administration/mail-templates.zh-cn.md
index 588f0b2ccb..e8c2817336 100644
--- a/docs/content/administration/mail-templates.zh-cn.md
+++ b/docs/content/administration/mail-templates.zh-cn.md
@@ -207,7 +207,7 @@ _主题_ å’Œ _邮件正文_ ç”± [Golang的模æ¿å¼•æ“Ž](https://go.dev/pkg/text/
{{if not (eq .Body "")}}
<h3>消æ¯å†…容:</h3>
<hr>
- {{.Body | Str2html}}
+ {{.Body | SanitizeHTML}}
{{end}}
</p>
<hr>
@@ -228,7 +228,7 @@ _主题_ å’Œ _邮件正文_ ç”± [Golang的模æ¿å¼•æ“Ž](https://go.dev/pkg/text/
> [@rhonda](#)(Rhonda Myers)更新了 [mike/stuff#38](#)。
>
-> #### 消æ¯å†…容:
+> #### 消æ¯å†…容
>
> \_********************************\_********************************
>
@@ -242,20 +242,20 @@ _主题_ å’Œ _邮件正文_ ç”± [Golang的模æ¿å¼•æ“Ž](https://go.dev/pkg/text/
模æ¿ç³»ç»ŸåŒ…å«ä¸€äº›å‡½æ•°ï¼Œå¯ç”¨äºŽè¿›ä¸€æ­¥å¤„ç†å’Œæ ¼å¼åŒ–消æ¯ã€‚以下是其中一些函数的列表:
-| 函数å | å‚æ•° | å¯ç”¨äºŽ | 用法 |
-| ----------------- | ----------- | ------------ | --------------------------------------------------------------------------------- |
-| `AppUrl` | - | 任何地方 | Gitea 的 URL |
-| `AppName` | - | 任何地方 | 从 `app.ini` 中设置,通常为 "Gitea" |
-| `AppDomain` | - | 任何地方 | Gitea 的主机å |
-| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根æ®éœ€è¦æ·»åŠ çœç•¥å· |
-| `Str2html` | string | 仅正文部分 | 通过删除其中的 HTML æ ‡ç­¾å¯¹æ–‡æœ¬è¿›è¡Œæ¸…ç† |
-| `Safe` | string | 仅正文部分 | 将输入作为 HTML 处ç†ï¼›å¯ç”¨äºŽ `.ReviewComments.RenderedContent` 等字段 |
+| 函数å | å‚æ•° | å¯ç”¨äºŽ | 用法 |
+|------------------| ----------- | ------------ | ------------------------------ |
+| `AppUrl` | - | 任何地方 | Gitea 的 URL |
+| `AppName` | - | 任何地方 | 从 `app.ini` 中设置,通常为 "Gitea" |
+| `AppDomain` | - | 任何地方 | Gitea 的主机å |
+| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根æ®éœ€è¦æ·»åŠ çœç•¥å· |
+| `SanitizeHTML` | string | 仅正文部分 | 通过删除其中的å±é™© HTML æ ‡ç­¾å¯¹æ–‡æœ¬è¿›è¡Œæ¸…ç† |
+| `SafeHTML` | string | 仅正文部分 | 将输入作为 HTML 处ç†ï¼›å¯ç”¨äºŽè¾“出原始的 HTML 内容 |
这些都是 _函数_,而ä¸æ˜¯å…ƒæ•°æ®ï¼Œå› æ­¤å¿…须按以下方å¼ä½¿ç”¨ï¼š
```html
-åƒè¿™æ ·ä½¿ç”¨ï¼š {{Str2html "Escape<my>text"}}
-或者这样使用: {{"Escape<my>text" | Str2html}}
+åƒè¿™æ ·ä½¿ç”¨ï¼š {{SanitizeHTML "Escape<my>text"}}
+或者这样使用: {{"Escape<my>text" | SanitizeHTML}}
或者这样使用: {{AppUrl}}
但ä¸è¦åƒè¿™æ ·ä½¿ç”¨ï¼š {{.AppUrl}}
```
diff --git a/docs/content/usage/issue-pull-request-templates.en-us.md b/docs/content/usage/issue-pull-request-templates.en-us.md
index 34475e3465..bd43131f4a 100644
--- a/docs/content/usage/issue-pull-request-templates.en-us.md
+++ b/docs/content/usage/issue-pull-request-templates.en-us.md
@@ -135,6 +135,12 @@ body:
attributes:
value: |
Thanks for taking the time to fill out this bug report!
+ # some markdown that will only be visible once the issue has been created
+ - type: markdown
+ attributes:
+ value: |
+ This issue was created by an issue **template** :)
+ visible: [content]
- type: input
id: contact
attributes:
@@ -186,11 +192,16 @@ body:
options:
- label: I agree to follow this project's Code of Conduct
required: true
+ - label: I have also read the CONTRIBUTION.MD
+ required: true
+ visible: [form]
+ - label: This is a TODO only visible after issue creation
+ visible: [content]
```
### Markdown
-You can use a `markdown` element to display Markdown in your form that provides extra context to the user, but is not submitted.
+You can use a `markdown` element to display Markdown in your form that provides extra context to the user, but is not submitted by default.
Attributes:
@@ -198,6 +209,8 @@ Attributes:
|-------|--------------------------------------------------------------|----------|--------|---------|--------------|
| value | The text that is rendered. Markdown formatting is supported. | Required | String | - | - |
+visible: Default is **[form]**
+
### Textarea
You can use a `textarea` element to add a multi-line text field to your form. Contributors can also attach files in `textarea` fields.
@@ -218,6 +231,8 @@ Validations:
|----------|------------------------------------------------------|----------|---------|---------|--------------|
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
+visible: Default is **[form, content]**
+
### Input
You can use an `input` element to add a single-line text field to your form.
@@ -239,6 +254,8 @@ Validations:
| is_number | Prevents form submission until element is filled with a number. | Optional | Boolean | false | - |
| regex | Prevents form submission until element is filled with a value that match the regular expression. | Optional | String | - | a [regular expression](https://en.wikipedia.org/wiki/Regular_expression) |
+visible: Default is **[form, content]**
+
### Dropdown
You can use a `dropdown` element to add a dropdown menu in your form.
@@ -258,6 +275,8 @@ Validations:
|----------|------------------------------------------------------|----------|---------|---------|--------------|
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
+visible: Default is **[form, content]**
+
### Checkboxes
You can use the `checkboxes` element to add a set of checkboxes to your form.
@@ -265,17 +284,20 @@ You can use the `checkboxes` element to add a set of checkboxes to your form.
Attributes:
| Key | Description | Required | Type | Default | Valid values |
-|-------------|-------------------------------------------------------------------------------------------------------|----------|--------|--------------|--------------|
+| ----------- | ----------------------------------------------------------------------------------------------------- | -------- | ------ | ------------ | ------------ |
| label | A brief description of the expected user input, which is displayed in the form. | Required | String | - | - |
| description | A description of the set of checkboxes, which is displayed in the form. Supports Markdown formatting. | Optional | String | Empty String | - |
| options | An array of checkboxes that the user can select. For syntax, see below. | Required | Array | - | - |
For each value in the options array, you can set the following keys.
-| Key | Description | Required | Type | Default | Options |
-|----------|------------------------------------------------------------------------------------------------------------------------------------------|----------|---------|---------|---------|
-| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - |
-| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
+| Key | Description | Required | Type | Default | Options |
+|--------------|------------------------------------------------------------------------------------------------------------------------------------------|----------|--------------|---------|---------|
+| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - |
+| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
+| visible | Whether a specific checkbox appears in the form only, in the created issue only, or both. Valid options are "form" and "content". | Optional | String array | false | - |
+
+visible: Default is **[form, content]**
## Syntax for issue config
@@ -291,15 +313,15 @@ contact_links:
### Possible Options
-| Key | Description | Type | Default |
-|----------------------|-------------------------------------------------------------------------------------------------------|--------------------|----------------|
-| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true |
-| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array |
+| Key | Description | Type | Default |
+|----------------------|-------------------------------------------------------|--------------------|-------------|
+| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true |
+| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array |
### Contact Link
-| Key | Description | Type | Required |
-|----------------------|-------------------------------------------------------------------------------------------------------|---------|----------|
-| name | the name of your link | String | true |
-| url | The URL of your Link | String | true |
-| about | A short description of your Link | String | true |
+| Key | Description | Type | Required |
+|-------|----------------------------------|--------|----------|
+| name | the name of your link | String | true |
+| url | The URL of your Link | String | true |
+| about | A short description of your Link | String | true |
diff --git a/models/actions/runner.go b/models/actions/runner.go
index b646146ee6..67f003387b 100644
--- a/models/actions/runner.go
+++ b/models/actions/runner.go
@@ -13,6 +13,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/shared/types"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
@@ -159,7 +160,7 @@ type FindRunnerOptions struct {
OwnerID int64
Sort string
Filter string
- IsOnline util.OptionalBool
+ IsOnline optional.Option[bool]
WithAvailable bool // not only runners belong to, but also runners can be used
}
@@ -186,10 +187,12 @@ func (opts FindRunnerOptions) ToConds() builder.Cond {
cond = cond.And(builder.Like{"name", opts.Filter})
}
- if opts.IsOnline.IsTrue() {
- cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
- } else if opts.IsOnline.IsFalse() {
- cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
+ if opts.IsOnline.Has() {
+ if opts.IsOnline.Value() {
+ cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
+ } else {
+ cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
+ }
}
return cond
}
diff --git a/models/activities/action.go b/models/activities/action.go
index 8cb32f6889..6df113138b 100644
--- a/models/activities/action.go
+++ b/models/activities/action.go
@@ -227,8 +227,8 @@ func (a *Action) ShortActUserName(ctx context.Context) string {
return base.EllipsisString(a.GetActUserName(ctx), 20)
}
-// GetDisplayName gets the action's display name based on DEFAULT_SHOW_FULL_NAME, or falls back to the username if it is blank.
-func (a *Action) GetDisplayName(ctx context.Context) string {
+// GetActDisplayName gets the action's display name based on DEFAULT_SHOW_FULL_NAME, or falls back to the username if it is blank.
+func (a *Action) GetActDisplayName(ctx context.Context) string {
if setting.UI.DefaultShowFullName {
trimmedFullName := strings.TrimSpace(a.GetActFullName(ctx))
if len(trimmedFullName) > 0 {
@@ -238,8 +238,8 @@ func (a *Action) GetDisplayName(ctx context.Context) string {
return a.ShortActUserName(ctx)
}
-// GetDisplayNameTitle gets the action's display name used for the title (tooltip) based on DEFAULT_SHOW_FULL_NAME
-func (a *Action) GetDisplayNameTitle(ctx context.Context) string {
+// GetActDisplayNameTitle gets the action's display name used for the title (tooltip) based on DEFAULT_SHOW_FULL_NAME
+func (a *Action) GetActDisplayNameTitle(ctx context.Context) string {
if setting.UI.DefaultShowFullName {
return a.ShortActUserName(ctx)
}
diff --git a/models/auth/source.go b/models/auth/source.go
index 53920f0597..1a3a1b20a6 100644
--- a/models/auth/source.go
+++ b/models/auth/source.go
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -243,14 +244,14 @@ func CreateSource(ctx context.Context, source *Source) error {
type FindSourcesOptions struct {
db.ListOptions
- IsActive util.OptionalBool
+ IsActive optional.Option[bool]
LoginType Type
}
func (opts FindSourcesOptions) ToConds() builder.Cond {
conds := builder.NewCond()
- if !opts.IsActive.IsNone() {
- conds = conds.And(builder.Eq{"is_active": opts.IsActive.IsTrue()})
+ if opts.IsActive.Has() {
+ conds = conds.And(builder.Eq{"is_active": opts.IsActive.Value()})
}
if opts.LoginType != NoType {
conds = conds.And(builder.Eq{"`type`": opts.LoginType})
@@ -262,7 +263,7 @@ func (opts FindSourcesOptions) ToConds() builder.Cond {
// source of type LoginSSPI
func IsSSPIEnabled(ctx context.Context) bool {
exist, err := db.Exist[Source](ctx, FindSourcesOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
LoginType: SSPI,
}.ToConds())
if err != nil {
diff --git a/models/fixtures/action_run.yml b/models/fixtures/action_run.yml
index 2c2151f354..a42ab77ca5 100644
--- a/models/fixtures/action_run.yml
+++ b/models/fixtures/action_run.yml
@@ -17,3 +17,22 @@
updated: 1683636626
need_approval: 0
approved_by: 0
+-
+ id: 792
+ title: "update actions"
+ repo_id: 4
+ owner_id: 1
+ workflow_id: "artifact.yaml"
+ index: 188
+ trigger_user_id: 1
+ ref: "refs/heads/master"
+ commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
+ event: "push"
+ is_fork_pull_request: 0
+ status: 1
+ started: 1683636528
+ stopped: 1683636626
+ created: 1683636108
+ updated: 1683636626
+ need_approval: 0
+ approved_by: 0
diff --git a/models/fixtures/action_run_job.yml b/models/fixtures/action_run_job.yml
index 071998b979..fd90f4fd5d 100644
--- a/models/fixtures/action_run_job.yml
+++ b/models/fixtures/action_run_job.yml
@@ -12,3 +12,17 @@
status: 1
started: 1683636528
stopped: 1683636626
+-
+ id: 193
+ run_id: 792
+ repo_id: 4
+ owner_id: 1
+ commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
+ is_fork_pull_request: 0
+ name: job_2
+ attempt: 1
+ job_id: job_2
+ task_id: 48
+ status: 1
+ started: 1683636528
+ stopped: 1683636626
diff --git a/models/fixtures/action_task.yml b/models/fixtures/action_task.yml
index c78fb3c5d6..443effe08c 100644
--- a/models/fixtures/action_task.yml
+++ b/models/fixtures/action_task.yml
@@ -18,3 +18,23 @@
log_length: 707
log_size: 90179
log_expired: 0
+-
+ id: 48
+ job_id: 193
+ attempt: 1
+ runner_id: 1
+ status: 6 # 6 is the status code for "running", running task can upload artifacts
+ started: 1683636528
+ stopped: 1683636626
+ repo_id: 4
+ owner_id: 1
+ commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
+ is_fork_pull_request: 0
+ token_hash: ffffcfffffffbffffffffffffffffefffffffafffffffffffffffffffffffffffffdffffffffffffffffffffffffffffffff
+ token_salt: ffffffffff
+ token_last_eight: ffffffff
+ log_filename: artifact-test2/2f/47.log
+ log_in_storage: 1
+ log_length: 707
+ log_size: 90179
+ log_expired: 0
diff --git a/models/issues/comment.go b/models/issues/comment.go
index 49c3159f6f..984fb9c9fc 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -8,6 +8,7 @@ package issues
import (
"context"
"fmt"
+ "html/template"
"strconv"
"unicode/utf8"
@@ -21,6 +22,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
@@ -259,8 +261,8 @@ type Comment struct {
CommitID int64
Line int64 // - previous line / + proposed line
TreePath string
- Content string `xorm:"LONGTEXT"`
- RenderedContent string `xorm:"-"`
+ Content string `xorm:"LONGTEXT"`
+ RenderedContent template.HTML `xorm:"-"`
// Path represents the 4 lines of code cemented by this comment
Patch string `xorm:"-"`
@@ -1043,8 +1045,8 @@ type FindCommentsOptions struct {
TreePath string
Type CommentType
IssueIDs []int64
- Invalidated util.OptionalBool
- IsPull util.OptionalBool
+ Invalidated optional.Option[bool]
+ IsPull optional.Option[bool]
}
// ToConds implements FindOptions interface
@@ -1076,11 +1078,11 @@ func (opts FindCommentsOptions) ToConds() builder.Cond {
if len(opts.TreePath) > 0 {
cond = cond.And(builder.Eq{"comment.tree_path": opts.TreePath})
}
- if !opts.Invalidated.IsNone() {
- cond = cond.And(builder.Eq{"comment.invalidated": opts.Invalidated.IsTrue()})
+ if opts.Invalidated.Has() {
+ cond = cond.And(builder.Eq{"comment.invalidated": opts.Invalidated.Value()})
}
- if opts.IsPull != util.OptionalBoolNone {
- cond = cond.And(builder.Eq{"issue.is_pull": opts.IsPull.IsTrue()})
+ if opts.IsPull.Has() {
+ cond = cond.And(builder.Eq{"issue.is_pull": opts.IsPull.Value()})
}
return cond
}
@@ -1089,7 +1091,7 @@ func (opts FindCommentsOptions) ToConds() builder.Cond {
func FindComments(ctx context.Context, opts *FindCommentsOptions) (CommentList, error) {
comments := make([]*Comment, 0, 10)
sess := db.GetEngine(ctx).Where(opts.ToConds())
- if opts.RepoID > 0 || opts.IsPull != util.OptionalBoolNone {
+ if opts.RepoID > 0 || opts.IsPull.Has() {
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
}
diff --git a/models/issues/issue.go b/models/issues/issue.go
index b3b1744969..baa79b30d1 100644
--- a/models/issues/issue.go
+++ b/models/issues/issue.go
@@ -7,6 +7,7 @@ package issues
import (
"context"
"fmt"
+ "html/template"
"regexp"
"slices"
@@ -105,7 +106,7 @@ type Issue struct {
OriginalAuthorID int64 `xorm:"index"`
Title string `xorm:"name"`
Content string `xorm:"LONGTEXT"`
- RenderedContent string `xorm:"-"`
+ RenderedContent template.HTML `xorm:"-"`
Labels []*Label `xorm:"-"`
MilestoneID int64 `xorm:"INDEX"`
Milestone *Milestone `xorm:"-"`
diff --git a/models/issues/issue_search.go b/models/issues/issue_search.go
index 7dc277327a..c5c9cecdb9 100644
--- a/models/issues/issue_search.go
+++ b/models/issues/issue_search.go
@@ -13,7 +13,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"xorm.io/builder"
"xorm.io/xorm"
@@ -34,8 +34,8 @@ type IssuesOptions struct { //nolint
MilestoneIDs []int64
ProjectID int64
ProjectBoardID int64
- IsClosed util.OptionalBool
- IsPull util.OptionalBool
+ IsClosed optional.Option[bool]
+ IsPull optional.Option[bool]
LabelIDs []int64
IncludedLabelNames []string
ExcludedLabelNames []string
@@ -46,7 +46,7 @@ type IssuesOptions struct { //nolint
UpdatedBeforeUnix int64
// prioritize issues from this repo
PriorityRepoID int64
- IsArchived util.OptionalBool
+ IsArchived optional.Option[bool]
Org *organization.Organization // issues permission scope
Team *organization.Team // issues permission scope
User *user_model.User // issues permission scope
@@ -217,8 +217,8 @@ func applyConditions(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
applyRepoConditions(sess, opts)
- if !opts.IsClosed.IsNone() {
- sess.And("issue.is_closed=?", opts.IsClosed.IsTrue())
+ if opts.IsClosed.Has() {
+ sess.And("issue.is_closed=?", opts.IsClosed.Value())
}
if opts.AssigneeID > 0 {
@@ -260,21 +260,18 @@ func applyConditions(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
applyProjectBoardCondition(sess, opts)
- switch opts.IsPull {
- case util.OptionalBoolTrue:
- sess.And("issue.is_pull=?", true)
- case util.OptionalBoolFalse:
- sess.And("issue.is_pull=?", false)
+ if opts.IsPull.Has() {
+ sess.And("issue.is_pull=?", opts.IsPull.Value())
}
- if opts.IsArchived != util.OptionalBoolNone {
- sess.And(builder.Eq{"repository.is_archived": opts.IsArchived.IsTrue()})
+ if opts.IsArchived.Has() {
+ sess.And(builder.Eq{"repository.is_archived": opts.IsArchived.Value()})
}
applyLabelsCondition(sess, opts)
if opts.User != nil {
- sess.And(issuePullAccessibleRepoCond("issue.repo_id", opts.User.ID, opts.Org, opts.Team, opts.IsPull.IsTrue()))
+ sess.And(issuePullAccessibleRepoCond("issue.repo_id", opts.User.ID, opts.Org, opts.Team, opts.IsPull.Value()))
}
return sess
diff --git a/models/issues/issue_stats.go b/models/issues/issue_stats.go
index 99ca19f804..32c5674fc9 100644
--- a/models/issues/issue_stats.go
+++ b/models/issues/issue_stats.go
@@ -8,7 +8,6 @@ import (
"fmt"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/util"
"xorm.io/builder"
"xorm.io/xorm"
@@ -170,11 +169,8 @@ func applyIssuesOptions(sess *xorm.Session, opts *IssuesOptions, issueIDs []int6
applyReviewedCondition(sess, opts.ReviewedID)
}
- switch opts.IsPull {
- case util.OptionalBoolTrue:
- sess.And("issue.is_pull=?", true)
- case util.OptionalBoolFalse:
- sess.And("issue.is_pull=?", false)
+ if opts.IsPull.Has() {
+ sess.And("issue.is_pull=?", opts.IsPull.Value())
}
return sess
diff --git a/models/issues/label.go b/models/issues/label.go
index 527d8d7853..f6ecc68cd1 100644
--- a/models/issues/label.go
+++ b/models/issues/label.go
@@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/label"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -126,7 +127,7 @@ func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{
RepoIDs: []int64{repoID},
LabelIDs: []int64{labelID},
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
})
for _, count := range counts {
diff --git a/models/issues/milestone.go b/models/issues/milestone.go
index 15987f2225..4b3cb0e858 100644
--- a/models/issues/milestone.go
+++ b/models/issues/milestone.go
@@ -6,10 +6,12 @@ package issues
import (
"context"
"fmt"
+ "html/template"
"strings"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -47,8 +49,8 @@ type Milestone struct {
RepoID int64 `xorm:"INDEX"`
Repo *repo_model.Repository `xorm:"-"`
Name string
- Content string `xorm:"TEXT"`
- RenderedContent string `xorm:"-"`
+ Content string `xorm:"TEXT"`
+ RenderedContent template.HTML `xorm:"-"`
IsClosed bool
NumIssues int
NumClosedIssues int
@@ -313,7 +315,7 @@ func DeleteMilestoneByRepoID(ctx context.Context, repoID, id int64) error {
}
numClosedMilestones, err := db.Count[Milestone](ctx, FindMilestoneOptions{
RepoID: repo.ID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
})
if err != nil {
return err
diff --git a/models/issues/milestone_list.go b/models/issues/milestone_list.go
index a73bf73c17..d1b3f0301b 100644
--- a/models/issues/milestone_list.go
+++ b/models/issues/milestone_list.go
@@ -8,7 +8,7 @@ import (
"strings"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"xorm.io/builder"
)
@@ -28,7 +28,7 @@ func (milestones MilestoneList) getMilestoneIDs() []int64 {
type FindMilestoneOptions struct {
db.ListOptions
RepoID int64
- IsClosed util.OptionalBool
+ IsClosed optional.Option[bool]
Name string
SortType string
RepoCond builder.Cond
@@ -40,8 +40,8 @@ func (opts FindMilestoneOptions) ToConds() builder.Cond {
if opts.RepoID != 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
- if opts.IsClosed != util.OptionalBoolNone {
- cond = cond.And(builder.Eq{"is_closed": opts.IsClosed.IsTrue()})
+ if opts.IsClosed.Has() {
+ cond = cond.And(builder.Eq{"is_closed": opts.IsClosed.Value()})
}
if opts.RepoCond != nil && opts.RepoCond.IsValid() {
cond = cond.And(builder.In("repo_id", builder.Select("id").From("repository").Where(opts.RepoCond)))
diff --git a/models/issues/milestone_test.go b/models/issues/milestone_test.go
index 7477af92c8..e5f6f15ca2 100644
--- a/models/issues/milestone_test.go
+++ b/models/issues/milestone_test.go
@@ -11,10 +11,10 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
)
@@ -39,10 +39,10 @@ func TestGetMilestoneByRepoID(t *testing.T) {
func TestGetMilestonesByRepoID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
test := func(repoID int64, state api.StateType) {
- var isClosed util.OptionalBool
+ var isClosed optional.Option[bool]
switch state {
case api.StateClosed, api.StateOpen:
- isClosed = util.OptionalBoolOf(state == api.StateClosed)
+ isClosed = optional.Some(state == api.StateClosed)
}
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{
@@ -84,7 +84,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{
RepoID: unittest.NonexistentID,
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
})
assert.NoError(t, err)
assert.Len(t, milestones, 0)
@@ -101,7 +101,7 @@ func TestGetMilestones(t *testing.T) {
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
SortType: sortType,
})
assert.NoError(t, err)
@@ -118,7 +118,7 @@ func TestGetMilestones(t *testing.T) {
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
Name: "",
SortType: sortType,
})
@@ -178,7 +178,7 @@ func TestCountRepoClosedMilestones(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
count, err := db.Count[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{
RepoID: repoID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
})
assert.NoError(t, err)
assert.EqualValues(t, repo.NumClosedMilestones, count)
@@ -189,7 +189,7 @@ func TestCountRepoClosedMilestones(t *testing.T) {
count, err := db.Count[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{
RepoID: unittest.NonexistentID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
})
assert.NoError(t, err)
assert.EqualValues(t, 0, count)
@@ -206,7 +206,7 @@ func TestCountMilestonesByRepoIDs(t *testing.T) {
openCounts, err := issues_model.CountMilestonesMap(db.DefaultContext, issues_model.FindMilestoneOptions{
RepoIDs: []int64{1, 2},
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
})
assert.NoError(t, err)
assert.EqualValues(t, repo1OpenCount, openCounts[1])
@@ -215,7 +215,7 @@ func TestCountMilestonesByRepoIDs(t *testing.T) {
closedCounts, err := issues_model.CountMilestonesMap(db.DefaultContext,
issues_model.FindMilestoneOptions{
RepoIDs: []int64{1, 2},
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
})
assert.NoError(t, err)
assert.EqualValues(t, repo1ClosedCount, closedCounts[1])
@@ -234,7 +234,7 @@ func TestGetMilestonesByRepoIDs(t *testing.T) {
PageSize: setting.UI.IssuePagingNum,
},
RepoIDs: []int64{repo1.ID, repo2.ID},
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
SortType: sortType,
})
assert.NoError(t, err)
@@ -252,7 +252,7 @@ func TestGetMilestonesByRepoIDs(t *testing.T) {
PageSize: setting.UI.IssuePagingNum,
},
RepoIDs: []int64{repo1.ID, repo2.ID},
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
SortType: sortType,
})
assert.NoError(t, err)
diff --git a/models/issues/review_list.go b/models/issues/review_list.go
index 282f18b4f7..ec6cb07988 100644
--- a/models/issues/review_list.go
+++ b/models/issues/review_list.go
@@ -9,7 +9,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"xorm.io/builder"
)
@@ -68,7 +68,7 @@ type FindReviewOptions struct {
IssueID int64
ReviewerID int64
OfficialOnly bool
- Dismissed util.OptionalBool
+ Dismissed optional.Option[bool]
}
func (opts *FindReviewOptions) toCond() builder.Cond {
@@ -85,8 +85,8 @@ func (opts *FindReviewOptions) toCond() builder.Cond {
if opts.OfficialOnly {
cond = cond.And(builder.Eq{"official": true})
}
- if !opts.Dismissed.IsNone() {
- cond = cond.And(builder.Eq{"dismissed": opts.Dismissed.IsTrue()})
+ if opts.Dismissed.Has() {
+ cond = cond.And(builder.Eq{"dismissed": opts.Dismissed.Value()})
}
return cond
}
diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go
index 91c4832e49..4063ca043b 100644
--- a/models/issues/tracked_time.go
+++ b/models/issues/tracked_time.go
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -340,7 +341,7 @@ func GetTrackedTimeByID(ctx context.Context, id int64) (*TrackedTime, error) {
}
// GetIssueTotalTrackedTime returns the total tracked time for issues by given conditions.
-func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed util.OptionalBool) (int64, error) {
+func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed optional.Option[bool]) (int64, error) {
if len(opts.IssueIDs) <= MaxQueryParameters {
return getIssueTotalTrackedTimeChunk(ctx, opts, isClosed, opts.IssueIDs)
}
@@ -363,7 +364,7 @@ func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed
return accum, nil
}
-func getIssueTotalTrackedTimeChunk(ctx context.Context, opts *IssuesOptions, isClosed util.OptionalBool, issueIDs []int64) (int64, error) {
+func getIssueTotalTrackedTimeChunk(ctx context.Context, opts *IssuesOptions, isClosed optional.Option[bool], issueIDs []int64) (int64, error) {
sumSession := func(opts *IssuesOptions, issueIDs []int64) *xorm.Session {
sess := db.GetEngine(ctx).
Table("tracked_time").
@@ -378,8 +379,8 @@ func getIssueTotalTrackedTimeChunk(ctx context.Context, opts *IssuesOptions, isC
}
session := sumSession(opts, issueIDs)
- if !isClosed.IsNone() {
- session = session.And("issue.is_closed = ?", isClosed.IsTrue())
+ if isClosed.Has() {
+ session = session.And("issue.is_closed = ?", isClosed.Value())
}
return session.SumInt(new(trackedTime), "tracked_time.time")
}
diff --git a/models/issues/tracked_time_test.go b/models/issues/tracked_time_test.go
index 9beb862ffb..d82bff967a 100644
--- a/models/issues/tracked_time_test.go
+++ b/models/issues/tracked_time_test.go
@@ -11,7 +11,7 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"github.com/stretchr/testify/assert"
)
@@ -120,15 +120,15 @@ func TestTotalTimesForEachUser(t *testing.T) {
func TestGetIssueTotalTrackedTime(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- ttt, err := issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, util.OptionalBoolFalse)
+ ttt, err := issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.Some(false))
assert.NoError(t, err)
assert.EqualValues(t, 3682, ttt)
- ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, util.OptionalBoolTrue)
+ ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.Some(true))
assert.NoError(t, err)
assert.EqualValues(t, 0, ttt)
- ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, util.OptionalBoolNone)
+ ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.None[bool]())
assert.NoError(t, err)
assert.EqualValues(t, 3682, ttt)
}
diff --git a/models/packages/descriptor.go b/models/packages/descriptor.go
index f849ab5c04..b8ef698d38 100644
--- a/models/packages/descriptor.go
+++ b/models/packages/descriptor.go
@@ -70,16 +70,26 @@ type PackageFileDescriptor struct {
Properties PackagePropertyList
}
-// PackageWebLink returns the package web link
+// PackageWebLink returns the relative package web link
func (pd *PackageDescriptor) PackageWebLink() string {
return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HomeLink(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName))
}
-// FullWebLink returns the package version web link
-func (pd *PackageDescriptor) FullWebLink() string {
+// VersionWebLink returns the relative package version web link
+func (pd *PackageDescriptor) VersionWebLink() string {
return fmt.Sprintf("%s/%s", pd.PackageWebLink(), url.PathEscape(pd.Version.LowerVersion))
}
+// PackageHTMLURL returns the absolute package HTML URL
+func (pd *PackageDescriptor) PackageHTMLURL() string {
+ return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HTMLURL(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName))
+}
+
+// VersionHTMLURL returns the absolute package version HTML URL
+func (pd *PackageDescriptor) VersionHTMLURL() string {
+ return fmt.Sprintf("%s/%s", pd.PackageHTMLURL(), url.PathEscape(pd.Version.LowerVersion))
+}
+
// CalculateBlobSize returns the total blobs size in bytes
func (pd *PackageDescriptor) CalculateBlobSize() int64 {
size := int64(0)
diff --git a/models/packages/nuget/search.go b/models/packages/nuget/search.go
index 53cdf2d4ad..7a505ff08f 100644
--- a/models/packages/nuget/search.go
+++ b/models/packages/nuget/search.go
@@ -55,7 +55,7 @@ func CountPackages(ctx context.Context, opts *packages_model.PackageSearchOption
func toConds(opts *packages_model.PackageSearchOptions) builder.Cond {
var cond builder.Cond = builder.Eq{
- "package.is_internal": opts.IsInternal.IsTrue(),
+ "package.is_internal": opts.IsInternal.Value(),
"package.owner_id": opts.OwnerID,
"package.type": packages_model.TypeNuGet,
}
diff --git a/models/packages/package_version.go b/models/packages/package_version.go
index 8fc475691b..505dbaa0a5 100644
--- a/models/packages/package_version.go
+++ b/models/packages/package_version.go
@@ -9,6 +9,7 @@ import (
"strings"
"code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -105,7 +106,7 @@ func getVersionByNameAndVersion(ctx context.Context, ownerID int64, packageType
ExactMatch: true,
Value: version,
},
- IsInternal: util.OptionalBoolOf(isInternal),
+ IsInternal: optional.Some(isInternal),
Paginator: db.NewAbsoluteListOptions(0, 1),
})
if err != nil {
@@ -122,7 +123,7 @@ func GetVersionsByPackageType(ctx context.Context, ownerID int64, packageType Ty
pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
OwnerID: ownerID,
Type: packageType,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
return pvs, err
}
@@ -136,7 +137,7 @@ func GetVersionsByPackageName(ctx context.Context, ownerID int64, packageType Ty
ExactMatch: true,
Value: name,
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
return pvs, err
}
@@ -182,18 +183,18 @@ type PackageSearchOptions struct {
Name SearchValue // only results with the specific name are found
Version SearchValue // only results with the specific version are found
Properties map[string]string // only results are found which contain all listed version properties with the specific value
- IsInternal util.OptionalBool
- HasFileWithName string // only results are found which are associated with a file with the specific name
- HasFiles util.OptionalBool // only results are found which have associated files
+ IsInternal optional.Option[bool]
+ HasFileWithName string // only results are found which are associated with a file with the specific name
+ HasFiles optional.Option[bool] // only results are found which have associated files
Sort VersionSort
db.Paginator
}
func (opts *PackageSearchOptions) ToConds() builder.Cond {
cond := builder.NewCond()
- if !opts.IsInternal.IsNone() {
+ if opts.IsInternal.Has() {
cond = builder.Eq{
- "package_version.is_internal": opts.IsInternal.IsTrue(),
+ "package_version.is_internal": opts.IsInternal.Value(),
}
}
@@ -250,10 +251,10 @@ func (opts *PackageSearchOptions) ToConds() builder.Cond {
cond = cond.And(builder.Exists(builder.Select("package_file.id").From("package_file").Where(fileCond)))
}
- if !opts.HasFiles.IsNone() {
+ if opts.HasFiles.Has() {
filesCond := builder.Exists(builder.Select("package_file.id").From("package_file").Where(builder.Expr("package_file.version_id = package_version.id")))
- if opts.HasFiles.IsFalse() {
+ if !opts.HasFiles.Value() {
filesCond = builder.Not{filesCond}
}
@@ -307,8 +308,8 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
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))")
- if !opts.IsInternal.IsNone() {
- joinCond = joinCond.And(builder.Eq{"pv2.is_internal": opts.IsInternal.IsTrue()})
+ if opts.IsInternal.Has() {
+ joinCond = joinCond.And(builder.Eq{"pv2.is_internal": opts.IsInternal.Value()})
}
sess := db.GetEngine(ctx).
diff --git a/models/project/project.go b/models/project/project.go
index d2fca6cdc8..8f9ee2a99e 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -6,11 +6,13 @@ package project
import (
"context"
"fmt"
+ "html/template"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -100,7 +102,7 @@ type Project struct {
CardType CardType
Type Type
- RenderedContent string `xorm:"-"`
+ RenderedContent template.HTML `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
@@ -195,7 +197,7 @@ type SearchOptions struct {
db.ListOptions
OwnerID int64
RepoID int64
- IsClosed util.OptionalBool
+ IsClosed optional.Option[bool]
OrderBy db.SearchOrderBy
Type Type
Title string
@@ -206,11 +208,8 @@ func (opts SearchOptions) ToConds() builder.Cond {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
- switch opts.IsClosed {
- case util.OptionalBoolTrue:
- cond = cond.And(builder.Eq{"is_closed": true})
- case util.OptionalBoolFalse:
- cond = cond.And(builder.Eq{"is_closed": false})
+ if opts.IsClosed.Has() {
+ cond = cond.And(builder.Eq{"is_closed": opts.IsClosed.Value()})
}
if opts.Type > 0 {
diff --git a/models/repo/release.go b/models/repo/release.go
index 1f37f11b2e..a9f65f6c3e 100644
--- a/models/repo/release.go
+++ b/models/repo/release.go
@@ -7,6 +7,7 @@ package repo
import (
"context"
"fmt"
+ "html/template"
"net/url"
"sort"
"strconv"
@@ -15,6 +16,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -79,7 +81,7 @@ type Release struct {
NumCommits int64
NumCommitsBehind int64 `xorm:"-"`
Note string `xorm:"TEXT"`
- RenderedNote string `xorm:"-"`
+ RenderedNote template.HTML `xorm:"-"`
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
IsTag bool `xorm:"NOT NULL DEFAULT false"` // will be true only if the record is a tag and has no related releases
@@ -228,10 +230,10 @@ type FindReleasesOptions struct {
RepoID int64
IncludeDrafts bool
IncludeTags bool
- IsPreRelease util.OptionalBool
- IsDraft util.OptionalBool
+ IsPreRelease optional.Option[bool]
+ IsDraft optional.Option[bool]
TagNames []string
- HasSha1 util.OptionalBool // useful to find draft releases which are created with existing tags
+ HasSha1 optional.Option[bool] // useful to find draft releases which are created with existing tags
}
func (opts FindReleasesOptions) ToConds() builder.Cond {
@@ -246,14 +248,14 @@ func (opts FindReleasesOptions) ToConds() builder.Cond {
if len(opts.TagNames) > 0 {
cond = cond.And(builder.In("tag_name", opts.TagNames))
}
- if !opts.IsPreRelease.IsNone() {
- cond = cond.And(builder.Eq{"is_prerelease": opts.IsPreRelease.IsTrue()})
+ if opts.IsPreRelease.Has() {
+ cond = cond.And(builder.Eq{"is_prerelease": opts.IsPreRelease.Value()})
}
- if !opts.IsDraft.IsNone() {
- cond = cond.And(builder.Eq{"is_draft": opts.IsDraft.IsTrue()})
+ if opts.IsDraft.Has() {
+ cond = cond.And(builder.Eq{"is_draft": opts.IsDraft.Value()})
}
- if !opts.HasSha1.IsNone() {
- if opts.HasSha1.IsTrue() {
+ if opts.HasSha1.Has() {
+ if opts.HasSha1.Value() {
cond = cond.And(builder.Neq{"sha1": ""})
} else {
cond = cond.And(builder.Eq{"sha1": ""})
@@ -275,7 +277,7 @@ func GetTagNamesByRepoID(ctx context.Context, repoID int64) ([]string, error) {
ListOptions: listOptions,
IncludeDrafts: true,
IncludeTags: true,
- HasSha1: util.OptionalBoolTrue,
+ HasSha1: optional.Some(true),
RepoID: repoID,
}
diff --git a/models/repo/repo.go b/models/repo/repo.go
index b24e5c1dbf..81ed6efa24 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -20,6 +20,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
@@ -873,7 +874,7 @@ func (repo *Repository) TemplateRepo(ctx context.Context) *Repository {
type CountRepositoryOptions struct {
OwnerID int64
- Private util.OptionalBool
+ Private optional.Option[bool]
}
// CountRepositories returns number of repositories.
@@ -885,8 +886,8 @@ func CountRepositories(ctx context.Context, opts CountRepositoryOptions) (int64,
if opts.OwnerID > 0 {
sess.And("owner_id = ?", opts.OwnerID)
}
- if !opts.Private.IsNone() {
- sess.And("is_private=?", opts.Private.IsTrue())
+ if opts.Private.Has() {
+ sess.And("is_private=?", opts.Private.Value())
}
count, err := sess.Count(new(Repository))
diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go
index 533ca5251f..6b452291ea 100644
--- a/models/repo/repo_list.go
+++ b/models/repo/repo_list.go
@@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
@@ -125,11 +126,11 @@ type SearchRepoOptions struct {
// None -> include public and private
// True -> include just private
// False -> include just public
- IsPrivate util.OptionalBool
+ IsPrivate optional.Option[bool]
// None -> include collaborative AND non-collaborative
// True -> include just collaborative
// False -> include just non-collaborative
- Collaborate util.OptionalBool
+ Collaborate optional.Option[bool]
// What type of unit the user can be collaborative in,
// it is ignored if Collaborate is False.
// TypeInvalid means any unit type.
@@ -137,19 +138,19 @@ type SearchRepoOptions struct {
// None -> include forks AND non-forks
// True -> include just forks
// False -> include just non-forks
- Fork util.OptionalBool
+ Fork optional.Option[bool]
// None -> include templates AND non-templates
// True -> include just templates
// False -> include just non-templates
- Template util.OptionalBool
+ Template optional.Option[bool]
// None -> include mirrors AND non-mirrors
// True -> include just mirrors
// False -> include just non-mirrors
- Mirror util.OptionalBool
+ Mirror optional.Option[bool]
// None -> include archived AND non-archived
// True -> include just archived
// False -> include just non-archived
- Archived util.OptionalBool
+ Archived optional.Option[bool]
// only search topic name
TopicOnly bool
// only search repositories with specified primary language
@@ -159,7 +160,7 @@ type SearchRepoOptions struct {
// None -> include has milestones AND has no milestone
// True -> include just has milestones
// False -> include just has no milestone
- HasMilestones util.OptionalBool
+ HasMilestones optional.Option[bool]
// LowerNames represents valid lower names to restrict to
LowerNames []string
// When specified true, apply some filters over the conditions:
@@ -359,12 +360,12 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
)))
}
- if opts.IsPrivate != util.OptionalBoolNone {
- cond = cond.And(builder.Eq{"is_private": opts.IsPrivate.IsTrue()})
+ if opts.IsPrivate.Has() {
+ cond = cond.And(builder.Eq{"is_private": opts.IsPrivate.Value()})
}
- if opts.Template != util.OptionalBoolNone {
- cond = cond.And(builder.Eq{"is_template": opts.Template == util.OptionalBoolTrue})
+ if opts.Template.Has() {
+ cond = cond.And(builder.Eq{"is_template": opts.Template.Value()})
}
// Restrict to starred repositories
@@ -380,11 +381,11 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
// Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate
if opts.OwnerID > 0 {
accessCond := builder.NewCond()
- if opts.Collaborate != util.OptionalBoolTrue {
+ if !opts.Collaborate.Value() {
accessCond = builder.Eq{"owner_id": opts.OwnerID}
}
- if opts.Collaborate != util.OptionalBoolFalse {
+ if opts.Collaborate.ValueOrDefault(true) {
// A Collaboration is:
collaborateCond := builder.NewCond()
@@ -472,31 +473,32 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
Where(builder.Eq{"language": opts.Language}).And(builder.Eq{"is_primary": true})))
}
- if opts.Fork != util.OptionalBoolNone || opts.OnlyShowRelevant {
- if opts.OnlyShowRelevant && opts.Fork == util.OptionalBoolNone {
+ if opts.Fork.Has() || opts.OnlyShowRelevant {
+ if opts.OnlyShowRelevant && !opts.Fork.Has() {
cond = cond.And(builder.Eq{"is_fork": false})
} else {
- cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue})
+ cond = cond.And(builder.Eq{"is_fork": opts.Fork.Value()})
}
}
- if opts.Mirror != util.OptionalBoolNone {
- cond = cond.And(builder.Eq{"is_mirror": opts.Mirror == util.OptionalBoolTrue})
+ if opts.Mirror.Has() {
+ cond = cond.And(builder.Eq{"is_mirror": opts.Mirror.Value()})
}
if opts.Actor != nil && opts.Actor.IsRestricted {
cond = cond.And(AccessibleRepositoryCondition(opts.Actor, unit.TypeInvalid))
}
- if opts.Archived != util.OptionalBoolNone {
- cond = cond.And(builder.Eq{"is_archived": opts.Archived == util.OptionalBoolTrue})
+ if opts.Archived.Has() {
+ cond = cond.And(builder.Eq{"is_archived": opts.Archived.Value()})
}
- switch opts.HasMilestones {
- case util.OptionalBoolTrue:
- cond = cond.And(builder.Gt{"num_milestones": 0})
- case util.OptionalBoolFalse:
- cond = cond.And(builder.Eq{"num_milestones": 0}.Or(builder.IsNull{"num_milestones"}))
+ if opts.HasMilestones.Has() {
+ if opts.HasMilestones.Value() {
+ cond = cond.And(builder.Gt{"num_milestones": 0})
+ } else {
+ cond = cond.And(builder.Eq{"num_milestones": 0}.Or(builder.IsNull{"num_milestones"}))
+ }
}
if opts.OnlyShowRelevant {
diff --git a/models/repo/repo_list_test.go b/models/repo/repo_list_test.go
index 8006289460..ca6007f6c7 100644
--- a/models/repo/repo_list_test.go
+++ b/models/repo/repo_list_test.go
@@ -10,7 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"github.com/stretchr/testify/assert"
)
@@ -27,62 +27,62 @@ func getTestCases() []struct {
}{
{
name: "PublicRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: optional.Some(false)},
count: 7,
},
{
name: "PublicAndPrivateRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFirstPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitSecondPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitThirdPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFourthPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicRepositoriesOfUser",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: optional.Some(false)},
count: 2,
},
{
name: "PublicRepositoriesOfUser2",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: optional.Some(false)},
count: 0,
},
{
name: "PublicRepositoriesOfOrg3",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: optional.Some(false)},
count: 2,
},
{
name: "PublicAndPrivateRepositoriesOfUser",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: optional.Some(false)},
count: 4,
},
{
name: "PublicAndPrivateRepositoriesOfUser2",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: optional.Some(false)},
count: 0,
},
{
name: "PublicAndPrivateRepositoriesOfOrg3",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: optional.Some(false)},
count: 4,
},
{
@@ -117,32 +117,32 @@ func getTestCases() []struct {
},
{
name: "PublicRepositoriesOfOrganization",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: optional.Some(false)},
count: 1,
},
{
name: "PublicAndPrivateRepositoriesOfOrganization",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: optional.Some(false)},
count: 2,
},
{
name: "AllPublic/PublicRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: optional.Some(false)},
count: 7,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: optional.Some(false)},
count: 34,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: optional.Some(false)},
count: 39,
},
{
@@ -157,12 +157,12 @@ func getTestCases() []struct {
},
{
name: "AllPublic/PublicRepositoriesOfOrganization",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: optional.Some(false), Template: optional.Some(false)},
count: 34,
},
{
name: "AllTemplates",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: util.OptionalBoolTrue},
+ opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: optional.Some(true)},
count: 2,
},
{
@@ -190,7 +190,7 @@ func TestSearchRepository(t *testing.T) {
PageSize: 10,
},
Keyword: "repo_12",
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
})
assert.NoError(t, err)
@@ -205,7 +205,7 @@ func TestSearchRepository(t *testing.T) {
PageSize: 10,
},
Keyword: "test_repo",
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
})
assert.NoError(t, err)
@@ -220,7 +220,7 @@ func TestSearchRepository(t *testing.T) {
},
Keyword: "repo_13",
Private: true,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
})
assert.NoError(t, err)
@@ -236,7 +236,7 @@ func TestSearchRepository(t *testing.T) {
},
Keyword: "test_repo",
Private: true,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
})
assert.NoError(t, err)
@@ -257,7 +257,7 @@ func TestSearchRepository(t *testing.T) {
PageSize: 10,
},
Keyword: "description_14",
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
IncludeDescription: true,
})
@@ -274,7 +274,7 @@ func TestSearchRepository(t *testing.T) {
PageSize: 10,
},
Keyword: "description_14",
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
IncludeDescription: false,
})
@@ -327,30 +327,25 @@ func TestSearchRepository(t *testing.T) {
assert.False(t, repo.IsPrivate)
}
- if testCase.opts.Fork == util.OptionalBoolTrue && testCase.opts.Mirror == util.OptionalBoolTrue {
- assert.True(t, repo.IsFork || repo.IsMirror)
+ if testCase.opts.Fork.Value() && testCase.opts.Mirror.Value() {
+ assert.True(t, repo.IsFork && repo.IsMirror)
} else {
- switch testCase.opts.Fork {
- case util.OptionalBoolFalse:
- assert.False(t, repo.IsFork)
- case util.OptionalBoolTrue:
- assert.True(t, repo.IsFork)
+ if testCase.opts.Fork.Has() {
+ assert.Equal(t, testCase.opts.Fork.Value(), repo.IsFork)
}
- switch testCase.opts.Mirror {
- case util.OptionalBoolFalse:
- assert.False(t, repo.IsMirror)
- case util.OptionalBoolTrue:
- assert.True(t, repo.IsMirror)
+ if testCase.opts.Mirror.Has() {
+ assert.Equal(t, testCase.opts.Mirror.Value(), repo.IsMirror)
}
}
if testCase.opts.OwnerID > 0 && !testCase.opts.AllPublic {
- switch testCase.opts.Collaborate {
- case util.OptionalBoolFalse:
- assert.Equal(t, testCase.opts.OwnerID, repo.Owner.ID)
- case util.OptionalBoolTrue:
- assert.NotEqual(t, testCase.opts.OwnerID, repo.Owner.ID)
+ if testCase.opts.Collaborate.Has() {
+ if testCase.opts.Collaborate.Value() {
+ assert.NotEqual(t, testCase.opts.OwnerID, repo.Owner.ID)
+ } else {
+ assert.Equal(t, testCase.opts.OwnerID, repo.Owner.ID)
+ }
}
}
}
diff --git a/models/repo/repo_test.go b/models/repo/repo_test.go
index ca9209d751..1a870224bf 100644
--- a/models/repo/repo_test.go
+++ b/models/repo/repo_test.go
@@ -12,17 +12,17 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
- "code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
)
var (
countRepospts = repo_model.CountRepositoryOptions{OwnerID: 10}
- countReposptsPublic = repo_model.CountRepositoryOptions{OwnerID: 10, Private: util.OptionalBoolFalse}
- countReposptsPrivate = repo_model.CountRepositoryOptions{OwnerID: 10, Private: util.OptionalBoolTrue}
+ countReposptsPublic = repo_model.CountRepositoryOptions{OwnerID: 10, Private: optional.Some(false)}
+ countReposptsPrivate = repo_model.CountRepositoryOptions{OwnerID: 10, Private: optional.Some(true)}
)
func TestGetRepositoryCount(t *testing.T) {
diff --git a/models/user/email_address.go b/models/user/email_address.go
index cc62620e0f..6f3d5b1dde 100644
--- a/models/user/email_address.go
+++ b/models/user/email_address.go
@@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
@@ -425,8 +426,8 @@ type SearchEmailOptions struct {
db.ListOptions
Keyword string
SortType SearchEmailOrderBy
- IsPrimary util.OptionalBool
- IsActivated util.OptionalBool
+ IsPrimary optional.Option[bool]
+ IsActivated optional.Option[bool]
}
// SearchEmailResult is an e-mail address found in the user or email_address table
@@ -453,18 +454,12 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail
))
}
- switch {
- case opts.IsPrimary.IsTrue():
- cond = cond.And(builder.Eq{"email_address.is_primary": true})
- case opts.IsPrimary.IsFalse():
- cond = cond.And(builder.Eq{"email_address.is_primary": false})
+ if opts.IsPrimary.Has() {
+ cond = cond.And(builder.Eq{"email_address.is_primary": opts.IsPrimary.Value()})
}
- switch {
- case opts.IsActivated.IsTrue():
- cond = cond.And(builder.Eq{"email_address.is_activated": true})
- case opts.IsActivated.IsFalse():
- cond = cond.And(builder.Eq{"email_address.is_activated": false})
+ if opts.IsActivated.Has() {
+ cond = cond.And(builder.Eq{"email_address.is_activated": opts.IsActivated.Value()})
}
count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.ID = email_address.uid").
diff --git a/models/user/email_address_test.go b/models/user/email_address_test.go
index be1ccea544..65befa5660 100644
--- a/models/user/email_address_test.go
+++ b/models/user/email_address_test.go
@@ -10,7 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"github.com/stretchr/testify/assert"
)
@@ -138,14 +138,14 @@ func TestListEmails(t *testing.T) {
assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 27 }))
// Must find only primary addresses (i.e. from the `user` table)
- opts = &user_model.SearchEmailOptions{IsPrimary: util.OptionalBoolTrue}
+ opts = &user_model.SearchEmailOptions{IsPrimary: optional.Some(true)}
emails, _, err = user_model.SearchEmails(db.DefaultContext, opts)
assert.NoError(t, err)
assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsPrimary }))
assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsPrimary }))
// Must find only inactive addresses (i.e. not validated)
- opts = &user_model.SearchEmailOptions{IsActivated: util.OptionalBoolFalse}
+ opts = &user_model.SearchEmailOptions{IsActivated: optional.Some(false)}
emails, _, err = user_model.SearchEmails(db.DefaultContext, opts)
assert.NoError(t, err)
assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsActivated }))
diff --git a/models/user/search.go b/models/user/search.go
index 0fa278c257..45b051187e 100644
--- a/models/user/search.go
+++ b/models/user/search.go
@@ -9,8 +9,9 @@ import (
"strings"
"code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/container"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"xorm.io/builder"
"xorm.io/xorm"
@@ -30,11 +31,13 @@ type SearchUserOptions struct {
Actor *User // The user doing the search
SearchByEmail bool // Search by email as well as username/full name
- IsActive util.OptionalBool
- IsAdmin util.OptionalBool
- IsRestricted util.OptionalBool
- IsTwoFactorEnabled util.OptionalBool
- IsProhibitLogin util.OptionalBool
+ SupportedSortOrders container.Set[string] // if not nil, only allow to use the sort orders in this set
+
+ IsActive optional.Option[bool]
+ IsAdmin optional.Option[bool]
+ IsRestricted optional.Option[bool]
+ IsTwoFactorEnabled optional.Option[bool]
+ IsProhibitLogin optional.Option[bool]
IncludeReserved bool
ExtraParamStrings map[string]string
@@ -86,24 +89,24 @@ func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) *xorm.Sess
cond = cond.And(builder.Eq{"login_name": opts.LoginName})
}
- if !opts.IsActive.IsNone() {
- cond = cond.And(builder.Eq{"is_active": opts.IsActive.IsTrue()})
+ if opts.IsActive.Has() {
+ cond = cond.And(builder.Eq{"is_active": opts.IsActive.Value()})
}
- if !opts.IsAdmin.IsNone() {
- cond = cond.And(builder.Eq{"is_admin": opts.IsAdmin.IsTrue()})
+ if opts.IsAdmin.Has() {
+ cond = cond.And(builder.Eq{"is_admin": opts.IsAdmin.Value()})
}
- if !opts.IsRestricted.IsNone() {
- cond = cond.And(builder.Eq{"is_restricted": opts.IsRestricted.IsTrue()})
+ if opts.IsRestricted.Has() {
+ cond = cond.And(builder.Eq{"is_restricted": opts.IsRestricted.Value()})
}
- if !opts.IsProhibitLogin.IsNone() {
- cond = cond.And(builder.Eq{"prohibit_login": opts.IsProhibitLogin.IsTrue()})
+ if opts.IsProhibitLogin.Has() {
+ cond = cond.And(builder.Eq{"prohibit_login": opts.IsProhibitLogin.Value()})
}
e := db.GetEngine(ctx)
- if opts.IsTwoFactorEnabled.IsNone() {
+ if !opts.IsTwoFactorEnabled.Has() {
return e.Where(cond)
}
@@ -111,7 +114,7 @@ func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) *xorm.Sess
// While using LEFT JOIN, sometimes the performance might not be good, but it won't be a problem now, such SQL is seldom executed.
// There are some possible methods to refactor this SQL in future when we really need to optimize the performance (but not now):
// (1) add a column in user table (2) add a setting value in user_setting table (3) use search engines (bleve/elasticsearch)
- if opts.IsTwoFactorEnabled.IsTrue() {
+ if opts.IsTwoFactorEnabled.Value() {
cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL"))
} else {
cond = cond.And(builder.Expr("two_factor.uid IS NULL"))
@@ -128,7 +131,7 @@ func SearchUsers(ctx context.Context, opts *SearchUserOptions) (users []*User, _
defer sessCount.Close()
count, err := sessCount.Count(new(User))
if err != nil {
- return nil, 0, fmt.Errorf("Count: %w", err)
+ return nil, 0, fmt.Errorf("count: %w", err)
}
if len(opts.OrderBy) == 0 {
diff --git a/models/user/user.go b/models/user/user.go
index 9ff4881ec9..710fab9f4e 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -727,7 +727,7 @@ func CreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOve
// IsLastAdminUser check whether user is the last admin
func IsLastAdminUser(ctx context.Context, user *User) bool {
- if user.IsAdmin && CountUsers(ctx, &CountUserFilter{IsAdmin: util.OptionalBoolTrue}) <= 1 {
+ if user.IsAdmin && CountUsers(ctx, &CountUserFilter{IsAdmin: optional.Some(true)}) <= 1 {
return true
}
return false
@@ -736,7 +736,7 @@ func IsLastAdminUser(ctx context.Context, user *User) bool {
// CountUserFilter represent optional filters for CountUsers
type CountUserFilter struct {
LastLoginSince *int64
- IsAdmin util.OptionalBool
+ IsAdmin optional.Option[bool]
}
// CountUsers returns number of users.
@@ -754,8 +754,8 @@ func countUsers(ctx context.Context, opts *CountUserFilter) int64 {
cond = cond.And(builder.Gte{"last_login_unix": *opts.LastLoginSince})
}
- if !opts.IsAdmin.IsNone() {
- cond = cond.And(builder.Eq{"is_admin": opts.IsAdmin.IsTrue()})
+ if opts.IsAdmin.Has() {
+ cond = cond.And(builder.Eq{"is_admin": opts.IsAdmin.Value()})
}
}
diff --git a/models/user/user_test.go b/models/user/user_test.go
index 87a842a4d3..bb72743301 100644
--- a/models/user/user_test.go
+++ b/models/user/user_test.go
@@ -16,10 +16,10 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password/hash"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
)
@@ -103,29 +103,29 @@ func TestSearchUsers(t *testing.T) {
testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}},
[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37, 38, 39, 40})
- testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolFalse},
+ testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(false)},
[]int64{9})
- testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(true)},
[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37, 38, 39, 40})
- testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(true)},
[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
// order by name asc default
- testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(true)},
[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
- testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsAdmin: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsAdmin: optional.Some(true)},
[]int64{1})
- testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsRestricted: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsRestricted: optional.Some(true)},
[]int64{29})
- testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsProhibitLogin: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsProhibitLogin: optional.Some(true)},
[]int64{37})
- testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsTwoFactorEnabled: util.OptionalBoolTrue},
+ testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsTwoFactorEnabled: optional.Some(true)},
[]int64{24})
}
diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go
index 4a84a3d411..894357e36a 100644
--- a/models/webhook/webhook.go
+++ b/models/webhook/webhook.go
@@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/secret"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
@@ -433,7 +434,7 @@ type ListWebhookOptions struct {
db.ListOptions
RepoID int64
OwnerID int64
- IsActive util.OptionalBool
+ IsActive optional.Option[bool]
}
func (opts ListWebhookOptions) ToConds() builder.Cond {
@@ -444,8 +445,8 @@ func (opts ListWebhookOptions) ToConds() builder.Cond {
if opts.OwnerID != 0 {
cond = cond.And(builder.Eq{"webhook.owner_id": opts.OwnerID})
}
- if !opts.IsActive.IsNone() {
- cond = cond.And(builder.Eq{"webhook.is_active": opts.IsActive.IsTrue()})
+ if opts.IsActive.Has() {
+ cond = cond.And(builder.Eq{"webhook.is_active": opts.IsActive.Value()})
}
return cond
}
diff --git a/models/webhook/webhook_system.go b/models/webhook/webhook_system.go
index 2e89f9547b..a2a9ee321a 100644
--- a/models/webhook/webhook_system.go
+++ b/models/webhook/webhook_system.go
@@ -8,7 +8,7 @@ import (
"fmt"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
)
// GetDefaultWebhooks returns all admin-default webhooks.
@@ -34,15 +34,15 @@ func GetSystemOrDefaultWebhook(ctx context.Context, id int64) (*Webhook, error)
}
// GetSystemWebhooks returns all admin system webhooks.
-func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webhook, error) {
+func GetSystemWebhooks(ctx context.Context, isActive optional.Option[bool]) ([]*Webhook, error) {
webhooks := make([]*Webhook, 0, 5)
- if isActive.IsNone() {
+ if !isActive.Has() {
return webhooks, db.GetEngine(ctx).
Where("repo_id=? AND owner_id=? AND is_system_webhook=?", 0, 0, true).
Find(&webhooks)
}
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND owner_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.Value()).
Find(&webhooks)
}
diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go
index 694fd7a873..c70c8e99fc 100644
--- a/models/webhook/webhook_test.go
+++ b/models/webhook/webhook_test.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
"github.com/stretchr/testify/assert"
@@ -123,7 +123,7 @@ func TestGetWebhookByOwnerID(t *testing.T) {
func TestGetActiveWebhooksByRepoID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue})
+ hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)})
assert.NoError(t, err)
if assert.Len(t, hooks, 1) {
assert.Equal(t, int64(1), hooks[0].ID)
@@ -143,7 +143,7 @@ func TestGetWebhooksByRepoID(t *testing.T) {
func TestGetActiveWebhooksByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: util.OptionalBoolTrue})
+ hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)})
assert.NoError(t, err)
if assert.Len(t, hooks, 1) {
assert.Equal(t, int64(3), hooks[0].ID)
diff --git a/modules/actions/task_state.go b/modules/actions/task_state.go
index cbbc0b357d..fe925bbb5d 100644
--- a/modules/actions/task_state.go
+++ b/modules/actions/task_state.go
@@ -35,6 +35,9 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
} else if task.Status.IsDone() {
preStep.Stopped = task.Stopped
preStep.Status = actions_model.StatusFailure
+ if task.Status.IsSkipped() {
+ preStep.Status = actions_model.StatusSkipped
+ }
}
logIndex += preStep.LogLength
diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go
index 81ab26bc27..8317f16dbd 100644
--- a/modules/actions/workflows.go
+++ b/modules/actions/workflows.go
@@ -406,6 +406,9 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa
// all acts conditions should be satisfied
for cond, vals := range acts {
switch cond {
+ case "types":
+ // types have been checked
+ continue
case "branches":
refName := git.RefName(prPayload.PullRequest.Base.Ref)
patterns, err := workflowpattern.CompilePatterns(vals...)
diff --git a/modules/git/command.go b/modules/git/command.go
index 9305ef6f92..371109730a 100644
--- a/modules/git/command.go
+++ b/modules/git/command.go
@@ -12,6 +12,7 @@ import (
"io"
"os"
"os/exec"
+ "runtime"
"strings"
"time"
@@ -344,6 +345,17 @@ func (c *Command) Run(opts *RunOpts) error {
log.Debug("slow git.Command.Run: %s (%s)", c, elapsed)
}
+ // We need to check if the context is canceled by the program on Windows.
+ // This is because Windows does not have signal checking when terminating the process.
+ // It always returns exit code 1, unlike Linux, which has many exit codes for signals.
+ if runtime.GOOS == "windows" &&
+ err != nil &&
+ err.Error() == "" &&
+ cmd.ProcessState.ExitCode() == 1 &&
+ ctx.Err() == context.Canceled {
+ return ctx.Err()
+ }
+
if err != nil && ctx.Err() != context.DeadlineExceeded {
return err
}
diff --git a/modules/indexer/issues/bleve/bleve.go b/modules/indexer/issues/bleve/bleve.go
index 7c82cfbb79..6a5d65cb66 100644
--- a/modules/indexer/issues/bleve/bleve.go
+++ b/modules/indexer/issues/bleve/bleve.go
@@ -175,11 +175,11 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
queries = append(queries, bleve.NewDisjunctionQuery(repoQueries...))
}
- if !options.IsPull.IsNone() {
- queries = append(queries, inner_bleve.BoolFieldQuery(options.IsPull.IsTrue(), "is_pull"))
+ if options.IsPull.Has() {
+ queries = append(queries, inner_bleve.BoolFieldQuery(options.IsPull.Value(), "is_pull"))
}
- if !options.IsClosed.IsNone() {
- queries = append(queries, inner_bleve.BoolFieldQuery(options.IsClosed.IsTrue(), "is_closed"))
+ if options.IsClosed.Has() {
+ queries = append(queries, inner_bleve.BoolFieldQuery(options.IsClosed.Value(), "is_closed"))
}
if options.NoLabelOnly {
diff --git a/modules/indexer/issues/db/options.go b/modules/indexer/issues/db/options.go
index 5406715bbc..69146573a8 100644
--- a/modules/indexer/issues/db/options.go
+++ b/modules/indexer/issues/db/options.go
@@ -11,6 +11,7 @@ import (
issue_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/indexer/issues/internal"
+ "code.gitea.io/gitea/modules/optional"
)
func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_model.IssuesOptions, error) {
@@ -75,7 +76,7 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
UpdatedAfterUnix: convertInt64(options.UpdatedAfterUnix),
UpdatedBeforeUnix: convertInt64(options.UpdatedBeforeUnix),
PriorityRepoID: 0,
- IsArchived: 0,
+ IsArchived: optional.None[bool](),
Org: nil,
Team: nil,
User: nil,
diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go
index d059f76b32..3acd3ade71 100644
--- a/modules/indexer/issues/elasticsearch/elasticsearch.go
+++ b/modules/indexer/issues/elasticsearch/elasticsearch.go
@@ -153,11 +153,11 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
query.Must(q)
}
- if !options.IsPull.IsNone() {
- query.Must(elastic.NewTermQuery("is_pull", options.IsPull.IsTrue()))
+ if options.IsPull.Has() {
+ query.Must(elastic.NewTermQuery("is_pull", options.IsPull.Value()))
}
- if !options.IsClosed.IsNone() {
- query.Must(elastic.NewTermQuery("is_closed", options.IsClosed.IsTrue()))
+ if options.IsClosed.Has() {
+ query.Must(elastic.NewTermQuery("is_closed", options.IsClosed.Value()))
}
if options.NoLabelOnly {
diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go
index 57037d2947..e3bc21b49d 100644
--- a/modules/indexer/issues/indexer.go
+++ b/modules/indexer/issues/indexer.go
@@ -20,10 +20,10 @@ import (
"code.gitea.io/gitea/modules/indexer/issues/internal"
"code.gitea.io/gitea/modules/indexer/issues/meilisearch"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
)
// IndexerMetadata is used to send data to the queue, so it contains only the ids.
@@ -220,7 +220,7 @@ func PopulateIssueIndexer(ctx context.Context) error {
ListOptions: db_model.ListOptions{Page: page, PageSize: repo_model.RepositoryListDefaultPageSize},
OrderBy: db_model.SearchOrderByID,
Private: true,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
})
if err != nil {
log.Error("SearchRepositoryByName: %v", err)
diff --git a/modules/indexer/issues/indexer_test.go b/modules/indexer/issues/indexer_test.go
index 3b96686d98..10ffa7cbe6 100644
--- a/modules/indexer/issues/indexer_test.go
+++ b/modules/indexer/issues/indexer_test.go
@@ -10,8 +10,8 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/indexer/issues/internal"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
@@ -210,13 +210,13 @@ func searchIssueIsPull(t *testing.T) {
}{
{
SearchOptions{
- IsPull: util.OptionalBoolFalse,
+ IsPull: optional.Some(false),
},
[]int64{17, 16, 15, 14, 13, 6, 5, 18, 10, 7, 4, 1},
},
{
SearchOptions{
- IsPull: util.OptionalBoolTrue,
+ IsPull: optional.Some(true),
},
[]int64{22, 21, 12, 11, 20, 19, 9, 8, 3, 2},
},
@@ -237,13 +237,13 @@ func searchIssueIsClosed(t *testing.T) {
}{
{
SearchOptions{
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 19, 18, 10, 7, 9, 8, 3, 2, 1},
},
{
SearchOptions{
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
},
[]int64{5, 4},
},
diff --git a/modules/indexer/issues/internal/model.go b/modules/indexer/issues/internal/model.go
index 031745dd2f..947335d8ce 100644
--- a/modules/indexer/issues/internal/model.go
+++ b/modules/indexer/issues/internal/model.go
@@ -5,8 +5,8 @@ package internal
import (
"code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
)
// IndexerData data stored in the issue indexer
@@ -77,8 +77,8 @@ type SearchOptions struct {
RepoIDs []int64 // repository IDs which the issues belong to
AllPublic bool // if include all public repositories
- IsPull util.OptionalBool // if the issues is a pull request
- IsClosed util.OptionalBool // if the issues is closed
+ IsPull optional.Option[bool] // if the issues is a pull request
+ IsClosed optional.Option[bool] // if the issues is closed
IncludedLabelIDs []int64 // labels the issues have
ExcludedLabelIDs []int64 // labels the issues don't have
diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go
index 06fddeb65b..6724471539 100644
--- a/modules/indexer/issues/internal/tests/tests.go
+++ b/modules/indexer/issues/internal/tests/tests.go
@@ -16,8 +16,8 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/indexer/issues/internal"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -166,7 +166,7 @@ var cases = []*testIndexerCase{
Paginator: &db.ListOptions{
PageSize: 5,
},
- IsPull: util.OptionalBoolFalse,
+ IsPull: optional.Some(false),
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
assert.Equal(t, 5, len(result.Hits))
@@ -182,7 +182,7 @@ var cases = []*testIndexerCase{
Paginator: &db.ListOptions{
PageSize: 5,
},
- IsPull: util.OptionalBoolTrue,
+ IsPull: optional.Some(true),
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
assert.Equal(t, 5, len(result.Hits))
@@ -198,7 +198,7 @@ var cases = []*testIndexerCase{
Paginator: &db.ListOptions{
PageSize: 5,
},
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
assert.Equal(t, 5, len(result.Hits))
@@ -214,7 +214,7 @@ var cases = []*testIndexerCase{
Paginator: &db.ListOptions{
PageSize: 5,
},
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
assert.Equal(t, 5, len(result.Hits))
diff --git a/modules/indexer/issues/meilisearch/meilisearch.go b/modules/indexer/issues/meilisearch/meilisearch.go
index ab8dcd0af4..325883196b 100644
--- a/modules/indexer/issues/meilisearch/meilisearch.go
+++ b/modules/indexer/issues/meilisearch/meilisearch.go
@@ -131,11 +131,11 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
query.And(q)
}
- if !options.IsPull.IsNone() {
- query.And(inner_meilisearch.NewFilterEq("is_pull", options.IsPull.IsTrue()))
+ if options.IsPull.Has() {
+ query.And(inner_meilisearch.NewFilterEq("is_pull", options.IsPull.Value()))
}
- if !options.IsClosed.IsNone() {
- query.And(inner_meilisearch.NewFilterEq("is_closed", options.IsClosed.IsTrue()))
+ if options.IsClosed.Has() {
+ query.And(inner_meilisearch.NewFilterEq("is_closed", options.IsClosed.Value()))
}
if options.NoLabelOnly {
diff --git a/modules/issue/template/template.go b/modules/issue/template/template.go
index 4e813fc91f..3be48b9edc 100644
--- a/modules/issue/template/template.go
+++ b/modules/issue/template/template.go
@@ -122,7 +122,13 @@ func validateRequired(field *api.IssueFormField, idx int) error {
// The label is not required for a markdown or checkboxes field
return nil
}
- return validateBoolItem(newErrorPosition(idx, field.Type), field.Validations, "required")
+ if err := validateBoolItem(newErrorPosition(idx, field.Type), field.Validations, "required"); err != nil {
+ return err
+ }
+ if required, _ := field.Validations["required"].(bool); required && !field.VisibleOnForm() {
+ return newErrorPosition(idx, field.Type).Errorf("can not require a hidden field")
+ }
+ return nil
}
func validateID(field *api.IssueFormField, idx int, ids container.Set[string]) error {
@@ -172,10 +178,38 @@ func validateOptions(field *api.IssueFormField, idx int) error {
return position.Errorf("'label' is required and should be a string")
}
+ if visibility, ok := opt["visible"]; ok {
+ visibilityList, ok := visibility.([]any)
+ if !ok {
+ return position.Errorf("'visible' should be list")
+ }
+ for _, visibleType := range visibilityList {
+ visibleType, ok := visibleType.(string)
+ if !ok || !(visibleType == "form" || visibleType == "content") {
+ return position.Errorf("'visible' list can only contain strings of 'form' and 'content'")
+ }
+ }
+ }
+
if required, ok := opt["required"]; ok {
if _, ok := required.(bool); !ok {
return position.Errorf("'required' should be a bool")
}
+
+ // validate if hidden field is required
+ if visibility, ok := opt["visible"]; ok {
+ visibilityList, _ := visibility.([]any)
+ isVisible := false
+ for _, v := range visibilityList {
+ if vv, _ := v.(string); vv == "form" {
+ isVisible = true
+ break
+ }
+ }
+ if !isVisible {
+ return position.Errorf("can not require a hidden checkbox")
+ }
+ }
}
}
}
@@ -238,7 +272,7 @@ func RenderToMarkdown(template *api.IssueTemplate, values url.Values) string {
IssueFormField: field,
Values: values,
}
- if f.ID == "" {
+ if f.ID == "" || !f.VisibleInContent() {
continue
}
f.WriteTo(builder)
@@ -253,11 +287,6 @@ type valuedField struct {
}
func (f *valuedField) WriteTo(builder *strings.Builder) {
- if f.Type == api.IssueFormFieldTypeMarkdown {
- // markdown blocks do not appear in output
- return
- }
-
// write label
if !f.HideLabel() {
_, _ = fmt.Fprintf(builder, "### %s\n\n", f.Label())
@@ -269,6 +298,9 @@ func (f *valuedField) WriteTo(builder *strings.Builder) {
switch f.Type {
case api.IssueFormFieldTypeCheckboxes:
for _, option := range f.Options() {
+ if !option.VisibleInContent() {
+ continue
+ }
checked := " "
if option.IsChecked() {
checked = "x"
@@ -302,6 +334,10 @@ func (f *valuedField) WriteTo(builder *strings.Builder) {
} else {
_, _ = fmt.Fprintf(builder, "%s\n", value)
}
+ case api.IssueFormFieldTypeMarkdown:
+ if value, ok := f.Attributes["value"].(string); ok {
+ _, _ = fmt.Fprintf(builder, "%s\n", value)
+ }
}
_, _ = fmt.Fprintln(builder)
}
@@ -314,6 +350,9 @@ func (f *valuedField) Label() string {
}
func (f *valuedField) HideLabel() bool {
+ if f.Type == api.IssueFormFieldTypeMarkdown {
+ return true
+ }
if label, ok := f.Attributes["hide_label"].(bool); ok {
return label
}
@@ -385,6 +424,22 @@ func (o *valuedOption) IsChecked() bool {
return false
}
+func (o *valuedOption) VisibleInContent() bool {
+ if o.field.Type == api.IssueFormFieldTypeCheckboxes {
+ if vs, ok := o.data.(map[string]any); ok {
+ if vl, ok := vs["visible"].([]any); ok {
+ for _, v := range vl {
+ if vv, _ := v.(string); vv == "content" {
+ return true
+ }
+ }
+ return false
+ }
+ }
+ }
+ return true
+}
+
var minQuotesRegex = regexp.MustCompilePOSIX("^`{3,}")
// minQuotes return 3 or more back-quotes.
diff --git a/modules/issue/template/template_test.go b/modules/issue/template/template_test.go
index 06e6b70d35..e24b962d61 100644
--- a/modules/issue/template/template_test.go
+++ b/modules/issue/template/template_test.go
@@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/modules/json"
api "code.gitea.io/gitea/modules/structs"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -319,6 +320,42 @@ body:
wantErr: "body[0](checkboxes), option[0]: 'required' should be a bool",
},
{
+ name: "field is required but hidden",
+ content: `
+name: "test"
+about: "this is about"
+body:
+ - type: "input"
+ id: "1"
+ attributes:
+ label: "a"
+ validations:
+ required: true
+ visible: [content]
+`,
+ wantErr: "body[0](input): can not require a hidden field",
+ },
+ {
+ name: "checkboxes is required but hidden",
+ content: `
+name: "test"
+about: "this is about"
+body:
+ - type: checkboxes
+ id: "1"
+ attributes:
+ label: Label of checkboxes
+ description: Description of checkboxes
+ options:
+ - label: Option 1
+ required: false
+ - label: Required and hidden
+ required: true
+ visible: [content]
+`,
+ wantErr: "body[0](checkboxes), option[1]: can not require a hidden checkbox",
+ },
+ {
name: "valid",
content: `
name: Name
@@ -374,8 +411,11 @@ body:
required: true
- label: Option 2 of checkboxes
required: false
- - label: Option 3 of checkboxes
+ - label: Hidden Option 3 of checkboxes
+ visible: [content]
+ - label: Required but not submitted
required: true
+ visible: [form]
`,
want: &api.IssueTemplate{
Name: "Name",
@@ -390,6 +430,7 @@ body:
Attributes: map[string]any{
"value": "Value of the markdown",
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
},
{
Type: "textarea",
@@ -404,6 +445,7 @@ body:
Validations: map[string]any{
"required": true,
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
},
{
Type: "input",
@@ -419,6 +461,7 @@ body:
"is_number": true,
"regex": "[a-zA-Z0-9]+",
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
},
{
Type: "dropdown",
@@ -436,6 +479,7 @@ body:
Validations: map[string]any{
"required": true,
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
},
{
Type: "checkboxes",
@@ -446,9 +490,11 @@ body:
"options": []any{
map[string]any{"label": "Option 1 of checkboxes", "required": true},
map[string]any{"label": "Option 2 of checkboxes", "required": false},
- map[string]any{"label": "Option 3 of checkboxes", "required": true},
+ map[string]any{"label": "Hidden Option 3 of checkboxes", "visible": []string{"content"}},
+ map[string]any{"label": "Required but not submitted", "required": true, "visible": []string{"form"}},
},
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
},
},
FileName: "test.yaml",
@@ -467,7 +513,12 @@ body:
- type: markdown
id: id1
attributes:
- value: Value of the markdown
+ value: Value of the markdown shown in form
+ - type: markdown
+ id: id2
+ attributes:
+ value: Value of the markdown shown in created issue
+ visible: [content]
`,
want: &api.IssueTemplate{
Name: "Name",
@@ -480,8 +531,17 @@ body:
Type: "markdown",
ID: "id1",
Attributes: map[string]any{
- "value": "Value of the markdown",
+ "value": "Value of the markdown shown in form",
+ },
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
+ },
+ {
+ Type: "markdown",
+ ID: "id2",
+ Attributes: map[string]any{
+ "value": "Value of the markdown shown in created issue",
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleContent},
},
},
FileName: "test.yaml",
@@ -515,6 +575,7 @@ body:
Attributes: map[string]any{
"value": "Value of the markdown",
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
},
},
FileName: "test.yaml",
@@ -548,6 +609,7 @@ body:
Attributes: map[string]any{
"value": "Value of the markdown",
},
+ Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
},
},
FileName: "test.yaml",
@@ -622,10 +684,15 @@ body:
- type: markdown
id: id1
attributes:
- value: Value of the markdown
- - type: textarea
+ value: Value of the markdown shown in form
+ - type: markdown
id: id2
attributes:
+ value: Value of the markdown shown in created issue
+ visible: [content]
+ - type: textarea
+ id: id3
+ attributes:
label: Label of textarea
description: Description of textarea
placeholder: Placeholder of textarea
@@ -634,7 +701,7 @@ body:
validations:
required: true
- type: input
- id: id3
+ id: id4
attributes:
label: Label of input
description: Description of input
@@ -646,7 +713,7 @@ body:
is_number: true
regex: "[a-zA-Z0-9]+"
- type: dropdown
- id: id4
+ id: id5
attributes:
label: Label of dropdown
description: Description of dropdown
@@ -658,7 +725,7 @@ body:
validations:
required: true
- type: checkboxes
- id: id5
+ id: id6
attributes:
label: Label of checkboxes
description: Description of checkboxes
@@ -669,20 +736,26 @@ body:
required: false
- label: Option 3 of checkboxes
required: true
+ visible: [form]
+ - label: Hidden Option of checkboxes
+ visible: [content]
`,
values: map[string][]string{
- "form-field-id2": {"Value of id2"},
"form-field-id3": {"Value of id3"},
- "form-field-id4": {"0,1"},
- "form-field-id5-0": {"on"},
- "form-field-id5-2": {"on"},
+ "form-field-id4": {"Value of id4"},
+ "form-field-id5": {"0,1"},
+ "form-field-id6-0": {"on"},
+ "form-field-id6-2": {"on"},
},
},
- want: `### Label of textarea
-` + "```bash\nValue of id2\n```" + `
+ want: `Value of the markdown shown in created issue
+
+### Label of textarea
+
+` + "```bash\nValue of id3\n```" + `
-Value of id3
+Value of id4
### Label of dropdown
@@ -692,7 +765,7 @@ Option 1 of dropdown, Option 2 of dropdown
- [x] Option 1 of checkboxes
- [ ] Option 2 of checkboxes
-- [x] Option 3 of checkboxes
+- [ ] Hidden Option of checkboxes
`,
},
@@ -704,7 +777,7 @@ Option 1 of dropdown, Option 2 of dropdown
t.Fatal(err)
}
if got := RenderToMarkdown(template, tt.args.values); got != tt.want {
- t.Errorf("RenderToMarkdown() = %v, want %v", got, tt.want)
+ assert.EqualValues(t, tt.want, got)
}
})
}
diff --git a/modules/issue/template/unmarshal.go b/modules/issue/template/unmarshal.go
index 8cae8d4c42..0fc13d7ddf 100644
--- a/modules/issue/template/unmarshal.go
+++ b/modules/issue/template/unmarshal.go
@@ -128,9 +128,18 @@ func unmarshal(filename string, content []byte) (*api.IssueTemplate, error) {
}
}
for i, v := range it.Fields {
+ // set default id value
if v.ID == "" {
v.ID = strconv.Itoa(i)
}
+ // set default visibility
+ if v.Visible == nil {
+ v.Visible = []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm}
+ // markdown is not submitted by default
+ if v.Type != api.IssueFormFieldTypeMarkdown {
+ v.Visible = append(v.Visible, api.IssueFormFieldVisibleContent)
+ }
+ }
}
}
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 89ecfc036b..132955c019 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -388,7 +388,7 @@ func TestRender_ShortLinks(t *testing.T) {
},
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
buffer, err = markdown.RenderString(&markup.RenderContext{
Ctx: git.DefaultContext,
Links: markup.Links{
@@ -398,7 +398,7 @@ func TestRender_ShortLinks(t *testing.T) {
IsWiki: true,
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
}
mediatree := util.URLJoin(markup.TestRepoURL, "media", "master")
@@ -501,7 +501,7 @@ func TestRender_RelativeImages(t *testing.T) {
Metas: localMetas,
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
buffer, err = markdown.RenderString(&markup.RenderContext{
Ctx: git.DefaultContext,
Links: markup.Links{
@@ -511,7 +511,7 @@ func TestRender_RelativeImages(t *testing.T) {
IsWiki: true,
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
}
rawwiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw")
diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go
index 00d01a2f55..7750279ef2 100644
--- a/modules/markup/markdown/markdown.go
+++ b/modules/markup/markdown/markdown.go
@@ -6,6 +6,7 @@ package markdown
import (
"fmt"
+ "html/template"
"io"
"strings"
"sync"
@@ -266,12 +267,12 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
}
// RenderString renders Markdown string to HTML with all specific handling stuff and return string
-func RenderString(ctx *markup.RenderContext, content string) (string, error) {
+func RenderString(ctx *markup.RenderContext, content string) (template.HTML, error) {
var buf strings.Builder
if err := Render(ctx, strings.NewReader(content), &buf); err != nil {
return "", err
}
- return buf.String(), nil
+ return template.HTML(buf.String()), nil
}
// RenderRaw renders Markdown to HTML without handling special links.
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index 1be8c6a273..e7c496a913 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -5,6 +5,7 @@ package markdown_test
import (
"context"
+ "html/template"
"os"
"strings"
"testing"
@@ -59,7 +60,7 @@ func TestRender_StandardLinks(t *testing.T) {
},
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
buffer, err = markdown.RenderString(&markup.RenderContext{
Ctx: git.DefaultContext,
@@ -69,7 +70,7 @@ func TestRender_StandardLinks(t *testing.T) {
IsWiki: true,
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
}
googleRendered := `<p><a href="https://google.com/" rel="nofollow">https://google.com/</a></p>`
@@ -94,7 +95,7 @@ func TestRender_Images(t *testing.T) {
},
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
}
url := "../../.images/src/02/train.jpg"
@@ -304,7 +305,7 @@ func TestTotal_RenderWiki(t *testing.T) {
IsWiki: true,
}, sameCases[i])
assert.NoError(t, err)
- assert.Equal(t, answers[i], line)
+ assert.Equal(t, template.HTML(answers[i]), line)
}
testCases := []string{
@@ -329,7 +330,7 @@ func TestTotal_RenderWiki(t *testing.T) {
IsWiki: true,
}, testCases[i])
assert.NoError(t, err)
- assert.Equal(t, testCases[i+1], line)
+ assert.Equal(t, template.HTML(testCases[i+1]), line)
}
}
@@ -349,7 +350,7 @@ func TestTotal_RenderString(t *testing.T) {
Metas: localMetas,
}, sameCases[i])
assert.NoError(t, err)
- assert.Equal(t, answers[i], line)
+ assert.Equal(t, template.HTML(answers[i]), line)
}
testCases := []string{}
@@ -362,7 +363,7 @@ func TestTotal_RenderString(t *testing.T) {
},
}, testCases[i])
assert.NoError(t, err)
- assert.Equal(t, testCases[i+1], line)
+ assert.Equal(t, template.HTML(testCases[i+1]), line)
}
}
@@ -429,7 +430,7 @@ func TestRenderEmojiInLinks_Issue12331(t *testing.T) {
`
res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase)
assert.NoError(t, err)
- assert.Equal(t, expected, res)
+ assert.Equal(t, template.HTML(expected), res)
}
func TestColorPreview(t *testing.T) {
@@ -463,7 +464,7 @@ func TestColorPreview(t *testing.T) {
for _, test := range positiveTests {
res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
- assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
+ assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase)
}
@@ -542,7 +543,7 @@ func TestMathBlock(t *testing.T) {
for _, test := range testcases {
res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
- assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
+ assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase)
}
}
@@ -741,7 +742,7 @@ Citation needed[^0].`,
for _, test := range testcases {
res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
- assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
+ assert.Equal(t, test.expected, string(res), "Unexpected result in testcase %q", test.testcase)
}
}
@@ -778,12 +779,12 @@ foo: bar
for _, test := range testcases {
res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
- assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
+ assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase)
}
}
func TestRenderLinks(t *testing.T) {
- input := ` space @mention-user
+ input := ` space @mention-user${SPACE}${SPACE}
/just/a/path.bin
https://example.com/file.bin
[local link](file.bin)
@@ -804,8 +805,9 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
mail@domain.com
@mention-user test
#123
- space
+ space${SPACE}${SPACE}
`
+ input = strings.ReplaceAll(input, "${SPACE}", " ") // replace ${SPACE} with " ", to avoid some editor's auto-trimming
cases := []struct {
Links markup.Links
IsWiki bool
@@ -1168,7 +1170,7 @@ space</p>
for i, c := range cases {
result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background(), Links: c.Links, IsWiki: c.IsWiki}, input)
assert.NoError(t, err, "Unexpected error in testcase: %v", i)
- assert.Equal(t, c.Expected, result, "Unexpected result in testcase %v", i)
+ assert.Equal(t, template.HTML(c.Expected), result, "Unexpected result in testcase %v", i)
}
}
@@ -1187,7 +1189,7 @@ func TestCustomMarkdownURL(t *testing.T) {
},
}, input)
assert.NoError(t, err)
- assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
+ assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
}
test("[test](abp:subscribe?location=https://codeberg.org/filters.txt&amp;title=joy)",
diff --git a/modules/optional/option_test.go b/modules/optional/option_test.go
index 410fd73577..4f55608004 100644
--- a/modules/optional/option_test.go
+++ b/modules/optional/option_test.go
@@ -27,6 +27,16 @@ func TestOption(t *testing.T) {
assert.Equal(t, int(1), some.Value())
assert.Equal(t, int(1), some.ValueOrDefault(2))
+ noneBool := optional.None[bool]()
+ assert.False(t, noneBool.Has())
+ assert.False(t, noneBool.Value())
+ assert.True(t, noneBool.ValueOrDefault(true))
+
+ someBool := optional.Some(true)
+ assert.True(t, someBool.Has())
+ assert.True(t, someBool.Value())
+ assert.True(t, someBool.ValueOrDefault(false))
+
var ptr *int
assert.False(t, optional.FromPtr(ptr).Has())
diff --git a/modules/queue/workergroup.go b/modules/queue/workergroup.go
index 147a4f335e..e3801ef2b2 100644
--- a/modules/queue/workergroup.go
+++ b/modules/queue/workergroup.go
@@ -60,6 +60,9 @@ func (q *WorkerPoolQueue[T]) doDispatchBatchToWorker(wg *workerGroup[T], flushCh
full = true
}
+ // TODO: the logic could be improved in the future, to avoid a data-race between "doStartNewWorker" and "workerNum"
+ // The root problem is that if we skip "doStartNewWorker" here, the "workerNum" might be decreased by other workers later
+ // So ideally, it should check whether there are enough workers by some approaches, and start new workers if necessary.
q.workerNumMu.Lock()
noWorker := q.workerNum == 0
if full || noWorker {
@@ -143,7 +146,11 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) {
log.Debug("Queue %q starts new worker", q.GetName())
defer log.Debug("Queue %q stops idle worker", q.GetName())
+ atomic.AddInt32(&q.workerStartedCounter, 1) // Only increase counter, used for debugging
+
t := time.NewTicker(workerIdleDuration)
+ defer t.Stop()
+
keepWorking := true
stopWorking := func() {
q.workerNumMu.Lock()
@@ -158,13 +165,18 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) {
case batch, ok := <-q.batchChan:
if !ok {
stopWorking()
- } else {
- q.doWorkerHandle(batch)
- t.Reset(workerIdleDuration)
+ continue
+ }
+ q.doWorkerHandle(batch)
+ // reset the idle ticker, and drain the tick after reset in case a tick is already triggered
+ t.Reset(workerIdleDuration)
+ select {
+ case <-t.C:
+ default:
}
case <-t.C:
q.workerNumMu.Lock()
- keepWorking = q.workerNum <= 1
+ keepWorking = q.workerNum <= 1 // keep the last worker running
if !keepWorking {
q.workerNum--
}
diff --git a/modules/queue/workerqueue.go b/modules/queue/workerqueue.go
index b28fd88027..4160622d81 100644
--- a/modules/queue/workerqueue.go
+++ b/modules/queue/workerqueue.go
@@ -40,6 +40,8 @@ type WorkerPoolQueue[T any] struct {
workerMaxNum int
workerActiveNum int
workerNumMu sync.Mutex
+
+ workerStartedCounter int32
}
type flushType chan struct{}
diff --git a/modules/queue/workerqueue_test.go b/modules/queue/workerqueue_test.go
index e60120162a..e09669c542 100644
--- a/modules/queue/workerqueue_test.go
+++ b/modules/queue/workerqueue_test.go
@@ -11,6 +11,7 @@ import (
"time"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
)
@@ -175,11 +176,7 @@ func testWorkerPoolQueuePersistence(t *testing.T, queueSetting setting.QueueSett
}
func TestWorkerPoolQueueActiveWorkers(t *testing.T) {
- oldWorkerIdleDuration := workerIdleDuration
- workerIdleDuration = 300 * time.Millisecond
- defer func() {
- workerIdleDuration = oldWorkerIdleDuration
- }()
+ defer test.MockVariableValue(&workerIdleDuration, 300*time.Millisecond)()
handler := func(items ...int) (unhandled []int) {
time.Sleep(100 * time.Millisecond)
@@ -250,3 +247,25 @@ func TestWorkerPoolQueueShutdown(t *testing.T) {
q, _ = newWorkerPoolQueueForTest("test-workpoolqueue", qs, handler, false)
assert.EqualValues(t, 20, q.GetQueueItemNumber())
}
+
+func TestWorkerPoolQueueWorkerIdleReset(t *testing.T) {
+ defer test.MockVariableValue(&workerIdleDuration, 10*time.Millisecond)()
+
+ handler := func(items ...int) (unhandled []int) {
+ time.Sleep(50 * time.Millisecond)
+ return nil
+ }
+
+ q, _ := newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false)
+ stop := runWorkerPoolQueue(q)
+ for i := 0; i < 20; i++ {
+ assert.NoError(t, q.Push(i))
+ }
+
+ time.Sleep(500 * time.Millisecond)
+ assert.EqualValues(t, 2, q.GetWorkerNumber())
+ assert.EqualValues(t, 2, q.GetWorkerActiveNumber())
+ // when the queue never becomes empty, the existing workers should keep working
+ assert.EqualValues(t, 2, q.workerStartedCounter)
+ stop()
+}
diff --git a/modules/references/references.go b/modules/references/references.go
index fce893cf5b..fd10992e8e 100644
--- a/modules/references/references.go
+++ b/modules/references/references.go
@@ -31,9 +31,9 @@ var (
// mentionPattern matches all mentions in the form of "@user" or "@org/team"
mentionPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(@[0-9a-zA-Z-_]+|@[0-9a-zA-Z-_]+\/?[0-9a-zA-Z-_]+|@[0-9a-zA-Z-_][0-9a-zA-Z-_.]+\/?[0-9a-zA-Z-_.]+[0-9a-zA-Z-_])(?:'|\s|[:,;.?!]\s|[:,;.?!]?$|\)|\])`)
// issueNumericPattern matches string that references to a numeric issue, e.g. #1287
- issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\')([#!][0-9]+)(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)`)
+ issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\'|\")([#!][0-9]+)(?:\s|$|\)|\]|\'|\"|[:;,.?!]\s|[:;,.?!]$)`)
// issueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234
- issueAlphanumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([A-Z]{1,10}-[1-9][0-9]*)(?:\s|$|\)|\]|:|\.(\s|$))`)
+ issueAlphanumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\"|\')([A-Z]{1,10}-[1-9][0-9]*)(?:\s|$|\)|\]|:|\.(\s|$)|\"|\')`)
// crossReferenceIssueNumericPattern matches string that references a numeric issue in a different repository
// e.g. org/repo#12345
crossReferenceIssueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+/[0-9a-zA-Z-_\.]+[#!][0-9]+)(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)`)
diff --git a/modules/references/references_test.go b/modules/references/references_test.go
index 3f1f52401a..498374b2a7 100644
--- a/modules/references/references_test.go
+++ b/modules/references/references_test.go
@@ -432,6 +432,8 @@ func TestRegExp_issueNumericPattern(t *testing.T) {
" #12",
"#12:",
"ref: #12: msg",
+ "\"#1234\"",
+ "'#1234'",
}
falseTestCases := []string{
"# 1234",
@@ -462,6 +464,8 @@ func TestRegExp_issueAlphanumericPattern(t *testing.T) {
"(ABC-123)",
"[ABC-123]",
"ABC-123:",
+ "\"ABC-123\"",
+ "'ABC-123'",
}
falseTestCases := []string{
"RC-08",
diff --git a/modules/repository/init.go b/modules/repository/init.go
index b90b234a73..5f500c5233 100644
--- a/modules/repository/init.go
+++ b/modules/repository/init.go
@@ -6,22 +6,18 @@ package repository
import (
"context"
"fmt"
- "os"
"path/filepath"
"sort"
"strings"
- "time"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
- user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/options"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
- asymkey_service "code.gitea.io/gitea/services/asymkey"
)
type OptionFile struct {
@@ -124,70 +120,6 @@ func LoadRepoConfig() error {
return nil
}
-// InitRepoCommit temporarily changes with work directory.
-func InitRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Repository, u *user_model.User, defaultBranch string) (err error) {
- commitTimeStr := time.Now().Format(time.RFC3339)
-
- sig := u.NewGitSig()
- // Because this may call hooks we should pass in the environment
- env := append(os.Environ(),
- "GIT_AUTHOR_NAME="+sig.Name,
- "GIT_AUTHOR_EMAIL="+sig.Email,
- "GIT_AUTHOR_DATE="+commitTimeStr,
- "GIT_COMMITTER_DATE="+commitTimeStr,
- )
- committerName := sig.Name
- committerEmail := sig.Email
-
- if stdout, _, err := git.NewCommand(ctx, "add", "--all").
- SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)).
- RunStdString(&git.RunOpts{Dir: tmpPath}); err != nil {
- log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err)
- return fmt.Errorf("git add --all: %w", err)
- }
-
- cmd := git.NewCommand(ctx, "commit", "--message=Initial commit").
- AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)
-
- sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u)
- if sign {
- cmd.AddOptionFormat("-S%s", keyID)
-
- if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
- // need to set the committer to the KeyID owner
- committerName = signer.Name
- committerEmail = signer.Email
- }
- } else {
- cmd.AddArguments("--no-gpg-sign")
- }
-
- env = append(env,
- "GIT_COMMITTER_NAME="+committerName,
- "GIT_COMMITTER_EMAIL="+committerEmail,
- )
-
- if stdout, _, err := cmd.
- SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)).
- RunStdString(&git.RunOpts{Dir: tmpPath, Env: env}); err != nil {
- log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.String(), stdout, err)
- return fmt.Errorf("git commit: %w", err)
- }
-
- if len(defaultBranch) == 0 {
- defaultBranch = setting.Repository.DefaultBranch
- }
-
- if stdout, _, err := git.NewCommand(ctx, "push", "origin").AddDynamicArguments("HEAD:" + defaultBranch).
- SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)).
- RunStdString(&git.RunOpts{Dir: tmpPath, Env: InternalPushingEnvironment(u, repo)}); err != nil {
- log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err)
- return fmt.Errorf("git push: %w", err)
- }
-
- return nil
-}
-
func CheckInitRepository(ctx context.Context, owner, name, objectFormatName string) (err error) {
// Somehow the directory could exist.
repoPath := repo_model.RepoPath(owner, name)
diff --git a/modules/setting/admin.go b/modules/setting/admin.go
index 502efd0eb9..c292db9c8f 100644
--- a/modules/setting/admin.go
+++ b/modules/setting/admin.go
@@ -21,5 +21,6 @@ func loadAdminFrom(rootCfg ConfigProvider) {
}
const (
- UserFeatureDeletion = "deletion"
+ UserFeatureDeletion = "deletion"
+ UserFeatureManageGPGKeys = "manage_gpg_keys"
)
diff --git a/modules/setting/session.go b/modules/setting/session.go
index 664c66f869..e9637fdfc5 100644
--- a/modules/setting/session.go
+++ b/modules/setting/session.go
@@ -21,7 +21,7 @@ var SessionConfig = struct {
ProviderConfig string
// Cookie name to save session ID. Default is "MacaronSession".
CookieName string
- // Cookie path to store. Default is "/". HINT: there was a bug, the old value doesn't have trailing slash, and could be empty "".
+ // Cookie path to store. Default is "/".
CookiePath string
// GC interval time in seconds. Default is 3600.
Gclifetime int64
@@ -49,7 +49,10 @@ func loadSessionFrom(rootCfg ConfigProvider) {
SessionConfig.ProviderConfig = path.Join(AppWorkPath, SessionConfig.ProviderConfig)
}
SessionConfig.CookieName = sec.Key("COOKIE_NAME").MustString("i_like_gitea")
- SessionConfig.CookiePath = AppSubURL + "/" // there was a bug, old code only set CookePath=AppSubURL, no trailing slash
+ SessionConfig.CookiePath = AppSubURL
+ if SessionConfig.CookiePath == "" {
+ SessionConfig.CookiePath = "/"
+ }
SessionConfig.Secure = sec.Key("COOKIE_SECURE").MustBool(strings.HasPrefix(strings.ToLower(AppURL), "https://"))
SessionConfig.Gclifetime = sec.Key("GC_INTERVAL_TIME").MustInt64(86400)
SessionConfig.Maxlifetime = sec.Key("SESSION_LIFE_TIME").MustInt64(86400)
diff --git a/modules/structs/issue.go b/modules/structs/issue.go
index 331dbc1f8e..e2b49e94c5 100644
--- a/modules/structs/issue.go
+++ b/modules/structs/issue.go
@@ -6,6 +6,7 @@ package structs
import (
"fmt"
"path"
+ "slices"
"strings"
"time"
@@ -143,12 +144,37 @@ const (
// IssueFormField represents a form field
// swagger:model
type IssueFormField struct {
- Type IssueFormFieldType `json:"type" yaml:"type"`
- ID string `json:"id" yaml:"id"`
- Attributes map[string]any `json:"attributes" yaml:"attributes"`
- Validations map[string]any `json:"validations" yaml:"validations"`
+ Type IssueFormFieldType `json:"type" yaml:"type"`
+ ID string `json:"id" yaml:"id"`
+ Attributes map[string]any `json:"attributes" yaml:"attributes"`
+ Validations map[string]any `json:"validations" yaml:"validations"`
+ Visible []IssueFormFieldVisible `json:"visible,omitempty"`
}
+func (iff IssueFormField) VisibleOnForm() bool {
+ if len(iff.Visible) == 0 {
+ return true
+ }
+ return slices.Contains(iff.Visible, IssueFormFieldVisibleForm)
+}
+
+func (iff IssueFormField) VisibleInContent() bool {
+ if len(iff.Visible) == 0 {
+ // we have our markdown exception
+ return iff.Type != IssueFormFieldTypeMarkdown
+ }
+ return slices.Contains(iff.Visible, IssueFormFieldVisibleContent)
+}
+
+// IssueFormFieldVisible defines issue form field visible
+// swagger:model
+type IssueFormFieldVisible string
+
+const (
+ IssueFormFieldVisibleForm IssueFormFieldVisible = "form"
+ IssueFormFieldVisibleContent IssueFormFieldVisible = "content"
+)
+
// IssueTemplate represents an issue template for a repository
// swagger:model
type IssueTemplate struct {
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 708de57c91..9afcb96fc9 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -33,16 +33,16 @@ func NewFuncMap() template.FuncMap {
// -----------------------------------------------------------------
// html/template related functions
- "dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names.
- "Eval": Eval,
- "SafeHTML": SafeHTML,
- "HTMLFormat": HTMLFormat,
- "HTMLEscape": HTMLEscape,
- "QueryEscape": url.QueryEscape,
- "JSEscape": JSEscapeSafe,
- "Str2html": Str2html, // TODO: rename it to SanitizeHTML
- "URLJoin": util.URLJoin,
- "DotEscape": DotEscape,
+ "dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names.
+ "Eval": Eval,
+ "SafeHTML": SafeHTML,
+ "HTMLFormat": HTMLFormat,
+ "HTMLEscape": HTMLEscape,
+ "QueryEscape": url.QueryEscape,
+ "JSEscape": JSEscapeSafe,
+ "SanitizeHTML": SanitizeHTML,
+ "URLJoin": util.URLJoin,
+ "DotEscape": DotEscape,
"PathEscape": url.PathEscape,
"PathEscapeSegments": util.PathEscapeSegments,
@@ -210,8 +210,8 @@ func SafeHTML(s any) template.HTML {
panic(fmt.Sprintf("unexpected type %T", s))
}
-// Str2html sanitizes the input by pre-defined markdown rules
-func Str2html(s any) template.HTML {
+// SanitizeHTML sanitizes the input by pre-defined markdown rules
+func SanitizeHTML(s any) template.HTML {
switch v := s.(type) {
case string:
return template.HTML(markup.Sanitize(v))
diff --git a/modules/templates/helper_test.go b/modules/templates/helper_test.go
index 8f5d633d4f..3365278ac2 100644
--- a/modules/templates/helper_test.go
+++ b/modules/templates/helper_test.go
@@ -61,3 +61,8 @@ func TestJSEscapeSafe(t *testing.T) {
func TestHTMLFormat(t *testing.T) {
assert.Equal(t, template.HTML("<a>&lt; < 1</a>"), HTMLFormat("<a>%s %s %d</a>", "<", template.HTML("<"), 1))
}
+
+func TestSanitizeHTML(t *testing.T) {
+ assert.Equal(t, template.HTML(`<a href="/" rel="nofollow">link</a> xss <div>inline</div>`), SanitizeHTML(`<a href="/">link</a> <a href="javascript:">xss</a> <div style="dangerous">inline</div>`))
+ assert.Equal(t, template.HTML(`<a href="/" rel="nofollow">link</a> xss <div>inline</div>`), SanitizeHTML(template.HTML(`<a href="/">link</a> <a href="javascript:">xss</a> <div style="dangerous">inline</div>`)))
+}
diff --git a/modules/templates/mailer.go b/modules/templates/mailer.go
index 54d857a8f6..f1832cba0e 100644
--- a/modules/templates/mailer.go
+++ b/modules/templates/mailer.go
@@ -5,6 +5,7 @@ package templates
import (
"context"
+ "fmt"
"html/template"
"regexp"
"strings"
@@ -33,7 +34,7 @@ func mailSubjectTextFuncMap() texttmpl.FuncMap {
}
}
-func buildSubjectBodyTemplate(stpl *texttmpl.Template, btpl *template.Template, name string, content []byte) {
+func buildSubjectBodyTemplate(stpl *texttmpl.Template, btpl *template.Template, name string, content []byte) error {
// Split template into subject and body
var subjectContent []byte
bodyContent := content
@@ -42,14 +43,13 @@ func buildSubjectBodyTemplate(stpl *texttmpl.Template, btpl *template.Template,
subjectContent = content[0:loc[0]]
bodyContent = content[loc[1]:]
}
- if _, err := stpl.New(name).
- Parse(string(subjectContent)); err != nil {
- log.Warn("Failed to parse template [%s/subject]: %v", name, err)
+ if _, err := stpl.New(name).Parse(string(subjectContent)); err != nil {
+ return fmt.Errorf("failed to parse template [%s/subject]: %w", name, err)
}
- if _, err := btpl.New(name).
- Parse(string(bodyContent)); err != nil {
- log.Warn("Failed to parse template [%s/body]: %v", name, err)
+ if _, err := btpl.New(name).Parse(string(bodyContent)); err != nil {
+ return fmt.Errorf("failed to parse template [%s/body]: %w", name, err)
}
+ return nil
}
// Mailer provides the templates required for sending notification mails.
@@ -81,7 +81,13 @@ func Mailer(ctx context.Context) (*texttmpl.Template, *template.Template) {
if firstRun {
log.Trace("Adding mail template %s: %s by %s", tmplName, assetPath, layerName)
}
- buildSubjectBodyTemplate(subjectTemplates, bodyTemplates, tmplName, content)
+ if err = buildSubjectBodyTemplate(subjectTemplates, bodyTemplates, tmplName, content); err != nil {
+ if firstRun {
+ log.Fatal("Failed to parse mail template, err: %v", err)
+ } else {
+ log.Error("Failed to parse mail template, err: %v", err)
+ }
+ }
}
}
diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go
index 1d9635410b..cdff31698c 100644
--- a/modules/templates/util_render.go
+++ b/modules/templates/util_render.go
@@ -208,7 +208,7 @@ func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //n
if err != nil {
log.Error("RenderString: %v", err)
}
- return template.HTML(output)
+ return output
}
func RenderLabels(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML {
diff --git a/modules/templates/util_string.go b/modules/templates/util_string.go
index 3f51c122b1..f23b74786a 100644
--- a/modules/templates/util_string.go
+++ b/modules/templates/util_string.go
@@ -4,6 +4,7 @@
package templates
import (
+ "fmt"
"html/template"
"strings"
@@ -28,6 +29,19 @@ func (su *StringUtils) HasPrefix(s any, prefix string) bool {
return false
}
+func (su *StringUtils) ToString(v any) string {
+ switch v := v.(type) {
+ case string:
+ return v
+ case template.HTML:
+ return string(v)
+ case fmt.Stringer:
+ return v.String()
+ default:
+ return fmt.Sprint(v)
+ }
+}
+
func (su *StringUtils) Contains(s, substr string) bool {
return strings.Contains(s, substr)
}
diff --git a/modules/translation/mock.go b/modules/translation/mock.go
index 1f0559f38d..18fbc1044a 100644
--- a/modules/translation/mock.go
+++ b/modules/translation/mock.go
@@ -9,7 +9,9 @@ import (
)
// MockLocale provides a mocked locale without any translations
-type MockLocale struct{}
+type MockLocale struct {
+ Lang, LangName string // these fields are used directly in templates: ctx.Locale.Lang
+}
var _ Locale = (*MockLocale)(nil)
diff --git a/modules/translation/translation.go b/modules/translation/translation.go
index b7c18f610a..36ae58a9f1 100644
--- a/modules/translation/translation.go
+++ b/modules/translation/translation.go
@@ -144,7 +144,7 @@ func Match(tags ...language.Tag) language.Tag {
// locale represents the information of localization.
type locale struct {
i18n.Locale
- Lang, LangName string // these fields are used directly in templates: .i18n.Lang
+ Lang, LangName string // these fields are used directly in templates: ctx.Locale.Lang
msgPrinter *message.Printer
}
diff --git a/modules/util/util.go b/modules/util/util.go
index 28b549f405..5c75158196 100644
--- a/modules/util/util.go
+++ b/modules/util/util.go
@@ -17,64 +17,13 @@ import (
"golang.org/x/text/language"
)
-// OptionalBool a boolean that can be "null"
-type OptionalBool byte
-
-const (
- // OptionalBoolNone a "null" boolean value
- OptionalBoolNone OptionalBool = iota
- // OptionalBoolTrue a "true" boolean value
- OptionalBoolTrue
- // OptionalBoolFalse a "false" boolean value
- OptionalBoolFalse
-)
-
-// IsTrue return true if equal to OptionalBoolTrue
-func (o OptionalBool) IsTrue() bool {
- return o == OptionalBoolTrue
-}
-
-// IsFalse return true if equal to OptionalBoolFalse
-func (o OptionalBool) IsFalse() bool {
- return o == OptionalBoolFalse
-}
-
-// IsNone return true if equal to OptionalBoolNone
-func (o OptionalBool) IsNone() bool {
- return o == OptionalBoolNone
-}
-
-// ToGeneric converts OptionalBool to optional.Option[bool]
-func (o OptionalBool) ToGeneric() optional.Option[bool] {
- if o.IsNone() {
- return optional.None[bool]()
- }
- return optional.Some[bool](o.IsTrue())
-}
-
-// OptionalBoolFromGeneric converts optional.Option[bool] to OptionalBool
-func OptionalBoolFromGeneric(o optional.Option[bool]) OptionalBool {
- if o.Has() {
- return OptionalBoolOf(o.Value())
- }
- return OptionalBoolNone
-}
-
-// OptionalBoolOf get the corresponding OptionalBool of a bool
-func OptionalBoolOf(b bool) OptionalBool {
- if b {
- return OptionalBoolTrue
- }
- return OptionalBoolFalse
-}
-
-// OptionalBoolParse get the corresponding OptionalBool of a string using strconv.ParseBool
-func OptionalBoolParse(s string) OptionalBool {
- b, e := strconv.ParseBool(s)
+// OptionalBoolParse get the corresponding optional.Option[bool] of a string using strconv.ParseBool
+func OptionalBoolParse(s string) optional.Option[bool] {
+ v, e := strconv.ParseBool(s)
if e != nil {
- return OptionalBoolNone
+ return optional.None[bool]()
}
- return OptionalBoolOf(b)
+ return optional.Some(v)
}
// IsEmptyString checks if the provided string is empty
diff --git a/modules/util/util_test.go b/modules/util/util_test.go
index c5830ce01c..819e12ee91 100644
--- a/modules/util/util_test.go
+++ b/modules/util/util_test.go
@@ -8,6 +8,8 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/optional"
+
"github.com/stretchr/testify/assert"
)
@@ -173,17 +175,17 @@ func Test_RandomBytes(t *testing.T) {
assert.NotEqual(t, bytes3, bytes4)
}
-func Test_OptionalBool(t *testing.T) {
- assert.Equal(t, OptionalBoolNone, OptionalBoolParse(""))
- assert.Equal(t, OptionalBoolNone, OptionalBoolParse("x"))
+func TestOptionalBoolParse(t *testing.T) {
+ assert.Equal(t, optional.None[bool](), OptionalBoolParse(""))
+ assert.Equal(t, optional.None[bool](), OptionalBoolParse("x"))
- assert.Equal(t, OptionalBoolFalse, OptionalBoolParse("0"))
- assert.Equal(t, OptionalBoolFalse, OptionalBoolParse("f"))
- assert.Equal(t, OptionalBoolFalse, OptionalBoolParse("False"))
+ assert.Equal(t, optional.Some(false), OptionalBoolParse("0"))
+ assert.Equal(t, optional.Some(false), OptionalBoolParse("f"))
+ assert.Equal(t, optional.Some(false), OptionalBoolParse("False"))
- assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("1"))
- assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("t"))
- assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("True"))
+ assert.Equal(t, optional.Some(true), OptionalBoolParse("1"))
+ assert.Equal(t, optional.Some(true), OptionalBoolParse("t"))
+ assert.Equal(t, optional.Some(true), OptionalBoolParse("True"))
}
// Test case for any function which accepts and returns a single string.
diff --git a/options/license/MIT-Khronos-old b/options/license/MIT-Khronos-old
new file mode 100644
index 0000000000..430863bc98
--- /dev/null
+++ b/options/license/MIT-Khronos-old
@@ -0,0 +1,23 @@
+Copyright (c) 2014-2020 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and/or associated documentation files (the "Materials"),
+to deal in the Materials without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Materials, and to permit persons to whom the
+Materials are furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Materials.
+
+MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+IN THE MATERIALS.
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index be798000f5..409b014fab 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -124,6 +124,7 @@ pin=Připnout
unpin=Odepnout
artifacts=Artefakty
+confirm_delete_artifact=Jste si jisti, že chcete odstranit artefakt „%s“?
archived=Archivováno
@@ -434,7 +435,7 @@ password_pwned_err=Nelze dokonÄit požadavek na HaveIBeenPwned
change_unconfirmed_email = Pokud jste při registraci zadali nesprávnou e-mailovou adresu, můžete ji změnit níže. Potvrzovací e-mail bude místo toho odeslán na novou adresu.
change_unconfirmed_email_error = Nepodařilo se změnit e-mailovou adresu: %v
change_unconfirmed_email_summary = ZmÄ›na e-mailové adresy, na kterou bude odeslán aktivaÄní e-mail.
-last_admin = Nemůžete odebrat posledního administrátora. Vždy musí existovat alespoň jeden administrátor.
+last_admin=Nelze odstranit posledního správce. Musí existovat alespoň jeden správce.
[mail]
view_it_on=Zobrazit na %s
@@ -605,6 +606,7 @@ target_branch_not_exist=Cílová větev neexistuje.
admin_cannot_delete_self = Nemůžete odstranit sami sebe, když jste administrátorem. Nejprve prosím odeberte svá práva administrátora.
username_error_no_dots = ` může obsahovat pouze alfanumerické znaky („0-9“, „a-z“, „A-Z“), pomlÄky („-“) a podtržítka („_“). Nemůže zaÄínat nebo konÄit nealfanumerickými znaky. Jsou také zakázány po sobÄ› jdoucí nealfanumerické znaky.`
+admin_cannot_delete_self=Nemůžete se smazat, dokud jste správce. Nejdříve prosím odeberte svá administrátorská oprávnění.
[user]
change_avatar=Změnit váš avatar…
@@ -999,6 +1001,8 @@ issue_labels_helper=Vyberte sadu štítků úkolů.
license=Licence
license_helper=Vyberte licenÄní soubor.
license_helper_desc=Licence řídí, co ostatní mohou a nemohou dělat s vaším kódem. Nejste si jisti, která je pro váš projekt správná? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">Zvolte licenci</a>
+object_format=Formát objektu
+object_format_helper=Objektový formát repozitáře. Nelze později změnit. SHA1 je nejvíce kompatibilní.
readme=README
readme_helper=Vyberte Å¡ablonu souboru README.
readme_helper_desc=Toto je místo, kde můžete napsat úplný popis vašeho projektu.
@@ -1065,6 +1069,7 @@ desc.public=Veřejný
desc.template=Å ablona
desc.internal=Interní
desc.archived=Archivováno
+desc.sha256=SHA256
template.items=Položky šablony
template.git_content=Obsah gitu (výchozí větev)
@@ -1215,6 +1220,8 @@ audio_not_supported_in_browser=Váš prohlížeÄ nepodporuje znaÄku HTML5 „a
stored_lfs=Uloženo pomocí Git LFS
symbolic_link=Symbolický odkaz
executable_file=Spustitelný soubor
+vendored=Vendorováno
+generated=Generováno
commit_graph=Graf commitů
commit_graph.select=Vybrat větve
commit_graph.hide_pr_refs=Skrýt požadavky na natažení
@@ -1550,7 +1557,11 @@ issues.label_title=Název štítku
issues.label_description=Popis štítku
issues.label_color=Barva štítku
issues.label_exclusive=Exkluzivní
+issues.label_archive=Archivovat štítek
issues.label_archived_filter=Zobrazit archivované popisky
+issues.label_archive_tooltip=Archivované Å¡títky jsou ve výchozím nastavení vylouÄeny z návrhů pÅ™i hledání podle popisku.
+issues.label_exclusive_desc=Pojmenujte štítek <code>rozsah/položka</code>, aby se stal vzájemně exkluzivním s jinými štítky <code>rozsah/</code>.
+issues.label_exclusive_warning=Jakékoliv protichůdné rozsahy štítků budou odstraněny při úpravě štítků u úkolů nebo u požadavku na natažení.
issues.label_count=%d štítků
issues.label_open_issues=%d otevřených úkolů
issues.label_edit=Upravit
@@ -1651,6 +1662,7 @@ issues.dependency.issue_closing_blockedby=Uzavření tohoto úkolu je blokováno
issues.dependency.issue_close_blocks=Tento úkol blokuje uzavření následujících úkolů
issues.dependency.pr_close_blocks=Tento požadavek na natažení blokuje uzavření následujících úkolů
issues.dependency.issue_close_blocked=Musíte zavřít všechny úkoly, které blokují tento úkol, aby jej bylo možné zavřít.
+issues.dependency.issue_batch_close_blocked=Nelze uzavřít úkoly, které jste vybrali, protože úkol #%d má stále otevřené závislosti
issues.dependency.pr_close_blocked=Musíte zavřít vÅ¡echny úkoly, které blokují tento požadavek na natažení, aby jej bylo možné slouÄit.
issues.dependency.blocks_short=Blokuje
issues.dependency.blocked_by_short=Závisí na
@@ -1732,6 +1744,7 @@ pulls.select_commit_hold_shift_for_range=Vyberte commit. Podržte klávesu shift
pulls.review_only_possible_for_full_diff=Posouzení je možné pouze při zobrazení plného rozlišení
pulls.filter_changes_by_commit=Filtrovat podle commitu
pulls.nothing_to_compare=Tyto větve jsou stejné. Není potřeba vytvářet požadavek na natažení.
+pulls.nothing_to_compare_have_tag=Vybraná vÄ›tev/znaÄka je stejná.
pulls.nothing_to_compare_and_allow_empty_pr=Tyto větve jsou stejné. Tento požadavek na natažení bude prázdný.
pulls.has_pull_request=`Požadavek na natažení mezi těmito větvemi již existuje: <a href="%[1]s">%[2]s#%[3]d</a>`
pulls.create=Vytvořit požadavek na natažení
@@ -1854,6 +1867,7 @@ milestones.update_ago=Aktualizováno %s
milestones.no_due_date=Bez lhůty dokonÄení
milestones.open=Otevřít
milestones.close=Zavřít
+milestones.new_subheader=Milníky vám pomohou organizovat úkoly a sledovat jejich pokrok.
milestones.completeness=%d%% DokonÄeno
milestones.create=Vytvořit milník
milestones.title=Název
@@ -1987,6 +2001,7 @@ activity.git_stats_and_deletions=a
activity.git_stats_deletion_1=%d odebrání
activity.git_stats_deletion_n=%d odebrání
+contributors.contribution_type.filter_label=Typ příspěvku:
contributors.contribution_type.commits=Commity
search=Vyhledat
@@ -2374,6 +2389,7 @@ settings.matrix.room_id=ID místnosti
settings.matrix.message_type=Typ zprávy
settings.archive.button=Archivovat repozitář
settings.archive.header=Archivovat tento repozitář
+settings.archive.text=Archivace repozitáře způsobí, že bude zcela urÄen pouze pro Ätení. Bude skryt z ovládacího panelu. Nikdo (ani vy!) nebude moci vytvářet nové revize ani otevírat nové úkoly nebo žádosti o natažení.
settings.archive.success=Repozitář byl úspěšně archivován.
settings.archive.error=Nastala chyba při archivování repozitáře. Prohlédněte si záznam pro více detailů.
settings.archive.error_ismirror=Nemůžete archivovat zrcadlený repozitář.
@@ -2835,6 +2851,7 @@ dashboard.delete_repo_archives.started=Spuštěna úloha smazání všech archiv
dashboard.delete_missing_repos=Smazat všechny repozitáře, které nemají Git soubory
dashboard.delete_missing_repos.started=Spuštěna úloha mazání všech repozitářů, které nemají Git soubory.
dashboard.delete_generated_repository_avatars=Odstranit vygenerované avatary repozitářů
+dashboard.sync_repo_tags=Synchronizovat znaÄky z git dat do databáze
dashboard.update_mirrors=Aktualizovat zrcadla
dashboard.repo_health_check=Kontrola stavu všech repozitářů
dashboard.check_repo_stats=Zkontrolovat všechny statistiky repositáře
@@ -2882,11 +2899,14 @@ dashboard.delete_old_actions=Odstranit všechny staré akce z databáze
dashboard.delete_old_actions.started=ZaÄalo odstraňování vÅ¡ech starých akcí z databáze.
dashboard.update_checker=Kontrola aktualizací
dashboard.delete_old_system_notices=Odstranit všechna stará systémová upozornění z databáze
+dashboard.gc_lfs=Úklid LFS meta objektů
dashboard.stop_zombie_tasks=Zastavit zombie úlohy
dashboard.stop_endless_tasks=Zastavit nekoneÄné úlohy
dashboard.cancel_abandoned_jobs=Zrušit opuštěné úlohy
dashboard.start_schedule_tasks=Spustit naplánované úlohy
dashboard.sync_branch.started=Synchronizace větví byla spuštěna
+dashboard.sync_tag.started=Synchronizace znaÄek spuÅ¡tÄ›na
+dashboard.rebuild_issue_indexer=Znovu sestavit index úkolů
users.user_manage_panel=Správa uživatelských úÄtů
users.new_account=VytvoÅ™it uživatelský úÄet
@@ -3326,6 +3346,12 @@ self_check.database_fix_mssql = Uživatelé MSSQL mohou tento problém vyřešit
auths.oauth2_map_group_to_team = Zmapovat zabrané skupiny u týmů organizací (volitelné - vyžaduje název zabrání výše)
monitor.queue.settings.desc = Pooly dynamicky rostou podle blokování fronty jejich workerů.
+self_check.no_problem_found=Zatím nebyl nalezen žádný problém.
+self_check.database_collation_mismatch=OÄekávejte, že databáze použije collation: %s
+self_check.database_collation_case_insensitive=Databáze používá collation %s, což je collation nerozliÅ¡ující velká a malá písmena. AÄkoli s ní Gitea může pracovat, mohou se vyskytnout vzácné případy, kdy nebude fungovat podle oÄekávání.
+self_check.database_inconsistent_collation_columns=Databáze používá collation %s, ale tyto sloupce používají chybné collation. To může způsobit neoÄekávané problémy.
+self_check.database_fix_mysql=Pro uživatele MySQL/MariaDB můžete použít příkaz "gitea doctor convert", který opraví problémy s collation, nebo můžete také problém vyÅ™eÅ¡it příkazem "ALTER ... COLLATE ..." SQL ruÄnÄ›.
+self_check.database_fix_mssql=Uživatelé MSSQL mohou problém vyÅ™eÅ¡it pouze pomocí příkazu "ALTER ... COLLATE ..." SQL ruÄnÄ›.
[action]
create_repo=vytvořil/a repozitář <a href="%s">%s</a>
@@ -3513,6 +3539,7 @@ rpm.distros.suse=na distribuce založené na SUSE
rpm.install=Pro instalaci balíÄku spusÅ¥te následující příkaz:
rpm.repository=Informace o repozitáři
rpm.repository.architectures=Architektury
+rpm.repository.multiple_groups=Tento balíÄek je k dispozici ve více skupinách.
rubygems.install=Pro instalaci balíÄku pomocí gem spusÅ¥te následující příkaz:
rubygems.install2=nebo ho přidejte do Gemfie:
rubygems.dependencies.runtime=Běhové závislosti
@@ -3642,6 +3669,8 @@ runs.actors_no_select=Všichni aktéři
runs.status_no_select=VÅ¡echny stavy
runs.no_results=Nebyly nalezeny žádné výsledky.
runs.no_workflows=Zatím neexistují žádné pracovní postupy.
+runs.no_workflows.quick_start=Nevíte jak zaÄít s Gitea Actions? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">průvodce rychlým startem</a>.
+runs.no_workflows.documentation=Další informace o Gitea Actions naleznete v <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>.
runs.no_runs=Pracovní postup zatím nebyl spuštěn.
runs.empty_commit_message=(prázdná zpráva commitu)
@@ -3659,6 +3688,7 @@ variables.none=Zatím nejsou žádné proměnné.
variables.deletion=Odstranit proměnnou
variables.deletion.description=OdstranÄ›ní promÄ›nné je trvalé a nelze jej vrátit zpÄ›t. PokraÄovat?
variables.description=PromÄ›nné budou pÅ™edány urÄitým akcím a nelze je pÅ™eÄíst jinak.
+variables.id_not_exist=Proměnná s ID %d neexistuje.
variables.edit=Upravit proměnnou
variables.deletion.failed=Nepodařilo se odstranit proměnnou.
variables.deletion.success=Proměnná byla odstraněna.
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index f01542ed23..07ad19aa7a 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -143,6 +143,19 @@ confirm_delete_selected = Confirm to delete all selected items?
name = Name
value = Value
+filter = Filter
+filter.clear = Clear Filter
+filter.is_archived = Archived
+filter.not_archived = Not Archived
+filter.is_fork = Forked
+filter.not_fork = Not Forked
+filter.is_mirror = Mirrored
+filter.not_mirror = Not Mirrored
+filter.is_template = Template
+filter.not_template = Not Template
+filter.public = Public
+filter.private = Private
+
[aria]
navbar = Navigation Bar
footer = Footer
@@ -1834,9 +1847,9 @@ pulls.unrelated_histories = Merge Failed: The merge head and base do not share a
pulls.merge_out_of_date = Merge Failed: Whilst generating the merge, the base was updated. Hint: Try again.
pulls.head_out_of_date = Merge Failed: Whilst generating the merge, the head was updated. Hint: Try again.
pulls.has_merged = Failed: The pull request has been merged, you cannot merge again or change the target branch.
-pulls.push_rejected = Merge Failed: The push was rejected. Review the Git Hooks for this repository.
+pulls.push_rejected = Push Failed: The push was rejected. Review the Git Hooks for this repository.
pulls.push_rejected_summary = Full Rejection Message
-pulls.push_rejected_no_message = Merge Failed: The push was rejected but there was no remote message.<br>Review the Git Hooks for this repository
+pulls.push_rejected_no_message = Push Failed: The push was rejected but there was no remote message. Review the Git Hooks for this repository
pulls.open_unmerged_pull_exists = `You cannot perform a reopen operation because there is a pending pull request (#%d) with identical properties.`
pulls.status_checking = Some checks are pending
pulls.status_checks_success = All checks were successful
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 98c524ac80..4cfde206af 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -124,6 +124,7 @@ pin=Épingler
unpin=Désépingler
artifacts=Artefacts
+confirm_delete_artifact=Êtes-vous sûr de vouloir supprimer l‘artefact « %s » ?
archived=Archivé
@@ -366,6 +367,7 @@ disable_register_prompt=Les inscriptions sont désactivées. Veuillez contacter
disable_register_mail=La confirmation par courriel à l’inscription est désactivée.
manual_activation_only=Contactez l'administrateur de votre site pour terminer l'activation.
remember_me=Mémoriser cet appareil
+remember_me.compromised=Le jeton de connexion n’est plus valide, ce qui peut indiquer un compte compromis. Veuillez inspecter les activités inhabituelles de votre compte.
forgot_password_title=Mot de passe oublié
forgot_password=Mot de passe oublié ?
sign_up_now=Pas de compte ? Inscrivez-vous maintenant.
@@ -602,6 +604,7 @@ target_branch_not_exist=La branche cible n'existe pas.
username_error_no_dots = ` peut uniquement contenir des caractères alphanumériques ('0-9','a-z','A-Z'), tiret ('-') et souligné ('_'). Ne peut commencer ou terminer avec un caractère non-alphanumérique, et l'utilisation de caractères non-alphanumériques consécutifs n'est pas permise.`
admin_cannot_delete_self = Vous ne pouvez supprimer votre compte lorsque vous disposez de droits d'administration. Veuillez d'abord renoncer à vos droits d'administration.
+admin_cannot_delete_self=Vous ne pouvez pas vous supprimer vous-même lorsque vous êtes admin. Veuillez d’abord supprimer vos privilèges d’administrateur.
[user]
change_avatar=Changer votre avatar…
@@ -817,7 +820,7 @@ valid_until_date=Valable jusqu'au %s
valid_forever=Valide pour toujours
last_used=Dernière utilisation le
no_activity=Aucune activité récente
-can_read_info=Lue(s)
+can_read_info=Lecture
can_write_info=Écriture
key_state_desc=Cette clé a été utilisée au cours des 7 derniers jours
token_state_desc=Ce jeton a été utilisé au cours des 7 derniers jours
@@ -850,7 +853,7 @@ permissions_public_only=Publique uniquement
permissions_access_all=Tout (public, privé et limité)
select_permissions=Sélectionner les autorisations
permission_no_access=Aucun accès
-permission_read=Lue(s)
+permission_read=Lecture
permission_write=Lecture et écriture
access_token_desc=Les autorisations des jetons sélectionnées se limitent aux <a %s>routes API</a> correspondantes. Lisez la <a %s>documentation</a> pour plus d’informations.
at_least_one_permission=Vous devez sélectionner au moins une permission pour créer un jeton
@@ -1013,6 +1016,7 @@ mirror_prune=Purger
mirror_prune_desc=Supprimer les références externes obsolètes
mirror_interval=Intervalle de synchronisation (les unités de temps valides sont 'h', 'm' et 's'). 0 pour désactiver la synchronisation automatique. (Intervalle minimum : %s)
mirror_interval_invalid=L'intervalle de synchronisation est invalide.
+mirror_sync=synchronisé
mirror_sync_on_commit=Synchroniser quand les révisions sont soumis
mirror_address=Cloner depuis une URL
mirror_address_desc=Insérez tous les identifiants requis dans la section Autorisation.
@@ -1063,6 +1067,7 @@ desc.public=Publique
desc.template=Modèle
desc.internal=Interne
desc.archived=Archivé
+desc.sha256=SHA256
template.items=Élément du modèle
template.git_content=Contenu Git (branche par défaut)
@@ -1213,6 +1218,8 @@ audio_not_supported_in_browser=Votre navigateur ne supporte pas la balise « au
stored_lfs=Stocké avec Git LFS
symbolic_link=Lien symbolique
executable_file=Fichiers exécutables
+vendored=Externe
+generated=Générée
commit_graph=Graphe des révisions
commit_graph.select=Sélectionner les branches
commit_graph.hide_pr_refs=Masquer les demandes d'ajout
@@ -1794,6 +1801,7 @@ pulls.merge_pull_request=Créer une révision de fusion
pulls.rebase_merge_pull_request=Rebaser puis avancer rapidement
pulls.rebase_merge_commit_pull_request=Rebaser puis créer une révision de fusion
pulls.squash_merge_pull_request=Créer une révision de concaténation
+pulls.fast_forward_only_merge_pull_request=Avance rapide uniquement
pulls.merge_manually=Fusionner manuellement
pulls.merge_commit_id=L'ID de la révision de fusion
pulls.require_signed_wont_sign=La branche nécessite des révisions signées mais cette fusion ne sera pas signée
@@ -1930,6 +1938,7 @@ wiki.page_name_desc=Entrez un nom pour cette page Wiki. Certains noms spéciaux
wiki.original_git_entry_tooltip=Voir le fichier Git original au lieu d'utiliser un lien convivial.
activity=Activité
+activity.navbar.contributors=Contributeurs
activity.period.filter_label=Période :
activity.period.daily=1 jour
activity.period.halfweekly=3 jours
@@ -1995,7 +2004,10 @@ activity.git_stats_and_deletions=et
activity.git_stats_deletion_1=%d suppression
activity.git_stats_deletion_n=%d suppressions
+contributors.contribution_type.filter_label=Type de contribution :
contributors.contribution_type.commits=Révisions
+contributors.contribution_type.additions=Ajouts
+contributors.contribution_type.deletions=Suppressions
search=Chercher
search.search_repo=Rechercher dans le dépôt
@@ -2344,6 +2356,8 @@ settings.protect_approvals_whitelist_users=Évaluateurs autorisés :
settings.protect_approvals_whitelist_teams=Équipes d’évaluateurs autorisés :
settings.dismiss_stale_approvals=Révoquer automatiquement les approbations périmées
settings.dismiss_stale_approvals_desc=Lorsque des nouvelles révisions changent le contenu de la demande d’ajout, les approbations existantes sont révoquées.
+settings.ignore_stale_approvals=Ignorer les approbations obsolètes
+settings.ignore_stale_approvals_desc=Ignorer les approbations d’anciennes révisions (évaluations obsolètes) du décompte des approbations de la demande d’ajout. Non pertinent quand les évaluations obsolètes sont déjà révoquées.
settings.require_signed_commits=Exiger des révisions signées
settings.require_signed_commits_desc=Rejeter les soumissions sur cette branche lorsqu'ils ne sont pas signés ou vérifiables.
settings.protect_branch_name_pattern=Motif de nom de branche protégé
@@ -2399,6 +2413,7 @@ settings.archive.error=Une erreur s'est produite lors de l'archivage du dépôt.
settings.archive.error_ismirror=Vous ne pouvez pas archiver un dépôt en miroir.
settings.archive.branchsettings_unavailable=Le paramétrage des branches n'est pas disponible quand le dépôt est archivé.
settings.archive.tagsettings_unavailable=Le paramétrage des étiquettes n'est pas disponible si le dépôt est archivé.
+settings.archive.mirrors_unavailable=Les miroirs ne sont pas disponibles lorsque le dépôt est archivé.
settings.unarchive.button=Réhabiliter
settings.unarchive.header=Réhabiliter ce dépôt
settings.unarchive.text=Réhabiliter un dépôt dégèle les actions de révisions et de soumissions, la gestion des tickets et des demandes d'ajouts.
@@ -2652,6 +2667,11 @@ activity.navbar.code_frequency = Fréquence de code
activity.navbar.recent_commits = Commits récents
[graphs]
+component_loading=Chargement de %s…
+component_loading_failed=Impossible de charger %s.
+component_loading_info=Ça prend son temps…
+component_failed_to_load=Une erreur inattendue s’est produite.
+contributors.what=contributions
[org]
org_name_holder=Nom de l'organisation
@@ -2780,6 +2800,7 @@ follow_blocked_user = Vous ne pouvez pas suivre cette organisation car elle vous
[admin]
dashboard=Tableau de bord
+self_check=Autodiagnostique
identity_access=Identité et accès
users=Comptes utilisateurs
organizations=Organisations
@@ -2825,6 +2846,7 @@ dashboard.delete_missing_repos=Supprimer tous les dépôts dont les fichiers Git
dashboard.delete_missing_repos.started=Tâche de suppression de tous les dépôts sans fichiers Git démarrée.
dashboard.delete_generated_repository_avatars=Supprimer les avatars de dépôt générés
dashboard.sync_repo_branches=Synchroniser les branches manquantes depuis Git vers la base de donnée.
+dashboard.sync_repo_tags=Synchroniser les étiquettes git depuis les dépôts vers la base de données
dashboard.update_mirrors=Actualiser les miroirs
dashboard.repo_health_check=Vérifier l'état de santé de tous les dépôts
dashboard.check_repo_stats=Voir les statistiques de tous les dépôts
@@ -2879,6 +2901,7 @@ dashboard.stop_endless_tasks=Arrêter les tâches sans fin
dashboard.cancel_abandoned_jobs=Annuler les jobs abandonnés
dashboard.start_schedule_tasks=Démarrer les tâches planifiées
dashboard.sync_branch.started=Début de la synchronisation des branches
+dashboard.sync_tag.started=Synchronisation des étiquettes
dashboard.rebuild_issue_indexer=Reconstruire l’indexeur des tickets
users.user_manage_panel=Gestion du compte utilisateur
@@ -3314,6 +3337,12 @@ self_check.database_inconsistent_collation_columns = La base de donnée utilise
self_check.database_fix_mysql = Les utilisateurs de MySQL/MariaDB peuvent utiliser la commande "forgejo doctor convert" pour corriger les problèmes de collation, ou bien manuellement avec la commande SQL "ALTER ... COLLATE ...".
self_check.database_fix_mssql = Les utilisateurs de MSSQL sont pour l'instant contraint d'utiliser la commande SQL "ALTER ... COLLATE ..." pour corriger ce problème.
+self_check.no_problem_found=Aucun problème trouvé pour l’instant.
+self_check.database_collation_mismatch=Exige que la base de données utilise la collation %s.
+self_check.database_collation_case_insensitive=La base de données utilise la collation %s, insensible à la casse. Bien que Gitea soit compatible, il peut y avoir quelques rares cas qui ne fonctionnent pas comme prévu.
+self_check.database_inconsistent_collation_columns=La base de données utilise la collation %s, mais ces colonnes utilisent des collations différentes. Cela peut causer des problèmes imprévus.
+self_check.database_fix_mysql=Pour les utilisateurs de MySQL ou MariaDB, vous pouvez utiliser la commande « gitea doctor convert » dans un terminal ou exécuter une requête du type « ALTER … COLLATE ... » pour résoudre les problèmes de collation.
+self_check.database_fix_mssql=Pour les utilisateurs de MSSQL, vous ne pouvez résoudre le problème qu’en exécutant une requête SQL du type « ALTER … COLLATE … ».
[action]
create_repo=a créé le dépôt <a href="%s">%s</a>
@@ -3501,6 +3530,7 @@ rpm.distros.suse=sur les distributions basées sur SUSE
rpm.install=Pour installer le paquet, exécutez la commande suivante :
rpm.repository=Informations sur le Dépôt
rpm.repository.architectures=Architectures
+rpm.repository.multiple_groups=Ce paquet est disponible en plusieurs groupes.
rubygems.install=Pour installer le paquet en utilisant gem, exécutez la commande suivante :
rubygems.install2=ou ajoutez-le au Gemfile :
rubygems.dependencies.runtime=Dépendances d'exécution
@@ -3636,6 +3666,8 @@ runs.actors_no_select=Tous les acteurs
runs.status_no_select=Touts les statuts
runs.no_results=Aucun résultat correspondant.
runs.no_workflows=Il n'y a pas encore de workflows.
+runs.no_workflows.quick_start=Vous découvrez les Actions Gitea ? Consultez <a target="_blank" rel="noopener noreferrer" href="%s">le didacticiel</a>.
+runs.no_workflows.documentation=Pour plus d’informations sur les actions Gitea, voir <a target="_blank" rel="noopener noreferrer" href="%s">la documentation</a>.
runs.no_runs=Le flux de travail n'a pas encore d'exécution.
runs.empty_commit_message=(message de révision vide)
@@ -3654,6 +3686,7 @@ variables.none=Il n'y a pas encore de variables.
variables.deletion=Retirer la variable
variables.deletion.description=La suppression d’une variable est permanente et ne peut être défaite. Continuer ?
variables.description=Les variables sont passées aux actions et ne peuvent être lues autrement.
+variables.id_not_exist=La variable avec l’ID %d n’existe pas.
variables.edit=Modifier la variable
variables.deletion.failed=Impossible de retirer la variable.
variables.deletion.success=La variable a bien été retirée.
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 210b4e230e..fcccac21cc 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -124,6 +124,7 @@ pin=ピン留ã‚
unpin=ピン留ã‚解除
artifacts=æˆæžœç‰©
+confirm_delete_artifact=アーティファクト %s を削除ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ
archived=アーカイブ
@@ -429,7 +430,7 @@ password_pwned_err=HaveIBeenPwnedã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’完了ã§ãã¾ã›ã‚“ã
change_unconfirmed_email = 登録時ã«é–“é•ã£ãŸãƒ¡ãƒ¼ãƒ« アドレスを入力ã—ãŸå ´åˆã¯ã€ä»¥ä¸‹ã§å¤‰æ›´ã§ãã¾ã™ã€‚代ã‚ã‚Šã«ç¢ºèªãƒ¡ãƒ¼ãƒ«ãŒæ–°ã—ã„アドレスã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚
change_unconfirmed_email_error = メール アドレスを変更ã§ãã¾ã›ã‚“: %v
change_unconfirmed_email_summary = アクティベーションメールã®é€ä¿¡å…ˆãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’変更ã—ã¾ã™ã€‚
-last_admin = 最後ã®ç®¡ç†è€…を削除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。少ãªãã¨ã‚‚ 1 人ã®ç®¡ç†è€…ãŒå¿…è¦ã§ã™ã€‚
+last_admin=最後ã®ç®¡ç†è€…ã¯å‰Šé™¤ã§ãã¾ã›ã‚“。少ãªãã¨ã‚‚一人ã®ç®¡ç†è€…ãŒå¿…è¦ã§ã™ã€‚
[mail]
view_it_on=%s ã§è¦‹ã‚‹
@@ -600,6 +601,7 @@ target_branch_not_exist=ターゲットã®ãƒ–ランãƒãŒå­˜åœ¨ã—ã¦ã„ã¾ã›ã‚
admin_cannot_delete_self = 管ç†è€…ã§ã‚ã‚‹å ´åˆã€è‡ªåˆ†è‡ªèº«ã‚’削除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。最åˆã«ç®¡ç†è€…権é™ã‚’削除ã—ã¦ãã ã•ã„。
username_error_no_dots = `英数字 (「0-9ã€ã€ã€Œa-zã€ã€ã€ŒA-Zã€)ã€ãƒ€ãƒƒã‚·ãƒ¥ (「-ã€)ã€ãŠã‚ˆã³ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ (「_ã€) ã®ã¿ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚英数字以外ã®æ–‡å­—ã§é–‹å§‹ã¾ãŸã¯çµ‚了ã™ã‚‹ã“ã¨ã¯ã§ããšã€é€£ç¶šã—ãŸè‹±æ•°å­—以外ã®æ–‡å­—ã‚‚ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚`
+admin_cannot_delete_self=ã‚ãªãŸãŒç®¡ç†è€…ã§ã‚ã‚‹å ´åˆã€è‡ªåˆ†è‡ªèº«ã‚’削除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。最åˆã«ç®¡ç†è€…権é™ã‚’削除ã—ã¦ãã ã•ã„。
[user]
change_avatar=ã‚¢ãƒã‚¿ãƒ¼ã‚’変更…
@@ -993,6 +995,8 @@ issue_labels_helper=イシューã®ãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆã‚’é¸æŠž
license=ライセンス
license_helper=ライセンス ファイルをé¸æŠžã—ã¦ãã ã•ã„。
license_helper_desc=ライセンスã«ã‚ˆã‚Šã€ä»–人ãŒã‚ãªãŸã®ã‚³ãƒ¼ãƒ‰ã«å¯¾ã—ã¦ä½•ãŒã§ãã¦ä½•ãŒã§ããªã„ã®ã‹ã‚’è¦å®šã—ã¾ã™ã€‚ ã©ã‚ŒãŒãƒ—ロジェクトã«ãµã•ã‚ã—ã„ã‹è¿·ã£ã¦ã„ã¾ã™ã‹ï¼Ÿ <a target="_blank" rel="noopener noreferrer" href="%s">ライセンスé¸æŠžã‚µã‚¤ãƒˆ</a> も確èªã—ã¦ã¿ã¦ãã ã•ã„。
+object_format=オブジェクトã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆ
+object_format_helper=リãƒã‚¸ãƒˆãƒªã®ã‚ªãƒ–ジェクトフォーマット。後ã§å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。SHA1 ã¯æœ€ã‚‚互æ›æ€§ãŒã‚ã‚Šã¾ã™ã€‚
readme=README
readme_helper=READMEファイル テンプレートをé¸æŠžã—ã¦ãã ã•ã„。
readme_helper_desc=プロジェクトã«ã¤ã„ã¦ã®èª¬æ˜Žã‚’ã²ã¨ã¨ãŠã‚Šæ›¸ã場所ã§ã™ã€‚
@@ -1060,6 +1064,7 @@ desc.public=公開
desc.template=テンプレート
desc.internal=組織内
desc.archived=アーカイブ
+desc.sha256=SHA256
template.items=テンプレート項目
template.git_content=Gitコンテンツ (デフォルトブランãƒ)
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index 15d24558df..718f3dc9a4 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -1036,6 +1036,7 @@ desc.public=Publisks
desc.template=Sagatave
desc.internal=Iekšējs
desc.archived=Arhivēts
+desc.sha256=SHA256
template.items=Sagataves ieraksti
template.git_content=Git saturs (noklusētais atzars)
@@ -2571,6 +2572,10 @@ error.csv.unexpected=Nevar attēlot šo failu, jo tas satur neparedzētu simbolu
error.csv.invalid_field_count=Nevar attÄ“lot Å¡o failu, jo tas satur nepareizu skaitu ar laukiem %d. lÄ«nijÄ.
[graphs]
+component_loading=IelÄdÄ“ %s...
+component_loading_failed=NevarÄ“ja ielÄdÄ“t %s
+component_loading_info=Å is var aizņemt kÄdu brÄ«di…
+component_failed_to_load=AtgadÄ«jÄs neparedzÄ“ta kļūda.
[org]
org_name_holder=OrganizÄcijas nosaukums
@@ -2698,6 +2703,7 @@ teams.invite.description=Nospiediet pogu zemÄk, lai pievienotos komandai.
[admin]
dashboard=Infopanelis
+self_check=PaÅ¡pÄrbaude
identity_access=IdentitÄte un piekļuve
users=LietotÄju konti
organizations=OrganizÄcijas
@@ -3223,6 +3229,7 @@ notices.desc=Apraksts
notices.op=Op.
notices.delete_success=Sistēmas paziņojumi ir dzēsti.
+self_check.no_problem_found=Pašlaik nav atrasta neviena problēma.
[action]
create_repo=izveidoja repozitoriju <a href="%s">%s</a>
@@ -3560,6 +3567,7 @@ variables.none=VÄ“l nav neviena mainÄ«gÄ.
variables.deletion=Noņemt mainīgo
variables.deletion.description=MainÄ«gÄ noņemÅ¡ana ir neatgriezeniska un nav atsaucama. Vai turpinÄt?
variables.description=MainÄ«gie tiks padoti noteiktÄm darbÄ«bÄm, un citÄdÄk tos nevar nolasÄ«t.
+variables.id_not_exist=MainÄ«gais ar identifikatoru %d nepastÄv.
variables.edit=Labot mainīgo
variables.deletion.failed=NeizdevÄs noņemt mainÄ«go.
variables.deletion.success=Mainīgais tika noņemts.
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 2265611004..8e2dee8ec2 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -2140,7 +2140,7 @@ settings.trust_model.collaborator.long=å作者:信任å作者的签å
settings.trust_model.collaborator.desc=此仓库中å作者的有效签å将被标记为「å¯ä¿¡ã€(无论它们是å¦æ˜¯æ交者),签ååªç¬¦åˆæ交者时将标记为「ä¸å¯ä¿¡ã€ï¼Œéƒ½ä¸åŒ¹é…时标记为「ä¸åŒ¹é…ã€ã€‚
settings.trust_model.committer=æ交者
settings.trust_model.committer.long=æ交者: 信任与æ交者相符的签å (此特性类似 GitHub,这会强制采用 Forgejo 作为æ交者和签å者)
-settings.trust_model.committer.desc=有效签ååªæœ‰å’Œæ交者相匹é…æ‰ä¼šè¢«æ ‡è®°ä¸ºâ€œå—ä¿¡ä»»â€ï¼Œå¦åˆ™å®ƒä»¬å°†è¢«æ ‡è®°ä¸ºâ€œä¸åŒ¹é…â€ã€‚这强制 Forgejo æˆä¸ºç­¾åæ交的æ交者,而实际æ交者被加上 Co-authored-by: å’Œ Co-committed-by: 的标记。 默认的 Forgejo 密钥必须撇撇数æ®åº“ç§çš„一å用户。
+settings.trust_model.committer.desc=有效签ååªæœ‰å’Œæ交者相匹é…æ‰ä¼šè¢«æ ‡è®°ä¸ºâ€œå—ä¿¡ä»»â€ï¼Œå¦åˆ™å®ƒä»¬å°†è¢«æ ‡è®°ä¸ºâ€œä¸åŒ¹é…â€ã€‚这强制 Forgejo æˆä¸ºç­¾åæ交的æ交者,而实际æ交者被加上 Co-authored-by: å’Œ Co-committed-by: 的标记。 默认的 Forgejo 密钥必须匹é…æ•°æ®åº“中的一å用户。
settings.trust_model.collaboratorcommitter=å作者+æ交者
settings.trust_model.collaboratorcommitter.long=å作者+æ交者:信任å作者åŒæ—¶æ˜¯æ交者的签å
settings.trust_model.collaboratorcommitter.desc=此仓库中å作者的有效签å在他åŒæ—¶æ˜¯æ交者时将被标记为「å¯ä¿¡ã€ï¼Œç­¾ååªåŒ¹é…了æ交者时将标记为「ä¸å¯ä¿¡ã€ï¼Œéƒ½ä¸åŒ¹é…时标记为「ä¸åŒ¹é…ã€ã€‚这会强制 Forgejo æˆä¸ºç­¾å者和æ交者,实际的æ交者将被标记于æ交消æ¯ç»“尾处的「Co-Authored-By:ã€å’Œã€ŒCo-Committed-By:ã€ã€‚默认的 Forgejo ç­¾å密钥必须匹é…æ•°æ®åº“中的一个用户密钥。
@@ -3325,7 +3325,9 @@ self_check.database_fix_mssql = 对于 MSSQL 用户,目å‰æ‚¨åªèƒ½é€šè¿‡SQLå‘
self_check.no_problem_found=尚未å‘现问题。
self_check.database_collation_mismatch=期望数æ®åº“使用的校验方å¼ï¼š%s
self_check.database_collation_case_insensitive=æ•°æ®åº“正在使用一个校验 %s, 这是一个ä¸æ•æ„Ÿçš„校验. 虽然Giteaå¯ä»¥ä¸Žå®ƒåˆä½œï¼Œä½†å¯èƒ½æœ‰ä¸€äº›ç½•è§çš„情况ä¸å¦‚预期的那样起作用。
+self_check.database_inconsistent_collation_columns=æ•°æ®åº“正在使用%s的排åºè§„则,但是这些列使用了ä¸åŒ¹é…的排åºè§„则。这å¯èƒ½ä¼šé€ æˆä¸€äº›æ„外问题。
self_check.database_fix_mysql=对于MySQL/MariaDB用户,您å¯ä»¥ä½¿ç”¨â€œgitea doctor convertâ€å‘½ä»¤æ¥è§£å†³æ ¡éªŒé—®é¢˜ã€‚ 或者您也å¯ä»¥é€šè¿‡ "ALTER ... COLLATE ..." 这样的SQL æ¥æ‰‹åŠ¨è§£å†³è¿™ä¸ªé—®é¢˜ã€‚
+self_check.database_fix_mssql=对于MSSQL用户,您现在åªèƒ½é€šè¿‡"ALTER ... COLLATE ..."SQLs手动解决这个问题。
[action]
create_repo=创建了仓库 <a href="%s">%s</a>
diff --git a/package-lock.json b/package-lock.json
index c833670f72..6d1d2850c1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"@citation-js/plugin-csl": "0.7.6",
"@citation-js/plugin-software-formats": "0.6.1",
"@claviska/jquery-minicolors": "2.3.6",
- "@github/markdown-toolbar-element": "2.2.1",
+ "@github/markdown-toolbar-element": "2.2.3",
"@github/relative-time-element": "4.3.1",
"@github/text-expander-element": "2.6.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
@@ -18,11 +18,11 @@
"@webcomponents/custom-elements": "1.6.0",
"add-asset-webpack-plugin": "2.0.1",
"ansi_up": "6.0.2",
- "asciinema-player": "3.6.4",
- "chart.js": "4.4.1",
+ "asciinema-player": "3.7.0",
+ "chart.js": "4.4.2",
"chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.0.1",
- "clippie": "4.0.6",
+ "clippie": "4.0.7",
"css-loader": "6.10.0",
"css-variables-parser": "1.0.1",
"dayjs": "1.11.10",
@@ -37,16 +37,16 @@
"katex": "0.16.9",
"license-checker-webpack-plugin": "0.2.1",
"mermaid": "10.8.0",
- "mini-css-extract-plugin": "2.8.0",
+ "mini-css-extract-plugin": "2.8.1",
"minimatch": "9.0.3",
"monaco-editor": "0.46.0",
"monaco-editor-webpack-plugin": "7.1.0",
"pdfobject": "2.3.0",
"postcss": "8.4.35",
- "postcss-loader": "8.1.0",
+ "postcss-loader": "8.1.1",
"pretty-ms": "9.0.0",
"sortablejs": "1.15.2",
- "swagger-ui-dist": "5.11.6",
+ "swagger-ui-dist": "5.11.8",
"tailwindcss": "3.4.1",
"throttle-debounce": "5.0.0",
"tinycolor2": "1.6.0",
@@ -54,25 +54,25 @@
"toastify-js": "1.12.0",
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
- "vue": "3.4.19",
+ "vue": "3.4.21",
"vue-bar-graph": "2.0.0",
"vue-chartjs": "5.3.0",
"vue-loader": "17.4.2",
"vue3-calendar-heatmap": "2.0.5",
- "webpack": "5.90.2",
+ "webpack": "5.90.3",
"webpack-cli": "5.1.4",
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.1.0",
- "@playwright/test": "1.41.2",
+ "@playwright/test": "1.42.1",
"@stoplight/spectral-cli": "6.11.0",
- "@stylistic/eslint-plugin-js": "1.6.2",
- "@stylistic/stylelint-plugin": "2.0.0",
+ "@stylistic/eslint-plugin-js": "1.6.3",
+ "@stylistic/stylelint-plugin": "2.1.0",
"@vitejs/plugin-vue": "5.0.4",
- "eslint": "8.56.0",
+ "eslint": "8.57.0",
"eslint-plugin-array-func": "4.0.0",
- "eslint-plugin-github": "4.10.1",
+ "eslint-plugin-github": "4.10.2",
"eslint-plugin-i": "2.29.1",
"eslint-plugin-jquery": "1.5.1",
"eslint-plugin-no-jquery": "2.7.0",
@@ -82,7 +82,7 @@
"eslint-plugin-unicorn": "51.0.1",
"eslint-plugin-vitest": "0.3.22",
"eslint-plugin-vitest-globals": "1.4.0",
- "eslint-plugin-vue": "9.21.1",
+ "eslint-plugin-vue": "9.22.0",
"eslint-plugin-vue-scoped-css": "2.7.2",
"eslint-plugin-wc": "2.0.4",
"jsdom": "24.0.0",
@@ -94,7 +94,7 @@
"svgo": "3.2.0",
"updates": "15.1.2",
"vite-string-plugin": "1.1.5",
- "vitest": "1.2.2"
+ "vitest": "1.3.1"
},
"engines": {
"node": ">= 18.0.0"
@@ -296,9 +296,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.23.9",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz",
- "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==",
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz",
+ "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -307,9 +307,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.23.9",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
- "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
+ "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -466,9 +466,9 @@
}
},
"node_modules/@csstools/css-parser-algorithms": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.5.0.tgz",
- "integrity": "sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.0.tgz",
+ "integrity": "sha512-YfEHq0eRH98ffb5/EsrrDspVWAuph6gDggAE74ZtjecsmyyWpW768hOyiONa8zwWGbIWYfa2Xp4tRTrpQQ00CQ==",
"dev": true,
"funding": [
{
@@ -507,9 +507,9 @@
}
},
"node_modules/@csstools/media-query-list-parser": {
- "version": "2.1.7",
- "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.7.tgz",
- "integrity": "sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ==",
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.8.tgz",
+ "integrity": "sha512-DiD3vG5ciNzeuTEoh74S+JMjQDs50R3zlxHnBnfd04YYfA/kh2KiBCGhzqLxlJcNq+7yNQ3stuZZYLX6wK/U2g==",
"dev": true,
"funding": [
{
@@ -525,14 +525,14 @@
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
- "@csstools/css-parser-algorithms": "^2.5.0",
+ "@csstools/css-parser-algorithms": "^2.6.0",
"@csstools/css-tokenizer": "^2.2.3"
}
},
"node_modules/@csstools/selector-specificity": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.1.tgz",
- "integrity": "sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.2.tgz",
+ "integrity": "sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==",
"dev": true,
"funding": [
{
@@ -1012,9 +1012,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
- "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1032,9 +1032,9 @@
"integrity": "sha512-gwxPzLw8XKecy1nP63i9lOBritS3bWmxl02UX6G0TwMQZbMem1BCS1tEZgYd3mkrkiDrUMWaX+DbFCuDFo3K+A=="
},
"node_modules/@github/markdown-toolbar-element": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.2.1.tgz",
- "integrity": "sha512-ap+ulyqzG3aVqwKsKjbDdYwM75TQXZpPtmIuPwm+54OTgcC96267oX3cEqd1wSqGsH7O5PonZ//fE9jH7Q4JkA=="
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.2.3.tgz",
+ "integrity": "sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A=="
},
"node_modules/@github/relative-time-element": {
"version": "4.3.1",
@@ -1142,11 +1142,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
- },
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
@@ -1206,13 +1201,13 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dependencies": {
- "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
+ "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
@@ -1227,9 +1222,9 @@
}
},
"node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"engines": {
"node": ">=6.0.0"
}
@@ -1249,9 +1244,9 @@
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.22",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
- "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -1389,12 +1384,12 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.41.2",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
- "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==",
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz",
+ "integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==",
"dev": true,
"dependencies": {
- "playwright": "1.41.2"
+ "playwright": "1.42.1"
},
"bin": {
"playwright": "cli.js"
@@ -1465,9 +1460,9 @@
"dev": true
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.11.0.tgz",
- "integrity": "sha512-BV+u2QSfK3i1o6FucqJh5IK9cjAU6icjFFhvknzFgu472jzl0bBojfDAkJLBEsHFMo+YZg6rthBvBBt8z12IBQ==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz",
+ "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==",
"cpu": [
"arm"
],
@@ -1478,9 +1473,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.11.0.tgz",
- "integrity": "sha512-0ij3iw7sT5jbcdXofWO2NqDNjSVVsf6itcAkV2I6Xsq4+6wjW1A8rViVB67TfBEan7PV2kbLzT8rhOVWLI2YXw==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz",
+ "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==",
"cpu": [
"arm64"
],
@@ -1491,9 +1486,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.11.0.tgz",
- "integrity": "sha512-yPLs6RbbBMupArf6qv1UDk6dzZvlH66z6NLYEwqTU0VHtss1wkI4UYeeMS7TVj5QRVvaNAWYKP0TD/MOeZ76Zg==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz",
+ "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==",
"cpu": [
"arm64"
],
@@ -1504,9 +1499,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.11.0.tgz",
- "integrity": "sha512-OvqIgwaGAwnASzXaZEeoJY3RltOFg+WUbdkdfoluh2iqatd090UeOG3A/h0wNZmE93dDew9tAtXgm3/+U/B6bw==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz",
+ "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==",
"cpu": [
"x64"
],
@@ -1517,9 +1512,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.11.0.tgz",
- "integrity": "sha512-X17s4hZK3QbRmdAuLd2EE+qwwxL8JxyVupEqAkxKPa/IgX49ZO+vf0ka69gIKsaYeo6c1CuwY3k8trfDtZ9dFg==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz",
+ "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==",
"cpu": [
"arm"
],
@@ -1530,9 +1525,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.11.0.tgz",
- "integrity": "sha512-673Lu9EJwxVB9NfYeA4AdNu0FOHz7g9t6N1DmT7bZPn1u6bTF+oZjj+fuxUcrfxWXE0r2jxl5QYMa9cUOj9NFg==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz",
+ "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==",
"cpu": [
"arm64"
],
@@ -1543,9 +1538,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.11.0.tgz",
- "integrity": "sha512-yFW2msTAQNpPJaMmh2NpRalr1KXI7ZUjlN6dY/FhWlOclMrZezm5GIhy3cP4Ts2rIAC+IPLAjNibjp1BsxCVGg==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz",
+ "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==",
"cpu": [
"arm64"
],
@@ -1556,9 +1551,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.11.0.tgz",
- "integrity": "sha512-kKT9XIuhbvYgiA3cPAGntvrBgzhWkGpBMzuk1V12Xuoqg7CI41chye4HU0vLJnGf9MiZzfNh4I7StPeOzOWJfA==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz",
+ "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==",
"cpu": [
"riscv64"
],
@@ -1569,9 +1564,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.11.0.tgz",
- "integrity": "sha512-6q4ESWlyTO+erp1PSCmASac+ixaDv11dBk1fqyIuvIUc/CmRAX2Zk+2qK1FGo5q7kyDcjHCFVwgGFCGIZGVwCA==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz",
+ "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==",
"cpu": [
"x64"
],
@@ -1582,9 +1577,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.11.0.tgz",
- "integrity": "sha512-vIAQUmXeMLmaDN78HSE4Kh6xqof2e3TJUKr+LPqXWU4NYNON0MDN9h2+t4KHrPAQNmU3w1GxBQ/n01PaWFwa5w==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz",
+ "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==",
"cpu": [
"x64"
],
@@ -1595,9 +1590,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.11.0.tgz",
- "integrity": "sha512-LVXo9dDTGPr0nezMdqa1hK4JeoMZ02nstUxGYY/sMIDtTYlli1ZxTXBYAz3vzuuvKO4X6NBETciIh7N9+abT1g==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz",
+ "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==",
"cpu": [
"arm64"
],
@@ -1608,9 +1603,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.11.0.tgz",
- "integrity": "sha512-xZVt6K70Gr3I7nUhug2dN6VRR1ibot3rXqXS3wo+8JP64t7djc3lBFyqO4GiVrhNaAIhUCJtwQ/20dr0h0thmQ==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz",
+ "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==",
"cpu": [
"ia32"
],
@@ -1621,9 +1616,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.11.0.tgz",
- "integrity": "sha512-f3I7h9oTg79UitEco9/2bzwdciYkWr8pITs3meSDSlr1TdvQ7IxkQaaYN2YqZXX5uZhiYL+VuYDmHwNzhx+HOg==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz",
+ "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==",
"cpu": [
"x64"
],
@@ -2091,9 +2086,9 @@
"dev": true
},
"node_modules/@stylistic/eslint-plugin-js": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.2.tgz",
- "integrity": "sha512-ndT6X2KgWGxv8101pdMOxL8pihlYIHcOv3ICd70cgaJ9exwkPn8hJj4YQwslxoAlre1TFHnXd/G1/hYXgDrjIA==",
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.3.tgz",
+ "integrity": "sha512-ckdz51oHxD2FaxgY2piJWJVJiwgp8Uu96s+as2yB3RMwavn3nHBrpliVukXY9S/DmMicPRB2+H8nBk23GDG+qA==",
"dev": true,
"dependencies": {
"@types/eslint": "^8.56.2",
@@ -2110,19 +2105,19 @@
}
},
"node_modules/@stylistic/stylelint-plugin": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-2.0.0.tgz",
- "integrity": "sha512-dHKuT6PGd1WGZLOTuozAM7GdQzdmlmnFXYzvV1jYJXXpcCpV/OJ3+n8TXpMkoOeKHpJydY43EOoZTO1W/FOA4Q==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-2.1.0.tgz",
+ "integrity": "sha512-mUZEW9uImHSbXeyzbFmHb8WPBv56UTaEnWL/3dGdAiJ54C+8GTfDwDVdI6gbqT9wV7zynkPu7tCXc5746H9mZQ==",
"dev": true,
"dependencies": {
- "@csstools/css-parser-algorithms": "^2.3.2",
- "@csstools/css-tokenizer": "^2.2.1",
- "@csstools/media-query-list-parser": "^2.1.5",
+ "@csstools/css-parser-algorithms": "^2.5.0",
+ "@csstools/css-tokenizer": "^2.2.3",
+ "@csstools/media-query-list-parser": "^2.1.7",
"is-plain-object": "^5.0.0",
- "postcss-selector-parser": "^6.0.13",
+ "postcss-selector-parser": "^6.0.15",
"postcss-value-parser": "^4.2.0",
"style-search": "^0.1.0",
- "stylelint": "^16.0.2"
+ "stylelint": "^16.2.1"
},
"engines": {
"node": "^18.12 || >=20.9"
@@ -2189,9 +2184,9 @@
}
},
"node_modules/@types/eslint": {
- "version": "8.56.2",
- "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
- "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
+ "version": "8.56.5",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz",
+ "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==",
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -2241,9 +2236,9 @@
"integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
},
"node_modules/@types/node": {
- "version": "20.11.19",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
- "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
+ "version": "20.11.24",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz",
+ "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==",
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -2261,9 +2256,9 @@
"dev": true
},
"node_modules/@types/semver": {
- "version": "7.5.7",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz",
- "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==",
+ "version": "7.5.8",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
"dev": true
},
"node_modules/@types/tern": {
@@ -2286,16 +2281,16 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
- "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz",
+ "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
- "@typescript-eslint/scope-manager": "6.21.0",
- "@typescript-eslint/type-utils": "6.21.0",
- "@typescript-eslint/utils": "6.21.0",
- "@typescript-eslint/visitor-keys": "6.21.0",
+ "@typescript-eslint/scope-manager": "7.1.0",
+ "@typescript-eslint/type-utils": "7.1.0",
+ "@typescript-eslint/utils": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
@@ -2311,8 +2306,8 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
- "eslint": "^7.0.0 || ^8.0.0"
+ "@typescript-eslint/parser": "^7.0.0",
+ "eslint": "^8.56.0"
},
"peerDependenciesMeta": {
"typescript": {
@@ -2321,15 +2316,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
- "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz",
+ "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "6.21.0",
- "@typescript-eslint/types": "6.21.0",
- "@typescript-eslint/typescript-estree": "6.21.0",
- "@typescript-eslint/visitor-keys": "6.21.0",
+ "@typescript-eslint/scope-manager": "7.1.0",
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/typescript-estree": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0",
"debug": "^4.3.4"
},
"engines": {
@@ -2340,7 +2335,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
+ "eslint": "^8.56.0"
},
"peerDependenciesMeta": {
"typescript": {
@@ -2349,13 +2344,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
- "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz",
+ "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.21.0",
- "@typescript-eslint/visitor-keys": "6.21.0"
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -2366,13 +2361,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
- "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz",
+ "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==",
"dev": true,
"dependencies": {
- "@typescript-eslint/typescript-estree": "6.21.0",
- "@typescript-eslint/utils": "6.21.0",
+ "@typescript-eslint/typescript-estree": "7.1.0",
+ "@typescript-eslint/utils": "7.1.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@@ -2384,7 +2379,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
+ "eslint": "^8.56.0"
},
"peerDependenciesMeta": {
"typescript": {
@@ -2393,9 +2388,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
- "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz",
+ "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -2406,13 +2401,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
- "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz",
+ "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.21.0",
- "@typescript-eslint/visitor-keys": "6.21.0",
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/visitor-keys": "7.1.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -2434,17 +2429,17 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
- "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz",
+ "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
- "@typescript-eslint/scope-manager": "6.21.0",
- "@typescript-eslint/types": "6.21.0",
- "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/scope-manager": "7.1.0",
+ "@typescript-eslint/types": "7.1.0",
+ "@typescript-eslint/typescript-estree": "7.1.0",
"semver": "^7.5.4"
},
"engines": {
@@ -2455,16 +2450,16 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
+ "eslint": "^8.56.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
- "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz",
+ "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/types": "7.1.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@@ -2495,13 +2490,13 @@
}
},
"node_modules/@vitest/expect": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.2.2.tgz",
- "integrity": "sha512-3jpcdPAD7LwHUUiT2pZTj2U82I2Tcgg2oVPvKxhn6mDI2On6tfvPQTjAI4628GUGDZrCm4Zna9iQHm5cEexOAg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz",
+ "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==",
"dev": true,
"dependencies": {
- "@vitest/spy": "1.2.2",
- "@vitest/utils": "1.2.2",
+ "@vitest/spy": "1.3.1",
+ "@vitest/utils": "1.3.1",
"chai": "^4.3.10"
},
"funding": {
@@ -2509,12 +2504,12 @@
}
},
"node_modules/@vitest/runner": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.2.2.tgz",
- "integrity": "sha512-JctG7QZ4LSDXr5CsUweFgcpEvrcxOV1Gft7uHrvkQ+fsAVylmWQvnaAr/HDp3LAH1fztGMQZugIheTWjaGzYIg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz",
+ "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==",
"dev": true,
"dependencies": {
- "@vitest/utils": "1.2.2",
+ "@vitest/utils": "1.3.1",
"p-limit": "^5.0.0",
"pathe": "^1.1.1"
},
@@ -2550,9 +2545,9 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.2.2.tgz",
- "integrity": "sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz",
+ "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==",
"dev": true,
"dependencies": {
"magic-string": "^0.30.5",
@@ -2576,9 +2571,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.2.2.tgz",
- "integrity": "sha512-k9Gcahssw8d7X3pSLq3e3XEu/0L78mUkCjivUqCQeXJm9clfXR/Td8+AP+VC1O6fKPIDLcHDTAmBOINVuv6+7g==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz",
+ "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==",
"dev": true,
"dependencies": {
"tinyspy": "^2.2.0"
@@ -2588,9 +2583,9 @@
}
},
"node_modules/@vitest/utils": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.2.2.tgz",
- "integrity": "sha512-WKITBHLsBHlpjnDQahr+XK6RE7MiAsgrIkr0pGhQ9ygoxBfUeG0lUG5iLlzqjmKSlBv3+j5EGsriBzh+C3Tq9g==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz",
+ "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==",
"dev": true,
"dependencies": {
"diff-sequences": "^29.6.3",
@@ -2618,39 +2613,39 @@
}
},
"node_modules/@vue/compiler-core": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz",
- "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz",
+ "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==",
"dependencies": {
"@babel/parser": "^7.23.9",
- "@vue/shared": "3.4.19",
+ "@vue/shared": "3.4.21",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-dom": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz",
- "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz",
+ "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==",
"dependencies": {
- "@vue/compiler-core": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-core": "3.4.21",
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/compiler-sfc": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz",
- "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz",
+ "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==",
"dependencies": {
"@babel/parser": "^7.23.9",
- "@vue/compiler-core": "3.4.19",
- "@vue/compiler-dom": "3.4.19",
- "@vue/compiler-ssr": "3.4.19",
- "@vue/shared": "3.4.19",
+ "@vue/compiler-core": "3.4.21",
+ "@vue/compiler-dom": "3.4.21",
+ "@vue/compiler-ssr": "3.4.21",
+ "@vue/shared": "3.4.21",
"estree-walker": "^2.0.2",
- "magic-string": "^0.30.6",
- "postcss": "^8.4.33",
+ "magic-string": "^0.30.7",
+ "postcss": "^8.4.35",
"source-map-js": "^1.0.2"
}
},
@@ -2666,57 +2661,57 @@
}
},
"node_modules/@vue/compiler-ssr": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz",
- "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz",
+ "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==",
"dependencies": {
- "@vue/compiler-dom": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-dom": "3.4.21",
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/reactivity": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz",
- "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.21.tgz",
+ "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
"dependencies": {
- "@vue/shared": "3.4.19"
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/runtime-core": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz",
- "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
+ "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
"dependencies": {
- "@vue/reactivity": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/reactivity": "3.4.21",
+ "@vue/shared": "3.4.21"
}
},
"node_modules/@vue/runtime-dom": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz",
- "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
+ "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
"dependencies": {
- "@vue/runtime-core": "3.4.19",
- "@vue/shared": "3.4.19",
+ "@vue/runtime-core": "3.4.21",
+ "@vue/shared": "3.4.21",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz",
- "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
+ "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
"dependencies": {
- "@vue/compiler-ssr": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-ssr": "3.4.21",
+ "@vue/shared": "3.4.21"
},
"peerDependencies": {
- "vue": "3.4.19"
+ "vue": "3.4.21"
}
},
"node_modules/@vue/shared": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
- "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
+ "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g=="
},
"node_modules/@webassemblyjs/ast": {
"version": "1.11.6",
@@ -3269,9 +3264,9 @@
}
},
"node_modules/asciinema-player": {
- "version": "3.6.4",
- "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.6.4.tgz",
- "integrity": "sha512-yyMHTjoDuz82/BYPrc3J5GjOtlNI5t2VHTZWss8BmRcY/6nXv+Vilip+XzwIyRBa3/2SSn9FJIEg8bJXBc9o4w==",
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.7.0.tgz",
+ "integrity": "sha512-0RDc4j7TkjyhAwxkDe3vNqjAcizc7tubYW2VZi/06csY8iAoSC2uRvSyfNzh9ONDZu8pdf0bZJ91A84Gexb3tg==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"solid-js": "^1.3.0"
@@ -3350,10 +3345,13 @@
}
},
"node_modules/available-typed-arrays": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz",
- "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"dev": true,
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
"engines": {
"node": ">= 0.4"
},
@@ -3566,9 +3564,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001587",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz",
- "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==",
+ "version": "1.0.30001591",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz",
+ "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==",
"funding": [
{
"type": "opencollective",
@@ -3627,14 +3625,14 @@
}
},
"node_modules/chart.js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
- "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.2.tgz",
+ "integrity": "sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
- "pnpm": ">=7"
+ "pnpm": ">=8"
}
},
"node_modules/chartjs-adapter-dayjs-4": {
@@ -3756,9 +3754,9 @@
}
},
"node_modules/clippie": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/clippie/-/clippie-4.0.6.tgz",
- "integrity": "sha512-E5EtOw8iMH0enuL3kBZJ+Po1nPnBD7O+HHpIaWpfWgHbHmdoOQoERrlNOcEEn2yMJQ98WqeKacouAcnRXn7oWA=="
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/clippie/-/clippie-4.0.7.tgz",
+ "integrity": "sha512-xmIARCRFQUoCR0kNNu4uIv5f/IFqM1fUts0vQwt1hQEdCPEqs3/dTaG38WenlWOgs3Fcn73PBYXbPIVSlOgFRw=="
},
"node_modules/cliui": {
"version": "7.0.4",
@@ -4842,9 +4840,9 @@
}
},
"node_modules/dompurify": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.8.tgz",
- "integrity": "sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ=="
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.9.tgz",
+ "integrity": "sha512-uyb4NDIvQ3hRn6NiC+SIFaP4mJ/MdXlvtunaqK9Bn6dD3RuB/1S/gasEjDHD8eiaqdSael2vBv+hOs7Y+jhYOQ=="
},
"node_modules/domutils": {
"version": "3.1.0",
@@ -4887,19 +4885,19 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.671",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.671.tgz",
- "integrity": "sha512-UUlE+/rWbydmp+FW8xlnnTA5WNA0ZZd2XL8CuMS72rh+k4y1f8+z6yk3UQhEwqHQWj6IBdL78DwWOdGMvYfQyA=="
+ "version": "1.4.690",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.690.tgz",
+ "integrity": "sha512-+2OAGjUx68xElQhydpcbqH50hE8Vs2K6TkAeLhICYfndb67CVH0UsZaijmRUE3rHlIxU1u0jxwhgVe6fK3YANA=="
},
"node_modules/elkjs": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.1.tgz",
- "integrity": "sha512-JWKDyqAdltuUcyxaECtYG6H4sqysXSLeoXuGUBfRNESMTkj+w+qdb0jya8Z/WI0jVd03WQtCGhS6FOFtlhD5FQ=="
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.2.tgz",
+ "integrity": "sha512-2Y/RaA1pdgSHpY0YG4TYuYCD2wh97CRvu22eLG3Kz0pgQ/6KbIFTxsTnDc4MH/6hFlg2L/9qXrDMG0nMjP63iw=="
},
"node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/emojis-list": {
"version": "3.0.0",
@@ -4910,9 +4908,9 @@
}
},
"node_modules/enhanced-resolve": {
- "version": "5.15.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
- "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+ "version": "5.15.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz",
+ "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -4960,18 +4958,18 @@
}
},
"node_modules/es-abstract": {
- "version": "1.22.4",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz",
- "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==",
+ "version": "1.22.5",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz",
+ "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==",
"dev": true,
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
"arraybuffer.prototype.slice": "^1.0.3",
- "available-typed-arrays": "^1.0.6",
+ "available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.7",
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
- "es-set-tostringtag": "^2.0.2",
+ "es-set-tostringtag": "^2.0.3",
"es-to-primitive": "^1.2.1",
"function.prototype.name": "^1.1.6",
"get-intrinsic": "^1.2.4",
@@ -4979,15 +4977,15 @@
"globalthis": "^1.0.3",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2",
- "has-proto": "^1.0.1",
+ "has-proto": "^1.0.3",
"has-symbols": "^1.0.3",
"hasown": "^2.0.1",
"internal-slot": "^1.0.7",
"is-array-buffer": "^3.0.4",
"is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
+ "is-negative-zero": "^2.0.3",
"is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
+ "is-shared-array-buffer": "^1.0.3",
"is-string": "^1.0.7",
"is-typed-array": "^1.1.13",
"is-weakref": "^1.0.2",
@@ -5000,10 +4998,10 @@
"string.prototype.trim": "^1.2.8",
"string.prototype.trimend": "^1.0.7",
"string.prototype.trimstart": "^1.0.7",
- "typed-array-buffer": "^1.0.1",
- "typed-array-byte-length": "^1.0.0",
- "typed-array-byte-offset": "^1.0.0",
- "typed-array-length": "^1.0.4",
+ "typed-array-buffer": "^1.0.2",
+ "typed-array-byte-length": "^1.0.1",
+ "typed-array-byte-offset": "^1.0.2",
+ "typed-array-length": "^1.0.5",
"unbox-primitive": "^1.0.2",
"which-typed-array": "^1.1.14"
},
@@ -5095,14 +5093,14 @@
"integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w=="
},
"node_modules/es-set-tostringtag": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
- "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
+ "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
"dev": true,
"dependencies": {
- "get-intrinsic": "^1.2.2",
- "has-tostringtag": "^1.0.0",
- "hasown": "^2.0.0"
+ "get-intrinsic": "^1.2.4",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.1"
},
"engines": {
"node": ">= 0.4"
@@ -5220,16 +5218,16 @@
}
},
"node_modules/eslint": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
- "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.4",
- "@eslint/js": "8.56.0",
- "@humanwhocodes/config-array": "^0.11.13",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
"@ungap/structured-clone": "^1.2.0",
@@ -5322,9 +5320,9 @@
}
},
"node_modules/eslint-module-utils": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
- "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz",
+ "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==",
"dev": true,
"dependencies": {
"debug": "^3.2.7"
@@ -5415,14 +5413,14 @@
}
},
"node_modules/eslint-plugin-github": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.10.1.tgz",
- "integrity": "sha512-1AqQBockOM+m0ZUpwfjWtX0lWdX5cRi/hwJnSNvXoOmz/Hh+ULH6QFz6ENWueTWjoWpgPv0af3bj+snps6o4og==",
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.10.2.tgz",
+ "integrity": "sha512-F1F5aAFgi1Y5hYoTFzGQACBkw5W1hu2Fu5FSTrMlXqrojJnKl1S2pWO/rprlowRQpt+hzHhqSpsfnodJEVd5QA==",
"dev": true,
"dependencies": {
"@github/browserslist-config": "^1.0.0",
- "@typescript-eslint/eslint-plugin": "^6.0.0",
- "@typescript-eslint/parser": "^6.0.0",
+ "@typescript-eslint/eslint-plugin": "^7.0.1",
+ "@typescript-eslint/parser": "^7.0.1",
"aria-query": "^5.3.0",
"eslint-config-prettier": ">=8.0.0",
"eslint-plugin-escompat": "^3.3.3",
@@ -5633,12 +5631,6 @@
"concat-map": "0.0.1"
}
},
- "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
- },
"node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -5810,17 +5802,117 @@
"integrity": "sha512-WE+YlK9X9s4vf5EaYRU0Scw7WItDZStm+PapFSYlg2ABNtaQ4zIG7wEqpoUB3SlfM+SgkhgmzR0TeJOO5k3/Nw==",
"dev": true
},
+ "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
+ "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
"node_modules/eslint-plugin-vue": {
- "version": "9.21.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.21.1.tgz",
- "integrity": "sha512-XVtI7z39yOVBFJyi8Ljbn7kY9yHzznKXL02qQYn+ta63Iy4A9JFBw6o4OSB9hyD2++tVT+su9kQqetUyCCwhjw==",
+ "version": "9.22.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.22.0.tgz",
+ "integrity": "sha512-7wCXv5zuVnBtZE/74z4yZ0CM8AjH6bk4MQGm7hZjUC2DBppKU5ioeOk5LGSg/s9a1ZJnIsdPLJpXnu1Rc+cVHg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"natural-compare": "^1.4.0",
"nth-check": "^2.1.1",
- "postcss-selector-parser": "^6.0.13",
- "semver": "^7.5.4",
+ "postcss-selector-parser": "^6.0.15",
+ "semver": "^7.6.0",
"vue-eslint-parser": "^9.4.2",
"xml-name-validator": "^4.0.0"
},
@@ -6231,9 +6323,9 @@
}
},
"node_modules/flatted": {
- "version": "3.2.9",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
- "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
"dev": true
},
"node_modules/for-each": {
@@ -6681,9 +6773,9 @@
}
},
"node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"engines": {
"node": ">= 0.4"
@@ -7218,9 +7310,9 @@
}
},
"node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
"dev": true,
"engines": {
"node": ">= 0.4"
@@ -7331,12 +7423,15 @@
}
},
"node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2"
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -8777,9 +8872,9 @@
}
},
"node_modules/mini-css-extract-plugin": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.0.tgz",
- "integrity": "sha512-CxmUYPFcTgET1zImteG/LZOy/4T5rTojesQXkSNBiquhydn78tfbCE9sjIjnJ/UcjNjOC1bphTCCW5rrS7cXAg==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz",
+ "integrity": "sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==",
"dependencies": {
"schema-utils": "^4.0.0",
"tapable": "^2.2.1"
@@ -8827,9 +8922,9 @@
}
},
"node_modules/mlly": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz",
- "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==",
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz",
+ "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==",
"dev": true,
"dependencies": {
"acorn": "^8.11.3",
@@ -9031,9 +9126,9 @@
}
},
"node_modules/npm-run-path": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz",
- "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==",
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+ "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
"dev": true,
"dependencies": {
"path-key": "^4.0.0"
@@ -9516,12 +9611,12 @@
"dev": true
},
"node_modules/playwright": {
- "version": "1.41.2",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz",
- "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==",
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz",
+ "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==",
"dev": true,
"dependencies": {
- "playwright-core": "1.41.2"
+ "playwright-core": "1.42.1"
},
"bin": {
"playwright": "cli.js"
@@ -9534,9 +9629,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.41.2",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz",
- "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==",
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz",
+ "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -9563,6 +9658,15 @@
"node": ">=12.0.0"
}
},
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/postcss": {
"version": "8.4.35",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
@@ -9640,9 +9744,9 @@
}
},
"node_modules/postcss-loader": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.0.tgz",
- "integrity": "sha512-AbperNcX3rlob7Ay7A/HQcrofug1caABBkopoFeOQMspZBqcqj6giYn1Bwey/0uiOPAcR+NQD0I2HC7rXzk91w==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz",
+ "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==",
"dependencies": {
"cosmiconfig": "^9.0.0",
"jiti": "^1.20.0",
@@ -10570,14 +10674,15 @@
}
},
"node_modules/set-function-name": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
- "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
"dev": true,
"dependencies": {
- "define-data-property": "^1.0.1",
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.0"
+ "has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -10614,12 +10719,12 @@
}
},
"node_modules/side-channel": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
- "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.6",
+ "call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4",
"object-inspect": "^1.13.1"
@@ -10860,6 +10965,16 @@
"node": ">=8"
}
},
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
"node_modules/string.prototype.trim": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
@@ -10974,12 +11089,12 @@
}
},
"node_modules/strip-literal": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
- "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz",
+ "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==",
"dev": true,
"dependencies": {
- "acorn": "^8.10.0"
+ "js-tokens": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
@@ -11102,41 +11217,18 @@
}
},
"node_modules/stylelint/node_modules/flat-cache": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz",
- "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
"dependencies": {
"flatted": "^3.2.9",
- "keyv": "^4.5.4",
- "rimraf": "^5.0.5"
+ "keyv": "^4.5.4"
},
"engines": {
"node": ">=16"
}
},
- "node_modules/stylelint/node_modules/glob": {
- "version": "10.3.10",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
- "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
- "dev": true,
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^2.3.5",
- "minimatch": "^9.0.1",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
- "path-scurry": "^1.10.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/stylelint/node_modules/postcss-safe-parser": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz",
@@ -11172,24 +11264,6 @@
"node": ">=8"
}
},
- "node_modules/stylelint/node_modules/rimraf": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
- "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
- "dev": true,
- "dependencies": {
- "glob": "^10.3.7"
- },
- "bin": {
- "rimraf": "dist/esm/bin.mjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/stylelint/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
@@ -11380,9 +11454,9 @@
}
},
"node_modules/swagger-ui-dist": {
- "version": "5.11.6",
- "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.11.6.tgz",
- "integrity": "sha512-K5BpYuMoPpJY7NwCHIWohH6tU9o0fs1+plNT5KJ+3BBlVEh4H1CpeKJV8o91lpscVY9oqb2jmaAassnW3wVoTg=="
+ "version": "5.11.8",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.11.8.tgz",
+ "integrity": "sha512-IfPtCPdf6opT5HXrzHO4kjL1eco0/8xJCtcs7ilhKuzatrpF2j9s+3QbOag6G3mVFKf+g+Ca5UG9DquVUs2obA=="
},
"node_modules/symbol-tree": {
"version": "3.2.4",
@@ -11524,9 +11598,9 @@
}
},
"node_modules/terser": {
- "version": "5.27.1",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz",
- "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==",
+ "version": "5.28.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz",
+ "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -11839,12 +11913,12 @@
}
},
"node_modules/typed-array-buffer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz",
- "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.6",
+ "call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"is-typed-array": "^1.1.13"
},
@@ -11853,15 +11927,16 @@
}
},
"node_modules/typed-array-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
- "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
+ "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
+ "call-bind": "^1.0.7",
"for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
},
"engines": {
"node": ">= 0.4"
@@ -11871,16 +11946,17 @@
}
},
"node_modules/typed-array-byte-offset": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
- "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
+ "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
"dev": true,
"dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
"for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
},
"engines": {
"node": ">= 0.4"
@@ -11890,14 +11966,20 @@
}
},
"node_modules/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz",
+ "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
+ "call-bind": "^1.0.7",
"for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -11923,9 +12005,9 @@
"integrity": "sha512-Oy/k+tFle5NAA3J/yrrYGfvEnPVrDZ8s8/WCwjUE75k331QyKIsFss7byQ/PzBmXLY6h1moRnZbnaxWBe3I3CA=="
},
"node_modules/uc.micro": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.0.0.tgz",
- "integrity": "sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true
},
"node_modules/ufo": {
@@ -12108,9 +12190,9 @@
}
},
"node_modules/vite": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz",
- "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==",
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz",
+ "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==",
"dev": true,
"dependencies": {
"esbuild": "^0.19.3",
@@ -12163,9 +12245,9 @@
}
},
"node_modules/vite-node": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.2.2.tgz",
- "integrity": "sha512-1as4rDTgVWJO3n1uHmUYqq7nsFgINQ9u+mRcXpjeOMJUmviqNKjcZB7UfRZrlM7MjYXMKpuWp5oGkjaFLnjawg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz",
+ "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
@@ -12211,9 +12293,9 @@
}
},
"node_modules/vite/node_modules/rollup": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.11.0.tgz",
- "integrity": "sha512-2xIbaXDXjf3u2tajvA5xROpib7eegJ9Y/uPlSFhXLNpK9ampCczXAhLEb5yLzJyG3LAdI1NWtNjDXiLyniNdjQ==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz",
+ "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -12226,35 +12308,34 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.11.0",
- "@rollup/rollup-android-arm64": "4.11.0",
- "@rollup/rollup-darwin-arm64": "4.11.0",
- "@rollup/rollup-darwin-x64": "4.11.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.11.0",
- "@rollup/rollup-linux-arm64-gnu": "4.11.0",
- "@rollup/rollup-linux-arm64-musl": "4.11.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.11.0",
- "@rollup/rollup-linux-x64-gnu": "4.11.0",
- "@rollup/rollup-linux-x64-musl": "4.11.0",
- "@rollup/rollup-win32-arm64-msvc": "4.11.0",
- "@rollup/rollup-win32-ia32-msvc": "4.11.0",
- "@rollup/rollup-win32-x64-msvc": "4.11.0",
+ "@rollup/rollup-android-arm-eabi": "4.12.0",
+ "@rollup/rollup-android-arm64": "4.12.0",
+ "@rollup/rollup-darwin-arm64": "4.12.0",
+ "@rollup/rollup-darwin-x64": "4.12.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.12.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.12.0",
+ "@rollup/rollup-linux-arm64-musl": "4.12.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.12.0",
+ "@rollup/rollup-linux-x64-gnu": "4.12.0",
+ "@rollup/rollup-linux-x64-musl": "4.12.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.12.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.12.0",
+ "@rollup/rollup-win32-x64-msvc": "4.12.0",
"fsevents": "~2.3.2"
}
},
"node_modules/vitest": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.2.2.tgz",
- "integrity": "sha512-d5Ouvrnms3GD9USIK36KG8OZ5bEvKEkITFtnGv56HFaSlbItJuYr7hv2Lkn903+AvRAgSixiamozUVfORUekjw==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz",
+ "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==",
"dev": true,
"dependencies": {
- "@vitest/expect": "1.2.2",
- "@vitest/runner": "1.2.2",
- "@vitest/snapshot": "1.2.2",
- "@vitest/spy": "1.2.2",
- "@vitest/utils": "1.2.2",
+ "@vitest/expect": "1.3.1",
+ "@vitest/runner": "1.3.1",
+ "@vitest/snapshot": "1.3.1",
+ "@vitest/spy": "1.3.1",
+ "@vitest/utils": "1.3.1",
"acorn-walk": "^8.3.2",
- "cac": "^6.7.14",
"chai": "^4.3.10",
"debug": "^4.3.4",
"execa": "^8.0.1",
@@ -12263,11 +12344,11 @@
"pathe": "^1.1.1",
"picocolors": "^1.0.0",
"std-env": "^3.5.0",
- "strip-literal": "^1.3.0",
+ "strip-literal": "^2.0.0",
"tinybench": "^2.5.1",
"tinypool": "^0.8.2",
"vite": "^5.0.0",
- "vite-node": "1.2.2",
+ "vite-node": "1.3.1",
"why-is-node-running": "^2.2.2"
},
"bin": {
@@ -12282,8 +12363,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "^1.0.0",
- "@vitest/ui": "^1.0.0",
+ "@vitest/browser": "1.3.1",
+ "@vitest/ui": "1.3.1",
"happy-dom": "*",
"jsdom": "*"
},
@@ -12321,15 +12402,15 @@
}
},
"node_modules/vue": {
- "version": "3.4.19",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz",
- "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==",
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz",
+ "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
"dependencies": {
- "@vue/compiler-dom": "3.4.19",
- "@vue/compiler-sfc": "3.4.19",
- "@vue/runtime-dom": "3.4.19",
- "@vue/server-renderer": "3.4.19",
- "@vue/shared": "3.4.19"
+ "@vue/compiler-dom": "3.4.21",
+ "@vue/compiler-sfc": "3.4.21",
+ "@vue/runtime-dom": "3.4.21",
+ "@vue/server-renderer": "3.4.21",
+ "@vue/shared": "3.4.21"
},
"peerDependencies": {
"typescript": "*"
@@ -12463,9 +12544,9 @@
}
},
"node_modules/webpack": {
- "version": "5.90.2",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.2.tgz",
- "integrity": "sha512-ziXu8ABGr0InCMEYFnHrYweinHK2PWrMqnwdHk2oK3rRhv/1B+2FnfwYv5oD+RrknK/Pp/Hmyvu+eAsaMYhzCw==",
+ "version": "5.90.3",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz",
+ "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.5",
@@ -12964,9 +13045,12 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yaml": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
- "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.0.tgz",
+ "integrity": "sha512-j9iR8g+/t0lArF4V6NE/QCfT+CO7iLqrXAHZbJdo+LfjqP1vR8Fg5bSiaq6Q2lOD1AUEVrEVIgABvBFYojJVYQ==",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
"engines": {
"node": ">= 14"
}
diff --git a/package.json b/package.json
index 3f0f9103cf..1152bfef72 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"@citation-js/plugin-csl": "0.7.6",
"@citation-js/plugin-software-formats": "0.6.1",
"@claviska/jquery-minicolors": "2.3.6",
- "@github/markdown-toolbar-element": "2.2.1",
+ "@github/markdown-toolbar-element": "2.2.3",
"@github/relative-time-element": "4.3.1",
"@github/text-expander-element": "2.6.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
@@ -17,11 +17,11 @@
"@webcomponents/custom-elements": "1.6.0",
"add-asset-webpack-plugin": "2.0.1",
"ansi_up": "6.0.2",
- "asciinema-player": "3.6.4",
- "chart.js": "4.4.1",
+ "asciinema-player": "3.7.0",
+ "chart.js": "4.4.2",
"chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.0.1",
- "clippie": "4.0.6",
+ "clippie": "4.0.7",
"css-loader": "6.10.0",
"css-variables-parser": "1.0.1",
"dayjs": "1.11.10",
@@ -36,16 +36,16 @@
"katex": "0.16.9",
"license-checker-webpack-plugin": "0.2.1",
"mermaid": "10.8.0",
- "mini-css-extract-plugin": "2.8.0",
+ "mini-css-extract-plugin": "2.8.1",
"minimatch": "9.0.3",
"monaco-editor": "0.46.0",
"monaco-editor-webpack-plugin": "7.1.0",
"pdfobject": "2.3.0",
"postcss": "8.4.35",
- "postcss-loader": "8.1.0",
+ "postcss-loader": "8.1.1",
"pretty-ms": "9.0.0",
"sortablejs": "1.15.2",
- "swagger-ui-dist": "5.11.6",
+ "swagger-ui-dist": "5.11.8",
"tailwindcss": "3.4.1",
"throttle-debounce": "5.0.0",
"tinycolor2": "1.6.0",
@@ -53,25 +53,25 @@
"toastify-js": "1.12.0",
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
- "vue": "3.4.19",
+ "vue": "3.4.21",
"vue-bar-graph": "2.0.0",
"vue-chartjs": "5.3.0",
"vue-loader": "17.4.2",
"vue3-calendar-heatmap": "2.0.5",
- "webpack": "5.90.2",
+ "webpack": "5.90.3",
"webpack-cli": "5.1.4",
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.1.0",
- "@playwright/test": "1.41.2",
+ "@playwright/test": "1.42.1",
"@stoplight/spectral-cli": "6.11.0",
- "@stylistic/eslint-plugin-js": "1.6.2",
- "@stylistic/stylelint-plugin": "2.0.0",
+ "@stylistic/eslint-plugin-js": "1.6.3",
+ "@stylistic/stylelint-plugin": "2.1.0",
"@vitejs/plugin-vue": "5.0.4",
- "eslint": "8.56.0",
+ "eslint": "8.57.0",
"eslint-plugin-array-func": "4.0.0",
- "eslint-plugin-github": "4.10.1",
+ "eslint-plugin-github": "4.10.2",
"eslint-plugin-i": "2.29.1",
"eslint-plugin-jquery": "1.5.1",
"eslint-plugin-no-jquery": "2.7.0",
@@ -81,7 +81,7 @@
"eslint-plugin-unicorn": "51.0.1",
"eslint-plugin-vitest": "0.3.22",
"eslint-plugin-vitest-globals": "1.4.0",
- "eslint-plugin-vue": "9.21.1",
+ "eslint-plugin-vue": "9.22.0",
"eslint-plugin-vue-scoped-css": "2.7.2",
"eslint-plugin-wc": "2.0.4",
"jsdom": "24.0.0",
@@ -93,7 +93,7 @@
"svgo": "3.2.0",
"updates": "15.1.2",
"vite-string-plugin": "1.1.5",
- "vitest": "1.2.2"
+ "vitest": "1.3.1"
},
"browserslist": [
"defaults"
diff --git a/poetry.lock b/poetry.lock
index 4cb58c6ef2..46520fba3c 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "click"
@@ -27,12 +27,12 @@ files = [
[[package]]
name = "cssbeautifier"
-version = "1.14.11"
+version = "1.15.1"
description = "CSS unobfuscator and beautifier."
optional = false
python-versions = "*"
files = [
- {file = "cssbeautifier-1.14.11.tar.gz", hash = "sha256:40544c2b62bbcb64caa5e7f37a02df95654e5ce1bcacadac4ca1f3dc89c31513"},
+ {file = "cssbeautifier-1.15.1.tar.gz", hash = "sha256:9f7064362aedd559c55eeecf6b6bed65e05f33488dcbe39044f0403c26e1c006"},
]
[package.dependencies]
@@ -67,13 +67,12 @@ tqdm = ">=4.62.2,<5.0.0"
[[package]]
name = "editorconfig"
-version = "0.12.3"
+version = "0.12.4"
description = "EditorConfig File Locator and Interpreter for Python"
optional = false
python-versions = "*"
files = [
- {file = "EditorConfig-0.12.3-py3-none-any.whl", hash = "sha256:6b0851425aa875b08b16789ee0eeadbd4ab59666e9ebe728e526314c4a2e52c1"},
- {file = "EditorConfig-0.12.3.tar.gz", hash = "sha256:57f8ce78afcba15c8b18d46b5170848c88d56fd38f05c2ec60dbbfcb8996e89e"},
+ {file = "EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80"},
]
[[package]]
@@ -100,12 +99,12 @@ files = [
[[package]]
name = "jsbeautifier"
-version = "1.14.11"
+version = "1.15.1"
description = "JavaScript unobfuscator and beautifier."
optional = false
python-versions = "*"
files = [
- {file = "jsbeautifier-1.14.11.tar.gz", hash = "sha256:6b632581ea60dd1c133cd25a48ad187b4b91f526623c4b0fb5443ef805250505"},
+ {file = "jsbeautifier-1.15.1.tar.gz", hash = "sha256:ebd733b560704c602d744eafc839db60a1ee9326e30a2a80c4adb8718adc1b24"},
]
[package.dependencies]
@@ -114,13 +113,13 @@ six = ">=1.13.0"
[[package]]
name = "json5"
-version = "0.9.14"
+version = "0.9.18"
description = "A Python implementation of the JSON5 data format."
optional = false
-python-versions = "*"
+python-versions = ">=3.8"
files = [
- {file = "json5-0.9.14-py2.py3-none-any.whl", hash = "sha256:740c7f1b9e584a468dbb2939d8d458db3427f2c93ae2139d05f47e453eae964f"},
- {file = "json5-0.9.14.tar.gz", hash = "sha256:9ed66c3a6ca3510a976a9ef9b8c0787de24802724ab1860bc0153c7fdd589b02"},
+ {file = "json5-0.9.18-py2.py3-none-any.whl", hash = "sha256:3f20193ff8dfdec6ab114b344e7ac5d76fac453c8bab9bdfe1460d1d528ec393"},
+ {file = "json5-0.9.18.tar.gz", hash = "sha256:ecb8ac357004e3522fb989da1bf08b146011edbd14fdffae6caad3bd68493467"},
]
[package.extras]
@@ -322,13 +321,13 @@ files = [
[[package]]
name = "tqdm"
-version = "4.66.1"
+version = "4.66.2"
description = "Fast, Extensible Progress Meter"
optional = false
python-versions = ">=3.7"
files = [
- {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"},
- {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"},
+ {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"},
+ {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"},
]
[package.dependencies]
@@ -342,13 +341,13 @@ telegram = ["requests"]
[[package]]
name = "yamllint"
-version = "1.35.0"
+version = "1.35.1"
description = "A linter for YAML files."
optional = false
python-versions = ">=3.8"
files = [
- {file = "yamllint-1.35.0-py3-none-any.whl", hash = "sha256:601b0adaaac6d9bacb16a2e612e7ee8d23caf941ceebf9bfe2cff0f196266004"},
- {file = "yamllint-1.35.0.tar.gz", hash = "sha256:9bc99c3e9fe89b4c6ee26e17aa817cf2d14390de6577cb6e2e6ed5f72120c835"},
+ {file = "yamllint-1.35.1-py3-none-any.whl", hash = "sha256:2e16e504bb129ff515b37823b472750b36b6de07963bd74b307341ef5ad8bdc3"},
+ {file = "yamllint-1.35.1.tar.gz", hash = "sha256:7a003809f88324fd2c877734f2d575ee7881dd9043360657cc8049c809eba6cd"},
]
[package.dependencies]
@@ -360,5 +359,5 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
[metadata]
lock-version = "2.0"
-python-versions = "^3.8"
-content-hash = "ba1c2c4235872f67354b5f52aa5bf0cd616354961530d9dc907f9fba28cc1ece"
+python-versions = "^3.10"
+content-hash = "cd2ff218e9f27a464dfbc8ec2387824a90f4360e04c3f2e58cc375796b7df33a"
diff --git a/pyproject.toml b/pyproject.toml
index ef763da24d..323307c1dc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,11 +5,11 @@ description = ""
authors = []
[tool.poetry.dependencies]
-python = "^3.8"
+python = "^3.10"
[tool.poetry.group.dev.dependencies]
djlint = "1.34.1"
-yamllint = "1.35.0"
+yamllint = "1.35.1"
[tool.djlint]
profile="golang"
diff --git a/routers/api/actions/artifact.pb.go b/routers/api/actions/artifact.pb.go
new file mode 100644
index 0000000000..590eda9fb9
--- /dev/null
+++ b/routers/api/actions/artifact.pb.go
@@ -0,0 +1,1058 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.32.0
+// protoc v4.25.2
+// source: artifact.proto
+
+package actions
+
+import (
+ reflect "reflect"
+ sync "sync"
+
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+ wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type CreateArtifactRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WorkflowRunBackendId string `protobuf:"bytes,1,opt,name=workflow_run_backend_id,json=workflowRunBackendId,proto3" json:"workflow_run_backend_id,omitempty"`
+ WorkflowJobRunBackendId string `protobuf:"bytes,2,opt,name=workflow_job_run_backend_id,json=workflowJobRunBackendId,proto3" json:"workflow_job_run_backend_id,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+ ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
+ Version int32 `protobuf:"varint,5,opt,name=version,proto3" json:"version,omitempty"`
+}
+
+func (x *CreateArtifactRequest) Reset() {
+ *x = CreateArtifactRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CreateArtifactRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateArtifactRequest) ProtoMessage() {}
+
+func (x *CreateArtifactRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateArtifactRequest.ProtoReflect.Descriptor instead.
+func (*CreateArtifactRequest) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateArtifactRequest) GetWorkflowRunBackendId() string {
+ if x != nil {
+ return x.WorkflowRunBackendId
+ }
+ return ""
+}
+
+func (x *CreateArtifactRequest) GetWorkflowJobRunBackendId() string {
+ if x != nil {
+ return x.WorkflowJobRunBackendId
+ }
+ return ""
+}
+
+func (x *CreateArtifactRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *CreateArtifactRequest) GetExpiresAt() *timestamppb.Timestamp {
+ if x != nil {
+ return x.ExpiresAt
+ }
+ return nil
+}
+
+func (x *CreateArtifactRequest) GetVersion() int32 {
+ if x != nil {
+ return x.Version
+ }
+ return 0
+}
+
+type CreateArtifactResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
+ SignedUploadUrl string `protobuf:"bytes,2,opt,name=signed_upload_url,json=signedUploadUrl,proto3" json:"signed_upload_url,omitempty"`
+}
+
+func (x *CreateArtifactResponse) Reset() {
+ *x = CreateArtifactResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CreateArtifactResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateArtifactResponse) ProtoMessage() {}
+
+func (x *CreateArtifactResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateArtifactResponse.ProtoReflect.Descriptor instead.
+func (*CreateArtifactResponse) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateArtifactResponse) GetOk() bool {
+ if x != nil {
+ return x.Ok
+ }
+ return false
+}
+
+func (x *CreateArtifactResponse) GetSignedUploadUrl() string {
+ if x != nil {
+ return x.SignedUploadUrl
+ }
+ return ""
+}
+
+type FinalizeArtifactRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WorkflowRunBackendId string `protobuf:"bytes,1,opt,name=workflow_run_backend_id,json=workflowRunBackendId,proto3" json:"workflow_run_backend_id,omitempty"`
+ WorkflowJobRunBackendId string `protobuf:"bytes,2,opt,name=workflow_job_run_backend_id,json=workflowJobRunBackendId,proto3" json:"workflow_job_run_backend_id,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+ Size int64 `protobuf:"varint,4,opt,name=size,proto3" json:"size,omitempty"`
+ Hash *wrapperspb.StringValue `protobuf:"bytes,5,opt,name=hash,proto3" json:"hash,omitempty"`
+}
+
+func (x *FinalizeArtifactRequest) Reset() {
+ *x = FinalizeArtifactRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FinalizeArtifactRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FinalizeArtifactRequest) ProtoMessage() {}
+
+func (x *FinalizeArtifactRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FinalizeArtifactRequest.ProtoReflect.Descriptor instead.
+func (*FinalizeArtifactRequest) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *FinalizeArtifactRequest) GetWorkflowRunBackendId() string {
+ if x != nil {
+ return x.WorkflowRunBackendId
+ }
+ return ""
+}
+
+func (x *FinalizeArtifactRequest) GetWorkflowJobRunBackendId() string {
+ if x != nil {
+ return x.WorkflowJobRunBackendId
+ }
+ return ""
+}
+
+func (x *FinalizeArtifactRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *FinalizeArtifactRequest) GetSize() int64 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+func (x *FinalizeArtifactRequest) GetHash() *wrapperspb.StringValue {
+ if x != nil {
+ return x.Hash
+ }
+ return nil
+}
+
+type FinalizeArtifactResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
+ ArtifactId int64 `protobuf:"varint,2,opt,name=artifact_id,json=artifactId,proto3" json:"artifact_id,omitempty"`
+}
+
+func (x *FinalizeArtifactResponse) Reset() {
+ *x = FinalizeArtifactResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FinalizeArtifactResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FinalizeArtifactResponse) ProtoMessage() {}
+
+func (x *FinalizeArtifactResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FinalizeArtifactResponse.ProtoReflect.Descriptor instead.
+func (*FinalizeArtifactResponse) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *FinalizeArtifactResponse) GetOk() bool {
+ if x != nil {
+ return x.Ok
+ }
+ return false
+}
+
+func (x *FinalizeArtifactResponse) GetArtifactId() int64 {
+ if x != nil {
+ return x.ArtifactId
+ }
+ return 0
+}
+
+type ListArtifactsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WorkflowRunBackendId string `protobuf:"bytes,1,opt,name=workflow_run_backend_id,json=workflowRunBackendId,proto3" json:"workflow_run_backend_id,omitempty"`
+ WorkflowJobRunBackendId string `protobuf:"bytes,2,opt,name=workflow_job_run_backend_id,json=workflowJobRunBackendId,proto3" json:"workflow_job_run_backend_id,omitempty"`
+ NameFilter *wrapperspb.StringValue `protobuf:"bytes,3,opt,name=name_filter,json=nameFilter,proto3" json:"name_filter,omitempty"`
+ IdFilter *wrapperspb.Int64Value `protobuf:"bytes,4,opt,name=id_filter,json=idFilter,proto3" json:"id_filter,omitempty"`
+}
+
+func (x *ListArtifactsRequest) Reset() {
+ *x = ListArtifactsRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListArtifactsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListArtifactsRequest) ProtoMessage() {}
+
+func (x *ListArtifactsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListArtifactsRequest.ProtoReflect.Descriptor instead.
+func (*ListArtifactsRequest) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ListArtifactsRequest) GetWorkflowRunBackendId() string {
+ if x != nil {
+ return x.WorkflowRunBackendId
+ }
+ return ""
+}
+
+func (x *ListArtifactsRequest) GetWorkflowJobRunBackendId() string {
+ if x != nil {
+ return x.WorkflowJobRunBackendId
+ }
+ return ""
+}
+
+func (x *ListArtifactsRequest) GetNameFilter() *wrapperspb.StringValue {
+ if x != nil {
+ return x.NameFilter
+ }
+ return nil
+}
+
+func (x *ListArtifactsRequest) GetIdFilter() *wrapperspb.Int64Value {
+ if x != nil {
+ return x.IdFilter
+ }
+ return nil
+}
+
+type ListArtifactsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Artifacts []*ListArtifactsResponse_MonolithArtifact `protobuf:"bytes,1,rep,name=artifacts,proto3" json:"artifacts,omitempty"`
+}
+
+func (x *ListArtifactsResponse) Reset() {
+ *x = ListArtifactsResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListArtifactsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListArtifactsResponse) ProtoMessage() {}
+
+func (x *ListArtifactsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListArtifactsResponse.ProtoReflect.Descriptor instead.
+func (*ListArtifactsResponse) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ListArtifactsResponse) GetArtifacts() []*ListArtifactsResponse_MonolithArtifact {
+ if x != nil {
+ return x.Artifacts
+ }
+ return nil
+}
+
+type ListArtifactsResponse_MonolithArtifact struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WorkflowRunBackendId string `protobuf:"bytes,1,opt,name=workflow_run_backend_id,json=workflowRunBackendId,proto3" json:"workflow_run_backend_id,omitempty"`
+ WorkflowJobRunBackendId string `protobuf:"bytes,2,opt,name=workflow_job_run_backend_id,json=workflowJobRunBackendId,proto3" json:"workflow_job_run_backend_id,omitempty"`
+ DatabaseId int64 `protobuf:"varint,3,opt,name=database_id,json=databaseId,proto3" json:"database_id,omitempty"`
+ Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
+ Size int64 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"`
+ CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) Reset() {
+ *x = ListArtifactsResponse_MonolithArtifact{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListArtifactsResponse_MonolithArtifact) ProtoMessage() {}
+
+func (x *ListArtifactsResponse_MonolithArtifact) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListArtifactsResponse_MonolithArtifact.ProtoReflect.Descriptor instead.
+func (*ListArtifactsResponse_MonolithArtifact) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) GetWorkflowRunBackendId() string {
+ if x != nil {
+ return x.WorkflowRunBackendId
+ }
+ return ""
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) GetWorkflowJobRunBackendId() string {
+ if x != nil {
+ return x.WorkflowJobRunBackendId
+ }
+ return ""
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) GetDatabaseId() int64 {
+ if x != nil {
+ return x.DatabaseId
+ }
+ return 0
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) GetSize() int64 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+func (x *ListArtifactsResponse_MonolithArtifact) GetCreatedAt() *timestamppb.Timestamp {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return nil
+}
+
+type GetSignedArtifactURLRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WorkflowRunBackendId string `protobuf:"bytes,1,opt,name=workflow_run_backend_id,json=workflowRunBackendId,proto3" json:"workflow_run_backend_id,omitempty"`
+ WorkflowJobRunBackendId string `protobuf:"bytes,2,opt,name=workflow_job_run_backend_id,json=workflowJobRunBackendId,proto3" json:"workflow_job_run_backend_id,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *GetSignedArtifactURLRequest) Reset() {
+ *x = GetSignedArtifactURLRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetSignedArtifactURLRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetSignedArtifactURLRequest) ProtoMessage() {}
+
+func (x *GetSignedArtifactURLRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetSignedArtifactURLRequest.ProtoReflect.Descriptor instead.
+func (*GetSignedArtifactURLRequest) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *GetSignedArtifactURLRequest) GetWorkflowRunBackendId() string {
+ if x != nil {
+ return x.WorkflowRunBackendId
+ }
+ return ""
+}
+
+func (x *GetSignedArtifactURLRequest) GetWorkflowJobRunBackendId() string {
+ if x != nil {
+ return x.WorkflowJobRunBackendId
+ }
+ return ""
+}
+
+func (x *GetSignedArtifactURLRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+type GetSignedArtifactURLResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SignedUrl string `protobuf:"bytes,1,opt,name=signed_url,json=signedUrl,proto3" json:"signed_url,omitempty"`
+}
+
+func (x *GetSignedArtifactURLResponse) Reset() {
+ *x = GetSignedArtifactURLResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetSignedArtifactURLResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetSignedArtifactURLResponse) ProtoMessage() {}
+
+func (x *GetSignedArtifactURLResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetSignedArtifactURLResponse.ProtoReflect.Descriptor instead.
+func (*GetSignedArtifactURLResponse) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *GetSignedArtifactURLResponse) GetSignedUrl() string {
+ if x != nil {
+ return x.SignedUrl
+ }
+ return ""
+}
+
+type DeleteArtifactRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WorkflowRunBackendId string `protobuf:"bytes,1,opt,name=workflow_run_backend_id,json=workflowRunBackendId,proto3" json:"workflow_run_backend_id,omitempty"`
+ WorkflowJobRunBackendId string `protobuf:"bytes,2,opt,name=workflow_job_run_backend_id,json=workflowJobRunBackendId,proto3" json:"workflow_job_run_backend_id,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *DeleteArtifactRequest) Reset() {
+ *x = DeleteArtifactRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *DeleteArtifactRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteArtifactRequest) ProtoMessage() {}
+
+func (x *DeleteArtifactRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteArtifactRequest.ProtoReflect.Descriptor instead.
+func (*DeleteArtifactRequest) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *DeleteArtifactRequest) GetWorkflowRunBackendId() string {
+ if x != nil {
+ return x.WorkflowRunBackendId
+ }
+ return ""
+}
+
+func (x *DeleteArtifactRequest) GetWorkflowJobRunBackendId() string {
+ if x != nil {
+ return x.WorkflowJobRunBackendId
+ }
+ return ""
+}
+
+func (x *DeleteArtifactRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+type DeleteArtifactResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
+ ArtifactId int64 `protobuf:"varint,2,opt,name=artifact_id,json=artifactId,proto3" json:"artifact_id,omitempty"`
+}
+
+func (x *DeleteArtifactResponse) Reset() {
+ *x = DeleteArtifactResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_artifact_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *DeleteArtifactResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteArtifactResponse) ProtoMessage() {}
+
+func (x *DeleteArtifactResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_artifact_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteArtifactResponse.ProtoReflect.Descriptor instead.
+func (*DeleteArtifactResponse) Descriptor() ([]byte, []int) {
+ return file_artifact_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *DeleteArtifactResponse) GetOk() bool {
+ if x != nil {
+ return x.Ok
+ }
+ return false
+}
+
+func (x *DeleteArtifactResponse) GetArtifactId() int64 {
+ if x != nil {
+ return x.ArtifactId
+ }
+ return 0
+}
+
+var File_artifact_proto protoreflect.FileDescriptor
+
+var file_artifact_proto_rawDesc = []byte{
+ 0x0a, 0x0e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x12, 0x1d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x1a,
+ 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x22, 0xf5, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66,
+ 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x77, 0x6f,
+ 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65,
+ 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72,
+ 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49,
+ 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6a, 0x6f,
+ 0x62, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
+ 0x4a, 0x6f, 0x62, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61,
+ 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
+ 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x18,
+ 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x54, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02,
+ 0x6f, 0x6b, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x6c,
+ 0x6f, 0x61, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73,
+ 0x69, 0x67, 0x6e, 0x65, 0x64, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x22, 0xe8,
+ 0x01, 0x0a, 0x17, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66,
+ 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x77, 0x6f,
+ 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65,
+ 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72,
+ 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49,
+ 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6a, 0x6f,
+ 0x62, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
+ 0x4a, 0x6f, 0x62, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4b, 0x0a, 0x18, 0x46, 0x69, 0x6e,
+ 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+ 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69,
+ 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x22, 0x84, 0x02, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x41,
+ 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x35, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f,
+ 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63,
+ 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
+ 0x6f, 0x77, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65,
+ 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x6f, 0x72,
+ 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f, 0x62, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65,
+ 0x6e, 0x64, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6c,
+ 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69,
+ 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c,
+ 0x74, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x52, 0x08, 0x69, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x7c, 0x0a,
+ 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61,
+ 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x67, 0x69, 0x74, 0x68,
+ 0x75, 0x62, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6c,
+ 0x74, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72,
+ 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x6f, 0x6c, 0x69, 0x74, 0x68, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+ 0x52, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xa1, 0x02, 0x0a, 0x26,
+ 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x6f, 0x6c, 0x69, 0x74, 0x68, 0x41, 0x72,
+ 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
+ 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
+ 0x77, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x3c, 0x0a,
+ 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x72, 0x75,
+ 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f, 0x62, 0x52,
+ 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x64,
+ 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04,
+ 0x73, 0x69, 0x7a, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
+ 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22,
+ 0xa6, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x72, 0x74,
+ 0x69, 0x66, 0x61, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x35, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f,
+ 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63,
+ 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
+ 0x6f, 0x77, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65,
+ 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x6f, 0x72,
+ 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f, 0x62, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x65,
+ 0x6e, 0x64, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53,
+ 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x55, 0x52, 0x4c,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e,
+ 0x65, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69,
+ 0x67, 0x6e, 0x65, 0x64, 0x55, 0x72, 0x6c, 0x22, 0xa0, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65,
+ 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x35, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75,
+ 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x42,
+ 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b,
+ 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x62, 0x61, 0x63,
+ 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77,
+ 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f, 0x62, 0x52, 0x75, 0x6e, 0x42, 0x61, 0x63,
+ 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x16, 0x44, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+ 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66,
+ 0x61, 0x63, 0x74, 0x49, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_artifact_proto_rawDescOnce sync.Once
+ file_artifact_proto_rawDescData = file_artifact_proto_rawDesc
+)
+
+func file_artifact_proto_rawDescGZIP() []byte {
+ file_artifact_proto_rawDescOnce.Do(func() {
+ file_artifact_proto_rawDescData = protoimpl.X.CompressGZIP(file_artifact_proto_rawDescData)
+ })
+ return file_artifact_proto_rawDescData
+}
+
+var (
+ file_artifact_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
+ file_artifact_proto_goTypes = []interface{}{
+ (*CreateArtifactRequest)(nil), // 0: github.actions.results.api.v1.CreateArtifactRequest
+ (*CreateArtifactResponse)(nil), // 1: github.actions.results.api.v1.CreateArtifactResponse
+ (*FinalizeArtifactRequest)(nil), // 2: github.actions.results.api.v1.FinalizeArtifactRequest
+ (*FinalizeArtifactResponse)(nil), // 3: github.actions.results.api.v1.FinalizeArtifactResponse
+ (*ListArtifactsRequest)(nil), // 4: github.actions.results.api.v1.ListArtifactsRequest
+ (*ListArtifactsResponse)(nil), // 5: github.actions.results.api.v1.ListArtifactsResponse
+ (*ListArtifactsResponse_MonolithArtifact)(nil), // 6: github.actions.results.api.v1.ListArtifactsResponse_MonolithArtifact
+ (*GetSignedArtifactURLRequest)(nil), // 7: github.actions.results.api.v1.GetSignedArtifactURLRequest
+ (*GetSignedArtifactURLResponse)(nil), // 8: github.actions.results.api.v1.GetSignedArtifactURLResponse
+ (*DeleteArtifactRequest)(nil), // 9: github.actions.results.api.v1.DeleteArtifactRequest
+ (*DeleteArtifactResponse)(nil), // 10: github.actions.results.api.v1.DeleteArtifactResponse
+ (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
+ (*wrapperspb.StringValue)(nil), // 12: google.protobuf.StringValue
+ (*wrapperspb.Int64Value)(nil), // 13: google.protobuf.Int64Value
+ }
+)
+
+var file_artifact_proto_depIdxs = []int32{
+ 11, // 0: github.actions.results.api.v1.CreateArtifactRequest.expires_at:type_name -> google.protobuf.Timestamp
+ 12, // 1: github.actions.results.api.v1.FinalizeArtifactRequest.hash:type_name -> google.protobuf.StringValue
+ 12, // 2: github.actions.results.api.v1.ListArtifactsRequest.name_filter:type_name -> google.protobuf.StringValue
+ 13, // 3: github.actions.results.api.v1.ListArtifactsRequest.id_filter:type_name -> google.protobuf.Int64Value
+ 6, // 4: github.actions.results.api.v1.ListArtifactsResponse.artifacts:type_name -> github.actions.results.api.v1.ListArtifactsResponse_MonolithArtifact
+ 11, // 5: github.actions.results.api.v1.ListArtifactsResponse_MonolithArtifact.created_at:type_name -> google.protobuf.Timestamp
+ 6, // [6:6] is the sub-list for method output_type
+ 6, // [6:6] is the sub-list for method input_type
+ 6, // [6:6] is the sub-list for extension type_name
+ 6, // [6:6] is the sub-list for extension extendee
+ 0, // [0:6] is the sub-list for field type_name
+}
+
+func init() { file_artifact_proto_init() }
+func file_artifact_proto_init() {
+ if File_artifact_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_artifact_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CreateArtifactRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CreateArtifactResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FinalizeArtifactRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FinalizeArtifactResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListArtifactsRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListArtifactsResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ListArtifactsResponse_MonolithArtifact); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetSignedArtifactURLRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetSignedArtifactURLResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DeleteArtifactRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_artifact_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DeleteArtifactResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_artifact_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 11,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_artifact_proto_goTypes,
+ DependencyIndexes: file_artifact_proto_depIdxs,
+ MessageInfos: file_artifact_proto_msgTypes,
+ }.Build()
+ File_artifact_proto = out.File
+ file_artifact_proto_rawDesc = nil
+ file_artifact_proto_goTypes = nil
+ file_artifact_proto_depIdxs = nil
+}
diff --git a/routers/api/actions/artifact.proto b/routers/api/actions/artifact.proto
new file mode 100644
index 0000000000..c68e5d030d
--- /dev/null
+++ b/routers/api/actions/artifact.proto
@@ -0,0 +1,73 @@
+syntax = "proto3";
+
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+
+package github.actions.results.api.v1;
+
+message CreateArtifactRequest {
+ string workflow_run_backend_id = 1;
+ string workflow_job_run_backend_id = 2;
+ string name = 3;
+ google.protobuf.Timestamp expires_at = 4;
+ int32 version = 5;
+}
+
+message CreateArtifactResponse {
+ bool ok = 1;
+ string signed_upload_url = 2;
+}
+
+message FinalizeArtifactRequest {
+ string workflow_run_backend_id = 1;
+ string workflow_job_run_backend_id = 2;
+ string name = 3;
+ int64 size = 4;
+ google.protobuf.StringValue hash = 5;
+}
+
+message FinalizeArtifactResponse {
+ bool ok = 1;
+ int64 artifact_id = 2;
+}
+
+message ListArtifactsRequest {
+ string workflow_run_backend_id = 1;
+ string workflow_job_run_backend_id = 2;
+ google.protobuf.StringValue name_filter = 3;
+ google.protobuf.Int64Value id_filter = 4;
+}
+
+message ListArtifactsResponse {
+ repeated ListArtifactsResponse_MonolithArtifact artifacts = 1;
+}
+
+message ListArtifactsResponse_MonolithArtifact {
+ string workflow_run_backend_id = 1;
+ string workflow_job_run_backend_id = 2;
+ int64 database_id = 3;
+ string name = 4;
+ int64 size = 5;
+ google.protobuf.Timestamp created_at = 6;
+}
+
+message GetSignedArtifactURLRequest {
+ string workflow_run_backend_id = 1;
+ string workflow_job_run_backend_id = 2;
+ string name = 3;
+}
+
+message GetSignedArtifactURLResponse {
+ string signed_url = 1;
+}
+
+message DeleteArtifactRequest {
+ string workflow_run_backend_id = 1;
+ string workflow_job_run_backend_id = 2;
+ string name = 3;
+}
+
+message DeleteArtifactResponse {
+ bool ok = 1;
+ int64 artifact_id = 2;
+}
diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go
index 9fbd3f045d..d530e9cee5 100644
--- a/routers/api/actions/artifacts.go
+++ b/routers/api/actions/artifacts.go
@@ -71,7 +71,6 @@ import (
"code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -80,6 +79,7 @@ import (
"code.gitea.io/gitea/modules/web"
web_types "code.gitea.io/gitea/modules/web/types"
actions_service "code.gitea.io/gitea/services/actions"
+ "code.gitea.io/gitea/services/context"
)
const artifactRouteBase = "/_apis/pipelines/workflows/{run_id}/artifacts"
diff --git a/routers/api/actions/artifacts_chunks.go b/routers/api/actions/artifacts_chunks.go
index 0713c8bba8..3a81724b3a 100644
--- a/routers/api/actions/artifacts_chunks.go
+++ b/routers/api/actions/artifacts_chunks.go
@@ -5,11 +5,16 @@ package actions
import (
"crypto/md5"
+ "crypto/sha256"
"encoding/base64"
+ "encoding/hex"
+ "errors"
"fmt"
+ "hash"
"io"
"path/filepath"
"sort"
+ "strings"
"time"
"code.gitea.io/gitea/models/actions"
@@ -18,39 +23,45 @@ import (
"code.gitea.io/gitea/modules/storage"
)
-func saveUploadChunk(st storage.ObjectStorage, ctx *ArtifactContext,
+func saveUploadChunkBase(st storage.ObjectStorage, ctx *ArtifactContext,
artifact *actions.ActionArtifact,
- contentSize, runID int64,
+ contentSize, runID, start, end, length int64, checkMd5 bool,
) (int64, error) {
- // parse content-range header, format: bytes 0-1023/146515
- contentRange := ctx.Req.Header.Get("Content-Range")
- start, end, length := int64(0), int64(0), int64(0)
- if _, err := fmt.Sscanf(contentRange, "bytes %d-%d/%d", &start, &end, &length); err != nil {
- log.Warn("parse content range error: %v, content-range: %s", err, contentRange)
- return -1, fmt.Errorf("parse content range error: %v", err)
- }
// build chunk store path
storagePath := fmt.Sprintf("tmp%d/%d-%d-%d-%d.chunk", runID, runID, artifact.ID, start, end)
- // use io.TeeReader to avoid reading all body to md5 sum.
- // it writes data to hasher after reading end
- // if hash is not matched, delete the read-end result
- hasher := md5.New()
- r := io.TeeReader(ctx.Req.Body, hasher)
+ var r io.Reader = ctx.Req.Body
+ var hasher hash.Hash
+ if checkMd5 {
+ // use io.TeeReader to avoid reading all body to md5 sum.
+ // it writes data to hasher after reading end
+ // if hash is not matched, delete the read-end result
+ hasher = md5.New()
+ r = io.TeeReader(r, hasher)
+ }
// save chunk to storage
writtenSize, err := st.Save(storagePath, r, -1)
if err != nil {
return -1, fmt.Errorf("save chunk to storage error: %v", err)
}
- // check md5
- reqMd5String := ctx.Req.Header.Get(artifactXActionsResultsMD5Header)
- chunkMd5String := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
- log.Info("[artifact] check chunk md5, sum: %s, header: %s", chunkMd5String, reqMd5String)
- // if md5 not match, delete the chunk
- if reqMd5String != chunkMd5String || writtenSize != contentSize {
+ var checkErr error
+ if checkMd5 {
+ // check md5
+ reqMd5String := ctx.Req.Header.Get(artifactXActionsResultsMD5Header)
+ chunkMd5String := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
+ log.Info("[artifact] check chunk md5, sum: %s, header: %s", chunkMd5String, reqMd5String)
+ // if md5 not match, delete the chunk
+ if reqMd5String != chunkMd5String {
+ checkErr = fmt.Errorf("md5 not match")
+ }
+ }
+ if writtenSize != contentSize {
+ checkErr = errors.Join(checkErr, fmt.Errorf("contentSize not match body size"))
+ }
+ if checkErr != nil {
if err := st.Delete(storagePath); err != nil {
log.Error("Error deleting chunk: %s, %v", storagePath, err)
}
- return -1, fmt.Errorf("md5 not match")
+ return -1, checkErr
}
log.Info("[artifact] save chunk %s, size: %d, artifact id: %d, start: %d, end: %d",
storagePath, contentSize, artifact.ID, start, end)
@@ -58,6 +69,28 @@ func saveUploadChunk(st storage.ObjectStorage, ctx *ArtifactContext,
return length, nil
}
+func saveUploadChunk(st storage.ObjectStorage, ctx *ArtifactContext,
+ artifact *actions.ActionArtifact,
+ contentSize, runID int64,
+) (int64, error) {
+ // parse content-range header, format: bytes 0-1023/146515
+ contentRange := ctx.Req.Header.Get("Content-Range")
+ start, end, length := int64(0), int64(0), int64(0)
+ if _, err := fmt.Sscanf(contentRange, "bytes %d-%d/%d", &start, &end, &length); err != nil {
+ log.Warn("parse content range error: %v, content-range: %s", err, contentRange)
+ return -1, fmt.Errorf("parse content range error: %v", err)
+ }
+ return saveUploadChunkBase(st, ctx, artifact, contentSize, runID, start, end, length, true)
+}
+
+func appendUploadChunk(st storage.ObjectStorage, ctx *ArtifactContext,
+ artifact *actions.ActionArtifact,
+ start, contentSize, runID int64,
+) (int64, error) {
+ end := start + contentSize - 1
+ return saveUploadChunkBase(st, ctx, artifact, contentSize, runID, start, end, contentSize, false)
+}
+
type chunkFileItem struct {
RunID int64
ArtifactID int64
@@ -111,14 +144,14 @@ func mergeChunksForRun(ctx *ArtifactContext, st storage.ObjectStorage, runID int
log.Debug("artifact %d chunks not found", art.ID)
continue
}
- if err := mergeChunksForArtifact(ctx, chunks, st, art); err != nil {
+ if err := mergeChunksForArtifact(ctx, chunks, st, art, ""); err != nil {
return err
}
}
return nil
}
-func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st storage.ObjectStorage, artifact *actions.ActionArtifact) error {
+func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st storage.ObjectStorage, artifact *actions.ActionArtifact, checksum string) error {
sort.Slice(chunks, func(i, j int) bool {
return chunks[i].Start < chunks[j].Start
})
@@ -157,6 +190,14 @@ func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st st
readers = append(readers, readCloser)
}
mergedReader := io.MultiReader(readers...)
+ shaPrefix := "sha256:"
+ var hash hash.Hash
+ if strings.HasPrefix(checksum, shaPrefix) {
+ hash = sha256.New()
+ }
+ if hash != nil {
+ mergedReader = io.TeeReader(mergedReader, hash)
+ }
// if chunk is gzip, use gz as extension
// download-artifact action will use content-encoding header to decide if it should decompress the file
@@ -185,6 +226,14 @@ func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st st
}
}()
+ if hash != nil {
+ rawChecksum := hash.Sum(nil)
+ actualChecksum := hex.EncodeToString(rawChecksum)
+ if !strings.HasSuffix(checksum, actualChecksum) {
+ return fmt.Errorf("update artifact error checksum is invalid")
+ }
+ }
+
// save storage path to artifact
log.Debug("[artifact] merge chunks to artifact: %d, %s, old:%s", artifact.ID, storagePath, artifact.StoragePath)
// if artifact is already uploaded, delete the old file
diff --git a/routers/api/actions/artifacts_utils.go b/routers/api/actions/artifacts_utils.go
index 381e7eb16e..aaf89ef40e 100644
--- a/routers/api/actions/artifacts_utils.go
+++ b/routers/api/actions/artifacts_utils.go
@@ -43,6 +43,17 @@ func validateRunID(ctx *ArtifactContext) (*actions.ActionTask, int64, bool) {
return task, runID, true
}
+func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (*actions.ActionTask, int64, bool) {
+ task := ctx.ActionTask
+ runID, err := strconv.ParseInt(rawRunID, 10, 64)
+ if err != nil || task.Job.RunID != runID {
+ log.Error("Error runID not match")
+ ctx.Error(http.StatusBadRequest, "run-id does not match")
+ return nil, 0, false
+ }
+ return task, runID, true
+}
+
func validateArtifactHash(ctx *ArtifactContext, artifactName string) bool {
paramHash := ctx.Params("artifact_hash")
// use artifact name to create upload url
diff --git a/routers/api/actions/artifactsv4.go b/routers/api/actions/artifactsv4.go
new file mode 100644
index 0000000000..8300989c75
--- /dev/null
+++ b/routers/api/actions/artifactsv4.go
@@ -0,0 +1,512 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package actions
+
+// GitHub Actions Artifacts V4 API Simple Description
+//
+// 1. Upload artifact
+// 1.1. CreateArtifact
+// Post: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact
+// Request:
+// {
+// "workflow_run_backend_id": "21",
+// "workflow_job_run_backend_id": "49",
+// "name": "test",
+// "version": 4
+// }
+// Response:
+// {
+// "ok": true,
+// "signedUploadUrl": "http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75"
+// }
+// 1.2. Upload Zip Content to Blobstorage (unauthenticated request)
+// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=block
+// 1.3. Continue Upload Zip Content to Blobstorage (unauthenticated request), repeat until everything is uploaded
+// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=appendBlock
+// 1.4. Unknown xml payload to Blobstorage (unauthenticated request), ignored for now
+// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=blockList
+// 1.5. FinalizeArtifact
+// Post: /twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact
+// Request
+// {
+// "workflow_run_backend_id": "21",
+// "workflow_job_run_backend_id": "49",
+// "name": "test",
+// "size": "2097",
+// "hash": "sha256:b6325614d5649338b87215d9536b3c0477729b8638994c74cdefacb020a2cad4"
+// }
+// Response
+// {
+// "ok": true,
+// "artifactId": "4"
+// }
+// 2. Download artifact
+// 2.1. ListArtifacts and optionally filter by artifact exact name or id
+// Post: /twirp/github.actions.results.api.v1.ArtifactService/ListArtifacts
+// Request
+// {
+// "workflow_run_backend_id": "21",
+// "workflow_job_run_backend_id": "49",
+// "name_filter": "test"
+// }
+// Response
+// {
+// "artifacts": [
+// {
+// "workflowRunBackendId": "21",
+// "workflowJobRunBackendId": "49",
+// "databaseId": "4",
+// "name": "test",
+// "size": "2093",
+// "createdAt": "2024-01-23T00:13:28Z"
+// }
+// ]
+// }
+// 2.2. GetSignedArtifactURL get the URL to download the artifact zip file of a specific artifact
+// Post: /twirp/github.actions.results.api.v1.ArtifactService/GetSignedArtifactURL
+// Request
+// {
+// "workflow_run_backend_id": "21",
+// "workflow_job_run_backend_id": "49",
+// "name": "test"
+// }
+// Response
+// {
+// "signedUrl": "http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/DownloadArtifact?sig=wHzFOwpF-6220-5CA0CIRmAX9VbiTC2Mji89UOqo1E8=&expires=2024-01-23+21%3A51%3A56.872846295+%2B0100+CET&artifactName=test&taskID=76"
+// }
+// 2.3. Download Zip from Blobstorage (unauthenticated request)
+// GET: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/DownloadArtifact?sig=wHzFOwpF-6220-5CA0CIRmAX9VbiTC2Mji89UOqo1E8=&expires=2024-01-23+21%3A51%3A56.872846295+%2B0100+CET&artifactName=test&taskID=76
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/storage"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
+
+ "google.golang.org/protobuf/encoding/protojson"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+const (
+ ArtifactV4RouteBase = "/twirp/github.actions.results.api.v1.ArtifactService"
+ ArtifactV4ContentEncoding = "application/zip"
+)
+
+type artifactV4Routes struct {
+ prefix string
+ fs storage.ObjectStorage
+}
+
+func ArtifactV4Contexter() func(next http.Handler) http.Handler {
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ base, baseCleanUp := context.NewBaseContext(resp, req)
+ defer baseCleanUp()
+
+ ctx := &ArtifactContext{Base: base}
+ ctx.AppendContextValue(artifactContextKey, ctx)
+
+ next.ServeHTTP(ctx.Resp, ctx.Req)
+ })
+ }
+}
+
+func ArtifactsV4Routes(prefix string) *web.Route {
+ m := web.NewRoute()
+
+ r := artifactV4Routes{
+ prefix: prefix,
+ fs: storage.ActionsArtifacts,
+ }
+
+ m.Group("", func() {
+ m.Post("CreateArtifact", r.createArtifact)
+ m.Post("FinalizeArtifact", r.finalizeArtifact)
+ m.Post("ListArtifacts", r.listArtifacts)
+ m.Post("GetSignedArtifactURL", r.getSignedArtifactURL)
+ m.Post("DeleteArtifact", r.deleteArtifact)
+ }, ArtifactContexter())
+ m.Group("", func() {
+ m.Put("UploadArtifact", r.uploadArtifact)
+ m.Get("DownloadArtifact", r.downloadArtifact)
+ }, ArtifactV4Contexter())
+
+ return m
+}
+
+func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, taskID int64) []byte {
+ mac := hmac.New(sha256.New, setting.GetGeneralTokenSigningSecret())
+ mac.Write([]byte(endp))
+ mac.Write([]byte(expires))
+ mac.Write([]byte(artifactName))
+ mac.Write([]byte(fmt.Sprint(taskID)))
+ return mac.Sum(nil)
+}
+
+func (r artifactV4Routes) buildArtifactURL(endp, artifactName string, taskID int64) string {
+ expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST")
+ uploadURL := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(r.prefix, "/") +
+ "/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID)
+ return uploadURL
+}
+
+func (r artifactV4Routes) verifySignature(ctx *ArtifactContext, endp string) (*actions.ActionTask, string, bool) {
+ rawTaskID := ctx.Req.URL.Query().Get("taskID")
+ sig := ctx.Req.URL.Query().Get("sig")
+ expires := ctx.Req.URL.Query().Get("expires")
+ artifactName := ctx.Req.URL.Query().Get("artifactName")
+ dsig, _ := base64.URLEncoding.DecodeString(sig)
+ taskID, _ := strconv.ParseInt(rawTaskID, 10, 64)
+
+ expecedsig := r.buildSignature(endp, expires, artifactName, taskID)
+ if !hmac.Equal(dsig, expecedsig) {
+ log.Error("Error unauthorized")
+ ctx.Error(http.StatusUnauthorized, "Error unauthorized")
+ return nil, "", false
+ }
+ t, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", expires)
+ if err != nil || t.Before(time.Now()) {
+ log.Error("Error link expired")
+ ctx.Error(http.StatusUnauthorized, "Error link expired")
+ return nil, "", false
+ }
+ task, err := actions.GetTaskByID(ctx, taskID)
+ if err != nil {
+ log.Error("Error runner api getting task by ID: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error runner api getting task by ID")
+ return nil, "", false
+ }
+ if task.Status != actions.StatusRunning {
+ log.Error("Error runner api getting task: task is not running")
+ ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
+ return nil, "", false
+ }
+ if err := task.LoadJob(ctx); err != nil {
+ log.Error("Error runner api getting job: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error runner api getting job")
+ return nil, "", false
+ }
+ return task, artifactName, true
+}
+
+func (r *artifactV4Routes) getArtifactByName(ctx *ArtifactContext, runID int64, name string) (*actions.ActionArtifact, error) {
+ var art actions.ActionArtifact
+ has, err := db.GetEngine(ctx).Where("run_id = ? AND artifact_name = ? AND artifact_path = ? AND content_encoding = ?", runID, name, name+".zip", ArtifactV4ContentEncoding).Get(&art)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, util.ErrNotExist
+ }
+ return &art, nil
+}
+
+func (r *artifactV4Routes) parseProtbufBody(ctx *ArtifactContext, req protoreflect.ProtoMessage) bool {
+ body, err := io.ReadAll(ctx.Req.Body)
+ if err != nil {
+ log.Error("Error decode request body: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error decode request body")
+ return false
+ }
+ err = protojson.Unmarshal(body, req)
+ if err != nil {
+ log.Error("Error decode request body: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error decode request body")
+ return false
+ }
+ return true
+}
+
+func (r *artifactV4Routes) sendProtbufBody(ctx *ArtifactContext, req protoreflect.ProtoMessage) {
+ resp, err := protojson.Marshal(req)
+ if err != nil {
+ log.Error("Error encode response body: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error encode response body")
+ return
+ }
+ ctx.Resp.Header().Set("Content-Type", "application/json;charset=utf-8")
+ ctx.Resp.WriteHeader(http.StatusOK)
+ _, _ = ctx.Resp.Write(resp)
+}
+
+func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
+ var req CreateArtifactRequest
+
+ if ok := r.parseProtbufBody(ctx, &req); !ok {
+ return
+ }
+ _, _, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
+ if !ok {
+ return
+ }
+
+ artifactName := req.Name
+
+ rententionDays := setting.Actions.ArtifactRetentionDays
+ if req.ExpiresAt != nil {
+ rententionDays = int64(time.Until(req.ExpiresAt.AsTime()).Hours() / 24)
+ }
+ // create or get artifact with name and path
+ artifact, err := actions.CreateArtifact(ctx, ctx.ActionTask, artifactName, artifactName+".zip", rententionDays)
+ if err != nil {
+ log.Error("Error create or get artifact: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error create or get artifact")
+ return
+ }
+ artifact.ContentEncoding = ArtifactV4ContentEncoding
+ if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
+ log.Error("Error UpdateArtifactByID: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
+ return
+ }
+
+ respData := CreateArtifactResponse{
+ Ok: true,
+ SignedUploadUrl: r.buildArtifactURL("UploadArtifact", artifactName, ctx.ActionTask.ID),
+ }
+ r.sendProtbufBody(ctx, &respData)
+}
+
+func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
+ task, artifactName, ok := r.verifySignature(ctx, "UploadArtifact")
+ if !ok {
+ return
+ }
+
+ comp := ctx.Req.URL.Query().Get("comp")
+ switch comp {
+ case "block", "appendBlock":
+ // get artifact by name
+ artifact, err := r.getArtifactByName(ctx, task.Job.RunID, artifactName)
+ if err != nil {
+ log.Error("Error artifact not found: %v", err)
+ ctx.Error(http.StatusNotFound, "Error artifact not found")
+ return
+ }
+
+ if comp == "block" {
+ artifact.FileSize = 0
+ artifact.FileCompressedSize = 0
+ }
+
+ _, err = appendUploadChunk(r.fs, ctx, artifact, artifact.FileSize, ctx.Req.ContentLength, artifact.RunID)
+ if err != nil {
+ log.Error("Error runner api getting task: task is not running")
+ ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
+ return
+ }
+ artifact.FileCompressedSize += ctx.Req.ContentLength
+ artifact.FileSize += ctx.Req.ContentLength
+ if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
+ log.Error("Error UpdateArtifactByID: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
+ return
+ }
+ ctx.JSON(http.StatusCreated, "appended")
+ case "blocklist":
+ ctx.JSON(http.StatusCreated, "created")
+ }
+}
+
+func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
+ var req FinalizeArtifactRequest
+
+ if ok := r.parseProtbufBody(ctx, &req); !ok {
+ return
+ }
+ _, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
+ if !ok {
+ return
+ }
+
+ // get artifact by name
+ artifact, err := r.getArtifactByName(ctx, runID, req.Name)
+ if err != nil {
+ log.Error("Error artifact not found: %v", err)
+ ctx.Error(http.StatusNotFound, "Error artifact not found")
+ return
+ }
+ chunkMap, err := listChunksByRunID(r.fs, runID)
+ if err != nil {
+ log.Error("Error merge chunks: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error merge chunks")
+ return
+ }
+ chunks, ok := chunkMap[artifact.ID]
+ if !ok {
+ log.Error("Error merge chunks")
+ ctx.Error(http.StatusInternalServerError, "Error merge chunks")
+ return
+ }
+ checksum := ""
+ if req.Hash != nil {
+ checksum = req.Hash.Value
+ }
+ if err := mergeChunksForArtifact(ctx, chunks, r.fs, artifact, checksum); err != nil {
+ log.Error("Error merge chunks: %v", err)
+ ctx.Error(http.StatusInternalServerError, "Error merge chunks")
+ return
+ }
+
+ respData := FinalizeArtifactResponse{
+ Ok: true,
+ ArtifactId: artifact.ID,
+ }
+ r.sendProtbufBody(ctx, &respData)
+}
+
+func (r *artifactV4Routes) listArtifacts(ctx *ArtifactContext) {
+ var req ListArtifactsRequest
+
+ if ok := r.parseProtbufBody(ctx, &req); !ok {
+ return
+ }
+ _, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
+ if !ok {
+ return
+ }
+
+ artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID})
+ if err != nil {
+ log.Error("Error getting artifacts: %v", err)
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+ if len(artifacts) == 0 {
+ log.Debug("[artifact] handleListArtifacts, no artifacts")
+ ctx.Error(http.StatusNotFound)
+ return
+ }
+
+ list := []*ListArtifactsResponse_MonolithArtifact{}
+
+ table := map[string]*ListArtifactsResponse_MonolithArtifact{}
+ for _, artifact := range artifacts {
+ if _, ok := table[artifact.ArtifactName]; ok || req.IdFilter != nil && artifact.ID != req.IdFilter.Value || req.NameFilter != nil && artifact.ArtifactName != req.NameFilter.Value || artifact.ArtifactName+".zip" != artifact.ArtifactPath || artifact.ContentEncoding != ArtifactV4ContentEncoding {
+ table[artifact.ArtifactName] = nil
+ continue
+ }
+
+ table[artifact.ArtifactName] = &ListArtifactsResponse_MonolithArtifact{
+ Name: artifact.ArtifactName,
+ CreatedAt: timestamppb.New(artifact.CreatedUnix.AsTime()),
+ DatabaseId: artifact.ID,
+ WorkflowRunBackendId: req.WorkflowRunBackendId,
+ WorkflowJobRunBackendId: req.WorkflowJobRunBackendId,
+ Size: artifact.FileSize,
+ }
+ }
+ for _, artifact := range table {
+ if artifact != nil {
+ list = append(list, artifact)
+ }
+ }
+
+ respData := ListArtifactsResponse{
+ Artifacts: list,
+ }
+ r.sendProtbufBody(ctx, &respData)
+}
+
+func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
+ var req GetSignedArtifactURLRequest
+
+ if ok := r.parseProtbufBody(ctx, &req); !ok {
+ return
+ }
+ _, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
+ if !ok {
+ return
+ }
+
+ artifactName := req.Name
+
+ // get artifact by name
+ artifact, err := r.getArtifactByName(ctx, runID, artifactName)
+ if err != nil {
+ log.Error("Error artifact not found: %v", err)
+ ctx.Error(http.StatusNotFound, "Error artifact not found")
+ return
+ }
+
+ respData := GetSignedArtifactURLResponse{}
+
+ if setting.Actions.ArtifactStorage.MinioConfig.ServeDirect {
+ u, err := storage.ActionsArtifacts.URL(artifact.StoragePath, artifact.ArtifactPath)
+ if u != nil && err == nil {
+ respData.SignedUrl = u.String()
+ }
+ }
+ if respData.SignedUrl == "" {
+ respData.SignedUrl = r.buildArtifactURL("DownloadArtifact", artifactName, ctx.ActionTask.ID)
+ }
+ r.sendProtbufBody(ctx, &respData)
+}
+
+func (r *artifactV4Routes) downloadArtifact(ctx *ArtifactContext) {
+ task, artifactName, ok := r.verifySignature(ctx, "DownloadArtifact")
+ if !ok {
+ return
+ }
+
+ // get artifact by name
+ artifact, err := r.getArtifactByName(ctx, task.Job.RunID, artifactName)
+ if err != nil {
+ log.Error("Error artifact not found: %v", err)
+ ctx.Error(http.StatusNotFound, "Error artifact not found")
+ return
+ }
+
+ file, _ := r.fs.Open(artifact.StoragePath)
+
+ _, _ = io.Copy(ctx.Resp, file)
+}
+
+func (r *artifactV4Routes) deleteArtifact(ctx *ArtifactContext) {
+ var req DeleteArtifactRequest
+
+ if ok := r.parseProtbufBody(ctx, &req); !ok {
+ return
+ }
+ _, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
+ if !ok {
+ return
+ }
+
+ // get artifact by name
+ artifact, err := r.getArtifactByName(ctx, runID, req.Name)
+ if err != nil {
+ log.Error("Error artifact not found: %v", err)
+ ctx.Error(http.StatusNotFound, "Error artifact not found")
+ return
+ }
+
+ err = actions.SetArtifactNeedDelete(ctx, runID, req.Name)
+ if err != nil {
+ log.Error("Error deleting artifacts: %v", err)
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+
+ respData := DeleteArtifactResponse{
+ Ok: true,
+ ArtifactId: artifact.ID,
+ }
+ r.sendProtbufBody(ctx, &respData)
+}
diff --git a/routers/api/packages/alpine/alpine.go b/routers/api/packages/alpine/alpine.go
index 3701fc97c9..cf0fe6c07c 100644
--- a/routers/api/packages/alpine/alpine.go
+++ b/routers/api/packages/alpine/alpine.go
@@ -15,12 +15,12 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
alpine_model "code.gitea.io/gitea/models/packages/alpine"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
packages_module "code.gitea.io/gitea/modules/packages"
alpine_module "code.gitea.io/gitea/modules/packages/alpine"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
alpine_service "code.gitea.io/gitea/services/packages/alpine"
)
diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go
index d990ebb56a..5e3cbac8f9 100644
--- a/routers/api/packages/api.go
+++ b/routers/api/packages/api.go
@@ -10,7 +10,6 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/perm"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
@@ -36,7 +35,7 @@ import (
"code.gitea.io/gitea/routers/api/packages/swift"
"code.gitea.io/gitea/routers/api/packages/vagrant"
"code.gitea.io/gitea/services/auth"
- context_service "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context"
)
func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
@@ -642,7 +641,7 @@ func CommonRoutes() *web.Route {
})
})
}, reqPackageAccess(perm.AccessModeRead))
- }, context_service.UserAssignmentWeb(), context.PackageAssignment())
+ }, context.UserAssignmentWeb(), context.PackageAssignment())
return r
}
@@ -812,7 +811,7 @@ func ContainerRoutes() *web.Route {
ctx.Status(http.StatusNotFound)
})
- }, container.ReqContainerAccess, context_service.UserAssignmentWeb(), context.PackageAssignment(), reqPackageAccess(perm.AccessModeRead))
+ }, container.ReqContainerAccess, context.UserAssignmentWeb(), context.PackageAssignment(), reqPackageAccess(perm.AccessModeRead))
return r
}
diff --git a/routers/api/packages/cargo/cargo.go b/routers/api/packages/cargo/cargo.go
index 8f1e965c9a..140e532efd 100644
--- a/routers/api/packages/cargo/cargo.go
+++ b/routers/api/packages/cargo/cargo.go
@@ -12,14 +12,15 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
cargo_module "code.gitea.io/gitea/modules/packages/cargo"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
packages_service "code.gitea.io/gitea/services/packages"
cargo_service "code.gitea.io/gitea/services/packages/cargo"
@@ -110,7 +111,7 @@ func SearchPackages(ctx *context.Context) {
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeCargo,
Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: &paginator,
},
)
diff --git a/routers/api/packages/chef/chef.go b/routers/api/packages/chef/chef.go
index f1e9ae12d8..b49f4e9d0a 100644
--- a/routers/api/packages/chef/chef.go
+++ b/routers/api/packages/chef/chef.go
@@ -15,12 +15,13 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
chef_module "code.gitea.io/gitea/modules/packages/chef"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
@@ -40,7 +41,7 @@ func PackagesUniverse(ctx *context.Context) {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeChef,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
@@ -85,7 +86,7 @@ func EnumeratePackages(ctx *context.Context) {
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeChef,
Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: db.NewAbsoluteListOptions(
ctx.FormInt("start"),
ctx.FormInt("items"),
diff --git a/routers/api/packages/composer/composer.go b/routers/api/packages/composer/composer.go
index 0551093cd1..a045da40de 100644
--- a/routers/api/packages/composer/composer.go
+++ b/routers/api/packages/composer/composer.go
@@ -14,12 +14,13 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
composer_module "code.gitea.io/gitea/modules/packages/composer"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
packages_service "code.gitea.io/gitea/services/packages"
@@ -66,7 +67,7 @@ func SearchPackages(ctx *context.Context) {
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeComposer,
Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: &paginator,
}
if ctx.FormTrim("type") != "" {
diff --git a/routers/api/packages/conan/conan.go b/routers/api/packages/conan/conan.go
index 4bf13222dc..c45e085a4d 100644
--- a/routers/api/packages/conan/conan.go
+++ b/routers/api/packages/conan/conan.go
@@ -15,13 +15,13 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
conan_model "code.gitea.io/gitea/models/packages/conan"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
conan_module "code.gitea.io/gitea/modules/packages/conan"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
notify_service "code.gitea.io/gitea/services/notify"
packages_service "code.gitea.io/gitea/services/packages"
)
diff --git a/routers/api/packages/conan/search.go b/routers/api/packages/conan/search.go
index 2bcf9df162..7370c702cd 100644
--- a/routers/api/packages/conan/search.go
+++ b/routers/api/packages/conan/search.go
@@ -9,9 +9,9 @@ import (
conan_model "code.gitea.io/gitea/models/packages/conan"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
conan_module "code.gitea.io/gitea/modules/packages/conan"
+ "code.gitea.io/gitea/services/context"
)
// SearchResult contains the found recipe names
diff --git a/routers/api/packages/conda/conda.go b/routers/api/packages/conda/conda.go
index 0bee7baa96..30c80fc15e 100644
--- a/routers/api/packages/conda/conda.go
+++ b/routers/api/packages/conda/conda.go
@@ -12,13 +12,13 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
conda_model "code.gitea.io/gitea/models/packages/conda"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
conda_module "code.gitea.io/gitea/modules/packages/conda"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/dsnet/compress/bzip2"
diff --git a/routers/api/packages/container/container.go b/routers/api/packages/container/container.go
index 8621242da4..e519766142 100644
--- a/routers/api/packages/container/container.go
+++ b/routers/api/packages/container/container.go
@@ -17,7 +17,6 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
container_model "code.gitea.io/gitea/models/packages/container"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
@@ -25,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
container_service "code.gitea.io/gitea/services/packages/container"
diff --git a/routers/api/packages/cran/cran.go b/routers/api/packages/cran/cran.go
index ae43df7c9a..2cec75294f 100644
--- a/routers/api/packages/cran/cran.go
+++ b/routers/api/packages/cran/cran.go
@@ -13,11 +13,11 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
cran_model "code.gitea.io/gitea/models/packages/cran"
- "code.gitea.io/gitea/modules/context"
packages_module "code.gitea.io/gitea/modules/packages"
cran_module "code.gitea.io/gitea/modules/packages/cran"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
diff --git a/routers/api/packages/debian/debian.go b/routers/api/packages/debian/debian.go
index 379137e87e..241de3ac5d 100644
--- a/routers/api/packages/debian/debian.go
+++ b/routers/api/packages/debian/debian.go
@@ -13,11 +13,11 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
packages_module "code.gitea.io/gitea/modules/packages"
debian_module "code.gitea.io/gitea/modules/packages/debian"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
notify_service "code.gitea.io/gitea/services/notify"
packages_service "code.gitea.io/gitea/services/packages"
debian_service "code.gitea.io/gitea/services/packages/debian"
diff --git a/routers/api/packages/generic/generic.go b/routers/api/packages/generic/generic.go
index 30854335c0..b65870a8d0 100644
--- a/routers/api/packages/generic/generic.go
+++ b/routers/api/packages/generic/generic.go
@@ -10,10 +10,10 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
diff --git a/routers/api/packages/goproxy/goproxy.go b/routers/api/packages/goproxy/goproxy.go
index 18e0074ab4..d658066bb4 100644
--- a/routers/api/packages/goproxy/goproxy.go
+++ b/routers/api/packages/goproxy/goproxy.go
@@ -12,11 +12,12 @@ import (
"time"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
goproxy_module "code.gitea.io/gitea/modules/packages/goproxy"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
@@ -129,7 +130,7 @@ func resolvePackage(ctx *context.Context, ownerID int64, name, version string) (
Value: name,
ExactMatch: true,
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Sort: packages_model.SortCreatedDesc,
})
if err != nil {
diff --git a/routers/api/packages/helm/helm.go b/routers/api/packages/helm/helm.go
index a8daa69dc3..efdb83ec0e 100644
--- a/routers/api/packages/helm/helm.go
+++ b/routers/api/packages/helm/helm.go
@@ -13,14 +13,15 @@ import (
"time"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
helm_module "code.gitea.io/gitea/modules/packages/helm"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
"gopkg.in/yaml.v3"
@@ -42,7 +43,7 @@ func Index(ctx *context.Context) {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeHelm,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
@@ -110,7 +111,7 @@ func DownloadPackageFile(ctx *context.Context) {
Value: ctx.Params("package"),
},
HasFileWithName: filename,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
diff --git a/routers/api/packages/helper/helper.go b/routers/api/packages/helper/helper.go
index aadb10376c..cdb64109ad 100644
--- a/routers/api/packages/helper/helper.go
+++ b/routers/api/packages/helper/helper.go
@@ -10,9 +10,9 @@ import (
"net/url"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
// LogAndProcessError logs an error and calls a custom callback with the processed error message.
diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go
index 5106395eb1..27f0578db7 100644
--- a/routers/api/packages/maven/maven.go
+++ b/routers/api/packages/maven/maven.go
@@ -20,12 +20,12 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
maven_module "code.gitea.io/gitea/modules/packages/maven"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
diff --git a/routers/api/packages/npm/api.go b/routers/api/packages/npm/api.go
index 8470874884..f8e839c424 100644
--- a/routers/api/packages/npm/api.go
+++ b/routers/api/packages/npm/api.go
@@ -12,6 +12,7 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
npm_module "code.gitea.io/gitea/modules/packages/npm"
+ "code.gitea.io/gitea/modules/setting"
)
func createPackageMetadataResponse(registryURL string, pds []*packages_model.PackageDescriptor) *npm_module.PackageMetadata {
@@ -98,7 +99,7 @@ func createPackageSearchResponse(pds []*packages_model.PackageDescriptor, total
Maintainers: []npm_module.User{}, // npm cli needs this field
Keywords: metadata.Keywords,
Links: &npm_module.PackageSearchPackageLinks{
- Registry: pd.FullWebLink(),
+ Registry: setting.AppURL + "api/packages/" + pd.Owner.Name + "/npm",
Homepage: metadata.ProjectURL,
},
},
diff --git a/routers/api/packages/npm/npm.go b/routers/api/packages/npm/npm.go
index 170edfbe11..84acfffae2 100644
--- a/routers/api/packages/npm/npm.go
+++ b/routers/api/packages/npm/npm.go
@@ -17,12 +17,13 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
npm_module "code.gitea.io/gitea/modules/packages/npm"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/hashicorp/go-version"
@@ -120,7 +121,7 @@ func DownloadPackageFileByName(ctx *context.Context) {
Value: packageNameFromParams(ctx),
},
HasFileWithName: filename,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
@@ -395,7 +396,7 @@ func setPackageTag(ctx std_ctx.Context, tag string, pv *packages_model.PackageVe
Properties: map[string]string{
npm_module.TagProperty: tag,
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
return err
@@ -431,7 +432,7 @@ func PackageSearch(ctx *context.Context) {
pvs, total, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeNpm,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Name: packages_model.SearchValue{
ExactMatch: false,
Value: ctx.FormTrim("text"),
diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go
index a63df2a1fc..0eb817c1a3 100644
--- a/routers/api/packages/nuget/nuget.go
+++ b/routers/api/packages/nuget/nuget.go
@@ -17,13 +17,14 @@ 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"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
nuget_module "code.gitea.io/gitea/modules/packages/nuget"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
@@ -122,7 +123,7 @@ func SearchServiceV2(ctx *context.Context) {
Name: packages_model.SearchValue{
Value: getSearchTerm(ctx),
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: paginator,
})
if err != nil {
@@ -172,7 +173,7 @@ func SearchServiceV2Count(ctx *context.Context) {
Name: packages_model.SearchValue{
Value: getSearchTerm(ctx),
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
@@ -187,7 +188,7 @@ func SearchServiceV3(ctx *context.Context) {
pvs, count, err := nuget_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: db.NewAbsoluteListOptions(
ctx.FormInt("skip"),
ctx.FormInt("take"),
@@ -313,7 +314,7 @@ func EnumeratePackageVersionsV2(ctx *context.Context) {
ExactMatch: true,
Value: packageName,
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: paginator,
})
if err != nil {
@@ -358,7 +359,7 @@ func EnumeratePackageVersionsV2Count(ctx *context.Context) {
ExactMatch: true,
Value: strings.Trim(ctx.FormTrim("id"), "'"),
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
diff --git a/routers/api/packages/pub/pub.go b/routers/api/packages/pub/pub.go
index 1f605c6c9f..f87df52a29 100644
--- a/routers/api/packages/pub/pub.go
+++ b/routers/api/packages/pub/pub.go
@@ -14,7 +14,6 @@ import (
"time"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
@@ -22,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
diff --git a/routers/api/packages/pypi/pypi.go b/routers/api/packages/pypi/pypi.go
index 5718b1203b..7824db1823 100644
--- a/routers/api/packages/pypi/pypi.go
+++ b/routers/api/packages/pypi/pypi.go
@@ -12,12 +12,12 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
packages_module "code.gitea.io/gitea/modules/packages"
pypi_module "code.gitea.io/gitea/modules/packages/pypi"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
diff --git a/routers/api/packages/rpm/rpm.go b/routers/api/packages/rpm/rpm.go
index 5d06680552..4de361c214 100644
--- a/routers/api/packages/rpm/rpm.go
+++ b/routers/api/packages/rpm/rpm.go
@@ -13,13 +13,13 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
packages_module "code.gitea.io/gitea/modules/packages"
rpm_module "code.gitea.io/gitea/modules/packages/rpm"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
notify_service "code.gitea.io/gitea/services/notify"
packages_service "code.gitea.io/gitea/services/packages"
rpm_service "code.gitea.io/gitea/services/packages/rpm"
diff --git a/routers/api/packages/rubygems/rubygems.go b/routers/api/packages/rubygems/rubygems.go
index 01fd4dad66..d2fbcd01f0 100644
--- a/routers/api/packages/rubygems/rubygems.go
+++ b/routers/api/packages/rubygems/rubygems.go
@@ -13,11 +13,12 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
rubygems_module "code.gitea.io/gitea/modules/packages/rubygems"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
)
@@ -43,7 +44,7 @@ func EnumeratePackagesLatest(ctx *context.Context) {
pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeRubyGems,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
@@ -304,7 +305,7 @@ func getVersionsByFilename(ctx *context.Context, filename string) ([]*packages_m
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeRubyGems,
HasFileWithName: filename,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
return pvs, err
}
diff --git a/routers/api/packages/swift/swift.go b/routers/api/packages/swift/swift.go
index 6ad289e51e..a9da3ea9c2 100644
--- a/routers/api/packages/swift/swift.go
+++ b/routers/api/packages/swift/swift.go
@@ -13,14 +13,15 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
swift_module "code.gitea.io/gitea/modules/packages/swift"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/hashicorp/go-version"
@@ -433,7 +434,7 @@ func LookupPackageIdentifiers(ctx *context.Context) {
Properties: map[string]string{
swift_module.PropertyRepositoryURL: url,
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
diff --git a/routers/api/packages/vagrant/vagrant.go b/routers/api/packages/vagrant/vagrant.go
index af9cd08a62..98a81da368 100644
--- a/routers/api/packages/vagrant/vagrant.go
+++ b/routers/api/packages/vagrant/vagrant.go
@@ -12,11 +12,11 @@ import (
"strings"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
packages_module "code.gitea.io/gitea/modules/packages"
vagrant_module "code.gitea.io/gitea/modules/packages/vagrant"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers/api/packages/helper"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/hashicorp/go-version"
diff --git a/routers/api/v1/activitypub/person.go b/routers/api/v1/activitypub/person.go
index cad5032d10..995a148f0b 100644
--- a/routers/api/v1/activitypub/person.go
+++ b/routers/api/v1/activitypub/person.go
@@ -9,9 +9,9 @@ import (
"strings"
"code.gitea.io/gitea/modules/activitypub"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
ap "github.com/go-ap/activitypub"
"github.com/go-ap/jsonld"
diff --git a/routers/api/v1/activitypub/reqsignature.go b/routers/api/v1/activitypub/reqsignature.go
index 3f60ed7776..59ebc74b89 100644
--- a/routers/api/v1/activitypub/reqsignature.go
+++ b/routers/api/v1/activitypub/reqsignature.go
@@ -13,9 +13,9 @@ import (
"net/url"
"code.gitea.io/gitea/modules/activitypub"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/setting"
+ gitea_context "code.gitea.io/gitea/services/context"
ap "github.com/go-ap/activitypub"
"github.com/go-fed/httpsig"
diff --git a/routers/api/v1/admin/adopt.go b/routers/api/v1/admin/adopt.go
index bf030eb222..a4708fe032 100644
--- a/routers/api/v1/admin/adopt.go
+++ b/routers/api/v1/admin/adopt.go
@@ -8,9 +8,9 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/api/v1/admin/cron.go b/routers/api/v1/admin/cron.go
index cc8c6c9e23..e1ca6048c9 100644
--- a/routers/api/v1/admin/cron.go
+++ b/routers/api/v1/admin/cron.go
@@ -6,11 +6,11 @@ package admin
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/cron"
)
diff --git a/routers/api/v1/admin/email.go b/routers/api/v1/admin/email.go
index 5914215bc2..ba963e9f69 100644
--- a/routers/api/v1/admin/email.go
+++ b/routers/api/v1/admin/email.go
@@ -7,9 +7,9 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/admin/hooks.go b/routers/api/v1/admin/hooks.go
index 8a095a7def..4c168b55bf 100644
--- a/routers/api/v1/admin/hooks.go
+++ b/routers/api/v1/admin/hooks.go
@@ -8,12 +8,13 @@ import (
"net/http"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
webhook_service "code.gitea.io/gitea/services/webhook"
)
@@ -37,7 +38,7 @@ func ListHooks(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/HookList"
- sysHooks, err := webhook.GetSystemWebhooks(ctx, util.OptionalBoolNone)
+ sysHooks, err := webhook.GetSystemWebhooks(ctx, optional.None[bool]())
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetSystemWebhooks", err)
return
diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go
index bf68942a9c..a5c299bbf0 100644
--- a/routers/api/v1/admin/org.go
+++ b/routers/api/v1/admin/org.go
@@ -10,10 +10,10 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/admin/repo.go b/routers/api/v1/admin/repo.go
index a4895f260b..c119d5390a 100644
--- a/routers/api/v1/admin/repo.go
+++ b/routers/api/v1/admin/repo.go
@@ -4,10 +4,10 @@
package admin
import (
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/repo"
+ "code.gitea.io/gitea/services/context"
)
// CreateRepo api for creating a repository
diff --git a/routers/api/v1/admin/runners.go b/routers/api/v1/admin/runners.go
index c0d9364435..329242d9f6 100644
--- a/routers/api/v1/admin/runners.go
+++ b/routers/api/v1/admin/runners.go
@@ -4,8 +4,8 @@
package admin
import (
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/api/v1/shared"
+ "code.gitea.io/gitea/services/context"
)
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go
index 2ce7651a09..64315108b0 100644
--- a/routers/api/v1/admin/user.go
+++ b/routers/api/v1/admin/user.go
@@ -15,7 +15,6 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
@@ -25,6 +24,7 @@ import (
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/api/v1/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/mailer"
user_service "code.gitea.io/gitea/services/user"
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 48ce494479..c296cac799 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -80,7 +80,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
@@ -96,7 +95,7 @@ import (
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/auth"
- context_service "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
_ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation
@@ -889,11 +888,11 @@ func Routes() *web.Route {
m.Group("/user/{username}", func() {
m.Get("", activitypub.Person)
m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox)
- }, context_service.UserAssignmentAPI())
+ }, context.UserAssignmentAPI())
m.Group("/user-id/{user-id}", func() {
m.Get("", activitypub.Person)
m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox)
- }, context_service.UserIDAssignmentAPI())
+ }, context.UserIDAssignmentAPI())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryActivityPub))
}
@@ -949,7 +948,7 @@ func Routes() *web.Route {
}, reqSelfOrAdmin(), reqBasicOrRevProxyAuth())
m.Get("/activities/feeds", user.ListUserActivityFeeds)
- }, context_service.UserAssignmentAPI(), individualPermsChecker)
+ }, context.UserAssignmentAPI(), individualPermsChecker)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser))
// Users (requires user scope)
@@ -969,7 +968,7 @@ func Routes() *web.Route {
}
m.Get("/subscriptions", user.GetWatchedRepos)
- }, context_service.UserAssignmentAPI())
+ }, context.UserAssignmentAPI())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
// Users (requires user scope)
@@ -1004,7 +1003,7 @@ func Routes() *web.Route {
m.Get("", user.CheckMyFollowing)
m.Put("", user.Follow)
m.Delete("", user.Unfollow)
- }, context_service.UserAssignmentAPI())
+ }, context.UserAssignmentAPI())
})
// (admin:public_key scope)
@@ -1068,7 +1067,7 @@ func Routes() *web.Route {
m.Group("", func() {
m.Put("/block/{username}", user.BlockUser)
m.Put("/unblock/{username}", user.UnblockUser)
- }, context_service.UserAssignmentAPI())
+ }, context.UserAssignmentAPI())
})
m.Group("/avatar", func() {
@@ -1485,14 +1484,14 @@ func Routes() *web.Route {
m.Get("/files", reqToken(), packages.ListPackageFiles)
})
m.Get("/", reqToken(), packages.ListPackages)
- }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryPackage), context_service.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
+ }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryPackage), context.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
// Organizations
m.Get("/user/orgs", reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), org.ListMyOrgs)
m.Group("/users/{username}/orgs", func() {
m.Get("", reqToken(), org.ListUserOrgs)
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions)
- }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context_service.UserAssignmentAPI())
+ }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context.UserAssignmentAPI())
m.Post("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), bind(api.CreateOrgOption{}), org.Create)
m.Get("/orgs", org.GetAll, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization))
m.Group("/orgs/{org}", func() {
@@ -1554,7 +1553,7 @@ func Routes() *web.Route {
m.Group("", func() {
m.Put("/block/{username}", org.BlockUser)
m.Put("/unblock/{username}", org.UnblockUser)
- }, context_service.UserAssignmentAPI())
+ }, context.UserAssignmentAPI())
}, reqToken(), reqOrgOwnership())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true))
m.Group("/teams/{teamid}", func() {
@@ -1598,7 +1597,7 @@ func Routes() *web.Route {
m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg)
m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo)
m.Post("/rename", bind(api.RenameUserOption{}), admin.RenameUser)
- }, context_service.UserAssignmentAPI())
+ }, context.UserAssignmentAPI())
})
m.Group("/emails", func() {
m.Get("", admin.GetAllEmails)
diff --git a/routers/api/v1/misc/gitignore.go b/routers/api/v1/misc/gitignore.go
index 7c7fe4b125..dffd771752 100644
--- a/routers/api/v1/misc/gitignore.go
+++ b/routers/api/v1/misc/gitignore.go
@@ -6,11 +6,11 @@ package misc
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/options"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
// Shows a list of all Gitignore templates
diff --git a/routers/api/v1/misc/label_templates.go b/routers/api/v1/misc/label_templates.go
index 0e0ca39fc5..cc11f37626 100644
--- a/routers/api/v1/misc/label_templates.go
+++ b/routers/api/v1/misc/label_templates.go
@@ -6,9 +6,9 @@ package misc
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/misc/licenses.go b/routers/api/v1/misc/licenses.go
index 65f63468cf..2a980f5084 100644
--- a/routers/api/v1/misc/licenses.go
+++ b/routers/api/v1/misc/licenses.go
@@ -8,12 +8,12 @@ import (
"net/http"
"net/url"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/options"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
// Returns a list of all License templates
diff --git a/routers/api/v1/misc/markup.go b/routers/api/v1/misc/markup.go
index 7b24b353b6..9699c79368 100644
--- a/routers/api/v1/misc/markup.go
+++ b/routers/api/v1/misc/markup.go
@@ -6,12 +6,12 @@ package misc
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/services/context"
)
// Markup render markup document to HTML
diff --git a/routers/api/v1/misc/markup_test.go b/routers/api/v1/misc/markup_test.go
index ec8f8f47b7..f499501c2f 100644
--- a/routers/api/v1/misc/markup_test.go
+++ b/routers/api/v1/misc/markup_test.go
@@ -10,11 +10,11 @@ import (
"strings"
"testing"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/api/v1/misc/nodeinfo.go b/routers/api/v1/misc/nodeinfo.go
index 6045208f24..9c2a0db8d2 100644
--- a/routers/api/v1/misc/nodeinfo.go
+++ b/routers/api/v1/misc/nodeinfo.go
@@ -9,9 +9,9 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
)
const cacheKeyNodeInfoUsage = "API_NodeInfoUsage"
diff --git a/routers/api/v1/misc/signing.go b/routers/api/v1/misc/signing.go
index 2ca9813e15..24a46c1e70 100644
--- a/routers/api/v1/misc/signing.go
+++ b/routers/api/v1/misc/signing.go
@@ -7,8 +7,8 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/modules/context"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
)
// SigningKey returns the public key of the default signing key if it exists
diff --git a/routers/api/v1/misc/version.go b/routers/api/v1/misc/version.go
index 83fa35219a..e3b43a0e6b 100644
--- a/routers/api/v1/misc/version.go
+++ b/routers/api/v1/misc/version.go
@@ -6,9 +6,9 @@ package misc
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
)
// Version shows the version of the Gitea server
diff --git a/routers/api/v1/notify/notifications.go b/routers/api/v1/notify/notifications.go
index c87da9399f..46b3c7f5e7 100644
--- a/routers/api/v1/notify/notifications.go
+++ b/routers/api/v1/notify/notifications.go
@@ -9,9 +9,9 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
)
// NewAvailable check if unread notifications exist
diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go
index 55ca6ad1fd..8d97e8a3f8 100644
--- a/routers/api/v1/notify/repo.go
+++ b/routers/api/v1/notify/repo.go
@@ -10,9 +10,9 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go
index 919e52952d..8e12d359cb 100644
--- a/routers/api/v1/notify/threads.go
+++ b/routers/api/v1/notify/threads.go
@@ -10,7 +10,7 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go
index 4abdfb2e92..879f484cce 100644
--- a/routers/api/v1/notify/user.go
+++ b/routers/api/v1/notify/user.go
@@ -9,8 +9,8 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/org/avatar.go b/routers/api/v1/org/avatar.go
index 7b621a50c3..e34c68dfc9 100644
--- a/routers/api/v1/org/avatar.go
+++ b/routers/api/v1/org/avatar.go
@@ -7,9 +7,9 @@ import (
"encoding/base64"
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/api/v1/org/hook.go b/routers/api/v1/org/hook.go
index 3c3f058b5d..c1dc0519ea 100644
--- a/routers/api/v1/org/hook.go
+++ b/routers/api/v1/org/hook.go
@@ -6,10 +6,10 @@ package org
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
webhook_service "code.gitea.io/gitea/services/webhook"
)
diff --git a/routers/api/v1/org/label.go b/routers/api/v1/org/label.go
index 5a03059ded..b5ec54ccf4 100644
--- a/routers/api/v1/org/label.go
+++ b/routers/api/v1/org/label.go
@@ -9,11 +9,11 @@ import (
"strings"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go
index 422b7cecfe..fb66d4c3f5 100644
--- a/routers/api/v1/org/member.go
+++ b/routers/api/v1/org/member.go
@@ -9,11 +9,11 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/organization"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go
index 2eefad6a98..9f9483d4ff 100644
--- a/routers/api/v1/org/org.go
+++ b/routers/api/v1/org/org.go
@@ -13,12 +13,12 @@ import (
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/org"
user_service "code.gitea.io/gitea/services/user"
diff --git a/routers/api/v1/org/runners.go b/routers/api/v1/org/runners.go
index 05bce8daef..2a52bd8778 100644
--- a/routers/api/v1/org/runners.go
+++ b/routers/api/v1/org/runners.go
@@ -4,8 +4,8 @@
package org
import (
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/api/v1/shared"
+ "code.gitea.io/gitea/services/context"
)
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
diff --git a/routers/api/v1/org/secrets.go b/routers/api/v1/org/secrets.go
index ddc74d865b..abb6bb26c4 100644
--- a/routers/api/v1/org/secrets.go
+++ b/routers/api/v1/org/secrets.go
@@ -9,11 +9,11 @@ import (
"code.gitea.io/gitea/models/db"
secret_model "code.gitea.io/gitea/models/secret"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
secret_service "code.gitea.io/gitea/services/secrets"
)
diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go
index f129c66230..b62a386fd7 100644
--- a/routers/api/v1/org/team.go
+++ b/routers/api/v1/org/team.go
@@ -15,12 +15,12 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
org_service "code.gitea.io/gitea/services/org"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/routers/api/v1/packages/package.go b/routers/api/v1/packages/package.go
index a79ba315be..b38aa13167 100644
--- a/routers/api/v1/packages/package.go
+++ b/routers/api/v1/packages/package.go
@@ -7,10 +7,10 @@ import (
"net/http"
"code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
packages_service "code.gitea.io/gitea/services/packages"
)
@@ -60,7 +60,7 @@ func ListPackages(ctx *context.APIContext) {
OwnerID: ctx.Package.Owner.ID,
Type: packages.Type(packageType),
Name: packages.SearchValue{Value: query},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: &listOptions,
})
if err != nil {
diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go
index 039cdadac9..e0af276c71 100644
--- a/routers/api/v1/repo/action.go
+++ b/routers/api/v1/repo/action.go
@@ -7,10 +7,10 @@ import (
"errors"
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
secret_service "code.gitea.io/gitea/services/secrets"
)
diff --git a/routers/api/v1/repo/avatar.go b/routers/api/v1/repo/avatar.go
index 1b661955f0..698337ffd2 100644
--- a/routers/api/v1/repo/avatar.go
+++ b/routers/api/v1/repo/avatar.go
@@ -7,9 +7,9 @@ import (
"encoding/base64"
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/api/v1/repo/blob.go b/routers/api/v1/repo/blob.go
index 26605bba03..3b116666ea 100644
--- a/routers/api/v1/repo/blob.go
+++ b/routers/api/v1/repo/blob.go
@@ -6,7 +6,7 @@ package repo
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
files_service "code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index 2cdbcd25a2..5e6b6a8658 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -14,7 +14,6 @@ import (
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/optional"
@@ -22,6 +21,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go
index 2c85657b93..a43a21a88e 100644
--- a/routers/api/v1/repo/collaborators.go
+++ b/routers/api/v1/repo/collaborators.go
@@ -13,11 +13,11 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
repo_module "code.gitea.io/gitea/modules/repository"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go
index d01cf6b8bc..d06a3b4e49 100644
--- a/routers/api/v1/repo/commits.go
+++ b/routers/api/v1/repo/commits.go
@@ -12,11 +12,11 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index 94a6381e25..72ada25ec7 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -19,7 +19,6 @@ import (
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/httpcache"
@@ -30,6 +29,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/services/context"
archiver_service "code.gitea.io/gitea/services/repository/archiver"
files_service "code.gitea.io/gitea/services/repository/files"
)
@@ -672,6 +672,7 @@ func UpdateFile(ctx *context.APIContext) {
apiOpts := web.GetForm(ctx).(*api.UpdateFileOptions)
if ctx.Repo.Repository.IsEmpty {
ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
+ return
}
if apiOpts.BranchName == "" {
diff --git a/routers/api/v1/repo/flags.go b/routers/api/v1/repo/flags.go
index cbb2c95914..ac5cb2e6d6 100644
--- a/routers/api/v1/repo/flags.go
+++ b/routers/api/v1/repo/flags.go
@@ -6,9 +6,9 @@ package repo
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
)
func ListFlags(ctx *context.APIContext) {
diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go
index 69433bf4cc..212cc7a93b 100644
--- a/routers/api/v1/repo/fork.go
+++ b/routers/api/v1/repo/fork.go
@@ -14,11 +14,11 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/api/v1/repo/git_hook.go b/routers/api/v1/repo/git_hook.go
index 7e471e263b..26ae84d08d 100644
--- a/routers/api/v1/repo/git_hook.go
+++ b/routers/api/v1/repo/git_hook.go
@@ -6,10 +6,10 @@ package repo
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/git_ref.go b/routers/api/v1/repo/git_ref.go
index 34d2dcfcc8..0fa58425b8 100644
--- a/routers/api/v1/repo/git_ref.go
+++ b/routers/api/v1/repo/git_ref.go
@@ -7,10 +7,10 @@ import (
"net/http"
"net/url"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
)
// GetGitAllRefs get ref or an list all the refs of a repository
diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go
index 8859e3ae23..ffd2313591 100644
--- a/routers/api/v1/repo/hook.go
+++ b/routers/api/v1/repo/hook.go
@@ -11,13 +11,13 @@ import (
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
webhook_service "code.gitea.io/gitea/services/webhook"
)
diff --git a/routers/api/v1/repo/hook_test.go b/routers/api/v1/repo/hook_test.go
index 94a71e20ad..37cf61c1ed 100644
--- a/routers/api/v1/repo/hook_test.go
+++ b/routers/api/v1/repo/hook_test.go
@@ -9,7 +9,7 @@ import (
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/contexttest"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index ae35bf2eef..af3f890f88 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -19,14 +19,14 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
notify_service "code.gitea.io/gitea/services/notify"
@@ -123,14 +123,14 @@ func SearchIssues(ctx *context.APIContext) {
return
}
- var isClosed util.OptionalBool
+ var isClosed optional.Option[bool]
switch ctx.FormString("state") {
case "closed":
- isClosed = util.OptionalBoolTrue
+ isClosed = optional.Some(true)
case "all":
- isClosed = util.OptionalBoolNone
+ isClosed = optional.None[bool]()
default:
- isClosed = util.OptionalBoolFalse
+ isClosed = optional.Some(false)
}
var (
@@ -143,7 +143,7 @@ func SearchIssues(ctx *context.APIContext) {
Private: false,
AllPublic: true,
TopicOnly: false,
- Collaborate: util.OptionalBoolNone,
+ Collaborate: optional.None[bool](),
// This needs to be a column that is not nil in fixtures or
// MySQL will return different results when sorting by null in some cases
OrderBy: db.SearchOrderByAlphabetically,
@@ -166,7 +166,7 @@ func SearchIssues(ctx *context.APIContext) {
opts.OwnerID = owner.ID
opts.AllLimited = false
opts.AllPublic = false
- opts.Collaborate = util.OptionalBoolFalse
+ opts.Collaborate = optional.Some(false)
}
if ctx.FormString("team") != "" {
if ctx.FormString("owner") == "" {
@@ -205,14 +205,14 @@ func SearchIssues(ctx *context.APIContext) {
keyword = ""
}
- var isPull util.OptionalBool
+ var isPull optional.Option[bool]
switch ctx.FormString("type") {
case "pulls":
- isPull = util.OptionalBoolTrue
+ isPull = optional.Some(true)
case "issues":
- isPull = util.OptionalBoolFalse
+ isPull = optional.Some(false)
default:
- isPull = util.OptionalBoolNone
+ isPull = optional.None[bool]()
}
var includedAnyLabels []int64
@@ -397,14 +397,14 @@ func ListIssues(ctx *context.APIContext) {
return
}
- var isClosed util.OptionalBool
+ var isClosed optional.Option[bool]
switch ctx.FormString("state") {
case "closed":
- isClosed = util.OptionalBoolTrue
+ isClosed = optional.Some(true)
case "all":
- isClosed = util.OptionalBoolNone
+ isClosed = optional.None[bool]()
default:
- isClosed = util.OptionalBoolFalse
+ isClosed = optional.Some(false)
}
keyword := ctx.FormTrim("q")
@@ -453,31 +453,29 @@ func ListIssues(ctx *context.APIContext) {
listOptions := utils.GetListOptions(ctx)
- var isPull util.OptionalBool
+ isPull := optional.None[bool]()
switch ctx.FormString("type") {
case "pulls":
- isPull = util.OptionalBoolTrue
+ isPull = optional.Some(true)
case "issues":
- isPull = util.OptionalBoolFalse
- default:
- isPull = util.OptionalBoolNone
+ isPull = optional.Some(false)
}
- if isPull != util.OptionalBoolNone && !ctx.Repo.CanReadIssuesOrPulls(isPull.IsTrue()) {
+ if isPull.Has() && !ctx.Repo.CanReadIssuesOrPulls(isPull.Value()) {
ctx.NotFound()
return
}
- if isPull == util.OptionalBoolNone {
+ if !isPull.Has() {
canReadIssues := ctx.Repo.CanRead(unit.TypeIssues)
canReadPulls := ctx.Repo.CanRead(unit.TypePullRequests)
if !canReadIssues && !canReadPulls {
ctx.NotFound()
return
} else if !canReadIssues {
- isPull = util.OptionalBoolTrue
+ isPull = optional.Some(true)
} else if !canReadPulls {
- isPull = util.OptionalBoolFalse
+ isPull = optional.Some(false)
}
}
diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go
index eaaaeaa9f9..fc9e88d63d 100644
--- a/routers/api/v1/repo/issue_attachment.go
+++ b/routers/api/v1/repo/issue_attachment.go
@@ -9,12 +9,12 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/attachment"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
)
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index 35d7658b6c..c3005dee3b 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -14,11 +14,11 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
)
@@ -278,15 +278,15 @@ func ListRepoIssueComments(ctx *context.APIContext) {
return
}
- var isPull util.OptionalBool
+ var isPull optional.Option[bool]
canReadIssue := ctx.Repo.CanRead(unit.TypeIssues)
canReadPull := ctx.Repo.CanRead(unit.TypePullRequests)
if canReadIssue && canReadPull {
- isPull = util.OptionalBoolNone
+ isPull = optional.None[bool]()
} else if canReadIssue {
- isPull = util.OptionalBoolFalse
+ isPull = optional.Some(false)
} else if canReadPull {
- isPull = util.OptionalBoolTrue
+ isPull = optional.Some(true)
} else {
ctx.NotFound()
return
diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go
index 5622a9292a..0f8fc96f08 100644
--- a/routers/api/v1/repo/issue_comment_attachment.go
+++ b/routers/api/v1/repo/issue_comment_attachment.go
@@ -9,12 +9,12 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/attachment"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
)
diff --git a/routers/api/v1/repo/issue_dependency.go b/routers/api/v1/repo/issue_dependency.go
index 62d1057cdf..a42920d4fd 100644
--- a/routers/api/v1/repo/issue_dependency.go
+++ b/routers/api/v1/repo/issue_dependency.go
@@ -11,10 +11,10 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go
index 008ff5c699..fd9625c0fb 100644
--- a/routers/api/v1/repo/issue_label.go
+++ b/routers/api/v1/repo/issue_label.go
@@ -8,9 +8,9 @@ import (
"net/http"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
)
diff --git a/routers/api/v1/repo/issue_pin.go b/routers/api/v1/repo/issue_pin.go
index 61f88de34e..ff1135862b 100644
--- a/routers/api/v1/repo/issue_pin.go
+++ b/routers/api/v1/repo/issue_pin.go
@@ -7,8 +7,8 @@ import (
"net/http"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go
index 27edc1abad..c395255c13 100644
--- a/routers/api/v1/repo/issue_reaction.go
+++ b/routers/api/v1/repo/issue_reaction.go
@@ -9,10 +9,10 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
)
diff --git a/routers/api/v1/repo/issue_stopwatch.go b/routers/api/v1/repo/issue_stopwatch.go
index 52bf8b5c7b..d9054e8f77 100644
--- a/routers/api/v1/repo/issue_stopwatch.go
+++ b/routers/api/v1/repo/issue_stopwatch.go
@@ -8,8 +8,8 @@ import (
"net/http"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go
index ece880c03e..a535172462 100644
--- a/routers/api/v1/repo/issue_subscription.go
+++ b/routers/api/v1/repo/issue_subscription.go
@@ -9,9 +9,9 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go
index cf03e72aa0..c640515881 100644
--- a/routers/api/v1/repo/issue_tracked_time.go
+++ b/routers/api/v1/repo/issue_tracked_time.go
@@ -12,10 +12,10 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go
index af48c40885..88444a2625 100644
--- a/routers/api/v1/repo/key.go
+++ b/routers/api/v1/repo/key.go
@@ -15,12 +15,12 @@ import (
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/label.go b/routers/api/v1/repo/label.go
index 420d3ab5b4..b6eb51fd20 100644
--- a/routers/api/v1/repo/label.go
+++ b/routers/api/v1/repo/label.go
@@ -9,11 +9,11 @@ import (
"strconv"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/language.go b/routers/api/v1/repo/language.go
index 12f1761ad0..f1d5bbe45f 100644
--- a/routers/api/v1/repo/language.go
+++ b/routers/api/v1/repo/language.go
@@ -9,8 +9,8 @@ import (
"strconv"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
type languageResponse []*repo_model.LanguageStat
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index 839fbfe8a1..2caaa130e8 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -17,7 +17,6 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
@@ -26,6 +25,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go
index 9c2ed16d93..b9534016e4 100644
--- a/routers/api/v1/repo/milestone.go
+++ b/routers/api/v1/repo/milestone.go
@@ -11,12 +11,12 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
@@ -61,10 +61,10 @@ func ListMilestones(ctx *context.APIContext) {
// "$ref": "#/responses/notFound"
state := api.StateType(ctx.FormString("state"))
- var isClosed util.OptionalBool
+ var isClosed optional.Option[bool]
switch state {
case api.StateClosed, api.StateOpen:
- isClosed = util.OptionalBoolOf(state == api.StateClosed)
+ isClosed = optional.Some(state == api.StateClosed)
}
milestones, total, err := db.FindAndCount[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
diff --git a/routers/api/v1/repo/mirror.go b/routers/api/v1/repo/mirror.go
index 26e0be301c..864644e1ef 100644
--- a/routers/api/v1/repo/mirror.go
+++ b/routers/api/v1/repo/mirror.go
@@ -13,12 +13,12 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
diff --git a/routers/api/v1/repo/notes.go b/routers/api/v1/repo/notes.go
index e7e00dae41..a4a1d4eab7 100644
--- a/routers/api/v1/repo/notes.go
+++ b/routers/api/v1/repo/notes.go
@@ -7,9 +7,9 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/patch.go b/routers/api/v1/repo/patch.go
index 9b5635d245..0e0601b7d9 100644
--- a/routers/api/v1/repo/patch.go
+++ b/routers/api/v1/repo/patch.go
@@ -10,10 +10,10 @@ import (
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index ef9b4893fb..f78e34d7b3 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -21,7 +21,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
@@ -32,6 +31,7 @@ import (
"code.gitea.io/gitea/routers/api/v1/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/automerge"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/gitdiff"
diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go
index e39a096add..6860d6e773 100644
--- a/routers/api/v1/repo/pull_review.go
+++ b/routers/api/v1/repo/pull_review.go
@@ -12,11 +12,11 @@ import (
"code.gitea.io/gitea/models/organization"
access_model "code.gitea.io/gitea/models/perm/access"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/gitrepo"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"
diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go
index a41c5ba7d8..f0f3c0bbc7 100644
--- a/routers/api/v1/repo/release.go
+++ b/routers/api/v1/repo/release.go
@@ -4,6 +4,7 @@
package repo
import (
+ "fmt"
"net/http"
"code.gitea.io/gitea/models"
@@ -11,10 +12,10 @@ import (
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
release_service "code.gitea.io/gitea/services/release"
)
@@ -215,6 +216,10 @@ func CreateRelease(ctx *context.APIContext) {
// "409":
// "$ref": "#/responses/error"
form := web.GetForm(ctx).(*api.CreateReleaseOption)
+ if ctx.Repo.Repository.IsEmpty {
+ ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
+ return
+ }
rel, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, form.TagName)
if err != nil {
if !repo_model.IsErrReleaseNotExist(err) {
diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go
index c36bf12e6d..59fd83e3a2 100644
--- a/routers/api/v1/repo/release_attachment.go
+++ b/routers/api/v1/repo/release_attachment.go
@@ -4,16 +4,18 @@
package repo
import (
+ "io"
"net/http"
+ "strings"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/attachment"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/convert"
)
@@ -154,6 +156,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
// - application/json
// consumes:
// - multipart/form-data
+ // - application/octet-stream
// parameters:
// - name: owner
// in: path
@@ -180,7 +183,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
// in: formData
// description: attachment to upload
// type: file
- // required: true
+ // required: false
// responses:
// "201":
// "$ref": "#/responses/Attachment"
@@ -202,20 +205,36 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
}
// Get uploaded file from request
- file, header, err := ctx.Req.FormFile("attachment")
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetFile", err)
- return
+ var content io.ReadCloser
+ var filename string
+ var size int64 = -1
+
+ if strings.HasPrefix(strings.ToLower(ctx.Req.Header.Get("Content-Type")), "multipart/form-data") {
+ file, header, err := ctx.Req.FormFile("attachment")
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "GetFile", err)
+ return
+ }
+ defer file.Close()
+
+ content = file
+ size = header.Size
+ filename = header.Filename
+ if name := ctx.FormString("name"); name != "" {
+ filename = name
+ }
+ } else {
+ content = ctx.Req.Body
+ filename = ctx.FormString("name")
}
- defer file.Close()
- filename := header.Filename
- if query := ctx.FormString("name"); query != "" {
- filename = query
+ if filename == "" {
+ ctx.Error(http.StatusBadRequest, "CreateReleaseAttachment", "Could not determine name of attachment.")
+ return
}
// Create a new attachment and save the file
- attach, err := attachment.UploadAttachment(ctx, file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{
+ attach, err := attachment.UploadAttachment(ctx, content, setting.Repository.Release.AllowedTypes, size, &repo_model.Attachment{
Name: filename,
UploaderID: ctx.Doer.ID,
RepoID: ctx.Repo.Repository.ID,
diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go
index 9f2098df06..fec91164a2 100644
--- a/routers/api/v1/repo/release_tags.go
+++ b/routers/api/v1/repo/release_tags.go
@@ -8,7 +8,7 @@ import (
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
releaseservice "code.gitea.io/gitea/services/release"
)
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index de105f474f..40960144c7 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -19,18 +19,18 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/issue"
repo_service "code.gitea.io/gitea/services/repository"
@@ -135,33 +135,33 @@ func Search(ctx *context.APIContext) {
PriorityOwnerID: ctx.FormInt64("priority_owner_id"),
TeamID: ctx.FormInt64("team_id"),
TopicOnly: ctx.FormBool("topic"),
- Collaborate: util.OptionalBoolNone,
+ Collaborate: optional.None[bool](),
Private: ctx.IsSigned && (ctx.FormString("private") == "" || ctx.FormBool("private")),
- Template: util.OptionalBoolNone,
+ Template: optional.None[bool](),
StarredByID: ctx.FormInt64("starredBy"),
IncludeDescription: ctx.FormBool("includeDesc"),
}
if ctx.FormString("template") != "" {
- opts.Template = util.OptionalBoolOf(ctx.FormBool("template"))
+ opts.Template = optional.Some(ctx.FormBool("template"))
}
if ctx.FormBool("exclusive") {
- opts.Collaborate = util.OptionalBoolFalse
+ opts.Collaborate = optional.Some(false)
}
mode := ctx.FormString("mode")
switch mode {
case "source":
- opts.Fork = util.OptionalBoolFalse
- opts.Mirror = util.OptionalBoolFalse
+ opts.Fork = optional.Some(false)
+ opts.Mirror = optional.Some(false)
case "fork":
- opts.Fork = util.OptionalBoolTrue
+ opts.Fork = optional.Some(true)
case "mirror":
- opts.Mirror = util.OptionalBoolTrue
+ opts.Mirror = optional.Some(true)
case "collaborative":
- opts.Mirror = util.OptionalBoolFalse
- opts.Collaborate = util.OptionalBoolTrue
+ opts.Mirror = optional.Some(false)
+ opts.Collaborate = optional.Some(true)
case "":
default:
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("Invalid search mode: \"%s\"", mode))
@@ -169,11 +169,11 @@ func Search(ctx *context.APIContext) {
}
if ctx.FormString("archived") != "" {
- opts.Archived = util.OptionalBoolOf(ctx.FormBool("archived"))
+ opts.Archived = optional.Some(ctx.FormBool("archived"))
}
if ctx.FormString("is_private") != "" {
- opts.IsPrivate = util.OptionalBoolOf(ctx.FormBool("is_private"))
+ opts.IsPrivate = optional.Some(ctx.FormBool("is_private"))
}
sortMode := ctx.FormString("sort")
@@ -358,7 +358,7 @@ func Generate(ctx *context.APIContext) {
return
}
- opts := repo_module.GenerateRepoOptions{
+ opts := repo_service.GenerateRepoOptions{
Name: form.Name,
DefaultBranch: form.DefaultBranch,
Description: form.Description,
diff --git a/routers/api/v1/repo/repo_test.go b/routers/api/v1/repo/repo_test.go
index 08ba7fabac..8d6ca9e3b5 100644
--- a/routers/api/v1/repo/repo_test.go
+++ b/routers/api/v1/repo/repo_test.go
@@ -9,9 +9,9 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/api/v1/repo/runners.go b/routers/api/v1/repo/runners.go
index 0a2bbf8117..fe133b311d 100644
--- a/routers/api/v1/repo/runners.go
+++ b/routers/api/v1/repo/runners.go
@@ -4,8 +4,8 @@
package repo
import (
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/api/v1/shared"
+ "code.gitea.io/gitea/services/context"
)
// GetRegistrationToken returns the token to register repo runners
diff --git a/routers/api/v1/repo/star.go b/routers/api/v1/repo/star.go
index 05227e33a0..99676de119 100644
--- a/routers/api/v1/repo/star.go
+++ b/routers/api/v1/repo/star.go
@@ -7,9 +7,9 @@ import (
"net/http"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go
index b4edf0608c..53711bedeb 100644
--- a/routers/api/v1/repo/status.go
+++ b/routers/api/v1/repo/status.go
@@ -9,10 +9,10 @@ import (
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
files_service "code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/api/v1/repo/subscriber.go b/routers/api/v1/repo/subscriber.go
index 05509fc443..8584182857 100644
--- a/routers/api/v1/repo/subscriber.go
+++ b/routers/api/v1/repo/subscriber.go
@@ -7,9 +7,9 @@ import (
"net/http"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go
index ad812ace56..84ec3dd91c 100644
--- a/routers/api/v1/repo/tag.go
+++ b/routers/api/v1/repo/tag.go
@@ -10,10 +10,10 @@ import (
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
releaseservice "code.gitea.io/gitea/services/release"
)
diff --git a/routers/api/v1/repo/teams.go b/routers/api/v1/repo/teams.go
index 1bacc71211..0ecf3a39d8 100644
--- a/routers/api/v1/repo/teams.go
+++ b/routers/api/v1/repo/teams.go
@@ -8,7 +8,7 @@ import (
"net/http"
"code.gitea.io/gitea/models/organization"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
org_service "code.gitea.io/gitea/services/org"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/routers/api/v1/repo/topic.go b/routers/api/v1/repo/topic.go
index d662b9b583..1d8e675bde 100644
--- a/routers/api/v1/repo/topic.go
+++ b/routers/api/v1/repo/topic.go
@@ -8,11 +8,11 @@ import (
"strings"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go
index a00bbcc17c..94c6bc6ded 100644
--- a/routers/api/v1/repo/transfer.go
+++ b/routers/api/v1/repo/transfer.go
@@ -14,10 +14,10 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/api/v1/repo/tree.go b/routers/api/v1/repo/tree.go
index f63100b6ea..353a996d5b 100644
--- a/routers/api/v1/repo/tree.go
+++ b/routers/api/v1/repo/tree.go
@@ -6,7 +6,7 @@ package repo
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
files_service "code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go
index ba3e978a83..347b7539b9 100644
--- a/routers/api/v1/repo/wiki.go
+++ b/routers/api/v1/repo/wiki.go
@@ -10,13 +10,13 @@ import (
"net/url"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
notify_service "code.gitea.io/gitea/services/notify"
wiki_service "code.gitea.io/gitea/services/wiki"
diff --git a/routers/api/v1/settings/settings.go b/routers/api/v1/settings/settings.go
index 957b839e66..c422315b22 100644
--- a/routers/api/v1/settings/settings.go
+++ b/routers/api/v1/settings/settings.go
@@ -6,9 +6,9 @@ package settings
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
)
// GetGeneralUISettings returns instance's global settings for ui
diff --git a/routers/api/v1/shared/runners.go b/routers/api/v1/shared/runners.go
index fe1584d2e7..f184786d7d 100644
--- a/routers/api/v1/shared/runners.go
+++ b/routers/api/v1/shared/runners.go
@@ -8,8 +8,8 @@ import (
"net/http"
actions_model "code.gitea.io/gitea/models/actions"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
// RegistrationToken is a string used to register a runner with a server
diff --git a/routers/api/v1/user/action.go b/routers/api/v1/user/action.go
index cbe332a779..babb8c0cf7 100644
--- a/routers/api/v1/user/action.go
+++ b/routers/api/v1/user/action.go
@@ -7,10 +7,10 @@ import (
"errors"
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
secret_service "code.gitea.io/gitea/services/secrets"
)
diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go
index eb35d8031a..b61ebac7d0 100644
--- a/routers/api/v1/user/app.go
+++ b/routers/api/v1/user/app.go
@@ -13,10 +13,10 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/user/avatar.go b/routers/api/v1/user/avatar.go
index 1c1bb6181a..f912296228 100644
--- a/routers/api/v1/user/avatar.go
+++ b/routers/api/v1/user/avatar.go
@@ -7,9 +7,9 @@ import (
"encoding/base64"
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/api/v1/user/email.go b/routers/api/v1/user/email.go
index 3dcea9083c..33aa851a80 100644
--- a/routers/api/v1/user/email.go
+++ b/routers/api/v1/user/email.go
@@ -8,9 +8,9 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go
index 783cee8584..1ba7346b8c 100644
--- a/routers/api/v1/user/follower.go
+++ b/routers/api/v1/user/follower.go
@@ -9,9 +9,9 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go
index 234da5dfdc..dcf5da0b2e 100644
--- a/routers/api/v1/user/gpg_key.go
+++ b/routers/api/v1/user/gpg_key.go
@@ -10,10 +10,11 @@ import (
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
@@ -132,6 +133,11 @@ func GetGPGKey(ctx *context.APIContext) {
// CreateUserGPGKey creates new GPG key to given user by ID.
func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) {
+ if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
+ ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
+ return
+ }
+
token := asymkey_model.VerificationToken(ctx.Doer, 1)
lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
@@ -268,6 +274,11 @@ func DeleteGPGKey(ctx *context.APIContext) {
// "404":
// "$ref": "#/responses/notFound"
+ if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
+ ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
+ return
+ }
+
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.ParamsInt64(":id")); err != nil {
if asymkey_model.IsErrGPGKeyAccessDenied(err) {
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
diff --git a/routers/api/v1/user/helper.go b/routers/api/v1/user/helper.go
index 392b266ebd..8b5c64e291 100644
--- a/routers/api/v1/user/helper.go
+++ b/routers/api/v1/user/helper.go
@@ -7,7 +7,7 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
// GetUserByParamsName get user by name
diff --git a/routers/api/v1/user/hook.go b/routers/api/v1/user/hook.go
index e87385e4a2..9d9ca5bf01 100644
--- a/routers/api/v1/user/hook.go
+++ b/routers/api/v1/user/hook.go
@@ -6,10 +6,10 @@ package user
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
webhook_service "code.gitea.io/gitea/services/webhook"
)
diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go
index dd185aa7d6..ada6759f8e 100644
--- a/routers/api/v1/user/key.go
+++ b/routers/api/v1/user/key.go
@@ -11,13 +11,13 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/repo"
"code.gitea.io/gitea/routers/api/v1/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go
index b8b2d265bf..81f8e0f3fe 100644
--- a/routers/api/v1/user/repo.go
+++ b/routers/api/v1/user/repo.go
@@ -11,9 +11,9 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/user/runners.go b/routers/api/v1/user/runners.go
index 51556ae0fb..899218473e 100644
--- a/routers/api/v1/user/runners.go
+++ b/routers/api/v1/user/runners.go
@@ -4,8 +4,8 @@
package user
import (
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/api/v1/shared"
+ "code.gitea.io/gitea/services/context"
)
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
diff --git a/routers/api/v1/user/settings.go b/routers/api/v1/user/settings.go
index 062df1ca43..d0a8daaa85 100644
--- a/routers/api/v1/user/settings.go
+++ b/routers/api/v1/user/settings.go
@@ -6,10 +6,10 @@ package user
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go
index 2659789ddd..e624884db3 100644
--- a/routers/api/v1/user/star.go
+++ b/routers/api/v1/user/star.go
@@ -12,9 +12,9 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go
index 67651062c7..831c1436da 100644
--- a/routers/api/v1/user/user.go
+++ b/routers/api/v1/user/user.go
@@ -10,8 +10,8 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go
index 7f531eafaa..706f4cc66b 100644
--- a/routers/api/v1/user/watch.go
+++ b/routers/api/v1/user/watch.go
@@ -11,9 +11,9 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/api/v1/utils/block.go b/routers/api/v1/utils/block.go
index 187d69044e..34fad96034 100644
--- a/routers/api/v1/utils/block.go
+++ b/routers/api/v1/utils/block.go
@@ -7,8 +7,8 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go
index 5e80190017..4e25137817 100644
--- a/routers/api/v1/utils/git.go
+++ b/routers/api/v1/utils/git.go
@@ -8,10 +8,10 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
// ResolveRefOrSha resolve ref to sha if exist
diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go
index 28b21ab8db..f1abd49a7d 100644
--- a/routers/api/v1/utils/hook.go
+++ b/routers/api/v1/utils/hook.go
@@ -12,12 +12,12 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
+ "code.gitea.io/gitea/services/context"
webhook_service "code.gitea.io/gitea/services/webhook"
)
diff --git a/routers/api/v1/utils/page.go b/routers/api/v1/utils/page.go
index 6910b82931..024ba7b8d9 100644
--- a/routers/api/v1/utils/page.go
+++ b/routers/api/v1/utils/page.go
@@ -5,7 +5,7 @@ package utils
import (
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/common/auth.go b/routers/common/auth.go
index 8904785d51..115d65ed10 100644
--- a/routers/common/auth.go
+++ b/routers/common/auth.go
@@ -5,9 +5,9 @@ package common
import (
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
auth_service "code.gitea.io/gitea/services/auth"
+ "code.gitea.io/gitea/services/context"
)
type AuthResult struct {
diff --git a/routers/common/errpage.go b/routers/common/errpage.go
index 923421a29c..402ca44c12 100644
--- a/routers/common/errpage.go
+++ b/routers/common/errpage.go
@@ -9,13 +9,13 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/modules/web/routing"
+ "code.gitea.io/gitea/services/context"
)
const tplStatus500 base.TplName = "status/500"
diff --git a/routers/common/markup.go b/routers/common/markup.go
index a1c2c37ac0..7819ee7227 100644
--- a/routers/common/markup.go
+++ b/routers/common/markup.go
@@ -9,11 +9,11 @@ import (
"net/http"
"strings"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
"mvdan.cc/xurls/v2"
)
diff --git a/routers/common/middleware.go b/routers/common/middleware.go
index 8a39dda179..c7c75fb099 100644
--- a/routers/common/middleware.go
+++ b/routers/common/middleware.go
@@ -9,11 +9,11 @@ import (
"strings"
"code.gitea.io/gitea/modules/cache"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/modules/web/routing"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/session"
"github.com/chi-middleware/proxy"
@@ -38,6 +38,7 @@ func ProtocolMiddlewares() (handlers []any) {
})
})
+ // wrap the request and response, use the process context and add it to the process manager
handlers = append(handlers, func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType, true)
diff --git a/routers/common/serve.go b/routers/common/serve.go
index 8a7f8b3332..446908db75 100644
--- a/routers/common/serve.go
+++ b/routers/common/serve.go
@@ -7,11 +7,11 @@ import (
"io"
"time"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
// ServeBlob download a git.Blob
diff --git a/routers/init.go b/routers/init.go
index 5ae6a551f9..28e1c49801 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -200,6 +200,8 @@ func NormalRoutes() *web.Route {
// TODO: this prefix should be generated with a token string with runner ?
prefix = "/api/actions_pipeline"
r.Mount(prefix, actions_router.ArtifactsRoutes(prefix))
+ prefix = actions_router.ArtifactV4RouteBase
+ r.Mount(prefix, actions_router.ArtifactsV4Routes(prefix))
}
return r
diff --git a/routers/install/install.go b/routers/install/install.go
index 13504953ce..5030306d89 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -22,7 +22,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password/hash"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
@@ -34,6 +33,7 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"gitea.com/go-chi/session"
diff --git a/routers/private/actions.go b/routers/private/actions.go
index 1325913e1b..397f20a091 100644
--- a/routers/private/actions.go
+++ b/routers/private/actions.go
@@ -13,11 +13,11 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
// GenerateActionsRunnerToken generates a new runner token for a given scope
diff --git a/routers/private/default_branch.go b/routers/private/default_branch.go
index a23e101e9d..2e323129ef 100644
--- a/routers/private/default_branch.go
+++ b/routers/private/default_branch.go
@@ -8,9 +8,9 @@ import (
"net/http"
repo_model "code.gitea.io/gitea/models/repo"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/private"
+ gitea_context "code.gitea.io/gitea/services/context"
)
// SetDefaultBranch updates the default branch
diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go
index 1b274ae154..f4c698d3ea 100644
--- a/routers/private/hook_post_receive.go
+++ b/routers/private/hook_post_receive.go
@@ -10,7 +10,6 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
@@ -18,6 +17,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ gitea_context "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
)
@@ -159,7 +159,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
}
// If we've pushed a branch (and not deleted it)
- if git.IsEmptyCommitID(newCommitID) && refFullName.IsBranch() {
+ if !git.IsEmptyCommitID(newCommitID) && refFullName.IsBranch() {
// First ensure we have the repository loaded, we're allowed pulls requests and we can get the base repo
if repo == nil {
repo = loadRepository(ctx, ownerName, repoName)
diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go
index f28ae4c0eb..f45e57b9e3 100644
--- a/routers/private/hook_pre_receive.go
+++ b/routers/private/hook_pre_receive.go
@@ -16,11 +16,11 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/web"
+ gitea_context "code.gitea.io/gitea/services/context"
pull_service "code.gitea.io/gitea/services/pull"
)
diff --git a/routers/private/hook_proc_receive.go b/routers/private/hook_proc_receive.go
index 5577120770..e4aabd858c 100644
--- a/routers/private/hook_proc_receive.go
+++ b/routers/private/hook_proc_receive.go
@@ -7,12 +7,12 @@ import (
"net/http"
repo_model "code.gitea.io/gitea/models/repo"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/agit"
+ gitea_context "code.gitea.io/gitea/services/context"
)
// HookProcReceive proc-receive hook - only handles agit Proc-Receive requests at present
diff --git a/routers/private/internal.go b/routers/private/internal.go
index 407edebeed..ede310113c 100644
--- a/routers/private/internal.go
+++ b/routers/private/internal.go
@@ -8,11 +8,11 @@ import (
"net/http"
"strings"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
chi_middleware "github.com/go-chi/chi/v5/middleware"
diff --git a/routers/private/internal_repo.go b/routers/private/internal_repo.go
index 615239d479..e8ee8ba8ac 100644
--- a/routers/private/internal_repo.go
+++ b/routers/private/internal_repo.go
@@ -9,10 +9,10 @@ import (
"net/http"
repo_model "code.gitea.io/gitea/models/repo"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
+ gitea_context "code.gitea.io/gitea/services/context"
)
// This file contains common functions relating to setting the Repository for the internal routes
diff --git a/routers/private/key.go b/routers/private/key.go
index 0096480d6a..5b8f238a83 100644
--- a/routers/private/key.go
+++ b/routers/private/key.go
@@ -7,9 +7,9 @@ import (
"net/http"
asymkey_model "code.gitea.io/gitea/models/asymkey"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/services/context"
)
// UpdatePublicKeyInRepo update public key and deploy key updates
diff --git a/routers/private/mail.go b/routers/private/mail.go
index e5e162c880..c19ee67896 100644
--- a/routers/private/mail.go
+++ b/routers/private/mail.go
@@ -11,11 +11,11 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/mailer"
)
diff --git a/routers/private/manager.go b/routers/private/manager.go
index 397e6fac7b..a6aa03e4ec 100644
--- a/routers/private/manager.go
+++ b/routers/private/manager.go
@@ -8,7 +8,6 @@ import (
"net/http"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/graceful/releasereopen"
"code.gitea.io/gitea/modules/log"
@@ -17,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
)
// ReloadTemplates reloads all the templates
diff --git a/routers/private/manager_process.go b/routers/private/manager_process.go
index 68e4a21805..9a0298a37c 100644
--- a/routers/private/manager_process.go
+++ b/routers/private/manager_process.go
@@ -11,10 +11,10 @@ import (
"runtime"
"time"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
process_module "code.gitea.io/gitea/modules/process"
+ "code.gitea.io/gitea/services/context"
)
// Processes prints out the processes
diff --git a/routers/private/manager_unix.go b/routers/private/manager_unix.go
index 09ced33b8d..0c63ebc918 100644
--- a/routers/private/manager_unix.go
+++ b/routers/private/manager_unix.go
@@ -8,8 +8,8 @@ package private
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/graceful"
+ "code.gitea.io/gitea/services/context"
)
// Restart causes the server to perform a graceful restart
diff --git a/routers/private/manager_windows.go b/routers/private/manager_windows.go
index bd3c3c30d0..f1b9365f52 100644
--- a/routers/private/manager_windows.go
+++ b/routers/private/manager_windows.go
@@ -8,9 +8,9 @@ package private
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/private"
+ "code.gitea.io/gitea/services/context"
)
// Restart is not implemented for Windows based servers as they can't fork
diff --git a/routers/private/restore_repo.go b/routers/private/restore_repo.go
index 7efc22a3d9..4e95d3071d 100644
--- a/routers/private/restore_repo.go
+++ b/routers/private/restore_repo.go
@@ -7,9 +7,9 @@ import (
"io"
"net/http"
- myCtx "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/private"
+ myCtx "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/migrations"
)
diff --git a/routers/private/serv.go b/routers/private/serv.go
index 00731947a5..ef3920d359 100644
--- a/routers/private/serv.go
+++ b/routers/private/serv.go
@@ -14,11 +14,11 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
wiki_service "code.gitea.io/gitea/services/wiki"
)
diff --git a/routers/private/ssh_log.go b/routers/private/ssh_log.go
index eacfa18f05..5bec632ead 100644
--- a/routers/private/ssh_log.go
+++ b/routers/private/ssh_log.go
@@ -6,11 +6,11 @@ package private
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
)
// SSHLog hook to response ssh log
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index 58bb281731..fe98178ac3 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -14,12 +14,12 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/updatechecker"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/cron"
"code.gitea.io/gitea/services/forms"
release_service "code.gitea.io/gitea/services/release"
diff --git a/routers/web/admin/admin_test.go b/routers/web/admin/admin_test.go
index 452291e179..c73780d60f 100644
--- a/routers/web/admin/admin_test.go
+++ b/routers/web/admin/admin_test.go
@@ -8,9 +8,9 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go
index b6f7bcd2a5..8583398074 100644
--- a/routers/web/admin/applications.go
+++ b/routers/web/admin/applications.go
@@ -10,9 +10,9 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
+ "code.gitea.io/gitea/services/context"
)
var (
diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go
index 7fdd18dfae..ba487d1045 100644
--- a/routers/web/admin/auths.go
+++ b/routers/web/admin/auths.go
@@ -16,7 +16,6 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/auth/pam"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -27,6 +26,7 @@ import (
pam_service "code.gitea.io/gitea/services/auth/source/pam"
"code.gitea.io/gitea/services/auth/source/smtp"
"code.gitea.io/gitea/services/auth/source/sspi"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"xorm.io/xorm/convert"
diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index c827f2a4f5..d9b1973332 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -12,13 +12,13 @@ import (
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/setting/config"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/mailer"
"gitea.com/go-chi/session"
diff --git a/routers/web/admin/diagnosis.go b/routers/web/admin/diagnosis.go
index 2d550125d5..020554a35a 100644
--- a/routers/web/admin/diagnosis.go
+++ b/routers/web/admin/diagnosis.go
@@ -9,8 +9,8 @@ import (
"runtime/pprof"
"time"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/httplib"
+ "code.gitea.io/gitea/services/context"
)
func MonitorDiagnosis(ctx *context.Context) {
diff --git a/routers/web/admin/emails.go b/routers/web/admin/emails.go
index 59f80035d8..2cf4035c6a 100644
--- a/routers/web/admin/emails.go
+++ b/routers/web/admin/emails.go
@@ -11,10 +11,10 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -68,10 +68,10 @@ func Emails(ctx *context.Context) {
opts.Keyword = ctx.FormTrim("q")
opts.SortType = orderBy
if len(ctx.FormString("is_activated")) != 0 {
- opts.IsActivated = util.OptionalBoolOf(ctx.FormBool("activated"))
+ opts.IsActivated = optional.Some(ctx.FormBool("activated"))
}
if len(ctx.FormString("is_primary")) != 0 {
- opts.IsPrimary = util.OptionalBoolOf(ctx.FormBool("primary"))
+ opts.IsPrimary = optional.Some(ctx.FormBool("primary"))
}
if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
diff --git a/routers/web/admin/hooks.go b/routers/web/admin/hooks.go
index cd8cc29cdf..8d59fbb858 100644
--- a/routers/web/admin/hooks.go
+++ b/routers/web/admin/hooks.go
@@ -8,9 +8,9 @@ import (
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -35,7 +35,7 @@ func DefaultOrSystemWebhooks(ctx *context.Context) {
sys["Title"] = ctx.Tr("admin.systemhooks")
sys["Description"] = ctx.Tr("admin.systemhooks.desc")
- sys["Webhooks"], err = webhook.GetSystemWebhooks(ctx, util.OptionalBoolNone)
+ sys["Webhooks"], err = webhook.GetSystemWebhooks(ctx, optional.None[bool]())
sys["BaseLink"] = setting.AppSubURL + "/admin/hooks"
sys["BaseLinkNew"] = setting.AppSubURL + "/admin/system-hooks"
if err != nil {
diff --git a/routers/web/admin/notice.go b/routers/web/admin/notice.go
index e1cb578d05..36303cbc06 100644
--- a/routers/web/admin/notice.go
+++ b/routers/web/admin/notice.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/db"
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/admin/orgs.go b/routers/web/admin/orgs.go
index 00131c9e2f..c5454db71e 100644
--- a/routers/web/admin/orgs.go
+++ b/routers/web/admin/orgs.go
@@ -8,10 +8,10 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/web/explore"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go
index 35ce215be4..39f064a1be 100644
--- a/routers/web/admin/packages.go
+++ b/routers/web/admin/packages.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup"
)
@@ -36,7 +36,7 @@ func Packages(ctx *context.Context) {
Type: packages_model.Type(packageType),
Name: packages_model.SearchValue{Value: query},
Sort: sort,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Paginator: &db.ListOptions{
PageSize: setting.UI.PackagesPagingNum,
Page: page,
diff --git a/routers/web/admin/queue.go b/routers/web/admin/queue.go
index 18a8d7d3e6..d8c50730b1 100644
--- a/routers/web/admin/queue.go
+++ b/routers/web/admin/queue.go
@@ -7,9 +7,9 @@ import (
"net/http"
"strconv"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
func Queues(ctx *context.Context) {
diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go
index 45c280ef73..ddf4440167 100644
--- a/routers/web/admin/repos.go
+++ b/routers/web/admin/repos.go
@@ -12,11 +12,11 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/explore"
+ "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/admin/runners.go b/routers/web/admin/runners.go
index eaa268b4f1..d73290a8db 100644
--- a/routers/web/admin/runners.go
+++ b/routers/web/admin/runners.go
@@ -4,8 +4,8 @@
package admin
import (
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
func RedirectToDefaultSetting(ctx *context.Context) {
diff --git a/routers/web/admin/stacktrace.go b/routers/web/admin/stacktrace.go
index b603fb59a2..d6def94bb4 100644
--- a/routers/web/admin/stacktrace.go
+++ b/routers/web/admin/stacktrace.go
@@ -7,9 +7,9 @@ import (
"net/http"
"runtime"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
// Stacktrace show admin monitor goroutines page
diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go
index adb9799c01..a34e0d0f0d 100644
--- a/routers/web/admin/users.go
+++ b/routers/web/admin/users.go
@@ -19,7 +19,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
@@ -27,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/explore"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/mailer"
user_service "code.gitea.io/gitea/services/user"
@@ -96,7 +96,7 @@ func NewUser(ctx *context.Context) {
ctx.Data["login_type"] = "0-0"
sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
})
if err != nil {
ctx.ServerError("auth.Sources", err)
@@ -117,7 +117,7 @@ func NewUserPost(ctx *context.Context) {
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
})
if err != nil {
ctx.ServerError("auth.Sources", err)
@@ -276,7 +276,7 @@ func ViewUser(ctx *context.Context) {
OwnerID: u.ID,
OrderBy: db.SearchOrderByAlphabetically,
Private: true,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
})
if err != nil {
ctx.ServerError("SearchRepository", err)
@@ -439,6 +439,7 @@ func EditUserPost(ctx *context.Context) {
AllowCreateOrganization: optional.Some(form.AllowCreateOrganization),
IsRestricted: optional.Some(form.Restricted),
Visibility: optional.Some(form.Visibility),
+ Language: optional.Some(form.Language),
}
if err := user_service.UpdateUser(ctx, u, opts); err != nil {
diff --git a/routers/web/admin/users_test.go b/routers/web/admin/users_test.go
index 560ee70ea0..f6f9237858 100644
--- a/routers/web/admin/users_test.go
+++ b/routers/web/admin/users_test.go
@@ -8,10 +8,10 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/forms"
"github.com/stretchr/testify/assert"
diff --git a/routers/web/auth/2fa.go b/routers/web/auth/2fa.go
index dc0062ebaa..f93177bf96 100644
--- a/routers/web/auth/2fa.go
+++ b/routers/web/auth/2fa.go
@@ -10,9 +10,9 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go
index 91f631acac..1adb891840 100644
--- a/routers/web/auth/auth.go
+++ b/routers/web/auth/auth.go
@@ -17,7 +17,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/eventsource"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
@@ -30,6 +29,7 @@ import (
"code.gitea.io/gitea/routers/utils"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/mailer"
@@ -171,7 +171,7 @@ func SignIn(ctx *context.Context) {
return
}
- oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
+ oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
ctx.ServerError("UserSignIn", err)
return
@@ -194,7 +194,7 @@ func SignIn(ctx *context.Context) {
func SignInPost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("sign_in")
- oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
+ oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
ctx.ServerError("UserSignIn", err)
return
@@ -414,7 +414,7 @@ func SignUp(ctx *context.Context) {
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
- oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
+ oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
ctx.ServerError("UserSignUp", err)
return
@@ -443,7 +443,7 @@ func SignUpPost(ctx *context.Context) {
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
- oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
+ oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
ctx.ServerError("UserSignUp", err)
return
diff --git a/routers/web/auth/linkaccount.go b/routers/web/auth/linkaccount.go
index 1d94e52fe3..f744a57a43 100644
--- a/routers/web/auth/linkaccount.go
+++ b/routers/web/auth/linkaccount.go
@@ -12,13 +12,13 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/forms"
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 4e4079d8ff..f5ca0bda5e 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -21,7 +21,6 @@ import (
auth_module "code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
@@ -33,6 +32,7 @@ import (
auth_service "code.gitea.io/gitea/services/auth"
source_service "code.gitea.io/gitea/services/auth/source"
"code.gitea.io/gitea/services/auth/source/oauth2"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/forms"
user_service "code.gitea.io/gitea/services/user"
diff --git a/routers/web/auth/openid.go b/routers/web/auth/openid.go
index 29ef772b1c..2143b8096a 100644
--- a/routers/web/auth/openid.go
+++ b/routers/web/auth/openid.go
@@ -11,12 +11,12 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/openid"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/auth"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/auth/password.go b/routers/web/auth/password.go
index 1f2d133282..c9e0386041 100644
--- a/routers/web/auth/password.go
+++ b/routers/web/auth/password.go
@@ -12,7 +12,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
@@ -20,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/mailer"
user_service "code.gitea.io/gitea/services/user"
diff --git a/routers/web/auth/webauthn.go b/routers/web/auth/webauthn.go
index 95c8d262a5..1079f44a08 100644
--- a/routers/web/auth/webauthn.go
+++ b/routers/web/auth/webauthn.go
@@ -11,9 +11,9 @@ import (
user_model "code.gitea.io/gitea/models/user"
wa "code.gitea.io/gitea/modules/auth/webauthn"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
"github.com/go-webauthn/webauthn/protocol"
diff --git a/routers/web/devtest/devtest.go b/routers/web/devtest/devtest.go
index 525ca9be53..dd20663f94 100644
--- a/routers/web/devtest/devtest.go
+++ b/routers/web/devtest/devtest.go
@@ -10,8 +10,8 @@ import (
"time"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/services/context"
)
// List all devtest templates, they will be used for e2e tests for the UI components
diff --git a/routers/web/events/events.go b/routers/web/events/events.go
index 1a5a162c1a..52f20e07dc 100644
--- a/routers/web/events/events.go
+++ b/routers/web/events/events.go
@@ -7,11 +7,11 @@ import (
"net/http"
"time"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/eventsource"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/routers/web/auth"
+ "code.gitea.io/gitea/services/context"
)
// Events listens for events
diff --git a/routers/web/explore/code.go b/routers/web/explore/code.go
index d81884ec62..2cde8b655e 100644
--- a/routers/web/explore/code.go
+++ b/routers/web/explore/code.go
@@ -8,9 +8,9 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/explore/org.go b/routers/web/explore/org.go
index dc1318beef..f8fd6ec38e 100644
--- a/routers/web/explore/org.go
+++ b/routers/web/explore/org.go
@@ -6,9 +6,10 @@ package explore
import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
)
// Organizations render explore organizations page
@@ -24,8 +25,16 @@ func Organizations(ctx *context.Context) {
visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate)
}
- if ctx.FormString("sort") == "" {
- ctx.SetFormString("sort", setting.UI.ExploreDefaultSort)
+ supportedSortOrders := container.SetOf(
+ "newest",
+ "oldest",
+ "alphabetically",
+ "reversealphabetically",
+ )
+ sortOrder := ctx.FormString("sort")
+ if sortOrder == "" {
+ sortOrder = "newest"
+ ctx.SetFormString("sort", sortOrder)
}
RenderUserSearch(ctx, &user_model.SearchUserOptions{
@@ -33,5 +42,7 @@ func Organizations(ctx *context.Context) {
Type: user_model.UserTypeOrganization,
ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum},
Visible: visibleTypes,
+
+ SupportedSortOrders: supportedSortOrders,
}, tplExploreUsers)
}
diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go
index 0446edebe6..cf7381512b 100644
--- a/routers/web/explore/repo.go
+++ b/routers/web/explore/repo.go
@@ -10,10 +10,10 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sitemap"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -109,6 +109,21 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
language := ctx.FormTrim("language")
ctx.Data["Language"] = language
+ archived := ctx.FormOptionalBool("archived")
+ ctx.Data["IsArchived"] = archived
+
+ fork := ctx.FormOptionalBool("fork")
+ ctx.Data["IsFork"] = fork
+
+ mirror := ctx.FormOptionalBool("mirror")
+ ctx.Data["IsMirror"] = mirror
+
+ template := ctx.FormOptionalBool("template")
+ ctx.Data["IsTemplate"] = template
+
+ private := ctx.FormOptionalBool("private")
+ ctx.Data["IsPrivate"] = private
+
repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: page,
@@ -125,6 +140,11 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
Language: language,
IncludeDescription: setting.UI.SearchRepoDescription,
OnlyShowRelevant: opts.OnlyShowRelevant,
+ Archived: archived,
+ Fork: fork,
+ Mirror: mirror,
+ Template: template,
+ IsPrivate: private,
})
if err != nil {
ctx.ServerError("SearchRepository", err)
diff --git a/routers/web/explore/topic.go b/routers/web/explore/topic.go
index bb1be310de..95fecfe2b8 100644
--- a/routers/web/explore/topic.go
+++ b/routers/web/explore/topic.go
@@ -8,8 +8,8 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go
index 09d31f95ef..b79a79fb2c 100644
--- a/routers/web/explore/user.go
+++ b/routers/web/explore/user.go
@@ -10,12 +10,13 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sitemap"
"code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -79,10 +80,16 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions,
fallthrough
default:
// in case the sortType is not valid, we set it to recentupdate
+ sortOrder = "recentupdate"
ctx.Data["SortType"] = "recentupdate"
orderBy = "`user`.updated_unix DESC"
}
+ if opts.SupportedSortOrders != nil && !opts.SupportedSortOrders.Contains(sortOrder) {
+ ctx.NotFound("unsupported sort order", nil)
+ return
+ }
+
opts.Keyword = ctx.FormTrim("q")
opts.OrderBy = orderBy
if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
@@ -132,15 +139,25 @@ func Users(ctx *context.Context) {
ctx.Data["PageIsExploreUsers"] = true
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
- if ctx.FormString("sort") == "" {
- ctx.SetFormString("sort", setting.UI.ExploreDefaultSort)
+ supportedSortOrders := container.SetOf(
+ "newest",
+ "oldest",
+ "alphabetically",
+ "reversealphabetically",
+ )
+ sortOrder := ctx.FormString("sort")
+ if sortOrder == "" {
+ sortOrder = "newest"
+ ctx.SetFormString("sort", sortOrder)
}
RenderUserSearch(ctx, &user_model.SearchUserOptions{
Actor: ctx.Doer,
Type: user_model.UserTypeIndividual,
ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum},
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
+
+ SupportedSortOrders: supportedSortOrders,
}, tplExploreUsers)
}
diff --git a/routers/web/feed/branch.go b/routers/web/feed/branch.go
index f13038ff9b..80ce2ad198 100644
--- a/routers/web/feed/branch.go
+++ b/routers/web/feed/branch.go
@@ -9,7 +9,7 @@ import (
"time"
"code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"github.com/gorilla/feeds"
)
diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go
index 5186d1a524..743465082e 100644
--- a/routers/web/feed/convert.go
+++ b/routers/web/feed/convert.go
@@ -14,12 +14,12 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
"github.com/gorilla/feeds"
"github.com/jaytaylor/html2text"
@@ -51,7 +51,7 @@ func toReleaseLink(ctx *context.Context, act *activities_model.Action) string {
// renderMarkdown creates a minimal markdown render context from an action.
// If rendering fails, the original markdown text is returned
-func renderMarkdown(ctx *context.Context, act *activities_model.Action, content string) string {
+func renderMarkdown(ctx *context.Context, act *activities_model.Action, content string) template.HTML {
markdownCtx := &markup.RenderContext{
Ctx: ctx,
Links: markup.Links{
@@ -65,7 +65,7 @@ func renderMarkdown(ctx *context.Context, act *activities_model.Action, content
}
markdown, err := markdown.RenderString(markdownCtx, content)
if err != nil {
- return content
+ return templates.SanitizeHTML(content) // old code did so: use SanitizeHTML to render in tmpl
}
return markdown
}
@@ -75,7 +75,11 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
for _, act := range actions {
act.LoadActUser(ctx)
- var content, desc, title string
+ // TODO: the code seems quite strange (maybe not right)
+ // sometimes it uses text content but sometimes it uses HTML content
+ // it should clearly defines which kind of content it should use for the feed items: plan text or rich HTML
+ var title, desc string
+ var content template.HTML
link := &feeds.Link{Href: act.GetCommentHTMLURL(ctx)}
@@ -229,7 +233,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
desc = act.GetIssueTitle(ctx)
comment := act.GetIssueInfos()[1]
if len(comment) != 0 {
- desc += "\n\n" + renderMarkdown(ctx, act, comment)
+ desc += "\n\n" + string(renderMarkdown(ctx, act, comment))
}
case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest:
desc = act.GetIssueInfos()[1]
@@ -240,7 +244,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
}
}
if len(content) == 0 {
- content = desc
+ content = templates.SanitizeHTML(desc)
}
// It's a common practice for feed generators to use plain text titles.
@@ -261,7 +265,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
},
Id: fmt.Sprintf("%v: %v", strconv.FormatInt(act.ID, 10), link.Href),
Created: act.CreatedUnix.AsTime(),
- Content: content,
+ Content: string(content),
})
}
return items, err
@@ -290,7 +294,8 @@ func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, i
return nil, err
}
- var title, content string
+ var title string
+ var content template.HTML
if rel.IsTag {
title = rel.TagName
@@ -319,7 +324,7 @@ func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, i
Email: rel.Publisher.GetEmail(),
},
Id: fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href),
- Content: content,
+ Content: string(content),
})
}
diff --git a/routers/web/feed/file.go b/routers/web/feed/file.go
index 56a9c54ddc..1ab768ff27 100644
--- a/routers/web/feed/file.go
+++ b/routers/web/feed/file.go
@@ -9,9 +9,9 @@ import (
"time"
"code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
"github.com/gorilla/feeds"
)
diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go
index 3feca68d61..08cbcd9e12 100644
--- a/routers/web/feed/profile.go
+++ b/routers/web/feed/profile.go
@@ -7,9 +7,9 @@ import (
"time"
activities_model "code.gitea.io/gitea/models/activities"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/services/context"
"github.com/gorilla/feeds"
)
@@ -58,7 +58,7 @@ func showUserFeed(ctx *context.Context, formatType string) {
feed := &feeds.Feed{
Title: ctx.Locale.TrString("home.feed_of", ctx.ContextUser.DisplayName()),
Link: &feeds.Link{Href: ctx.ContextUser.HTMLURL()},
- Description: ctxUserDescription,
+ Description: string(ctxUserDescription),
Created: time.Now(),
}
diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go
index 558c03dba7..273f47e3b4 100644
--- a/routers/web/feed/release.go
+++ b/routers/web/feed/release.go
@@ -8,7 +8,7 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"github.com/gorilla/feeds"
)
diff --git a/routers/web/feed/render.go b/routers/web/feed/render.go
index 41f9af1c8c..dc99fb49ed 100644
--- a/routers/web/feed/render.go
+++ b/routers/web/feed/render.go
@@ -4,7 +4,7 @@
package feed
import (
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
// RenderBranchFeed render format for branch or file
diff --git a/routers/web/feed/repo.go b/routers/web/feed/repo.go
index 51c24510c7..bfcc3a37d6 100644
--- a/routers/web/feed/repo.go
+++ b/routers/web/feed/repo.go
@@ -8,7 +8,7 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"github.com/gorilla/feeds"
)
diff --git a/routers/web/githttp.go b/routers/web/githttp.go
index ab74e9a333..5f1dedce76 100644
--- a/routers/web/githttp.go
+++ b/routers/web/githttp.go
@@ -6,11 +6,10 @@ package web
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/repo"
- context_service "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context"
)
func requireSignIn(ctx *context.Context) {
@@ -39,5 +38,5 @@ func gitHTTPRouters(m *web.Route) {
m.Methods("GET,OPTIONS", "/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38,62}}", repo.GetLooseObject)
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.pack", repo.GetPackFile)
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.idx", repo.GetIdxFile)
- }, ignSignInAndCsrf, requireSignIn, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context_service.UserAssignmentWeb())
+ }, ignSignInAndCsrf, requireSignIn, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context.UserAssignmentWeb())
}
diff --git a/routers/web/goget.go b/routers/web/goget.go
index c5b8b6cbc0..8d5612ebfe 100644
--- a/routers/web/goget.go
+++ b/routers/web/goget.go
@@ -12,9 +12,9 @@ import (
"strings"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
func goGet(ctx *context.Context) {
diff --git a/routers/web/home.go b/routers/web/home.go
index 2321b00efe..d4be0931e8 100644
--- a/routers/web/home.go
+++ b/routers/web/home.go
@@ -12,15 +12,15 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sitemap"
"code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/web/auth"
"code.gitea.io/gitea/routers/web/user"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -71,7 +71,7 @@ func HomeSitemap(ctx *context.Context) {
_, cnt, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
Type: user_model.UserTypeIndividual,
ListOptions: db.ListOptions{PageSize: 1},
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
Visible: []structs.VisibleType{structs.VisibleTypePublic},
})
if err != nil {
diff --git a/routers/web/misc/markup.go b/routers/web/misc/markup.go
index c91da9a7f1..2dbbd6fc09 100644
--- a/routers/web/misc/markup.go
+++ b/routers/web/misc/markup.go
@@ -5,10 +5,10 @@
package misc
import (
- "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/services/context"
)
// Markup render markup document to HTML
diff --git a/routers/web/misc/swagger-forgejo.go b/routers/web/misc/swagger-forgejo.go
index 2f539e955c..e3aff02c5f 100644
--- a/routers/web/misc/swagger-forgejo.go
+++ b/routers/web/misc/swagger-forgejo.go
@@ -7,7 +7,7 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
// tplSwagger swagger page template
diff --git a/routers/web/misc/swagger.go b/routers/web/misc/swagger.go
index 72c09a3780..5fddfa8885 100644
--- a/routers/web/misc/swagger.go
+++ b/routers/web/misc/swagger.go
@@ -7,7 +7,7 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
// tplSwagger swagger page template
diff --git a/routers/web/nodeinfo.go b/routers/web/nodeinfo.go
index 01b71e7086..f1cc7bf530 100644
--- a/routers/web/nodeinfo.go
+++ b/routers/web/nodeinfo.go
@@ -7,8 +7,8 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
type nodeInfoLinks struct {
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index 36f543dc45..71d10f3a43 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -12,7 +12,6 @@ import (
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
@@ -20,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -85,6 +85,21 @@ func Home(ctx *context.Context) {
page = 1
}
+ archived := ctx.FormOptionalBool("archived")
+ ctx.Data["IsArchived"] = archived
+
+ fork := ctx.FormOptionalBool("fork")
+ ctx.Data["IsFork"] = fork
+
+ mirror := ctx.FormOptionalBool("mirror")
+ ctx.Data["IsMirror"] = mirror
+
+ template := ctx.FormOptionalBool("template")
+ ctx.Data["IsTemplate"] = template
+
+ private := ctx.FormOptionalBool("private")
+ ctx.Data["IsPrivate"] = private
+
var (
repos []*repo_model.Repository
count int64
@@ -102,6 +117,11 @@ func Home(ctx *context.Context) {
Actor: ctx.Doer,
Language: language,
IncludeDescription: setting.UI.SearchRepoDescription,
+ Archived: archived,
+ Fork: fork,
+ Mirror: mirror,
+ Template: template,
+ IsPrivate: private,
})
if err != nil {
ctx.ServerError("SearchRepository", err)
diff --git a/routers/web/org/members.go b/routers/web/org/members.go
index 15a615c706..9a3d60e122 100644
--- a/routers/web/org/members.go
+++ b/routers/web/org/members.go
@@ -10,10 +10,10 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/org/org.go b/routers/web/org/org.go
index 1e4544730e..f94dd16eae 100644
--- a/routers/web/org/org.go
+++ b/routers/web/org/org.go
@@ -12,10 +12,10 @@ import (
"code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go
index f78bd00274..02eae8052e 100644
--- a/routers/web/org/org_labels.go
+++ b/routers/web/org/org_labels.go
@@ -8,10 +8,10 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index f062127d24..ad8bb90d9e 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -17,12 +17,13 @@ import (
attachment_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
@@ -66,7 +67,7 @@ func Projects(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
OwnerID: ctx.ContextUser.ID,
- IsClosed: util.OptionalBoolOf(isShowClosed),
+ IsClosed: optional.Some(isShowClosed),
OrderBy: project_model.GetSearchOrderByBySortType(sortType),
Type: projectType,
Title: keyword,
@@ -78,7 +79,7 @@ func Projects(ctx *context.Context) {
opTotal, err := db.Count[project_model.Project](ctx, project_model.SearchOptions{
OwnerID: ctx.ContextUser.ID,
- IsClosed: util.OptionalBoolOf(!isShowClosed),
+ IsClosed: optional.Some(!isShowClosed),
Type: projectType,
})
if err != nil {
@@ -104,7 +105,7 @@ func Projects(ctx *context.Context) {
}
for _, project := range projects {
- project.RenderedContent = project.Description
+ project.RenderedContent = templates.SanitizeHTML(project.Description) // FIXME: is it right? why not render?
}
err = shared_user.LoadHeaderCount(ctx)
@@ -387,7 +388,7 @@ func ViewProject(ctx *context.Context) {
if len(referencedIDs) > 0 {
if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{
IssueIDs: referencedIDs,
- IsPull: util.OptionalBoolTrue,
+ IsPull: optional.Some(true),
}); err == nil {
linkedPrsMap[issue.ID] = linkedPrs
}
@@ -395,7 +396,7 @@ func ViewProject(ctx *context.Context) {
}
}
- project.RenderedContent = project.Description
+ project.RenderedContent = templates.SanitizeHTML(project.Description) // FIXME: is it right? why not render?
ctx.Data["LinkedPRs"] = linkedPrsMap
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
diff --git a/routers/web/org/projects_test.go b/routers/web/org/projects_test.go
index 8053ab4cf9..f4ccfe1c06 100644
--- a/routers/web/org/projects_test.go
+++ b/routers/web/org/projects_test.go
@@ -7,8 +7,8 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/routers/web/org"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 47d0063f76..494ada4323 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -14,7 +14,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
@@ -22,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
org_service "code.gitea.io/gitea/services/org"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/routers/web/org/setting/blocked_users.go b/routers/web/org/setting/blocked_users.go
index d872dabd83..b23f5ba596 100644
--- a/routers/web/org/setting/blocked_users.go
+++ b/routers/web/org/setting/blocked_users.go
@@ -10,7 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/web/org/setting/runners.go b/routers/web/org/setting/runners.go
index c3c771036a..fe05709237 100644
--- a/routers/web/org/setting/runners.go
+++ b/routers/web/org/setting/runners.go
@@ -4,7 +4,7 @@
package setting
import (
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
func RedirectToDefaultSetting(ctx *context.Context) {
diff --git a/routers/web/org/setting_oauth2.go b/routers/web/org/setting_oauth2.go
index ca4fe09f38..7f855795d3 100644
--- a/routers/web/org/setting_oauth2.go
+++ b/routers/web/org/setting_oauth2.go
@@ -10,10 +10,10 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/org/setting_packages.go b/routers/web/org/setting_packages.go
index 796829d34e..af9836e42c 100644
--- a/routers/web/org/setting_packages.go
+++ b/routers/web/org/setting_packages.go
@@ -8,10 +8,10 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
shared "code.gitea.io/gitea/routers/web/shared/packages"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go
index 71fe99c97c..fd7486cacd 100644
--- a/routers/web/org/teams.go
+++ b/routers/web/org/teams.go
@@ -20,11 +20,11 @@ import (
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
org_service "code.gitea.io/gitea/services/org"
diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go
index 19aca26711..f27329aa0f 100644
--- a/routers/web/repo/actions/actions.go
+++ b/routers/web/repo/actions/actions.go
@@ -15,11 +15,11 @@ import (
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/repo"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"github.com/nektos/act/pkg/model"
@@ -78,7 +78,7 @@ func List(ctx *context.Context) {
// Get all runner labels
runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{
RepoID: ctx.Repo.Repository.ID,
- IsOnline: util.OptionalBoolTrue,
+ IsOnline: optional.Some(true),
WithAvailable: true,
})
if err != nil {
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index 05675d73c0..23ce70a153 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -13,6 +13,7 @@ import (
"io"
"net/http"
"net/url"
+ "strconv"
"strings"
"time"
@@ -22,12 +23,13 @@ import (
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/base"
- context_module "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
actions_service "code.gitea.io/gitea/services/actions"
+ context_module "code.gitea.io/gitea/services/context"
"xorm.io/builder"
)
@@ -312,10 +314,14 @@ func ViewPost(ctx *context_module.Context) {
}
// Rerun will rerun jobs in the given run
-// jobIndex = 0 means rerun all jobs
+// If jobIndexStr is a blank string, it means rerun all jobs
func Rerun(ctx *context_module.Context) {
runIndex := ctx.ParamsInt64("run")
- jobIndex := ctx.ParamsInt64("job")
+ jobIndexStr := ctx.Params("job")
+ var jobIndex int64
+ if jobIndexStr != "" {
+ jobIndex, _ = strconv.ParseInt(jobIndexStr, 10, 64)
+ }
run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
if err != nil {
@@ -347,7 +353,7 @@ func Rerun(ctx *context_module.Context) {
return
}
- if jobIndex != 0 {
+ if jobIndexStr != "" {
jobs = []*actions_model.ActionRunJob{job}
}
@@ -642,6 +648,28 @@ func ArtifactsDownloadView(ctx *context_module.Context) {
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.zip; filename*=UTF-8''%s.zip", url.PathEscape(artifactName), artifactName))
+ // Artifacts using the v4 backend are stored as a single combined zip file per artifact on the backend
+ // The v4 backend enshures ContentEncoding is set to "application/zip", which is not the case for the old backend
+ if len(artifacts) == 1 && artifacts[0].ArtifactName+".zip" == artifacts[0].ArtifactPath && artifacts[0].ContentEncoding == "application/zip" {
+ art := artifacts[0]
+ if setting.Actions.ArtifactStorage.MinioConfig.ServeDirect {
+ u, err := storage.ActionsArtifacts.URL(art.StoragePath, art.ArtifactPath)
+ if u != nil && err == nil {
+ ctx.Redirect(u.String())
+ return
+ }
+ }
+ f, err := storage.ActionsArtifacts.Open(art.StoragePath)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+ _, _ = io.Copy(ctx.Resp, f)
+ return
+ }
+
+ // Artifacts using the v1-v3 backend are stored as multiple individual files per artifact on the backend
+ // Those need to be zipped for download
writer := zip.NewWriter(ctx.Resp)
defer writer.Close()
for _, art := range artifacts {
diff --git a/routers/web/repo/activity.go b/routers/web/repo/activity.go
index af99c4ed98..6f6641cc65 100644
--- a/routers/web/repo/activity.go
+++ b/routers/web/repo/activity.go
@@ -10,7 +10,7 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go
index 8c322b45e5..f0c5622aec 100644
--- a/routers/web/repo/attachment.go
+++ b/routers/web/repo/attachment.go
@@ -9,15 +9,15 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/attachment"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/repo/badges/badges.go b/routers/web/repo/badges/badges.go
index 8fe99c7fc1..7f4549d606 100644
--- a/routers/web/repo/badges/badges.go
+++ b/routers/web/repo/badges/badges.go
@@ -11,8 +11,8 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- context_module "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ context_module "code.gitea.io/gitea/services/context"
)
func getBadgeURL(ctx *context_module.Context, label, text, color string) string {
diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go
index 2c938dc966..0f464ad076 100644
--- a/routers/web/repo/blame.go
+++ b/routers/web/repo/blame.go
@@ -12,7 +12,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
@@ -20,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
files_service "code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go
index c543160f42..ae51f0596b 100644
--- a/routers/web/repo/branch.go
+++ b/routers/web/repo/branch.go
@@ -16,14 +16,15 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository"
@@ -53,7 +54,7 @@ func Branches(ctx *context.Context) {
kw := ctx.FormString("q")
- defaultBranch, branches, branchesCount, err := repo_service.LoadBranches(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, util.OptionalBoolNone, kw, page, pageSize)
+ defaultBranch, branches, branchesCount, err := repo_service.LoadBranches(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, optional.None[bool](), kw, page, pageSize)
if err != nil {
ctx.ServerError("LoadBranches", err)
return
@@ -231,7 +232,7 @@ func CreateBranch(ctx *context.Context) {
if len(e.Message) == 0 {
ctx.Flash.Error(ctx.Tr("repo.editor.push_rejected_no_message"))
} else {
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.push_rejected"),
"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
"Details": utils.SanitizeFlashErrorString(e.Message),
diff --git a/routers/web/repo/cherry_pick.go b/routers/web/repo/cherry_pick.go
index 63516bb4d9..90dae704f4 100644
--- a/routers/web/repo/cherry_pick.go
+++ b/routers/web/repo/cherry_pick.go
@@ -12,11 +12,11 @@ import (
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/web/repo/code_frequency.go b/routers/web/repo/code_frequency.go
index 48ade655b7..c76f492da0 100644
--- a/routers/web/repo/code_frequency.go
+++ b/routers/web/repo/code_frequency.go
@@ -8,7 +8,7 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
contributors_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go
index 3b6e482281..7c89ce5a38 100644
--- a/routers/web/repo/commit.go
+++ b/routers/web/repo/commit.go
@@ -19,7 +19,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitgraph"
"code.gitea.io/gitea/modules/gitrepo"
@@ -27,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/gitdiff"
git_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index 535487d5fd..b0570f97c3 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -25,7 +25,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/context"
csv_module "code.gitea.io/gitea/modules/csv"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
@@ -35,8 +34,9 @@ import (
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/typesniffer"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/gitdiff"
)
diff --git a/routers/web/repo/contributors.go b/routers/web/repo/contributors.go
index bcfef7580a..5fda17469e 100644
--- a/routers/web/repo/contributors.go
+++ b/routers/web/repo/contributors.go
@@ -8,7 +8,7 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
contributors_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/repo/download.go b/routers/web/repo/download.go
index a9e2e2b2fa..c4a8baecca 100644
--- a/routers/web/repo/download.go
+++ b/routers/web/repo/download.go
@@ -9,7 +9,6 @@ import (
"time"
git_model "code.gitea.io/gitea/models/git"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/lfs"
@@ -17,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/services/context"
)
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index 075477e5f0..4f26c0c521 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -17,17 +17,17 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/typesniffer"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/forms"
files_service "code.gitea.io/gitea/services/repository/files"
)
@@ -382,7 +382,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
if len(errPushRej.Message) == 0 {
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplEditFile, &form)
} else {
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.push_rejected"),
"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
@@ -394,7 +394,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
ctx.RenderWithErr(flashError, tplEditFile, &form)
}
} else {
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.fail_to_update_file", form.TreePath),
"Summary": ctx.Tr("repo.editor.fail_to_update_file_summary"),
"Details": utils.SanitizeFlashErrorString(err.Error()),
@@ -590,7 +590,7 @@ func DeleteFilePost(ctx *context.Context) {
if len(errPushRej.Message) == 0 {
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplDeleteFile, &form)
} else {
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.push_rejected"),
"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
@@ -797,7 +797,7 @@ func UploadFilePost(ctx *context.Context) {
if len(errPushRej.Message) == 0 {
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplUploadFile, &form)
} else {
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.push_rejected"),
"Summary": ctx.Tr("repo.editor.push_rejected_summary"),
"Details": utils.SanitizeFlashErrorString(errPushRej.Message),
diff --git a/routers/web/repo/editor_test.go b/routers/web/repo/editor_test.go
index c28c3ef1d6..313fcfe33a 100644
--- a/routers/web/repo/editor_test.go
+++ b/routers/web/repo/editor_test.go
@@ -7,9 +7,9 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/web/repo/find.go b/routers/web/repo/find.go
index daefe59c8f..07b3722798 100644
--- a/routers/web/repo/find.go
+++ b/routers/web/repo/find.go
@@ -7,7 +7,7 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/flags/manage.go b/routers/web/repo/flags/manage.go
index 840f6c3773..377a5c20f8 100644
--- a/routers/web/repo/flags/manage.go
+++ b/routers/web/repo/flags/manage.go
@@ -7,9 +7,9 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go
index f52abbfb02..9f3b63698a 100644
--- a/routers/web/repo/githttp.go
+++ b/routers/web/repo/githttp.go
@@ -24,13 +24,13 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
"github.com/go-chi/cors"
diff --git a/routers/web/repo/helper.go b/routers/web/repo/helper.go
index a98abe566f..5e1e116018 100644
--- a/routers/web/repo/helper.go
+++ b/routers/web/repo/helper.go
@@ -8,8 +8,8 @@ import (
"sort"
"code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/services/context"
)
func MakeSelfOnTop(doer *user.User, users []*user.User) []*user.User {
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index 963c6289b2..2e2d12672e 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -9,6 +9,7 @@ import (
stdCtx "context"
"errors"
"fmt"
+ "html/template"
"math/big"
"net/http"
"net/url"
@@ -31,7 +32,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
@@ -39,16 +39,19 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/templates/vars"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
issue_service "code.gitea.io/gitea/services/issue"
@@ -143,7 +146,7 @@ func MustAllowPulls(ctx *context.Context) {
}
}
-func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption util.OptionalBool) {
+func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption optional.Option[bool]) {
var err error
viewType := ctx.FormString("type")
sortType := ctx.FormString("sort")
@@ -244,18 +247,18 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
}
}
- var isShowClosed util.OptionalBool
+ var isShowClosed optional.Option[bool]
switch ctx.FormString("state") {
case "closed":
- isShowClosed = util.OptionalBoolTrue
+ isShowClosed = optional.Some(true)
case "all":
- isShowClosed = util.OptionalBoolNone
+ isShowClosed = optional.None[bool]()
default:
- isShowClosed = util.OptionalBoolFalse
+ isShowClosed = optional.Some(false)
}
// if there are closed issues and no open issues, default to showing all issues
if len(ctx.FormString("state")) == 0 && issueStats.OpenCount == 0 && issueStats.ClosedCount != 0 {
- isShowClosed = util.OptionalBoolNone
+ isShowClosed = optional.None[bool]()
}
if repo.IsTimetrackerEnabled(ctx) {
@@ -275,10 +278,10 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
}
var total int
- switch isShowClosed {
- case util.OptionalBoolTrue:
+ switch {
+ case isShowClosed.Value():
total = int(issueStats.ClosedCount)
- case util.OptionalBoolNone:
+ case !isShowClosed.Has():
total = int(issueStats.OpenCount + issueStats.ClosedCount)
default:
total = int(issueStats.OpenCount)
@@ -434,7 +437,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
return
}
- pinned, err := issues_model.GetPinnedIssues(ctx, repo.ID, isPullOption.IsTrue())
+ pinned, err := issues_model.GetPinnedIssues(ctx, repo.ID, isPullOption.Value())
if err != nil {
ctx.ServerError("GetPinnedIssues", err)
return
@@ -464,10 +467,10 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
ctx.Data["AssigneeID"] = assigneeID
ctx.Data["PosterID"] = posterID
ctx.Data["Keyword"] = keyword
- switch isShowClosed {
- case util.OptionalBoolTrue:
+ switch {
+ case isShowClosed.Value():
ctx.Data["State"] = "closed"
- case util.OptionalBoolNone:
+ case !isShowClosed.Has():
ctx.Data["State"] = "all"
default:
ctx.Data["State"] = "open"
@@ -516,7 +519,7 @@ func Issues(ctx *context.Context) {
ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo)
}
- issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList))
+ issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), optional.Some(isPullList))
if ctx.Written() {
return
}
@@ -558,7 +561,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
var err error
ctx.Data["OpenMilestones"], err = db.Find[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
RepoID: repo.ID,
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
})
if err != nil {
ctx.ServerError("GetMilestones", err)
@@ -566,7 +569,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
}
ctx.Data["ClosedMilestones"], err = db.Find[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
RepoID: repo.ID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
})
if err != nil {
ctx.ServerError("GetMilestones", err)
@@ -594,7 +597,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
projects, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
ListOptions: db.ListOptionsAll,
RepoID: repo.ID,
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
Type: project_model.TypeRepository,
})
if err != nil {
@@ -604,7 +607,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
projects2, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
ListOptions: db.ListOptionsAll,
OwnerID: repo.OwnerID,
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
Type: repoOwnerType,
})
if err != nil {
@@ -617,7 +620,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
projects, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
ListOptions: db.ListOptionsAll,
RepoID: repo.ID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
Type: project_model.TypeRepository,
})
if err != nil {
@@ -627,7 +630,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
projects2, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
ListOptions: db.ListOptionsAll,
OwnerID: repo.OwnerID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
Type: repoOwnerType,
})
if err != nil {
@@ -1020,7 +1023,7 @@ func NewIssue(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplIssueNew)
}
-func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) string {
+func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) template.HTML {
var files []string
for k := range errs {
files = append(files, k)
@@ -1032,14 +1035,14 @@ func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) string
lines = append(lines, fmt.Sprintf("%s: %v", file, errs[file]))
}
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.issues.choose.ignore_invalid_templates"),
"Summary": ctx.Tr("repo.issues.choose.invalid_templates", len(errs)),
"Details": utils.SanitizeFlashErrorString(strings.Join(lines, "\n")),
})
if err != nil {
log.Debug("render flash error: %v", err)
- flashError = ctx.Locale.TrString("repo.issues.choose.ignore_invalid_templates")
+ flashError = ctx.Locale.Tr("repo.issues.choose.ignore_invalid_templates")
}
return flashError
}
@@ -1768,7 +1771,7 @@ func ViewIssue(ctx *context.Context) {
// so "|" is used as delimeter to mark the new format
if comment.Content[0] != '|' {
// handle old time comments that have formatted text stored
- comment.RenderedContent = comment.Content
+ comment.RenderedContent = templates.SanitizeHTML(comment.Content)
comment.Content = ""
} else {
// else it's just a duration in seconds to pass on to the frontend
@@ -2509,14 +2512,14 @@ func SearchIssues(ctx *context.Context) {
return
}
- var isClosed util.OptionalBool
+ var isClosed optional.Option[bool]
switch ctx.FormString("state") {
case "closed":
- isClosed = util.OptionalBoolTrue
+ isClosed = optional.Some(true)
case "all":
- isClosed = util.OptionalBoolNone
+ isClosed = optional.None[bool]()
default:
- isClosed = util.OptionalBoolFalse
+ isClosed = optional.Some(false)
}
var (
@@ -2529,7 +2532,7 @@ func SearchIssues(ctx *context.Context) {
Private: false,
AllPublic: true,
TopicOnly: false,
- Collaborate: util.OptionalBoolNone,
+ Collaborate: optional.None[bool](),
// This needs to be a column that is not nil in fixtures or
// MySQL will return different results when sorting by null in some cases
OrderBy: db.SearchOrderByAlphabetically,
@@ -2553,7 +2556,7 @@ func SearchIssues(ctx *context.Context) {
opts.OwnerID = owner.ID
opts.AllLimited = false
opts.AllPublic = false
- opts.Collaborate = util.OptionalBoolFalse
+ opts.Collaborate = optional.Some(false)
}
if ctx.FormString("team") != "" {
if ctx.FormString("owner") == "" {
@@ -2594,14 +2597,12 @@ func SearchIssues(ctx *context.Context) {
keyword = ""
}
- var isPull util.OptionalBool
+ isPull := optional.None[bool]()
switch ctx.FormString("type") {
case "pulls":
- isPull = util.OptionalBoolTrue
+ isPull = optional.Some(true)
case "issues":
- isPull = util.OptionalBoolFalse
- default:
- isPull = util.OptionalBoolNone
+ isPull = optional.Some(false)
}
var includedAnyLabels []int64
@@ -2740,14 +2741,14 @@ func ListIssues(ctx *context.Context) {
return
}
- var isClosed util.OptionalBool
+ var isClosed optional.Option[bool]
switch ctx.FormString("state") {
case "closed":
- isClosed = util.OptionalBoolTrue
+ isClosed = optional.Some(true)
case "all":
- isClosed = util.OptionalBoolNone
+ isClosed = optional.None[bool]()
default:
- isClosed = util.OptionalBoolFalse
+ isClosed = optional.Some(false)
}
keyword := ctx.FormTrim("q")
@@ -2799,14 +2800,12 @@ func ListIssues(ctx *context.Context) {
projectID = &v
}
- var isPull util.OptionalBool
+ isPull := optional.None[bool]()
switch ctx.FormString("type") {
case "pulls":
- isPull = util.OptionalBoolTrue
+ isPull = optional.Some(true)
case "issues":
- isPull = util.OptionalBoolFalse
- default:
- isPull = util.OptionalBoolNone
+ isPull = optional.Some(false)
}
// FIXME: we should be more efficient here
@@ -3322,7 +3321,7 @@ func ChangeIssueReaction(ctx *context.Context) {
return
}
- html, err := ctx.RenderToString(tplReactions, map[string]any{
+ html, err := ctx.RenderToHTML(tplReactions, map[string]any{
"ctxData": ctx.Data,
"ActionURL": fmt.Sprintf("%s/issues/%d/reactions", ctx.Repo.RepoLink, issue.Index),
"Reactions": issue.Reactions.GroupByType(),
@@ -3429,7 +3428,7 @@ func ChangeCommentReaction(ctx *context.Context) {
return
}
- html, err := ctx.RenderToString(tplReactions, map[string]any{
+ html, err := ctx.RenderToHTML(tplReactions, map[string]any{
"ctxData": ctx.Data,
"ActionURL": fmt.Sprintf("%s/comments/%d/reactions", ctx.Repo.RepoLink, comment.ID),
"Reactions": comment.Reactions.GroupByType(),
@@ -3572,8 +3571,8 @@ func updateAttachments(ctx *context.Context, item any, files []string) error {
return err
}
-func attachmentsHTML(ctx *context.Context, attachments []*repo_model.Attachment, content string) string {
- attachHTML, err := ctx.RenderToString(tplAttachment, map[string]any{
+func attachmentsHTML(ctx *context.Context, attachments []*repo_model.Attachment, content string) template.HTML {
+ attachHTML, err := ctx.RenderToHTML(tplAttachment, map[string]any{
"ctxData": ctx.Data,
"Attachments": attachments,
"Content": content,
diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go
index 4dc537a06e..dfee2863b5 100644
--- a/routers/web/repo/issue_content_history.go
+++ b/routers/web/repo/issue_content_history.go
@@ -11,11 +11,11 @@ import (
"code.gitea.io/gitea/models/avatars"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/services/context"
"github.com/sergi/go-diff/diffmatchpatch"
)
diff --git a/routers/web/repo/issue_dependency.go b/routers/web/repo/issue_dependency.go
index 022ec3ae3e..e3b85ee638 100644
--- a/routers/web/repo/issue_dependency.go
+++ b/routers/web/repo/issue_dependency.go
@@ -8,8 +8,8 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
// AddDependency adds new dependencies
diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go
index dd3e2803b4..9dedaefa4b 100644
--- a/routers/web/repo/issue_label.go
+++ b/routers/web/repo/issue_label.go
@@ -10,12 +10,12 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
issue_service "code.gitea.io/gitea/services/issue"
)
diff --git a/routers/web/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go
index 742f12114d..93fc72300b 100644
--- a/routers/web/repo/issue_label_test.go
+++ b/routers/web/repo/issue_label_test.go
@@ -10,10 +10,10 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/forms"
"github.com/stretchr/testify/assert"
diff --git a/routers/web/repo/issue_lock.go b/routers/web/repo/issue_lock.go
index f83109d9b3..1d5fc8a5f3 100644
--- a/routers/web/repo/issue_lock.go
+++ b/routers/web/repo/issue_lock.go
@@ -5,8 +5,8 @@ package repo
import (
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/repo/issue_pin.go b/routers/web/repo/issue_pin.go
index 9f334129f9..365c812681 100644
--- a/routers/web/repo/issue_pin.go
+++ b/routers/web/repo/issue_pin.go
@@ -7,9 +7,9 @@ import (
"net/http"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
// IssuePinOrUnpin pin or unpin a Issue
diff --git a/routers/web/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go
index ab9fe3e69d..70d42b27c0 100644
--- a/routers/web/repo/issue_stopwatch.go
+++ b/routers/web/repo/issue_stopwatch.go
@@ -9,8 +9,8 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/eventsource"
+ "code.gitea.io/gitea/services/context"
)
// IssueStopwatch creates or stops a stopwatch for the given issue.
diff --git a/routers/web/repo/issue_timetrack.go b/routers/web/repo/issue_timetrack.go
index c9bf861b84..241e434049 100644
--- a/routers/web/repo/issue_timetrack.go
+++ b/routers/web/repo/issue_timetrack.go
@@ -9,9 +9,9 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/repo/issue_watch.go b/routers/web/repo/issue_watch.go
index 1f51ceba5e..8b033f3b17 100644
--- a/routers/web/repo/issue_watch.go
+++ b/routers/web/repo/issue_watch.go
@@ -9,8 +9,8 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/middlewares.go b/routers/web/repo/middlewares.go
index ee49649654..ddda9f3ff2 100644
--- a/routers/web/repo/middlewares.go
+++ b/routers/web/repo/middlewares.go
@@ -9,9 +9,9 @@ import (
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go
index b70901d5f2..97b0c425ea 100644
--- a/routers/web/repo/migrate.go
+++ b/routers/web/repo/migrate.go
@@ -15,13 +15,13 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
"code.gitea.io/gitea/services/task"
diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go
index 19db2abd68..1c53f73fdb 100644
--- a/routers/web/repo/milestone.go
+++ b/routers/web/repo/milestone.go
@@ -12,13 +12,13 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/issue"
@@ -51,7 +51,7 @@ func Milestones(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
RepoID: ctx.Repo.Repository.ID,
- IsClosed: util.OptionalBoolOf(isShowClosed),
+ IsClosed: optional.Some(isShowClosed),
SortType: sortType,
Name: keyword,
})
@@ -292,7 +292,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) {
ctx.Data["Title"] = milestone.Name
ctx.Data["Milestone"] = milestone
- issues(ctx, milestoneID, projectID, util.OptionalBoolNone)
+ issues(ctx, milestoneID, projectID, optional.None[bool]())
ret, _ := issue.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
ctx.Data["NewIssueChooseTemplate"] = len(ret) > 0
diff --git a/routers/web/repo/packages.go b/routers/web/repo/packages.go
index ac9e64d774..11874ab0d0 100644
--- a/routers/web/repo/packages.go
+++ b/routers/web/repo/packages.go
@@ -10,9 +10,9 @@ import (
"code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -37,7 +37,7 @@ func Packages(ctx *context.Context) {
RepoID: ctx.Repo.Repository.ID,
Type: packages.Type(packageType),
Name: packages.SearchValue{Value: query},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
ctx.ServerError("SearchLatestVersions", err)
diff --git a/routers/web/repo/patch.go b/routers/web/repo/patch.go
index 03ea03467a..d234f6c964 100644
--- a/routers/web/repo/patch.go
+++ b/routers/web/repo/patch.go
@@ -10,10 +10,10 @@ import (
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index cc0127e7e1..4c171defbd 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -17,13 +17,13 @@ import (
attachment_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
@@ -78,7 +78,7 @@ func Projects(ctx *context.Context) {
Page: page,
},
RepoID: repo.ID,
- IsClosed: util.OptionalBoolOf(isShowClosed),
+ IsClosed: optional.Some(isShowClosed),
OrderBy: project_model.GetSearchOrderByBySortType(sortType),
Type: project_model.TypeRepository,
Title: keyword,
@@ -349,7 +349,7 @@ func ViewProject(ctx *context.Context) {
if len(referencedIDs) > 0 {
if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{
IssueIDs: referencedIDs,
- IsPull: util.OptionalBoolTrue,
+ IsPull: optional.Some(true),
}); err == nil {
linkedPrsMap[issue.ID] = linkedPrs
}
diff --git a/routers/web/repo/projects_test.go b/routers/web/repo/projects_test.go
index 6698d47028..479f8c55a2 100644
--- a/routers/web/repo/projects_test.go
+++ b/routers/web/repo/projects_test.go
@@ -7,7 +7,7 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 561039c413..c93d342e62 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -28,7 +28,6 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
@@ -37,12 +36,13 @@ import (
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/automerge"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/gitdiff"
notify_service "code.gitea.io/gitea/services/notify"
@@ -1159,7 +1159,7 @@ func UpdatePullRequest(ctx *context.Context) {
if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil {
if models.IsErrMergeConflicts(err) {
conflictError := err.(models.ErrMergeConflicts)
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.merge_conflict"),
"Summary": ctx.Tr("repo.pulls.merge_conflict_summary"),
"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
@@ -1173,7 +1173,7 @@ func UpdatePullRequest(ctx *context.Context) {
return
} else if models.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts)
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
@@ -1305,7 +1305,7 @@ func MergePullRequest(ctx *context.Context) {
ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
} else if models.IsErrMergeConflicts(err) {
conflictError := err.(models.ErrMergeConflicts)
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.merge_conflict"),
"Summary": ctx.Tr("repo.editor.merge_conflict_summary"),
"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
@@ -1318,7 +1318,7 @@ func MergePullRequest(ctx *context.Context) {
ctx.JSONRedirect(issue.Link())
} else if models.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts)
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
"Details": utils.SanitizeFlashErrorString(conflictError.StdErr) + "<br>" + utils.SanitizeFlashErrorString(conflictError.StdOut),
@@ -1348,7 +1348,7 @@ func MergePullRequest(ctx *context.Context) {
if len(message) == 0 {
ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected_no_message"))
} else {
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.push_rejected"),
"Summary": ctx.Tr("repo.pulls.push_rejected_summary"),
"Details": utils.SanitizeFlashErrorString(pushrejErr.Message),
@@ -1525,7 +1525,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
ctx.JSONError(ctx.Tr("repo.pulls.push_rejected_no_message"))
return
}
- flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
+ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.push_rejected"),
"Summary": ctx.Tr("repo.pulls.push_rejected_summary"),
"Details": utils.SanitizeFlashErrorString(pushrejErr.Message),
@@ -1534,8 +1534,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
ctx.ServerError("CompareAndPullRequest.HTMLString", err)
return
}
- ctx.Flash.Error(flashError)
- ctx.JSONRedirect(pullIssue.Link()) // FIXME: it's unfriendly, and will make the content lost
+ ctx.JSONError(flashError)
return
}
ctx.ServerError("NewPullRequest", err)
diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go
index 798d3d5454..ead7592fd0 100644
--- a/routers/web/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
@@ -11,12 +11,12 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
pull_model "code.gitea.io/gitea/models/pull"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/forms"
pull_service "code.gitea.io/gitea/services/pull"
)
diff --git a/routers/web/repo/pull_review_test.go b/routers/web/repo/pull_review_test.go
index 68f68d7bb0..d87656f796 100644
--- a/routers/web/repo/pull_review_test.go
+++ b/routers/web/repo/pull_review_test.go
@@ -10,9 +10,9 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/context"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/pull"
"github.com/stretchr/testify/assert"
diff --git a/routers/web/repo/recent_commits.go b/routers/web/repo/recent_commits.go
index 3507cb8752..c158fb30b6 100644
--- a/routers/web/repo/recent_commits.go
+++ b/routers/web/repo/recent_commits.go
@@ -8,7 +8,7 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
contributors_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go
index 79f3181ba0..95447a8f54 100644
--- a/routers/web/repo/release.go
+++ b/routers/web/repo/release.go
@@ -17,16 +17,17 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/feed"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/forms"
releaseservice "code.gitea.io/gitea/services/release"
)
@@ -112,7 +113,7 @@ func getReleaseInfos(ctx *context.Context, opts *repo_model.FindReleasesOptions)
cacheUsers[r.PublisherID] = r.Publisher
}
- r.Note, err = markdown.RenderString(&markup.RenderContext{
+ r.RenderedNote, err = markdown.RenderString(&markup.RenderContext{
Links: markup.Links{
Base: ctx.Repo.RepoLink,
},
@@ -228,7 +229,7 @@ func TagsList(ctx *context.Context) {
// the drafts should also be included because a real tag might be used as a draft.
IncludeDrafts: true,
IncludeTags: true,
- HasSha1: util.OptionalBoolTrue,
+ HasSha1: optional.Some(true),
RepoID: ctx.Repo.Repository.ID,
}
diff --git a/routers/web/repo/release_test.go b/routers/web/repo/release_test.go
index c4a2c1904e..7ebea4c3fb 100644
--- a/routers/web/repo/release_test.go
+++ b/routers/web/repo/release_test.go
@@ -10,8 +10,8 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/forms"
"github.com/stretchr/testify/assert"
diff --git a/routers/web/repo/render.go b/routers/web/repo/render.go
index 7eb5a42aa4..10fa21c60e 100644
--- a/routers/web/repo/render.go
+++ b/routers/web/repo/render.go
@@ -10,11 +10,11 @@ import (
"path"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
// RenderFile renders a file by repos path
diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go
index 17e5d9b582..77aab8354b 100644
--- a/routers/web/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -21,7 +21,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
@@ -31,6 +30,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
repo_service "code.gitea.io/gitea/services/repository"
@@ -244,7 +244,7 @@ func CreatePost(ctx *context.Context) {
var repo *repo_model.Repository
var err error
if form.RepoTemplate > 0 {
- opts := repo_module.GenerateRepoOptions{
+ opts := repo_service.GenerateRepoOptions{
Name: form.RepoName,
Description: form.Description,
Private: form.Private,
@@ -553,33 +553,33 @@ func SearchRepo(ctx *context.Context) {
PriorityOwnerID: ctx.FormInt64("priority_owner_id"),
TeamID: ctx.FormInt64("team_id"),
TopicOnly: ctx.FormBool("topic"),
- Collaborate: util.OptionalBoolNone,
+ Collaborate: optional.None[bool](),
Private: ctx.IsSigned && (ctx.FormString("private") == "" || ctx.FormBool("private")),
- Template: util.OptionalBoolNone,
+ Template: optional.None[bool](),
StarredByID: ctx.FormInt64("starredBy"),
IncludeDescription: ctx.FormBool("includeDesc"),
}
if ctx.FormString("template") != "" {
- opts.Template = util.OptionalBoolOf(ctx.FormBool("template"))
+ opts.Template = optional.Some(ctx.FormBool("template"))
}
if ctx.FormBool("exclusive") {
- opts.Collaborate = util.OptionalBoolFalse
+ opts.Collaborate = optional.Some(false)
}
mode := ctx.FormString("mode")
switch mode {
case "source":
- opts.Fork = util.OptionalBoolFalse
- opts.Mirror = util.OptionalBoolFalse
+ opts.Fork = optional.Some(false)
+ opts.Mirror = optional.Some(false)
case "fork":
- opts.Fork = util.OptionalBoolTrue
+ opts.Fork = optional.Some(true)
case "mirror":
- opts.Mirror = util.OptionalBoolTrue
+ opts.Mirror = optional.Some(true)
case "collaborative":
- opts.Mirror = util.OptionalBoolFalse
- opts.Collaborate = util.OptionalBoolTrue
+ opts.Mirror = optional.Some(false)
+ opts.Collaborate = optional.Some(true)
case "":
default:
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("Invalid search mode: \"%s\"", mode))
@@ -587,11 +587,11 @@ func SearchRepo(ctx *context.Context) {
}
if ctx.FormString("archived") != "" {
- opts.Archived = util.OptionalBoolOf(ctx.FormBool("archived"))
+ opts.Archived = optional.Some(ctx.FormBool("archived"))
}
if ctx.FormString("is_private") != "" {
- opts.IsPrivate = util.OptionalBoolOf(ctx.FormBool("is_private"))
+ opts.IsPrivate = optional.Some(ctx.FormBool("is_private"))
}
sortMode := ctx.FormString("sort")
diff --git a/routers/web/repo/search.go b/routers/web/repo/search.go
index 29b3b7b476..74970c02c9 100644
--- a/routers/web/repo/search.go
+++ b/routers/web/repo/search.go
@@ -7,9 +7,9 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/repository/files"
)
diff --git a/routers/web/repo/setting/avatar.go b/routers/web/repo/setting/avatar.go
index 44468d2666..504f57cfc2 100644
--- a/routers/web/repo/setting/avatar.go
+++ b/routers/web/repo/setting/avatar.go
@@ -8,11 +8,11 @@ import (
"fmt"
"io"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/repo/setting/collaboration.go b/routers/web/repo/setting/collaboration.go
index a73a7e5a8a..75b55151e7 100644
--- a/routers/web/repo/setting/collaboration.go
+++ b/routers/web/repo/setting/collaboration.go
@@ -14,10 +14,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/mailer"
org_service "code.gitea.io/gitea/services/org"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/routers/web/repo/setting/default_branch.go b/routers/web/repo/setting/default_branch.go
index 9bf54e706a..610fc5bcdf 100644
--- a/routers/web/repo/setting/default_branch.go
+++ b/routers/web/repo/setting/default_branch.go
@@ -7,11 +7,11 @@ import (
"net/http"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers/web/repo"
+ "code.gitea.io/gitea/services/context"
notify_service "code.gitea.io/gitea/services/notify"
)
diff --git a/routers/web/repo/setting/deploy_key.go b/routers/web/repo/setting/deploy_key.go
index 3d4420006c..abc3eb4af1 100644
--- a/routers/web/repo/setting/deploy_key.go
+++ b/routers/web/repo/setting/deploy_key.go
@@ -8,11 +8,11 @@ import (
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/repo/setting/git_hooks.go b/routers/web/repo/setting/git_hooks.go
index 551327d44b..217a01c90c 100644
--- a/routers/web/repo/setting/git_hooks.go
+++ b/routers/web/repo/setting/git_hooks.go
@@ -6,8 +6,8 @@ package setting
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/services/context"
)
// GitHooks hooks of a repository
diff --git a/routers/web/repo/setting/lfs.go b/routers/web/repo/setting/lfs.go
index 53e7b22d1b..9b66af37b2 100644
--- a/routers/web/repo/setting/lfs.go
+++ b/routers/web/repo/setting/lfs.go
@@ -18,7 +18,6 @@ import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git/pipeline"
"code.gitea.io/gitea/modules/lfs"
@@ -28,6 +27,7 @@ import (
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go
index 827ebea7f8..b37520a390 100644
--- a/routers/web/repo/setting/protected_branch.go
+++ b/routers/web/repo/setting/protected_branch.go
@@ -15,9 +15,9 @@ import (
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/repo"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
pull_service "code.gitea.io/gitea/services/pull"
"code.gitea.io/gitea/services/repository"
diff --git a/routers/web/repo/setting/protected_tag.go b/routers/web/repo/setting/protected_tag.go
index 46addb3f0a..2c25b650b9 100644
--- a/routers/web/repo/setting/protected_tag.go
+++ b/routers/web/repo/setting/protected_tag.go
@@ -13,9 +13,9 @@ import (
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/repo/setting/runners.go b/routers/web/repo/setting/runners.go
index 8d4112c157..a47d3b45e2 100644
--- a/routers/web/repo/setting/runners.go
+++ b/routers/web/repo/setting/runners.go
@@ -11,10 +11,10 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
actions_shared "code.gitea.io/gitea/routers/web/shared/actions"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/setting/secrets.go b/routers/web/repo/setting/secrets.go
index cf427b2c44..d4d56bfc57 100644
--- a/routers/web/repo/setting/secrets.go
+++ b/routers/web/repo/setting/secrets.go
@@ -8,10 +8,10 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
shared "code.gitea.io/gitea/routers/web/shared/secrets"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go
index 0fdae7ec56..99c15b74f3 100644
--- a/routers/web/repo/setting/setting.go
+++ b/routers/web/repo/setting/setting.go
@@ -19,7 +19,6 @@ import (
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/indexer/stats"
@@ -31,6 +30,7 @@ import (
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
mirror_service "code.gitea.io/gitea/services/mirror"
diff --git a/routers/web/repo/setting/settings_test.go b/routers/web/repo/setting/settings_test.go
index 1ed6858b99..b771113841 100644
--- a/routers/web/repo/setting/settings_test.go
+++ b/routers/web/repo/setting/settings_test.go
@@ -14,10 +14,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/forms"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/routers/web/repo/setting/variables.go b/routers/web/repo/setting/variables.go
index 428aa0bd5c..45b6c0f39a 100644
--- a/routers/web/repo/setting/variables.go
+++ b/routers/web/repo/setting/variables.go
@@ -8,10 +8,10 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
shared "code.gitea.io/gitea/routers/web/shared/actions"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go
index 7bbe4d81a9..4e967c86d6 100644
--- a/routers/web/repo/setting/webhook.go
+++ b/routers/web/repo/setting/webhook.go
@@ -18,7 +18,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
@@ -26,6 +25,7 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
webhook_module "code.gitea.io/gitea/modules/webhook"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
webhook_service "code.gitea.io/gitea/services/webhook"
diff --git a/routers/web/repo/topic.go b/routers/web/repo/topic.go
index d0e706c5bd..d81a695df9 100644
--- a/routers/web/repo/topic.go
+++ b/routers/web/repo/topic.go
@@ -8,8 +8,8 @@ import (
"strings"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
// TopicsPost response for creating repository
diff --git a/routers/web/repo/treelist.go b/routers/web/repo/treelist.go
index c364e7090f..d11af4669f 100644
--- a/routers/web/repo/treelist.go
+++ b/routers/web/repo/treelist.go
@@ -7,8 +7,8 @@ import (
"net/http"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/services/context"
"github.com/go-enry/go-enry/v2"
)
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index 32c09bb5f2..27984e7621 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -35,8 +35,6 @@ import (
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/lfs"
@@ -48,6 +46,7 @@ import (
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
+ "code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
files_service "code.gitea.io/gitea/services/repository/files"
@@ -881,25 +880,18 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
defer cancel()
}
- selected := make(container.Set[string])
- selected.AddMultiple(ctx.FormStrings("f[]")...)
-
- entries := allEntries
- if len(selected) > 0 {
- entries = make(git.Entries, 0, len(selected))
- for _, entry := range allEntries {
- if selected.Contains(entry.Name()) {
- entries = append(entries, entry)
- }
- }
- }
-
- var latestCommit *git.Commit
- ctx.Data["Files"], latestCommit, err = entries.GetCommitsInfo(commitInfoCtx, ctx.Repo.Commit, ctx.Repo.TreePath)
+ files, latestCommit, err := allEntries.GetCommitsInfo(commitInfoCtx, ctx.Repo.Commit, ctx.Repo.TreePath)
if err != nil {
ctx.ServerError("GetCommitsInfo", err)
return nil
}
+ ctx.Data["Files"] = files
+ for _, f := range files {
+ if f.Commit == nil {
+ ctx.Data["HasFilesWithoutLatestCommit"] = true
+ break
+ }
+ }
if !loadLatestCommitData(ctx, latestCommit) {
return nil
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 157ebd4d5d..f0743cc89c 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -18,7 +18,6 @@ import (
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
@@ -29,6 +28,7 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
notify_service "code.gitea.io/gitea/services/notify"
wiki_service "code.gitea.io/gitea/services/wiki"
diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go
index d3decdae2d..49c83cfef5 100644
--- a/routers/web/repo/wiki_test.go
+++ b/routers/web/repo/wiki_test.go
@@ -11,10 +11,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/forms"
wiki_service "code.gitea.io/gitea/services/wiki"
diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go
index ae9a376724..34b7969442 100644
--- a/routers/web/shared/actions/runners.go
+++ b/routers/web/shared/actions/runners.go
@@ -8,10 +8,10 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/shared/actions/variables.go b/routers/web/shared/actions/variables.go
index 07a0575207..0f705399c9 100644
--- a/routers/web/shared/actions/variables.go
+++ b/routers/web/shared/actions/variables.go
@@ -10,9 +10,9 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
secret_service "code.gitea.io/gitea/services/secrets"
)
diff --git a/routers/web/shared/packages/packages.go b/routers/web/shared/packages/packages.go
index 30c25374d1..57671ad8f1 100644
--- a/routers/web/shared/packages/packages.go
+++ b/routers/web/shared/packages/packages.go
@@ -12,10 +12,10 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
cargo_service "code.gitea.io/gitea/services/packages/cargo"
container_service "code.gitea.io/gitea/services/packages/container"
@@ -157,7 +157,7 @@ func SetRulePreviewContext(ctx *context.Context, owner *user_model.User) {
for _, p := range packages {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
PackageID: p.ID,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Sort: packages_model.SortCreatedDesc,
Paginator: db.NewAbsoluteListOptions(pcr.KeepCount, 200),
})
diff --git a/routers/web/shared/secrets/secrets.go b/routers/web/shared/secrets/secrets.go
index c805da734a..73505ec372 100644
--- a/routers/web/shared/secrets/secrets.go
+++ b/routers/web/shared/secrets/secrets.go
@@ -6,10 +6,10 @@ package secrets
import (
"code.gitea.io/gitea/models/db"
secret_model "code.gitea.io/gitea/models/secret"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/shared/actions"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
secret_service "code.gitea.io/gitea/services/secrets"
)
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
index 07026e484f..f007772d6c 100644
--- a/routers/web/shared/user/header.go
+++ b/routers/web/shared/user/header.go
@@ -13,12 +13,12 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
)
// prepareContextForCommonProfile store some common data into context data for user's profile related pages (including the nav menu)
@@ -36,8 +36,9 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) {
ctx.Data["IsBlocked"] = ctx.Doer != nil && user_model.IsBlocked(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
- ctx.Data["ContextUserLocationMapURL"] = setting.Service.UserLocationMapURL + url.QueryEscape(ctx.ContextUser.Location)
-
+ if setting.Service.UserLocationMapURL != "" {
+ ctx.Data["ContextUserLocationMapURL"] = setting.Service.UserLocationMapURL + url.QueryEscape(ctx.ContextUser.Location)
+ }
// Show OpenID URIs
openIDs, err := user_model.GetUserOpenIDs(ctx, ctx.ContextUser.ID)
if err != nil {
@@ -114,7 +115,7 @@ func LoadHeaderCount(ctx *context.Context) error {
Actor: ctx.Doer,
OwnerID: ctx.ContextUser.ID,
Private: ctx.IsSigned,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
IncludeDescription: setting.UI.SearchRepoDescription,
})
if err != nil {
@@ -130,7 +131,7 @@ func LoadHeaderCount(ctx *context.Context) error {
}
projectCount, err := db.Count[project_model.Project](ctx, project_model.SearchOptions{
OwnerID: ctx.ContextUser.ID,
- IsClosed: util.OptionalBoolOf(false),
+ IsClosed: optional.Some(false),
Type: projectType,
})
if err != nil {
diff --git a/routers/web/swagger_json.go b/routers/web/swagger_json.go
index 42e9dbe967..fc39b504a9 100644
--- a/routers/web/swagger_json.go
+++ b/routers/web/swagger_json.go
@@ -4,7 +4,7 @@
package web
import (
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
)
// SwaggerV1Json render swagger v1 json
diff --git a/routers/web/user/avatar.go b/routers/web/user/avatar.go
index 772cc38bea..04f510161d 100644
--- a/routers/web/user/avatar.go
+++ b/routers/web/user/avatar.go
@@ -9,8 +9,8 @@ import (
"code.gitea.io/gitea/models/avatars"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/httpcache"
+ "code.gitea.io/gitea/services/context"
)
func cacheableRedirect(ctx *context.Context, location string) {
diff --git a/routers/web/user/code.go b/routers/web/user/code.go
index ee514a7cfe..eb711b76eb 100644
--- a/routers/web/user/code.go
+++ b/routers/web/user/code.go
@@ -8,10 +8,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/user/home.go b/routers/web/user/home.go
index 8759ba32b1..3ff4efc489 100644
--- a/routers/web/user/home.go
+++ b/routers/web/user/home.go
@@ -24,15 +24,14 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
- context_service "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"
@@ -162,8 +161,8 @@ func Milestones(ctx *context.Context) {
Private: true,
AllPublic: false, // Include also all public repositories of users and public organisations
AllLimited: false, // Include also all public repositories of limited organisations
- Archived: util.OptionalBoolFalse,
- HasMilestones: util.OptionalBoolTrue, // Just needs display repos has milestones
+ Archived: optional.Some(false),
+ HasMilestones: optional.Some(true), // Just needs display repos has milestones
}
if ctxUser.IsOrganization() && ctx.Org.Team != nil {
@@ -215,7 +214,7 @@ func Milestones(ctx *context.Context) {
counts, err := issues_model.CountMilestonesMap(ctx, issues_model.FindMilestoneOptions{
RepoCond: userRepoCond,
Name: keyword,
- IsClosed: util.OptionalBoolOf(isShowClosed),
+ IsClosed: optional.Some(isShowClosed),
})
if err != nil {
ctx.ServerError("CountMilestonesByRepoIDs", err)
@@ -228,7 +227,7 @@ func Milestones(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
RepoCond: repoCond,
- IsClosed: util.OptionalBoolOf(isShowClosed),
+ IsClosed: optional.Some(isShowClosed),
SortType: sortType,
Name: keyword,
})
@@ -440,9 +439,9 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
isPullList := unitType == unit.TypePullRequests
opts := &issues_model.IssuesOptions{
- IsPull: util.OptionalBoolOf(isPullList),
+ IsPull: optional.Some(isPullList),
SortType: sortType,
- IsArchived: util.OptionalBoolFalse,
+ IsArchived: optional.Some(false),
Org: org,
Team: team,
User: ctx.Doer,
@@ -466,9 +465,9 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
Private: true,
AllPublic: false,
AllLimited: false,
- Collaborate: util.OptionalBoolNone,
+ Collaborate: optional.None[bool](),
UnitType: unitType,
- Archived: util.OptionalBoolFalse,
+ Archived: optional.Some(false),
}
if team != nil {
repoOpts.TeamID = team.ID
@@ -516,7 +515,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
// Educated guess: Do or don't show closed issues.
isShowClosed := ctx.FormString("state") == "closed"
- opts.IsClosed = util.OptionalBoolOf(isShowClosed)
+ opts.IsClosed = optional.Some(isShowClosed)
// Make sure page number is at least 1. Will be posted to ctx.Data.
page := ctx.FormInt("page")
@@ -714,7 +713,7 @@ func UsernameSubRoute(ctx *context.Context) {
username := ctx.Params("username")
reloadParam := func(suffix string) (success bool) {
ctx.SetParams("username", strings.TrimSuffix(username, suffix))
- context_service.UserAssignmentWeb()(ctx)
+ context.UserAssignmentWeb()(ctx)
if ctx.Written() {
return false
}
@@ -744,7 +743,7 @@ func UsernameSubRoute(ctx *context.Context) {
return
}
if reloadParam(".rss") {
- context_service.UserAssignmentWeb()(ctx)
+ context.UserAssignmentWeb()(ctx)
feed.ShowUserFeedRSS(ctx)
}
case strings.HasSuffix(username, ".atom"):
@@ -756,7 +755,7 @@ func UsernameSubRoute(ctx *context.Context) {
feed.ShowUserFeedAtom(ctx)
}
default:
- context_service.UserAssignmentWeb()(ctx)
+ context.UserAssignmentWeb()(ctx)
if !ctx.Written() {
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
OwnerProfile(ctx)
@@ -803,12 +802,12 @@ func getUserIssueStats(ctx *context.Context, ctxUser *user_model.User, filterMod
case issues_model.FilterModeReviewed:
openClosedOpts.ReviewedID = &doerID
}
- openClosedOpts.IsClosed = util.OptionalBoolFalse
+ openClosedOpts.IsClosed = optional.Some(false)
ret.OpenCount, err = issue_indexer.CountIssues(ctx, openClosedOpts)
if err != nil {
return nil, err
}
- openClosedOpts.IsClosed = util.OptionalBoolTrue
+ openClosedOpts.IsClosed = optional.Some(true)
ret.ClosedCount, err = issue_indexer.CountIssues(ctx, openClosedOpts)
if err != nil {
return nil, err
diff --git a/routers/web/user/home_test.go b/routers/web/user/home_test.go
index a32b015cd1..1cc9886308 100644
--- a/routers/web/user/home_test.go
+++ b/routers/web/user/home_test.go
@@ -10,8 +10,10 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
@@ -113,3 +115,18 @@ func TestMilestonesForSpecificRepo(t *testing.T) {
assert.Len(t, ctx.Data["Milestones"], 1)
assert.Len(t, ctx.Data["Repos"], 2) // both repo 42 and 1 have milestones and both are owned by user 2
}
+
+func TestDashboardPagination(t *testing.T) {
+ ctx, _ := contexttest.MockContext(t, "/", contexttest.MockContextOption{Render: templates.HTMLRenderer()})
+ page := context.NewPagination(10, 3, 1, 3)
+
+ setting.AppSubURL = "/SubPath"
+ out, err := ctx.RenderToHTML("base/paginate", map[string]any{"Link": setting.AppSubURL, "Page": page})
+ assert.NoError(t, err)
+ assert.Contains(t, out, `<a class=" item navigation" href="/SubPath/?page=2">`)
+
+ setting.AppSubURL = ""
+ out, err = ctx.RenderToHTML("base/paginate", map[string]any{"Link": setting.AppSubURL, "Page": page})
+ assert.NoError(t, err)
+ assert.Contains(t, out, `<a class=" item navigation" href="/?page=2">`)
+}
diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go
index 26f77cfc3a..324205ed91 100644
--- a/routers/web/user/notification.go
+++ b/routers/web/user/notification.go
@@ -16,11 +16,12 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"
)
@@ -232,26 +233,25 @@ func NotificationSubscriptions(ctx *context.Context) {
if !util.SliceContainsString([]string{"all", "open", "closed"}, state, true) {
state = "all"
}
+
ctx.Data["State"] = state
- var showClosed util.OptionalBool
+ // default state filter is "all"
+ showClosed := optional.None[bool]()
switch state {
- case "all":
- showClosed = util.OptionalBoolNone
case "closed":
- showClosed = util.OptionalBoolTrue
+ showClosed = optional.Some(true)
case "open":
- showClosed = util.OptionalBoolFalse
+ showClosed = optional.Some(false)
}
- var issueTypeBool util.OptionalBool
issueType := ctx.FormString("issueType")
+ // default issue type is no filter
+ issueTypeBool := optional.None[bool]()
switch issueType {
case "issues":
- issueTypeBool = util.OptionalBoolFalse
+ issueTypeBool = optional.Some(false)
case "pulls":
- issueTypeBool = util.OptionalBoolTrue
- default:
- issueTypeBool = util.OptionalBoolNone
+ issueTypeBool = optional.Some(true)
}
ctx.Data["IssueType"] = issueType
@@ -389,6 +389,21 @@ func NotificationWatching(ctx *context.Context) {
orderBy = db.SearchOrderByRecentUpdated
}
+ archived := ctx.FormOptionalBool("archived")
+ ctx.Data["IsArchived"] = archived
+
+ fork := ctx.FormOptionalBool("fork")
+ ctx.Data["IsFork"] = fork
+
+ mirror := ctx.FormOptionalBool("mirror")
+ ctx.Data["IsMirror"] = mirror
+
+ template := ctx.FormOptionalBool("template")
+ ctx.Data["IsTemplate"] = template
+
+ private := ctx.FormOptionalBool("private")
+ ctx.Data["IsPrivate"] = private
+
repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
PageSize: setting.UI.User.RepoPagingNum,
@@ -399,9 +414,14 @@ func NotificationWatching(ctx *context.Context) {
OrderBy: orderBy,
Private: ctx.IsSigned,
WatchedByID: ctx.Doer.ID,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
TopicOnly: ctx.FormBool("topic"),
IncludeDescription: setting.UI.SearchRepoDescription,
+ Archived: archived,
+ Fork: fork,
+ Mirror: mirror,
+ Template: template,
+ IsPrivate: private,
})
if err != nil {
ctx.ServerError("SearchRepository", err)
diff --git a/routers/web/user/package.go b/routers/web/user/package.go
index 708af3e43c..3ecc59a2ab 100644
--- a/routers/web/user/package.go
+++ b/routers/web/user/package.go
@@ -15,8 +15,8 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
alpine_module "code.gitea.io/gitea/modules/packages/alpine"
debian_module "code.gitea.io/gitea/modules/packages/debian"
rpm_module "code.gitea.io/gitea/modules/packages/rpm"
@@ -25,6 +25,7 @@ import (
"code.gitea.io/gitea/modules/web"
packages_helper "code.gitea.io/gitea/routers/api/packages/helper"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
packages_service "code.gitea.io/gitea/services/packages"
)
@@ -54,7 +55,7 @@ func ListPackages(ctx *context.Context) {
OwnerID: ctx.ContextUser.ID,
Type: packages_model.Type(packageType),
Name: packages_model.SearchValue{Value: query},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
ctx.ServerError("SearchLatestVersions", err)
@@ -145,7 +146,7 @@ func RedirectToLastVersion(ctx *context.Context) {
pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
PackageID: p.ID,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
ctx.ServerError("GetPackageByName", err)
@@ -162,7 +163,7 @@ func RedirectToLastVersion(ctx *context.Context) {
return
}
- ctx.Redirect(pd.FullWebLink())
+ ctx.Redirect(pd.VersionWebLink())
}
// ViewPackageVersion displays a single package version
@@ -255,7 +256,7 @@ func ViewPackageVersion(ctx *context.Context) {
pvs, total, err = packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
Paginator: db.NewAbsoluteListOptions(0, 5),
PackageID: pd.Package.ID,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
}
if err != nil {
@@ -359,7 +360,7 @@ func ListPackageVersions(ctx *context.Context) {
ExactMatch: false,
Value: query,
},
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Sort: sort,
})
if err != nil {
@@ -467,7 +468,7 @@ func PackageSettingsPost(ctx *context.Context) {
redirectURL := ctx.Package.Owner.HomeLink() + "/-/packages"
// redirect to the package if there are still versions available
- if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID, IsInternal: util.OptionalBoolFalse}); has {
+ if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID, IsInternal: optional.Some(false)}); has {
redirectURL = ctx.Package.Descriptor.PackageWebLink()
}
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 4eec0e9905..89d22d3ef4 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -16,16 +16,17 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
"code.gitea.io/gitea/routers/web/org"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
@@ -163,6 +164,21 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
}
ctx.Data["NumFollowing"] = numFollowing
+ archived := ctx.FormOptionalBool("archived")
+ ctx.Data["IsArchived"] = archived
+
+ fork := ctx.FormOptionalBool("fork")
+ ctx.Data["IsFork"] = fork
+
+ mirror := ctx.FormOptionalBool("mirror")
+ ctx.Data["IsMirror"] = mirror
+
+ template := ctx.FormOptionalBool("template")
+ ctx.Data["IsTemplate"] = template
+
+ private := ctx.FormOptionalBool("private")
+ ctx.Data["IsPrivate"] = private
+
switch tab {
case "followers":
ctx.Data["Cards"] = followers
@@ -205,10 +221,15 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
OrderBy: orderBy,
Private: ctx.IsSigned,
StarredByID: ctx.ContextUser.ID,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
TopicOnly: topicOnly,
Language: language,
IncludeDescription: setting.UI.SearchRepoDescription,
+ Archived: archived,
+ Fork: fork,
+ Mirror: mirror,
+ Template: template,
+ IsPrivate: private,
})
if err != nil {
ctx.ServerError("SearchRepository", err)
@@ -227,10 +248,15 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
OrderBy: orderBy,
Private: ctx.IsSigned,
WatchedByID: ctx.ContextUser.ID,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
TopicOnly: topicOnly,
Language: language,
IncludeDescription: setting.UI.SearchRepoDescription,
+ Archived: archived,
+ Fork: fork,
+ Mirror: mirror,
+ Template: template,
+ IsPrivate: private,
})
if err != nil {
ctx.ServerError("SearchRepository", err)
@@ -272,10 +298,15 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
OwnerID: ctx.ContextUser.ID,
OrderBy: orderBy,
Private: ctx.IsSigned,
- Collaborate: util.OptionalBoolFalse,
+ Collaborate: optional.Some(false),
TopicOnly: topicOnly,
Language: language,
IncludeDescription: setting.UI.SearchRepoDescription,
+ Archived: archived,
+ Fork: fork,
+ Mirror: mirror,
+ Template: template,
+ IsPrivate: private,
})
if err != nil {
ctx.ServerError("SearchRepository", err)
diff --git a/routers/web/user/search.go b/routers/web/user/search.go
index 4d090a3784..fb7729bbe1 100644
--- a/routers/web/user/search.go
+++ b/routers/web/user/search.go
@@ -8,7 +8,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/web/user/setting/account.go b/routers/web/user/setting/account.go
index 6042e0b6cd..ef02cd24a7 100644
--- a/routers/web/user/setting/account.go
+++ b/routers/web/user/setting/account.go
@@ -13,13 +13,13 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/auth"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/mailer"
"code.gitea.io/gitea/services/user"
diff --git a/routers/web/user/setting/account_test.go b/routers/web/user/setting/account_test.go
index 6742c382e9..9fdc5e4d53 100644
--- a/routers/web/user/setting/account_test.go
+++ b/routers/web/user/setting/account_test.go
@@ -8,9 +8,9 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/forms"
"github.com/stretchr/testify/assert"
diff --git a/routers/web/user/setting/adopt.go b/routers/web/user/setting/adopt.go
index decb35c1e1..171c1933d4 100644
--- a/routers/web/user/setting/adopt.go
+++ b/routers/web/user/setting/adopt.go
@@ -8,9 +8,9 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
)
diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go
index a7e31fd505..e3822ca988 100644
--- a/routers/web/user/setting/applications.go
+++ b/routers/web/user/setting/applications.go
@@ -10,9 +10,9 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/user/setting/blocked_users.go b/routers/web/user/setting/blocked_users.go
index ed1c340fb9..3f35b2eadf 100644
--- a/routers/web/user/setting/blocked_users.go
+++ b/routers/web/user/setting/blocked_users.go
@@ -9,8 +9,8 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go
index 16410d06ff..cb01913bda 100644
--- a/routers/web/user/setting/keys.go
+++ b/routers/web/user/setting/keys.go
@@ -5,15 +5,16 @@
package setting
import (
+ "fmt"
"net/http"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
@@ -77,6 +78,11 @@ func KeysPost(ctx *context.Context) {
ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
case "gpg":
+ if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
+ ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
+ return
+ }
+
token := asymkey_model.VerificationToken(ctx.Doer, 1)
lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
@@ -224,6 +230,10 @@ func KeysPost(ctx *context.Context) {
func DeleteKey(ctx *context.Context) {
switch ctx.FormString("type") {
case "gpg":
+ if setting.Admin.UserDisabledFeatures.Contains(setting.UserFeatureManageGPGKeys) {
+ ctx.NotFound("Not Found", fmt.Errorf("gpg keys setting is not allowed to be visited"))
+ return
+ }
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.FormInt64("id")); err != nil {
ctx.Flash.Error("DeleteGPGKey: " + err.Error())
} else {
diff --git a/routers/web/user/setting/oauth2.go b/routers/web/user/setting/oauth2.go
index 93142c21fc..1f485e06c8 100644
--- a/routers/web/user/setting/oauth2.go
+++ b/routers/web/user/setting/oauth2.go
@@ -5,8 +5,8 @@ package setting
import (
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/user/setting/oauth2_common.go b/routers/web/user/setting/oauth2_common.go
index fecaa4b873..85d1e820a5 100644
--- a/routers/web/user/setting/oauth2_common.go
+++ b/routers/web/user/setting/oauth2_common.go
@@ -9,10 +9,10 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/user/setting/packages.go b/routers/web/user/setting/packages.go
index 34d18f999e..4132659495 100644
--- a/routers/web/user/setting/packages.go
+++ b/routers/web/user/setting/packages.go
@@ -9,11 +9,11 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
chef_module "code.gitea.io/gitea/modules/packages/chef"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
shared "code.gitea.io/gitea/routers/web/shared/packages"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index 24a807d518..49eb050dcb 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -20,7 +20,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
@@ -29,6 +28,7 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/routers/web/user/setting/runner.go b/routers/web/user/setting/runner.go
index 451fd0ca97..2bb10cceb9 100644
--- a/routers/web/user/setting/runner.go
+++ b/routers/web/user/setting/runner.go
@@ -4,8 +4,8 @@
package setting
import (
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
func RedirectToDefaultSetting(ctx *context.Context) {
diff --git a/routers/web/user/setting/security/2fa.go b/routers/web/user/setting/security/2fa.go
index 7858b634ce..cd09102369 100644
--- a/routers/web/user/setting/security/2fa.go
+++ b/routers/web/user/setting/security/2fa.go
@@ -13,10 +13,10 @@ import (
"strings"
"code.gitea.io/gitea/models/auth"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"github.com/pquerna/otp"
diff --git a/routers/web/user/setting/security/openid.go b/routers/web/user/setting/security/openid.go
index 9a207e149d..8f788e1735 100644
--- a/routers/web/user/setting/security/openid.go
+++ b/routers/web/user/setting/security/openid.go
@@ -8,10 +8,10 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/openid"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go
index 3647d606ee..8d6859ab87 100644
--- a/routers/web/user/setting/security/security.go
+++ b/routers/web/user/setting/security/security.go
@@ -12,10 +12,10 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/auth/source/oauth2"
+ "code.gitea.io/gitea/services/context"
)
const (
@@ -112,7 +112,7 @@ func loadSecurityData(ctx *context.Context) {
ctx.Data["AccountLinks"] = sources
authSources, err := db.Find[auth_model.Source](ctx, auth_model.FindSourcesOptions{
- IsActive: util.OptionalBoolNone,
+ IsActive: optional.None[bool](),
LoginType: auth_model.OAuth2,
})
if err != nil {
diff --git a/routers/web/user/setting/security/webauthn.go b/routers/web/user/setting/security/webauthn.go
index ce103528c5..e382c8b9af 100644
--- a/routers/web/user/setting/security/webauthn.go
+++ b/routers/web/user/setting/security/webauthn.go
@@ -11,10 +11,10 @@ import (
"code.gitea.io/gitea/models/auth"
wa "code.gitea.io/gitea/modules/auth/webauthn"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"github.com/go-webauthn/webauthn/protocol"
diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go
index 679b72e501..4423b62781 100644
--- a/routers/web/user/setting/webhooks.go
+++ b/routers/web/user/setting/webhooks.go
@@ -9,8 +9,8 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
const (
diff --git a/routers/web/user/stop_watch.go b/routers/web/user/stop_watch.go
index 86f66e64a6..38f74ea455 100644
--- a/routers/web/user/stop_watch.go
+++ b/routers/web/user/stop_watch.go
@@ -8,7 +8,7 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/routers/web/user/task.go b/routers/web/user/task.go
index bec68c5f20..8476767e9e 100644
--- a/routers/web/user/task.go
+++ b/routers/web/user/task.go
@@ -8,8 +8,8 @@ import (
"strconv"
admin_model "code.gitea.io/gitea/models/admin"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/services/context"
)
// TaskStatus returns task's status
diff --git a/routers/web/web.go b/routers/web/web.go
index fc09ed2b6b..114a50cf08 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -12,7 +12,6 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/metrics"
"code.gitea.io/gitea/modules/public"
@@ -44,7 +43,7 @@ import (
user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/routers/web/user/setting/security"
auth_service "code.gitea.io/gitea/services/auth"
- context_service "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/lfs"
@@ -795,7 +794,7 @@ func registerRoutes(m *web.Route) {
m.Methods("GET, OPTIONS", "/attachments/{uuid}", optionsCorsHandler(), repo.GetAttachment)
}, ignSignIn)
- m.Post("/{username}", reqSignIn, context_service.UserAssignmentWeb(), user.Action)
+ m.Post("/{username}", reqSignIn, context.UserAssignmentWeb(), user.Action)
reqRepoAdmin := context.RequireRepoAdmin()
reqRepoCodeWriter := context.RequireRepoWriter(unit.TypeCode)
@@ -1029,7 +1028,7 @@ func registerRoutes(m *web.Route) {
m.Group("", func() {
m.Get("/code", user.CodeSearch)
}, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false), individualPermsChecker)
- }, ignSignIn, context_service.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code)
+ }, ignSignIn, context.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code)
m.Group("/{username}/{reponame}", func() {
m.Group("/settings", func() {
diff --git a/routers/web/webfinger.go b/routers/web/webfinger.go
index faa35b8d2f..a87c426b3b 100644
--- a/routers/web/webfinger.go
+++ b/routers/web/webfinger.go
@@ -10,9 +10,9 @@ import (
"strings"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
// https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-webfinger-14#section-4.4
diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go
index fe39312386..d2bbbd9a7c 100644
--- a/services/actions/job_emitter.go
+++ b/services/actions/job_emitter.go
@@ -7,12 +7,14 @@ import (
"context"
"errors"
"fmt"
+ "strings"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/queue"
+ "github.com/nektos/act/pkg/jobparser"
"xorm.io/builder"
)
@@ -76,12 +78,15 @@ func checkJobsOfRun(ctx context.Context, runID int64) error {
type jobStatusResolver struct {
statuses map[int64]actions_model.Status
needs map[int64][]int64
+ jobMap map[int64]*actions_model.ActionRunJob
}
func newJobStatusResolver(jobs actions_model.ActionJobList) *jobStatusResolver {
idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs))
+ jobMap := make(map[int64]*actions_model.ActionRunJob)
for _, job := range jobs {
idToJobs[job.JobID] = append(idToJobs[job.JobID], job)
+ jobMap[job.ID] = job
}
statuses := make(map[int64]actions_model.Status, len(jobs))
@@ -97,6 +102,7 @@ func newJobStatusResolver(jobs actions_model.ActionJobList) *jobStatusResolver {
return &jobStatusResolver{
statuses: statuses,
needs: needs,
+ jobMap: jobMap,
}
}
@@ -135,7 +141,20 @@ func (r *jobStatusResolver) resolve() map[int64]actions_model.Status {
if allSucceed {
ret[id] = actions_model.StatusWaiting
} else {
- ret[id] = actions_model.StatusSkipped
+ // If a job's "if" condition is "always()", the job should always run even if some of its dependencies did not succeed.
+ // See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds
+ always := false
+ if wfJobs, _ := jobparser.Parse(r.jobMap[id].WorkflowPayload); len(wfJobs) == 1 {
+ _, wfJob := wfJobs[0].Job()
+ expr := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(wfJob.If.Value, "${{"), "}}"))
+ always = expr == "always()"
+ }
+
+ if always {
+ ret[id] = actions_model.StatusWaiting
+ } else {
+ ret[id] = actions_model.StatusSkipped
+ }
}
}
}
diff --git a/services/actions/job_emitter_test.go b/services/actions/job_emitter_test.go
index e81aa61d80..038df7d4f8 100644
--- a/services/actions/job_emitter_test.go
+++ b/services/actions/job_emitter_test.go
@@ -70,6 +70,62 @@ func Test_jobStatusResolver_Resolve(t *testing.T) {
},
want: map[int64]actions_model.Status{},
},
+ {
+ name: "with ${{ always() }} condition",
+ jobs: actions_model.ActionJobList{
+ {ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
+ {ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
+ `
+name: test
+on: push
+jobs:
+ job2:
+ runs-on: ubuntu-latest
+ needs: job1
+ if: ${{ always() }}
+ steps:
+ - run: echo "always run"
+`)},
+ },
+ want: map[int64]actions_model.Status{2: actions_model.StatusWaiting},
+ },
+ {
+ name: "with always() condition",
+ jobs: actions_model.ActionJobList{
+ {ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
+ {ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
+ `
+name: test
+on: push
+jobs:
+ job2:
+ runs-on: ubuntu-latest
+ needs: job1
+ if: always()
+ steps:
+ - run: echo "always run"
+`)},
+ },
+ want: map[int64]actions_model.Status{2: actions_model.StatusWaiting},
+ },
+ {
+ name: "without always() condition",
+ jobs: actions_model.ActionJobList{
+ {ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
+ {ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
+ `
+name: test
+on: push
+jobs:
+ job2:
+ runs-on: ubuntu-latest
+ needs: job1
+ steps:
+ - run: echo "not always run"
+`)},
+ },
+ want: map[int64]actions_model.Status{2: actions_model.StatusSkipped},
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/services/actions/notifier.go b/services/actions/notifier.go
index e144484dab..aa88d4e0d8 100644
--- a/services/actions/notifier.go
+++ b/services/actions/notifier.go
@@ -152,7 +152,13 @@ func (n *actionsNotifier) IssueChangeAssignee(ctx context.Context, doer *user_mo
} else {
action = api.HookIssueAssigned
}
- notifyIssueChange(ctx, doer, issue, webhook_module.HookEventPullRequestAssign, action)
+
+ hookEvent := webhook_module.HookEventIssueAssign
+ if issue.IsPull {
+ hookEvent = webhook_module.HookEventPullRequestAssign
+ }
+
+ notifyIssueChange(ctx, doer, issue, hookEvent, action)
}
// IssueChangeMilestone notifies assignee to notifiers
@@ -165,14 +171,26 @@ func (n *actionsNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m
} else {
action = api.HookIssueDemilestoned
}
- notifyIssueChange(ctx, doer, issue, webhook_module.HookEventPullRequestMilestone, action)
+
+ hookEvent := webhook_module.HookEventIssueMilestone
+ if issue.IsPull {
+ hookEvent = webhook_module.HookEventPullRequestMilestone
+ }
+
+ notifyIssueChange(ctx, doer, issue, hookEvent, action)
}
func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue,
_, _ []*issues_model.Label,
) {
ctx = withMethod(ctx, "IssueChangeLabels")
- notifyIssueChange(ctx, doer, issue, webhook_module.HookEventPullRequestLabel, api.HookIssueLabelUpdated)
+
+ hookEvent := webhook_module.HookEventIssueLabel
+ if issue.IsPull {
+ hookEvent = webhook_module.HookEventPullRequestLabel
+ }
+
+ notifyIssueChange(ctx, doer, issue, hookEvent, api.HookIssueLabelUpdated)
}
func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, event webhook_module.HookEventType, action api.HookIssueAction) {
diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go
index 2d138aaf33..19a5c66b71 100644
--- a/services/actions/notifier_helper.go
+++ b/services/actions/notifier_helper.go
@@ -117,6 +117,9 @@ func notify(ctx context.Context, input *notifyInput) error {
log.Debug("ignore executing %v for event %v whose doer is %v", getMethod(ctx), input.Event, input.Doer.Name)
return nil
}
+ if input.Repo.IsEmpty {
+ return nil
+ }
if unit_model.TypeActions.UnitGlobalDisabled() {
return nil
}
diff --git a/services/attachment/attachment.go b/services/attachment/attachment.go
index 1bcd460e3c..4481966b4a 100644
--- a/services/attachment/attachment.go
+++ b/services/attachment/attachment.go
@@ -12,8 +12,8 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/storage"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/context/upload"
"github.com/google/uuid"
)
@@ -44,14 +44,14 @@ func NewAttachment(ctx context.Context, attach *repo_model.Attachment, file io.R
}
// UploadAttachment upload new attachment into storage and update database
-func UploadAttachment(ctx context.Context, file io.Reader, allowedTypes string, fileSize int64, opts *repo_model.Attachment) (*repo_model.Attachment, error) {
+func UploadAttachment(ctx context.Context, file io.Reader, allowedTypes string, fileSize int64, attach *repo_model.Attachment) (*repo_model.Attachment, error) {
buf := make([]byte, 1024)
n, _ := util.ReadAtMost(file, buf)
buf = buf[:n]
- if err := upload.Verify(buf, opts.Name, allowedTypes); err != nil {
+ if err := upload.Verify(buf, attach.Name, allowedTypes); err != nil {
return nil, err
}
- return NewAttachment(ctx, opts, io.MultiReader(bytes.NewReader(buf), file), fileSize)
+ return NewAttachment(ctx, attach, io.MultiReader(bytes.NewReader(buf), file), fileSize)
}
diff --git a/services/auth/auth.go b/services/auth/auth.go
index e53ff02dcf..c10872313f 100644
--- a/services/auth/auth.go
+++ b/services/auth/auth.go
@@ -12,12 +12,12 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/webauthn"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
+ gitea_context "code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
diff --git a/services/auth/signin.go b/services/auth/signin.go
index fafe3ef3c6..e116a088e0 100644
--- a/services/auth/signin.go
+++ b/services/auth/signin.go
@@ -11,7 +11,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/auth/source/smtp"
@@ -87,7 +87,7 @@ func UserSignIn(ctx context.Context, username, password string) (*user_model.Use
}
sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
})
if err != nil {
return nil, nil, err
diff --git a/services/auth/source/oauth2/init.go b/services/auth/source/oauth2/init.go
index 3ad6e307f1..5c25681548 100644
--- a/services/auth/source/oauth2/init.go
+++ b/services/auth/source/oauth2/init.go
@@ -12,8 +12,8 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"github.com/google/uuid"
"github.com/gorilla/sessions"
@@ -66,7 +66,7 @@ func ResetOAuth2(ctx context.Context) error {
// initOAuth2Sources is used to load and register all active OAuth2 providers
func initOAuth2Sources(ctx context.Context) error {
authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
LoginType: auth.OAuth2,
})
if err != nil {
diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go
index f4edb507f2..ac32647839 100644
--- a/services/auth/source/oauth2/providers.go
+++ b/services/auth/source/oauth2/providers.go
@@ -15,8 +15,8 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"github.com/markbates/goth"
)
@@ -107,7 +107,7 @@ func CreateProviderFromSource(source *auth.Source) (Provider, error) {
}
// GetOAuth2Providers returns the list of configured OAuth2 providers
-func GetOAuth2Providers(ctx context.Context, isActive util.OptionalBool) ([]Provider, error) {
+func GetOAuth2Providers(ctx context.Context, isActive optional.Option[bool]) ([]Provider, error) {
authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{
IsActive: isActive,
LoginType: auth.OAuth2,
diff --git a/services/auth/sspi.go b/services/auth/sspi.go
index 8c0fc77a96..64a127e97a 100644
--- a/services/auth/sspi.go
+++ b/services/auth/sspi.go
@@ -14,13 +14,12 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/auth/source/sspi"
+ gitea_context "code.gitea.io/gitea/services/context"
gouuid "github.com/google/uuid"
)
@@ -132,7 +131,7 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
// getConfig retrieves the SSPI configuration from login sources
func (s *SSPI) getConfig(ctx context.Context) (*sspi.Source, error) {
sources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
LoginType: auth.SSPI,
})
if err != nil {
diff --git a/modules/context/access_log.go b/services/context/access_log.go
index 0926748ac5..0926748ac5 100644
--- a/modules/context/access_log.go
+++ b/services/context/access_log.go
diff --git a/modules/context/api.go b/services/context/api.go
index fafd49fd42..fafd49fd42 100644
--- a/modules/context/api.go
+++ b/services/context/api.go
diff --git a/modules/context/api_org.go b/services/context/api_org.go
index dad02b1719..dad02b1719 100644
--- a/modules/context/api_org.go
+++ b/services/context/api_org.go
diff --git a/modules/context/api_test.go b/services/context/api_test.go
index 911a49949e..911a49949e 100644
--- a/modules/context/api_test.go
+++ b/services/context/api_test.go
diff --git a/modules/context/base.go b/services/context/base.go
index fa05850a16..c4aa467ff4 100644
--- a/modules/context/base.go
+++ b/services/context/base.go
@@ -17,8 +17,8 @@ import (
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/translation"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web/middleware"
"github.com/go-chi/chi/v5"
@@ -207,17 +207,17 @@ func (b *Base) FormBool(key string) bool {
return v
}
-// FormOptionalBool returns an OptionalBoolTrue or OptionalBoolFalse if the value
-// for the provided key exists in the form else it returns OptionalBoolNone
-func (b *Base) FormOptionalBool(key string) util.OptionalBool {
+// FormOptionalBool returns an optional.Some(true) or optional.Some(false) if the value
+// for the provided key exists in the form else it returns optional.None[bool]()
+func (b *Base) FormOptionalBool(key string) optional.Option[bool] {
value := b.Req.FormValue(key)
if len(value) == 0 {
- return util.OptionalBoolNone
+ return optional.None[bool]()
}
s := b.Req.FormValue(key)
v, _ := strconv.ParseBool(s)
v = v || strings.EqualFold(s, "on")
- return util.OptionalBoolOf(v)
+ return optional.Some(v)
}
func (b *Base) SetFormString(key, value string) {
@@ -265,6 +265,14 @@ func (b *Base) Redirect(location string, status ...int) {
// So in this case, we should remove the session cookie from the response header
removeSessionCookieHeader(b.Resp)
}
+ // in case the request is made by htmx, have it redirect the browser instead of trying to follow the redirect inside htmx
+ if b.Req.Header.Get("HX-Request") == "true" {
+ b.Resp.Header().Set("HX-Redirect", location)
+ // we have to return a non-redirect status code so XMLHTTPRequest will not immediately follow the redirect
+ // so as to give htmx redirect logic a chance to run
+ b.Status(http.StatusNoContent)
+ return
+ }
http.Redirect(b.Resp, b.Req, location, code)
}
diff --git a/modules/context/captcha.go b/services/context/captcha.go
index a1999900c9..a1999900c9 100644
--- a/modules/context/captcha.go
+++ b/services/context/captcha.go
diff --git a/modules/context/context.go b/services/context/context.go
index a06ebfb0dc..a06ebfb0dc 100644
--- a/modules/context/context.go
+++ b/services/context/context.go
diff --git a/modules/context/context_cookie.go b/services/context/context_cookie.go
index 39e3218d1b..39e3218d1b 100644
--- a/modules/context/context_cookie.go
+++ b/services/context/context_cookie.go
diff --git a/modules/context/context_model.go b/services/context/context_model.go
index 4f70aac516..4f70aac516 100644
--- a/modules/context/context_model.go
+++ b/services/context/context_model.go
diff --git a/modules/context/context_request.go b/services/context/context_request.go
index 984b9ac793..984b9ac793 100644
--- a/modules/context/context_request.go
+++ b/services/context/context_request.go
diff --git a/modules/context/context_response.go b/services/context/context_response.go
index 829bca1f59..372b4cb38b 100644
--- a/modules/context/context_response.go
+++ b/services/context/context_response.go
@@ -6,6 +6,7 @@ package context
import (
"errors"
"fmt"
+ "html/template"
"net"
"net/http"
"net/url"
@@ -104,11 +105,11 @@ func (ctx *Context) JSONTemplate(tmpl base.TplName) {
}
}
-// RenderToString renders the template content to a string
-func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
+// RenderToHTML renders the template content to a HTML string
+func (ctx *Context) RenderToHTML(name base.TplName, data map[string]any) (template.HTML, error) {
var buf strings.Builder
- err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data, ctx.TemplateContext)
- return buf.String(), err
+ err := ctx.Render.HTML(&buf, 0, string(name), data, ctx.TemplateContext)
+ return template.HTML(buf.String()), err
}
// RenderWithErr used for page has form validation but need to prompt error to users.
diff --git a/modules/context/context_template.go b/services/context/context_template.go
index 7878d409ca..7878d409ca 100644
--- a/modules/context/context_template.go
+++ b/services/context/context_template.go
diff --git a/modules/context/context_test.go b/services/context/context_test.go
index 033ce2ef0a..033ce2ef0a 100644
--- a/modules/context/context_test.go
+++ b/services/context/context_test.go
diff --git a/modules/context/csrf.go b/services/context/csrf.go
index 9b0dc2923b..9b0dc2923b 100644
--- a/modules/context/csrf.go
+++ b/services/context/csrf.go
diff --git a/modules/context/org.go b/services/context/org.go
index 018b76de43..018b76de43 100644
--- a/modules/context/org.go
+++ b/services/context/org.go
diff --git a/modules/context/package.go b/services/context/package.go
index c452c657e7..c452c657e7 100644
--- a/modules/context/package.go
+++ b/services/context/package.go
diff --git a/modules/context/pagination.go b/services/context/pagination.go
index 68237c630c..68237c630c 100644
--- a/modules/context/pagination.go
+++ b/services/context/pagination.go
diff --git a/modules/context/permission.go b/services/context/permission.go
index 14a9801dcc..14a9801dcc 100644
--- a/modules/context/permission.go
+++ b/services/context/permission.go
diff --git a/modules/context/private.go b/services/context/private.go
index 8b41949f60..8b41949f60 100644
--- a/modules/context/private.go
+++ b/services/context/private.go
diff --git a/modules/context/repo.go b/services/context/repo.go
index e8ed1134fe..e78dfc585d 100644
--- a/modules/context/repo.go
+++ b/services/context/repo.go
@@ -547,7 +547,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
ctx.Data["NumTags"], err = db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{
IncludeDrafts: true,
IncludeTags: true,
- HasSha1: util.OptionalBoolTrue, // only draft releases which are created with existing tags
+ HasSha1: optional.Some(true), // only draft releases which are created with existing tags
RepoID: ctx.Repo.Repository.ID,
})
if err != nil {
diff --git a/modules/context/response.go b/services/context/response.go
index 2f271f211b..2f271f211b 100644
--- a/modules/context/response.go
+++ b/services/context/response.go
diff --git a/modules/upload/upload.go b/services/context/upload/upload.go
index cd10715864..77a7eb9377 100644
--- a/modules/upload/upload.go
+++ b/services/context/upload/upload.go
@@ -11,9 +11,9 @@ import (
"regexp"
"strings"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
)
// ErrFileTypeForbidden not allowed file type error
diff --git a/modules/upload/upload_test.go b/services/context/upload/upload_test.go
index f2c3242e9a..f2c3242e9a 100644
--- a/modules/upload/upload_test.go
+++ b/services/context/upload/upload_test.go
diff --git a/services/context/user.go b/services/context/user.go
index 8b2faf3369..4c9cd2928b 100644
--- a/services/context/user.go
+++ b/services/context/user.go
@@ -9,12 +9,11 @@ import (
"strings"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
)
// UserAssignmentWeb returns a middleware to handle context-user assignment for web routes
-func UserAssignmentWeb() func(ctx *context.Context) {
- return func(ctx *context.Context) {
+func UserAssignmentWeb() func(ctx *Context) {
+ return func(ctx *Context) {
errorFn := func(status int, title string, obj any) {
err, ok := obj.(error)
if !ok {
@@ -32,8 +31,8 @@ func UserAssignmentWeb() func(ctx *context.Context) {
}
// UserIDAssignmentAPI returns a middleware to handle context-user assignment for api routes
-func UserIDAssignmentAPI() func(ctx *context.APIContext) {
- return func(ctx *context.APIContext) {
+func UserIDAssignmentAPI() func(ctx *APIContext) {
+ return func(ctx *APIContext) {
userID := ctx.ParamsInt64(":user-id")
if ctx.IsSigned && ctx.Doer.ID == userID {
@@ -53,13 +52,13 @@ func UserIDAssignmentAPI() func(ctx *context.APIContext) {
}
// UserAssignmentAPI returns a middleware to handle context-user assignment for api routes
-func UserAssignmentAPI() func(ctx *context.APIContext) {
- return func(ctx *context.APIContext) {
+func UserAssignmentAPI() func(ctx *APIContext) {
+ return func(ctx *APIContext) {
ctx.ContextUser = userAssignment(ctx.Base, ctx.Doer, ctx.Error)
}
}
-func userAssignment(ctx *context.Base, doer *user_model.User, errCb func(int, string, any)) (contextUser *user_model.User) {
+func userAssignment(ctx *Base, doer *user_model.User, errCb func(int, string, any)) (contextUser *user_model.User) {
username := ctx.Params(":username")
if doer != nil && doer.LowerName == strings.ToLower(username) {
@@ -70,7 +69,7 @@ func userAssignment(ctx *context.Base, doer *user_model.User, errCb func(int, st
if err != nil {
if user_model.IsErrUserNotExist(err) {
if redirectUserID, err := user_model.LookupUserRedirect(ctx, username); err == nil {
- context.RedirectToUser(ctx, username, redirectUserID)
+ RedirectToUser(ctx, username, redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
errCb(http.StatusNotFound, "GetUserByName", err)
} else {
diff --git a/modules/context/utils.go b/services/context/utils.go
index 293750fee1..293750fee1 100644
--- a/modules/context/utils.go
+++ b/services/context/utils.go
diff --git a/modules/context/xsrf.go b/services/context/xsrf.go
index 15e36d1859..15e36d1859 100644
--- a/modules/context/xsrf.go
+++ b/services/context/xsrf.go
diff --git a/modules/context/xsrf_test.go b/services/context/xsrf_test.go
index 21cda5d5d4..21cda5d5d4 100644
--- a/modules/context/xsrf_test.go
+++ b/services/context/xsrf_test.go
diff --git a/modules/contexttest/context_tests.go b/services/contexttest/context_tests.go
index 9ca028bb6e..431017a30d 100644
--- a/modules/contexttest/context_tests.go
+++ b/services/contexttest/context_tests.go
@@ -12,16 +12,17 @@ import (
"net/url"
"strings"
"testing"
+ "time"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
@@ -40,8 +41,19 @@ func mockRequest(t *testing.T, reqPath string) *http.Request {
return req
}
+type MockContextOption struct {
+ Render context.Render
+}
+
// MockContext mock context for unit tests
-func MockContext(t *testing.T, reqPath string) (*context.Context, *httptest.ResponseRecorder) {
+func MockContext(t *testing.T, reqPath string, opts ...MockContextOption) (*context.Context, *httptest.ResponseRecorder) {
+ var opt MockContextOption
+ if len(opts) > 0 {
+ opt = opts[0]
+ }
+ if opt.Render == nil {
+ opt.Render = &MockRender{}
+ }
resp := httptest.NewRecorder()
req := mockRequest(t, reqPath)
base, baseCleanUp := context.NewBaseContext(resp, req)
@@ -49,8 +61,9 @@ func MockContext(t *testing.T, reqPath string) (*context.Context, *httptest.Resp
base.Data = middleware.GetContextData(req.Context())
base.Locale = &translation.MockLocale{}
- ctx := context.NewWebContext(base, &MockRender{}, nil)
-
+ ctx := context.NewWebContext(base, opt.Render, nil)
+ ctx.PageData = map[string]any{}
+ ctx.Data["PageStartTime"] = time.Now()
chiCtx := chi.NewRouteContext()
ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx)
return ctx, resp
diff --git a/services/convert/git_commit.go b/services/convert/git_commit.go
index ed08691c8b..e0efcddbcb 100644
--- a/services/convert/git_commit.go
+++ b/services/convert/git_commit.go
@@ -10,11 +10,11 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- ctx "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
+ ctx "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/gitdiff"
)
diff --git a/services/convert/package.go b/services/convert/package.go
index e90ce8a00f..b5fca21a3c 100644
--- a/services/convert/package.go
+++ b/services/convert/package.go
@@ -35,7 +35,7 @@ func ToPackage(ctx context.Context, pd *packages.PackageDescriptor, doer *user_m
Name: pd.Package.Name,
Version: pd.Version.Version,
CreatedAt: pd.Version.CreatedUnix.AsTime(),
- HTMLURL: pd.FullWebLink(),
+ HTMLURL: pd.VersionHTMLURL(),
}, nil
}
diff --git a/services/forms/admin.go b/services/forms/admin.go
index 4b3cacc606..81276f8f46 100644
--- a/services/forms/admin.go
+++ b/services/forms/admin.go
@@ -6,9 +6,9 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
@@ -41,6 +41,7 @@ type AdminEditUserForm struct {
Password string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`
+ Language string `binding:"MaxSize(5)"`
MaxRepoCreation int
Active bool
Admin bool
diff --git a/services/forms/auth_form.go b/services/forms/auth_form.go
index 25acbbb99e..c9f3182b3a 100644
--- a/services/forms/auth_form.go
+++ b/services/forms/auth_form.go
@@ -6,8 +6,8 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/org.go b/services/forms/org.go
index 6e2d787516..3677fcf429 100644
--- a/services/forms/org.go
+++ b/services/forms/org.go
@@ -7,9 +7,9 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/package_form.go b/services/forms/package_form.go
index 2f08dfe9f4..cc940d42d3 100644
--- a/services/forms/package_form.go
+++ b/services/forms/package_form.go
@@ -6,8 +6,8 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/repo_branch_form.go b/services/forms/repo_branch_form.go
index 5deb0ae463..42e6c85c37 100644
--- a/services/forms/repo_branch_form.go
+++ b/services/forms/repo_branch_form.go
@@ -6,8 +6,8 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index da54f4de61..f9ebb6ebaf 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -12,10 +12,10 @@ import (
"code.gitea.io/gitea/models"
issues_model "code.gitea.io/gitea/models/issues"
project_model "code.gitea.io/gitea/models/project"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/webhook"
"gitea.com/go-chi/binding"
diff --git a/services/forms/repo_tag_form.go b/services/forms/repo_tag_form.go
index 4dd99f9e32..0135684737 100644
--- a/services/forms/repo_tag_form.go
+++ b/services/forms/repo_tag_form.go
@@ -6,8 +6,8 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/runner.go b/services/forms/runner.go
index 6d16cfce49..6abfc66fc2 100644
--- a/services/forms/runner.go
+++ b/services/forms/runner.go
@@ -6,8 +6,8 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/user_form.go b/services/forms/user_form.go
index fd4649025f..77316fb13a 100644
--- a/services/forms/user_form.go
+++ b/services/forms/user_form.go
@@ -10,11 +10,11 @@ import (
"strings"
auth_model "code.gitea.io/gitea/models/auth"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/user_form_auth_openid.go b/services/forms/user_form_auth_openid.go
index d8137a8d13..ca1c77e320 100644
--- a/services/forms/user_form_auth_openid.go
+++ b/services/forms/user_form_auth_openid.go
@@ -6,8 +6,8 @@ package forms
import (
"net/http"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/services/context"
"gitea.com/go-chi/binding"
)
diff --git a/services/forms/user_form_hidden_comments.go b/services/forms/user_form_hidden_comments.go
index 03e629a553..c21fddf478 100644
--- a/services/forms/user_form_hidden_comments.go
+++ b/services/forms/user_form_hidden_comments.go
@@ -7,8 +7,8 @@ import (
"math/big"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
)
type hiddenCommentTypeGroupsType map[string][]issues_model.CommentType
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 715c5bf9b8..2b796181d8 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -152,7 +152,7 @@ func (d *DiffLine) GetBlobExcerptQuery() string {
// GetExpandDirection gets DiffLineExpandDirection
func (d *DiffLine) GetExpandDirection() DiffLineExpandDirection {
- if d.Type != DiffLineSection || d.SectionInfo == nil || d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx <= 1 {
+ if d.Type != DiffLineSection || d.SectionInfo == nil || d.SectionInfo.LeftIdx-d.SectionInfo.LastLeftIdx <= 1 || d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx <= 1 {
return DiffLineExpandNone
}
if d.SectionInfo.LastLeftIdx <= 0 && d.SectionInfo.LastRightIdx <= 0 {
diff --git a/services/lfs/locks.go b/services/lfs/locks.go
index 08d7432656..2a362b1c0d 100644
--- a/services/lfs/locks.go
+++ b/services/lfs/locks.go
@@ -11,12 +11,12 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
lfs_module "code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
diff --git a/services/lfs/server.go b/services/lfs/server.go
index 56714120ad..706be0d080 100644
--- a/services/lfs/server.go
+++ b/services/lfs/server.go
@@ -26,12 +26,12 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
lfs_module "code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
+ "code.gitea.io/gitea/services/context"
"github.com/golang-jwt/jwt/v5"
)
diff --git a/services/mailer/incoming/incoming_handler.go b/services/mailer/incoming/incoming_handler.go
index 5ce2cd5fd5..dc0b539822 100644
--- a/services/mailer/incoming/incoming_handler.go
+++ b/services/mailer/incoming/incoming_handler.go
@@ -14,9 +14,9 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
attachment_service "code.gitea.io/gitea/services/attachment"
+ "code.gitea.io/gitea/services/context/upload"
issue_service "code.gitea.io/gitea/services/issue"
incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload"
"code.gitea.io/gitea/services/mailer/token"
diff --git a/services/mailer/mail_admin_new_user.go b/services/mailer/mail_admin_new_user.go
index ecf0ddf5fa..aa0571e57c 100644
--- a/services/mailer/mail_admin_new_user.go
+++ b/services/mailer/mail_admin_new_user.go
@@ -55,13 +55,13 @@ func mailNewUser(ctx context.Context, u *user_model.User, lang string, tos []str
subject := locale.TrString("mail.admin.new_user.subject", u.Name)
body := locale.TrString("mail.admin.new_user.text", manageUserURL)
mailMeta := map[string]any{
- "NewUser": u,
- "NewUserUrl": u.HTMLURL(),
- "Subject": subject,
- "Body": body,
- "Language": locale.Language(),
- "Locale": locale,
- "Str2html": templates.Str2html,
+ "NewUser": u,
+ "NewUserUrl": u.HTMLURL(),
+ "Subject": subject,
+ "Body": body,
+ "Language": locale.Language(),
+ "Locale": locale,
+ "SanitizeHTML": templates.SanitizeHTML,
}
var mailBody bytes.Buffer
diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go
index 3551f85c46..a4378678a0 100644
--- a/services/markup/processorhelper.go
+++ b/services/markup/processorhelper.go
@@ -7,8 +7,8 @@ import (
"context"
"code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
+ gitea_context "code.gitea.io/gitea/services/context"
)
func ProcessorHelper() *markup.ProcessorHelper {
diff --git a/services/markup/processorhelper_test.go b/services/markup/processorhelper_test.go
index ef8f562245..170edae0e0 100644
--- a/services/markup/processorhelper_test.go
+++ b/services/markup/processorhelper_test.go
@@ -12,8 +12,8 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
- "code.gitea.io/gitea/modules/contexttest"
+ gitea_context "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go
index 717be7b7f3..9baae6d31d 100644
--- a/services/migrations/gitea_uploader.go
+++ b/services/migrations/gitea_uploader.go
@@ -483,6 +483,10 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
}
switch cm.Type {
+ case issues_model.CommentTypeReopen:
+ cm.Content = ""
+ case issues_model.CommentTypeClose:
+ cm.Content = ""
case issues_model.CommentTypeAssignees:
if assigneeID, ok := comment.Meta["AssigneeID"].(int); ok {
cm.AssigneeID = int64(assigneeID)
@@ -503,6 +507,8 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
cm.NewRef = fmt.Sprint(comment.Meta["NewRef"])
cm.Content = ""
}
+ case issues_model.CommentTypeMergePull:
+ cm.Content = ""
case issues_model.CommentTypePRScheduledToAutoMerge, issues_model.CommentTypePRUnScheduledToAutoMerge:
cm.Content = ""
default:
diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go
index 33b7c6808f..e98582f31a 100644
--- a/services/migrations/gitea_uploader_test.go
+++ b/services/migrations/gitea_uploader_test.go
@@ -23,9 +23,9 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
base "code.gitea.io/gitea/modules/migration"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
- "code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
)
@@ -68,14 +68,14 @@ func TestGiteaUploadRepo(t *testing.T) {
milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{
RepoID: repo.ID,
- IsClosed: util.OptionalBoolFalse,
+ IsClosed: optional.Some(false),
})
assert.NoError(t, err)
assert.Len(t, milestones, 1)
milestones, err = db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{
RepoID: repo.ID,
- IsClosed: util.OptionalBoolTrue,
+ IsClosed: optional.Some(true),
})
assert.NoError(t, err)
assert.Empty(t, milestones)
@@ -108,7 +108,7 @@ func TestGiteaUploadRepo(t *testing.T) {
issues, err := issues_model.Issues(db.DefaultContext, &issues_model.IssuesOptions{
RepoIDs: []int64{repo.ID},
- IsPull: util.OptionalBoolFalse,
+ IsPull: optional.Some(false),
SortType: "oldest",
})
assert.NoError(t, err)
diff --git a/services/migrations/gitlab.go b/services/migrations/gitlab.go
index 5e49ae6d57..bbc44e958a 100644
--- a/services/migrations/gitlab.go
+++ b/services/migrations/gitlab.go
@@ -517,6 +517,60 @@ func (g *GitlabDownloader) GetComments(commentable base.Commentable) ([]*base.Co
}
page = resp.NextPage
}
+
+ page = 1
+ for {
+ var stateEvents []*gitlab.StateEvent
+ var resp *gitlab.Response
+ var err error
+ if context.IsMergeRequest {
+ stateEvents, resp, err = g.client.ResourceStateEvents.ListMergeStateEvents(g.repoID, int(commentable.GetForeignIndex()), &gitlab.ListStateEventsOptions{
+ ListOptions: gitlab.ListOptions{
+ Page: page,
+ PerPage: g.maxPerPage,
+ },
+ }, nil, gitlab.WithContext(g.ctx))
+ } else {
+ stateEvents, resp, err = g.client.ResourceStateEvents.ListIssueStateEvents(g.repoID, int(commentable.GetForeignIndex()), &gitlab.ListStateEventsOptions{
+ ListOptions: gitlab.ListOptions{
+ Page: page,
+ PerPage: g.maxPerPage,
+ },
+ }, nil, gitlab.WithContext(g.ctx))
+ }
+ if err != nil {
+ return nil, false, fmt.Errorf("error while listing state events: %v %w", g.repoID, err)
+ }
+
+ for _, stateEvent := range stateEvents {
+ comment := &base.Comment{
+ IssueIndex: commentable.GetLocalIndex(),
+ Index: int64(stateEvent.ID),
+ PosterID: int64(stateEvent.User.ID),
+ PosterName: stateEvent.User.Username,
+ Content: "",
+ Created: *stateEvent.CreatedAt,
+ }
+ switch stateEvent.State {
+ case gitlab.ClosedEventType:
+ comment.CommentType = issues_model.CommentTypeClose.String()
+ case gitlab.MergedEventType:
+ comment.CommentType = issues_model.CommentTypeMergePull.String()
+ case gitlab.ReopenedEventType:
+ comment.CommentType = issues_model.CommentTypeReopen.String()
+ default:
+ // Ignore other event types
+ continue
+ }
+ allComments = append(allComments, comment)
+ }
+
+ if resp.NextPage == 0 {
+ break
+ }
+ page = resp.NextPage
+ }
+
return allComments, true, nil
}
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026
index 4ecfe77e65..e102c2ee11 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026
@@ -1,22 +1,17 @@
X-Frame-Options: SAMEORIGIN
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:46 GMT
-Cf-Cache-Status: MISS
-Set-Cookie: _cfuvid=TkY5Br2q4C67LJ2jZWlgdQaosj3Z4aI81Qb27PNKXfo-1701333886606-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Etag: W/"3cacfe29f44a69e84a577337eac55d89"
-X-Content-Type-Options: nosniff
-Ratelimit-Remaining: 1996
-Gitlab-Lb: haproxy-main-29-lb-gprd
-Cache-Control: max-age=0, private, must-revalidate
-Referrer-Policy: strict-origin-when-cross-origin
-X-Gitlab-Meta: {"correlation_id":"291f87cd975a51a7b756806ce7b53e2e","version":"1"}
-Ratelimit-Observed: 4
Vary: Origin, Accept-Encoding
-Gitlab-Sv: localhost
+Strict-Transport-Security: max-age=31536000
+Cache-Control: max-age=0, private, must-revalidate
+X-Content-Type-Options: nosniff
+X-Gitlab-Meta: {"correlation_id":"fcbfb8d789b3f092196e301b01add051","version":"1"}
+Gitlab-Sv: api-gke-us-east1-b
+Cf-Cache-Status: MISS
Content-Security-Policy: default-src 'none'
-Ratelimit-Reset: 1701333946
+Etag: W/"8db4917b3be5f4ca0d101a702179b75a"
+X-Runtime: 0.230015
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Lb: haproxy-main-39-lb-gprd
+Set-Cookie: _cfuvid=cvUyaJC1KTpP.SBvDCjaIYRgZYh4zbY7BihbhwIUzt4-1709516922501-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Content-Type: application/json
-X-Runtime: 0.101081
-Strict-Transport-Security: max-age=31536000
-Ratelimit-Limit: 2000
-{"id":15578026,"description":"Test repository for testing migration from gitlab to gitea","name":"test_repo","name_with_namespace":"gitea / test_repo","path":"test_repo","path_with_namespace":"gitea/test_repo","created_at":"2019-11-28T08:20:33.019Z","default_branch":"master","tag_list":["migration","test"],"topics":["migration","test"],"ssh_url_to_repo":"git@gitlab.com:gitea/test_repo.git","http_url_to_repo":"https://gitlab.com/gitea/test_repo.git","web_url":"https://gitlab.com/gitea/test_repo","readme_url":"https://gitlab.com/gitea/test_repo/-/blob/master/README.md","forks_count":1,"avatar_url":null,"star_count":0,"last_activity_at":"2020-04-19T19:46:04.527Z","namespace":{"id":3181312,"name":"gitea","path":"gitea","kind":"group","full_path":"gitea","parent_id":null,"avatar_url":"/uploads/-/system/group/avatar/3181312/gitea.png","web_url":"https://gitlab.com/groups/gitea"},"container_registry_image_prefix":"registry.gitlab.com/gitea/test_repo","_links":{"self":"https://gitlab.com/api/v4/projects/15578026","issues":"https://gitlab.com/api/v4/projects/15578026/issues","merge_requests":"https://gitlab.com/api/v4/projects/15578026/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/15578026/repository/branches","labels":"https://gitlab.com/api/v4/projects/15578026/labels","events":"https://gitlab.com/api/v4/projects/15578026/events","members":"https://gitlab.com/api/v4/projects/15578026/members","cluster_agents":"https://gitlab.com/api/v4/projects/15578026/cluster_agents"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"public","resolve_outdated_diff_discussions":false,"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"container_registry_enabled":true,"service_desk_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","analytics_access_level":"enabled","container_registry_access_level":"enabled","security_and_compliance_access_level":"private","releases_access_level":"enabled","environments_access_level":"enabled","feature_flags_access_level":"enabled","infrastructure_access_level":"enabled","monitor_access_level":"enabled","model_experiments_access_level":"enabled","emails_disabled":false,"emails_enabled":true,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":1241334,"import_status":"none","open_issues_count":0,"description_html":"\u003cp data-sourcepos=\"1:1-1:58\" dir=\"auto\"\u003eTest repository for testing migration from gitlab to gitea\u003c/p\u003e","updated_at":"2022-08-26T19:41:46.691Z","ci_config_path":null,"public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"ff","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":null,"merge_commit_template":null,"squash_commit_template":null,"issue_branch_template":null,"autoclose_referenced_issues":true,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":false,"compliance_frameworks":[],"permissions":{"project_access":null,"group_access":null}} \ No newline at end of file
+{"id":15578026,"description":"Test repository for testing migration from gitlab to gitea","name":"test_repo","name_with_namespace":"gitea / test_repo","path":"test_repo","path_with_namespace":"gitea/test_repo","created_at":"2019-11-28T08:20:33.019Z","default_branch":"master","tag_list":["migration","test"],"topics":["migration","test"],"ssh_url_to_repo":"git@gitlab.com:gitea/test_repo.git","http_url_to_repo":"https://gitlab.com/gitea/test_repo.git","web_url":"https://gitlab.com/gitea/test_repo","readme_url":"https://gitlab.com/gitea/test_repo/-/blob/master/README.md","forks_count":1,"avatar_url":null,"star_count":0,"last_activity_at":"2020-04-19T19:46:04.527Z","namespace":{"id":3181312,"name":"gitea","path":"gitea","kind":"group","full_path":"gitea","parent_id":null,"avatar_url":"/uploads/-/system/group/avatar/3181312/gitea.png","web_url":"https://gitlab.com/groups/gitea"},"container_registry_image_prefix":"registry.gitlab.com/gitea/test_repo","_links":{"self":"https://gitlab.com/api/v4/projects/15578026","issues":"https://gitlab.com/api/v4/projects/15578026/issues","merge_requests":"https://gitlab.com/api/v4/projects/15578026/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/15578026/repository/branches","labels":"https://gitlab.com/api/v4/projects/15578026/labels","events":"https://gitlab.com/api/v4/projects/15578026/events","members":"https://gitlab.com/api/v4/projects/15578026/members","cluster_agents":"https://gitlab.com/api/v4/projects/15578026/cluster_agents"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"public","resolve_outdated_diff_discussions":false,"repository_object_format":"sha1","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"container_registry_enabled":true,"service_desk_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","analytics_access_level":"enabled","container_registry_access_level":"enabled","security_and_compliance_access_level":"private","releases_access_level":"enabled","environments_access_level":"enabled","feature_flags_access_level":"enabled","infrastructure_access_level":"enabled","monitor_access_level":"enabled","model_experiments_access_level":"enabled","model_registry_access_level":"enabled","emails_disabled":false,"emails_enabled":true,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":1241334,"import_status":"none","open_issues_count":0,"description_html":"\u003cp data-sourcepos=\"1:1-1:58\" dir=\"auto\"\u003eTest repository for testing migration from gitlab to gitea\u003c/p\u003e","updated_at":"2024-01-11T01:23:21.057Z","ci_config_path":null,"public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"ff","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":null,"merge_commit_template":null,"squash_commit_template":null,"issue_branch_template":null,"warn_about_potentially_unwanted_characters":true,"autoclose_referenced_issues":true,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":false,"compliance_frameworks":[],"permissions":{"project_access":null,"group_access":null}} \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues!page=1&per_page=2&sort=asc&state=all b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues!page=1&per_page=2&sort=asc&state=all
index 331a82720c..17139efa29 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues!page=1&per_page=2&sort=asc&state=all
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues!page=1&per_page=2&sort=asc&state=all
@@ -1,29 +1,24 @@
-Cache-Control: max-age=0, private, must-revalidate
-Vary: Origin, Accept-Encoding
-Gitlab-Lb: haproxy-main-24-lb-gprd
-Content-Type: application/json
+X-Content-Type-Options: nosniff
X-Per-Page: 2
+X-Total-Pages: 1
+Content-Type: application/json
X-Prev-Page:
-Set-Cookie: _cfuvid=N.nfy5eIdFH5lXhsnMyEbeBkoxabcl1SVeyyP0_NrdE-1701333887790-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Content-Security-Policy: default-src 'none'
-X-Content-Type-Options: nosniff
+X-Total: 2
+Cache-Control: max-age=0, private, must-revalidate
+Vary: Origin, Accept-Encoding
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Sv: api-gke-us-east1-d
+X-Gitlab-Meta: {"correlation_id":"52846fcab419461a2c2f29f707dbd103","version":"1"}
X-Next-Page:
-X-Total-Pages: 1
+Strict-Transport-Security: max-age=31536000
+Cf-Cache-Status: MISS
+Link: <https://gitlab.com/api/v4/projects/15578026/issues?id=15578026&order_by=created_at&page=1&per_page=2&sort=asc&state=all&with_labels_details=false>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues?id=15578026&order_by=created_at&page=1&per_page=2&sort=asc&state=all&with_labels_details=false>; rel="last"
Etag: W/"4c0531a3595f741f229f5a105e013b95"
-X-Gitlab-Meta: {"correlation_id":"b2eca136986f016d946685fb99287f1c","version":"1"}
-Ratelimit-Observed: 8
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:47 GMT
X-Frame-Options: SAMEORIGIN
-Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Remaining: 1992
-Gitlab-Sv: localhost
-Cf-Cache-Status: MISS
-Strict-Transport-Security: max-age=31536000
-Ratelimit-Limit: 2000
-X-Total: 2
X-Page: 1
-X-Runtime: 0.178587
-Ratelimit-Reset: 1701333947
-Link: <https://gitlab.com/api/v4/projects/15578026/issues?id=15578026&order_by=created_at&page=1&per_page=2&sort=asc&state=all&with_labels_details=false>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues?id=15578026&order_by=created_at&page=1&per_page=2&sort=asc&state=all&with_labels_details=false>; rel="last"
+Content-Security-Policy: default-src 'none'
+Set-Cookie: _cfuvid=0ScIwDvsVw_dRSgtT9czuTLY6R5TGzB2UIk9653BEf0-1709516924974-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Gitlab-Lb: haproxy-main-38-lb-gprd
+X-Runtime: 0.187797
[{"id":27687675,"iid":1,"project_id":15578026,"title":"Please add an animated gif icon to the merge button","description":"I just want the merge button to hurt my eyes a little. :stuck_out_tongue_closed_eyes:","state":"closed","created_at":"2019-11-28T08:43:35.459Z","updated_at":"2019-11-28T08:46:23.304Z","closed_at":"2019-11-28T08:46:23.275Z","closed_by":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"labels":["bug","discussion"],"milestone":{"id":1082926,"iid":1,"project_id":15578026,"title":"1.0.0","description":"","state":"closed","created_at":"2019-11-28T08:42:30.301Z","updated_at":"2019-11-28T15:57:52.401Z","due_date":null,"start_date":null,"expired":false,"web_url":"https://gitlab.com/gitea/test_repo/-/milestones/1"},"assignees":[],"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"type":"ISSUE","assignee":null,"user_notes_count":0,"merge_requests_count":0,"upvotes":1,"downvotes":0,"due_date":null,"confidential":false,"discussion_locked":null,"issue_type":"issue","web_url":"https://gitlab.com/gitea/test_repo/-/issues/1","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"task_completion_status":{"count":0,"completed_count":0},"blocking_issues_count":0,"has_tasks":true,"task_status":"0 of 0 checklist items completed","_links":{"self":"https://gitlab.com/api/v4/projects/15578026/issues/1","notes":"https://gitlab.com/api/v4/projects/15578026/issues/1/notes","award_emoji":"https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji","project":"https://gitlab.com/api/v4/projects/15578026","closed_as_duplicate_of":null},"references":{"short":"#1","relative":"#1","full":"gitea/test_repo#1"},"severity":"UNKNOWN","moved_to_id":null,"service_desk_reply_to":null},{"id":27687706,"iid":2,"project_id":15578026,"title":"Test issue","description":"This is test issue 2, do not touch!","state":"closed","created_at":"2019-11-28T08:44:46.277Z","updated_at":"2019-11-28T08:45:44.987Z","closed_at":"2019-11-28T08:45:44.959Z","closed_by":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"labels":["duplicate"],"milestone":{"id":1082927,"iid":2,"project_id":15578026,"title":"1.1.0","description":"","state":"active","created_at":"2019-11-28T08:42:44.575Z","updated_at":"2019-11-28T08:42:44.575Z","due_date":null,"start_date":null,"expired":false,"web_url":"https://gitlab.com/gitea/test_repo/-/milestones/2"},"assignees":[],"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"type":"ISSUE","assignee":null,"user_notes_count":2,"merge_requests_count":0,"upvotes":1,"downvotes":1,"due_date":null,"confidential":false,"discussion_locked":null,"issue_type":"issue","web_url":"https://gitlab.com/gitea/test_repo/-/issues/2","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"task_completion_status":{"count":0,"completed_count":0},"blocking_issues_count":0,"has_tasks":true,"task_status":"0 of 0 checklist items completed","_links":{"self":"https://gitlab.com/api/v4/projects/15578026/issues/2","notes":"https://gitlab.com/api/v4/projects/15578026/issues/2/notes","award_emoji":"https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji","project":"https://gitlab.com/api/v4/projects/15578026","closed_as_duplicate_of":null},"references":{"short":"#2","relative":"#2","full":"gitea/test_repo#2"},"severity":"UNKNOWN","moved_to_id":null,"service_desk_reply_to":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=1&per_page=2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=1&per_page=2
index d8ab294ee1..7b37f59f5e 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=1&per_page=2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=1&per_page=2
@@ -1,29 +1,24 @@
X-Total-Pages: 1
-Referrer-Policy: strict-origin-when-cross-origin
-Cache-Control: max-age=0, private, must-revalidate
-X-Frame-Options: SAMEORIGIN
-X-Runtime: 0.052748
-X-Total: 2
-Gitlab-Sv: localhost
-Link: <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="last"
-X-Content-Type-Options: nosniff
-X-Gitlab-Meta: {"correlation_id":"22fc215ac386644c9cb8736b652cf702","version":"1"}
-X-Per-Page: 2
-Strict-Transport-Security: max-age=31536000
-Ratelimit-Reset: 1701333947
-Content-Security-Policy: default-src 'none'
-Ratelimit-Remaining: 1991
-Ratelimit-Observed: 9
-X-Next-Page:
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:47 GMT
-Ratelimit-Limit: 2000
-Gitlab-Lb: haproxy-main-43-lb-gprd
Cf-Cache-Status: MISS
-Etag: W/"69c922434ed11248c864d157eb8eabfc"
+Set-Cookie: _cfuvid=UtNiLvpRoIS0606tZnebN.nDbGog2IEOTI0M6iH6tKE-1709516925325-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Content-Type: application/json
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="last"
+X-Gitlab-Meta: {"correlation_id":"7078187b1af666261210081509905846","version":"1"}
+Strict-Transport-Security: max-age=31536000
Vary: Origin, Accept-Encoding
+X-Total: 2
+Gitlab-Sv: api-gke-us-east1-b
+Content-Security-Policy: default-src 'none'
+X-Content-Type-Options: nosniff
X-Page: 1
+X-Frame-Options: SAMEORIGIN
X-Prev-Page:
-Set-Cookie: _cfuvid=POpffkskz4lvLcv2Fhjp7lF3MsmIOugWDzFGtb3ZUig-1701333887995-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+X-Runtime: 0.070454
+X-Next-Page:
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Lb: haproxy-main-51-lb-gprd
+X-Per-Page: 2
+Cache-Control: max-age=0, private, must-revalidate
+Etag: W/"69c922434ed11248c864d157eb8eabfc"
[{"id":3009580,"name":"thumbsup","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:43:40.322Z","updated_at":"2019-11-28T08:43:40.322Z","awardable_id":27687675,"awardable_type":"Issue","url":null},{"id":3009585,"name":"open_mouth","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:44:01.902Z","updated_at":"2019-11-28T08:44:01.902Z","awardable_id":27687675,"awardable_type":"Issue","url":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=2&per_page=2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=2&per_page=2
index 248afeff8f..7f64231eb7 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=2&per_page=2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_1_award_emoji!page=2&per_page=2
@@ -1,31 +1,26 @@
-Content-Type: application/json
Content-Length: 2
-X-Next-Page:
-X-Gitlab-Meta: {"correlation_id":"6b9bc368e2cdc69a1b8e7d2dff7546c5","version":"1"}
-Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Reset: 1701333948
+Cache-Control: max-age=0, private, must-revalidate
+Accept-Ranges: bytes
Strict-Transport-Security: max-age=31536000
+Gitlab-Lb: haproxy-main-57-lb-gprd
+Gitlab-Sv: api-gke-us-east1-b
+X-Prev-Page:
+X-Runtime: 0.048686
+Cf-Cache-Status: MISS
+Vary: Origin, Accept-Encoding
X-Per-Page: 2
+Referrer-Policy: strict-origin-when-cross-origin
+X-Gitlab-Meta: {"correlation_id":"53764b779171a3a641999caf45eb5cda","version":"1"}
+X-Page: 2
X-Total: 2
-Ratelimit-Limit: 2000
-Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
-Link: <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="last"
-X-Runtime: 0.069944
-Ratelimit-Remaining: 1990
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:48 GMT
-Gitlab-Sv: localhost
-X-Prev-Page:
X-Total-Pages: 1
-Ratelimit-Observed: 10
-Gitlab-Lb: haproxy-main-17-lb-gprd
+Content-Type: application/json
+X-Next-Page:
+Set-Cookie: _cfuvid=.aWihkIt1YOKnLoix6oJ3avCXZ_942rAkWJpHXKtKXk-1709516926358-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
-Accept-Ranges: bytes
-Cache-Control: max-age=0, private, must-revalidate
-Vary: Origin, Accept-Encoding
-X-Page: 2
-Cf-Cache-Status: MISS
-Set-Cookie: _cfuvid=vcfsxezcg_2Kdh8xD5coOU_uxQIH1in.6BsRttrSIYg-1701333888217-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/1/award_emoji?id=15578026&issue_iid=1&page=1&per_page=2>; rel="last"
[] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=1&per_page=2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=1&per_page=2
index 70c50c8fed..db1573c43c 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=1&per_page=2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=1&per_page=2
@@ -1,29 +1,24 @@
-Cf-Cache-Status: MISS
-Etag: W/"5fdbcbf64f34ba0e74ce9dd8d6e0efe3"
+Vary: Origin, Accept-Encoding
+Set-Cookie: _cfuvid=eR1OqXm9Zq42ps0oFIf0s4qBdC4lKtotvp9jBqOVcko-1709516927407-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
-X-Per-Page: 2
-Ratelimit-Limit: 2000
-Set-Cookie: _cfuvid=NLtUZdQlWvWiXr4L8Zfc555FowZOCxJlA0pAOAEkNvg-1701333888445-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-X-Runtime: 0.075612
-Ratelimit-Reset: 1701333948
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:48 GMT
+X-Next-Page: 2
X-Page: 1
X-Prev-Page:
X-Total-Pages: 3
-X-Frame-Options: SAMEORIGIN
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=2&per_page=2>; rel="next", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
Referrer-Policy: strict-origin-when-cross-origin
-Content-Security-Policy: default-src 'none'
-Ratelimit-Observed: 11
-Gitlab-Lb: haproxy-main-09-lb-gprd
-Gitlab-Sv: localhost
-Ratelimit-Remaining: 1989
+X-Total: 6
Cache-Control: max-age=0, private, must-revalidate
-Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=2&per_page=2>; rel="next", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
-X-Gitlab-Meta: {"correlation_id":"a69709cf552479bc5f5f3e4e1f808790","version":"1"}
-X-Next-Page: 2
+X-Per-Page: 2
+Gitlab-Sv: api-gke-us-east1-d
+X-Gitlab-Meta: {"correlation_id":"05328c4fe2465085c0b9a5a5a1103836","version":"1"}
+X-Runtime: 0.075509
Strict-Transport-Security: max-age=31536000
+Gitlab-Lb: haproxy-main-50-lb-gprd
Content-Type: application/json
-Vary: Origin, Accept-Encoding
-X-Total: 6
+Etag: W/"5fdbcbf64f34ba0e74ce9dd8d6e0efe3"
+X-Frame-Options: SAMEORIGIN
+Cf-Cache-Status: MISS
[{"id":3009627,"name":"thumbsup","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:46:42.657Z","updated_at":"2019-11-28T08:46:42.657Z","awardable_id":27687706,"awardable_type":"Issue","url":null},{"id":3009628,"name":"thumbsdown","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:46:43.471Z","updated_at":"2019-11-28T08:46:43.471Z","awardable_id":27687706,"awardable_type":"Issue","url":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=2&per_page=2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=2&per_page=2
index 1014d9dbc5..d52e358e91 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=2&per_page=2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=2&per_page=2
@@ -1,29 +1,24 @@
-Ratelimit-Limit: 2000
X-Content-Type-Options: nosniff
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:48 GMT
-X-Total: 6
-Set-Cookie: _cfuvid=E5GyZy0rB2zrRH0ewMyrJd1wBrt7A2sGNmOHTiWwbYk-1701333888703-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-X-Next-Page: 3
-X-Page: 2
-Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="prev", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="next", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
-X-Gitlab-Meta: {"correlation_id":"41e59fb2e78f5e68518b81bd4ff3bb1b","version":"1"}
-X-Prev-Page: 1
-Cf-Cache-Status: MISS
+X-Runtime: 0.091658
+Set-Cookie: _cfuvid=aVGYOkTTE5ngoJripH93fZ9JhYhafbwSPqzjRZ7JCyk-1709516927910-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Referrer-Policy: strict-origin-when-cross-origin
-Gitlab-Lb: haproxy-main-26-lb-gprd
-Cache-Control: max-age=0, private, must-revalidate
-Etag: W/"d16c513b32212d9286fce6f53340c1cf"
-Vary: Origin, Accept-Encoding
-X-Per-Page: 2
+X-Frame-Options: SAMEORIGIN
+X-Gitlab-Meta: {"correlation_id":"b1d1356c71e3f52fc9bccd80a711467f","version":"1"}
+X-Prev-Page: 1
Strict-Transport-Security: max-age=31536000
-Ratelimit-Reset: 1701333948
+Gitlab-Sv: api-gke-us-east1-c
Content-Type: application/json
-X-Runtime: 0.105758
-Ratelimit-Remaining: 1988
Content-Security-Policy: default-src 'none'
-X-Frame-Options: SAMEORIGIN
-Gitlab-Sv: localhost
+Vary: Origin, Accept-Encoding
+X-Page: 2
+X-Per-Page: 2
+Cf-Cache-Status: MISS
+X-Total: 6
+Gitlab-Lb: haproxy-main-13-lb-gprd
+Etag: W/"d16c513b32212d9286fce6f53340c1cf"
+X-Next-Page: 3
X-Total-Pages: 3
-Ratelimit-Observed: 12
+Cache-Control: max-age=0, private, must-revalidate
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="prev", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="next", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
[{"id":3009632,"name":"laughing","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:47:14.381Z","updated_at":"2019-11-28T08:47:14.381Z","awardable_id":27687706,"awardable_type":"Issue","url":null},{"id":3009634,"name":"tada","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:47:18.254Z","updated_at":"2019-11-28T08:47:18.254Z","awardable_id":27687706,"awardable_type":"Issue","url":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=3&per_page=2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=3&per_page=2
index 9c42bfb9bf..e35aa62cdf 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=3&per_page=2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=3&per_page=2
@@ -1,29 +1,24 @@
-Content-Type: application/json
-X-Content-Type-Options: nosniff
-X-Frame-Options: SAMEORIGIN
+Gitlab-Lb: haproxy-main-13-lb-gprd
+Set-Cookie: _cfuvid=t4_LSY2Wo_P8jPVZKgbX7DhNDlsiazGyv6awHkbP29M-1709516929175-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Cache-Control: max-age=0, private, must-revalidate
+Vary: Origin, Accept-Encoding
Referrer-Policy: strict-origin-when-cross-origin
-Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=2&per_page=2>; rel="prev", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
Cf-Cache-Status: MISS
-Etag: W/"165d37bf09a54bb31f4619cca8722cb4"
-Ratelimit-Observed: 13
-Ratelimit-Limit: 2000
-Set-Cookie: _cfuvid=W6F2uJSFkB3Iyl27_xtklVvP4Z_nSsjPqytClHPW9H8-1701333888913-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-X-Page: 3
+X-Total: 6
X-Total-Pages: 3
+Etag: W/"165d37bf09a54bb31f4619cca8722cb4"
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=2&per_page=2>; rel="prev", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
+Gitlab-Sv: api-gke-us-east1-c
+X-Runtime: 0.084688
Strict-Transport-Security: max-age=31536000
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:48 GMT
-Cache-Control: max-age=0, private, must-revalidate
-Vary: Origin, Accept-Encoding
-X-Gitlab-Meta: {"correlation_id":"b805751aeb6f562dff684cec34dfdc0b","version":"1"}
-X-Per-Page: 2
+Content-Type: application/json
+X-Content-Type-Options: nosniff
X-Prev-Page: 2
-X-Runtime: 0.061943
-Gitlab-Lb: haproxy-main-11-lb-gprd
-Gitlab-Sv: localhost
-X-Total: 6
-Ratelimit-Remaining: 1987
-Content-Security-Policy: default-src 'none'
X-Next-Page:
-Ratelimit-Reset: 1701333948
+X-Page: 3
+X-Frame-Options: SAMEORIGIN
+X-Gitlab-Meta: {"correlation_id":"3d4b896e9b25fba2880f8cf4179b4db3","version":"1"}
+Content-Security-Policy: default-src 'none'
+X-Per-Page: 2
[{"id":3009636,"name":"confused","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:47:27.248Z","updated_at":"2019-11-28T08:47:27.248Z","awardable_id":27687706,"awardable_type":"Issue","url":null},{"id":3009640,"name":"hearts","user":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:47:33.059Z","updated_at":"2019-11-28T08:47:33.059Z","awardable_id":27687706,"awardable_type":"Issue","url":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=4&per_page=2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=4&per_page=2
index e550e4ad19..2c757e2034 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=4&per_page=2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_award_emoji!page=4&per_page=2
@@ -1,31 +1,26 @@
-Ratelimit-Remaining: 1986
-Accept-Ranges: bytes
-Set-Cookie: _cfuvid=DZQIMINjFohqKKjkWnojkq2xuUaqb42YEQg3BZXe68w-1701333889148-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Strict-Transport-Security: max-age=31536000
-X-Prev-Page:
-Ratelimit-Reset: 1701333949
-Ratelimit-Limit: 2000
+Vary: Origin, Accept-Encoding
+Content-Length: 2
Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
-Cache-Control: max-age=0, private, must-revalidate
X-Next-Page:
X-Page: 4
-Referrer-Policy: strict-origin-when-cross-origin
-Gitlab-Sv: localhost
+Strict-Transport-Security: max-age=31536000
+Gitlab-Lb: haproxy-main-40-lb-gprd
+Set-Cookie: _cfuvid=V6zFYEypjQbDjYSsP9fTmKa2nKJP5kvVJDoSbH7rU34-1709516930295-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Content-Type: application/json
+X-Gitlab-Meta: {"correlation_id":"58338440ce0dd25dea95208140617efc","version":"1"}
+X-Total-Pages: 3
+Cf-Cache-Status: MISS
+Cache-Control: max-age=0, private, must-revalidate
+X-Frame-Options: SAMEORIGIN
+X-Total: 6
+X-Prev-Page:
+Accept-Ranges: bytes
X-Content-Type-Options: nosniff
-Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
-Vary: Origin, Accept-Encoding
+X-Runtime: 0.052295
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Sv: api-gke-us-east1-c
Content-Security-Policy: default-src 'none'
-X-Runtime: 0.081728
-X-Total: 6
-Content-Length: 2
-X-Frame-Options: SAMEORIGIN
-X-Gitlab-Meta: {"correlation_id":"588184d2d9ad2c4a7e7c00a51575091c","version":"1"}
-Cf-Cache-Status: MISS
-X-Total-Pages: 3
-Ratelimit-Observed: 14
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:49 GMT
-Gitlab-Lb: haproxy-main-34-lb-gprd
X-Per-Page: 2
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=1&per_page=2>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/award_emoji?id=15578026&issue_iid=2&page=3&per_page=2>; rel="last"
[] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_discussions!page=1&per_page=100 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_discussions!page=1&per_page=100
index d74fc325a3..2dc290a405 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_discussions!page=1&per_page=100
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_discussions!page=1&per_page=100
@@ -1,29 +1,24 @@
-X-Runtime: 0.173849
-Content-Security-Policy: default-src 'none'
+X-Gitlab-Meta: {"correlation_id":"f7ea96beef459528c06bcf21a37f8950","version":"1"}
X-Per-Page: 100
-X-Prev-Page:
-X-Total: 4
-Ratelimit-Observed: 15
-X-Page: 1
-Ratelimit-Remaining: 1985
+X-Runtime: 0.294630
Cache-Control: max-age=0, private, must-revalidate
-X-Gitlab-Meta: {"correlation_id":"1d2b49b1b17e0c2d58c800a1b6c7eca3","version":"1"}
+Gitlab-Sv: gke-cny-api
+X-Frame-Options: SAMEORIGIN
X-Next-Page:
-Referrer-Policy: strict-origin-when-cross-origin
-Cf-Cache-Status: MISS
-Content-Type: application/json
Etag: W/"bcc91e8a7b2eac98b4d96ae791e0649d"
-Vary: Origin, Accept-Encoding
-X-Frame-Options: SAMEORIGIN
+X-Total: 4
+X-Page: 1
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Lb: haproxy-main-32-lb-gprd
Strict-Transport-Security: max-age=31536000
-Ratelimit-Reset: 1701333949
-Gitlab-Lb: haproxy-main-08-lb-gprd
-Gitlab-Sv: localhost
+Set-Cookie: _cfuvid=bVDOhVwoTt.rATMQeCGhPoIH4lvwoCZQqEHaWL0EOVY-1709516931074-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/discussions?id=15578026&noteable_id=2&page=1&per_page=100>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/discussions?id=15578026&noteable_id=2&page=1&per_page=100>; rel="last"
X-Content-Type-Options: nosniff
+X-Prev-Page:
+Content-Type: application/json
+Cf-Cache-Status: MISS
+Content-Security-Policy: default-src 'none'
+Vary: Origin, Accept-Encoding
X-Total-Pages: 1
-Ratelimit-Limit: 2000
-Set-Cookie: _cfuvid=yj.PGr9ftsz1kNpgtsmQhAcGpdMnklLE.NQ9h71hm5Q-1701333889475-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:49 GMT
[{"id":"617967369d98d8b73b6105a40318fe839f931a24","individual_note":true,"notes":[{"id":251637434,"type":null,"body":"This is a comment","attachment":null,"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:44:52.501Z","updated_at":"2019-11-28T08:44:52.501Z","system":false,"noteable_id":27687706,"noteable_type":"Issue","project_id":15578026,"resolvable":false,"confidential":false,"internal":false,"noteable_iid":2,"commands_changes":{}}]},{"id":"b92d74daee411a17d844041bcd3c267ade58f680","individual_note":true,"notes":[{"id":251637528,"type":null,"body":"changed milestone to %2","attachment":null,"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:45:02.329Z","updated_at":"2019-11-28T08:45:02.335Z","system":true,"noteable_id":27687706,"noteable_type":"Issue","project_id":15578026,"resolvable":false,"confidential":false,"internal":false,"noteable_iid":2,"commands_changes":{}}]},{"id":"6010f567d2b58758ef618070372c97891ac75349","individual_note":true,"notes":[{"id":251637892,"type":null,"body":"closed","attachment":null,"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:45:45.007Z","updated_at":"2019-11-28T08:45:45.010Z","system":true,"noteable_id":27687706,"noteable_type":"Issue","project_id":15578026,"resolvable":false,"confidential":false,"internal":false,"noteable_iid":2,"commands_changes":{}}]},{"id":"632d0cbfd6a1a08f38aaf9ef7715116f4b188ebb","individual_note":true,"notes":[{"id":251637999,"type":null,"body":"A second comment","attachment":null,"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"created_at":"2019-11-28T08:45:53.501Z","updated_at":"2019-11-28T08:45:53.501Z","system":false,"noteable_id":27687706,"noteable_type":"Issue","project_id":15578026,"resolvable":false,"confidential":false,"internal":false,"noteable_iid":2,"commands_changes":{}}]}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_resource_state_events!page=1&per_page=100 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_resource_state_events!page=1&per_page=100
new file mode 100644
index 0000000000..a67d0c45b7
--- /dev/null
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_issues_2_resource_state_events!page=1&per_page=100
@@ -0,0 +1,26 @@
+Cf-Cache-Status: MISS
+Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
+X-Content-Type-Options: nosniff
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Lb: haproxy-main-52-lb-gprd
+Content-Length: 2
+X-Prev-Page:
+Set-Cookie: _cfuvid=W2TdoA.hvJeMOjx.ZmMBWpZVvCP6nNxmeM6PQsr8.Kw-1709516931498-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Link: <https://gitlab.com/api/v4/projects/15578026/issues/2/resource_state_events?eventable_id=2&id=15578026&page=1&per_page=100>; rel="first", <https://gitlab.com/api/v4/projects/15578026/issues/2/resource_state_events?eventable_id=2&id=15578026&page=1&per_page=100>; rel="last"
+X-Frame-Options: SAMEORIGIN
+Strict-Transport-Security: max-age=31536000
+Vary: Origin, Accept-Encoding
+Content-Security-Policy: default-src 'none'
+X-Gitlab-Meta: {"correlation_id":"527e08a612a163b94cd95046842d5e64","version":"1"}
+X-Page: 1
+X-Per-Page: 100
+X-Total: 0
+Content-Type: application/json
+Accept-Ranges: bytes
+Cache-Control: max-age=0, private, must-revalidate
+X-Next-Page:
+X-Total-Pages: 1
+Gitlab-Sv: api-gke-us-east1-c
+X-Runtime: 0.123529
+
+[] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_labels!page=1&per_page=100 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_labels!page=1&per_page=100
index c79889fbf4..03a46d057b 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_labels!page=1&per_page=100
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_labels!page=1&per_page=100
@@ -1,29 +1,24 @@
-Cache-Control: max-age=0, private, must-revalidate
-Strict-Transport-Security: max-age=31536000
-Gitlab-Lb: haproxy-main-28-lb-gprd
-Link: <https://gitlab.com/api/v4/projects/15578026/labels?id=15578026&include_ancestor_groups=true&page=1&per_page=100&with_counts=false>; rel="first", <https://gitlab.com/api/v4/projects/15578026/labels?id=15578026&include_ancestor_groups=true&page=1&per_page=100&with_counts=false>; rel="last"
+X-Prev-Page:
+Referrer-Policy: strict-origin-when-cross-origin
+Content-Type: application/json
X-Per-Page: 100
-X-Runtime: 0.149464
X-Total: 9
-Ratelimit-Observed: 6
-Gitlab-Sv: localhost
-X-Frame-Options: SAMEORIGIN
-X-Gitlab-Meta: {"correlation_id":"2ccddf20767704a98ed6b582db3b103e","version":"1"}
-X-Next-Page:
-X-Prev-Page:
+X-Runtime: 0.114167
X-Total-Pages: 1
-Ratelimit-Remaining: 1994
-Etag: W/"5a3fb9bc7b1018070943f4aa1353f8b6"
-Ratelimit-Limit: 2000
-X-Page: 1
-Content-Type: application/json
-Vary: Origin, Accept-Encoding
-Set-Cookie: _cfuvid=geNpLvH8Cv5XeYfUVwtpaazw43v9lCcqHE.vyXGk3kU-1701333887126-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Set-Cookie: _cfuvid=UMIyFl_InnSbX4Uxs5X.6ssGMrTVlv5uJzGE_UhDR3w-1709516923392-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Cache-Control: max-age=0, private, must-revalidate
+Link: <https://gitlab.com/api/v4/projects/15578026/labels?id=15578026&include_ancestor_groups=true&page=1&per_page=100&with_counts=false>; rel="first", <https://gitlab.com/api/v4/projects/15578026/labels?id=15578026&include_ancestor_groups=true&page=1&per_page=100&with_counts=false>; rel="last"
X-Content-Type-Options: nosniff
-Ratelimit-Reset: 1701333947
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:47 GMT
+Gitlab-Sv: api-gke-us-east1-b
Content-Security-Policy: default-src 'none'
-Referrer-Policy: strict-origin-when-cross-origin
+Vary: Origin, Accept-Encoding
+X-Next-Page:
+X-Frame-Options: SAMEORIGIN
+X-Gitlab-Meta: {"correlation_id":"3b4e48efc61f09520ea23b3bca5ea469","version":"1"}
+X-Page: 1
Cf-Cache-Status: MISS
+Etag: W/"5a3fb9bc7b1018070943f4aa1353f8b6"
+Strict-Transport-Security: max-age=31536000
+Gitlab-Lb: haproxy-main-30-lb-gprd
[{"id":12959095,"name":"bug","description":null,"description_html":"","text_color":"#FFFFFF","color":"#d9534f","subscribed":false,"priority":null,"is_project_label":true},{"id":12959097,"name":"confirmed","description":null,"description_html":"","text_color":"#FFFFFF","color":"#d9534f","subscribed":false,"priority":null,"is_project_label":true},{"id":12959096,"name":"critical","description":null,"description_html":"","text_color":"#FFFFFF","color":"#d9534f","subscribed":false,"priority":null,"is_project_label":true},{"id":12959100,"name":"discussion","description":null,"description_html":"","text_color":"#FFFFFF","color":"#428bca","subscribed":false,"priority":null,"is_project_label":true},{"id":12959098,"name":"documentation","description":null,"description_html":"","text_color":"#1F1E24","color":"#f0ad4e","subscribed":false,"priority":null,"is_project_label":true},{"id":12959554,"name":"duplicate","description":null,"description_html":"","text_color":"#FFFFFF","color":"#7F8C8D","subscribed":false,"priority":null,"is_project_label":true},{"id":12959102,"name":"enhancement","description":null,"description_html":"","text_color":"#FFFFFF","color":"#5cb85c","subscribed":false,"priority":null,"is_project_label":true},{"id":12959101,"name":"suggestion","description":null,"description_html":"","text_color":"#FFFFFF","color":"#428bca","subscribed":false,"priority":null,"is_project_label":true},{"id":12959099,"name":"support","description":null,"description_html":"","text_color":"#1F1E24","color":"#f0ad4e","subscribed":false,"priority":null,"is_project_label":true}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests!page=1&per_page=1&view=simple b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests!page=1&per_page=1&view=simple
index 7eec1ca917..6f8d70200c 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests!page=1&per_page=1&view=simple
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests!page=1&per_page=1&view=simple
@@ -1,29 +1,24 @@
-Content-Type: application/json
-X-Page: 1
-Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests?id=15578026&order_by=created_at&page=2&per_page=1&sort=desc&state=all&view=simple&with_labels_details=false&with_merge_status_recheck=false>; rel="next", <https://gitlab.com/api/v4/projects/15578026/merge_requests?id=15578026&order_by=created_at&page=1&per_page=1&sort=desc&state=all&view=simple&with_labels_details=false&with_merge_status_recheck=false>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests?id=15578026&order_by=created_at&page=2&per_page=1&sort=desc&state=all&view=simple&with_labels_details=false&with_merge_status_recheck=false>; rel="last"
-Vary: Origin, Accept-Encoding
-X-Runtime: 0.139912
-X-Gitlab-Meta: {"correlation_id":"002c20b78ace441f5585931fed7093ed","version":"1"}
-Gitlab-Sv: localhost
-Cache-Control: max-age=0, private, must-revalidate
+Content-Security-Policy: default-src 'none'
+Etag: W/"14f72c1f555b0e6348d338190e9e4839"
+Strict-Transport-Security: max-age=31536000
+Cf-Cache-Status: MISS
+Set-Cookie: _cfuvid=V__PxQ60qzlepbd7My22SIsuTFfjEafoCsqahPDPjMg-1709516932676-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+X-Frame-Options: SAMEORIGIN
+X-Per-Page: 1
X-Total: 2
X-Total-Pages: 2
-Ratelimit-Observed: 16
-Ratelimit-Limit: 2000
+Gitlab-Sv: api-gke-us-east1-d
+Content-Type: application/json
X-Content-Type-Options: nosniff
-Ratelimit-Remaining: 1984
-Set-Cookie: _cfuvid=6nsOEFMJm7NgrvYZAMGwiJBdm5A5CU71S33zOdN8Kyo-1701333889768-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-X-Per-Page: 1
-X-Prev-Page:
-Strict-Transport-Security: max-age=31536000
-Ratelimit-Reset: 1701333949
-Gitlab-Lb: haproxy-main-09-lb-gprd
X-Next-Page: 2
-Cf-Cache-Status: MISS
-Content-Security-Policy: default-src 'none'
-Etag: W/"14f72c1f555b0e6348d338190e9e4839"
-X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:49 GMT
+Vary: Origin, Accept-Encoding
+Cache-Control: max-age=0, private, must-revalidate
+Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests?id=15578026&order_by=created_at&page=2&per_page=1&sort=desc&state=all&view=simple&with_labels_details=false&with_merge_status_recheck=false>; rel="next", <https://gitlab.com/api/v4/projects/15578026/merge_requests?id=15578026&order_by=created_at&page=1&per_page=1&sort=desc&state=all&view=simple&with_labels_details=false&with_merge_status_recheck=false>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests?id=15578026&order_by=created_at&page=2&per_page=1&sort=desc&state=all&view=simple&with_labels_details=false&with_merge_status_recheck=false>; rel="last"
+X-Prev-Page:
+X-Gitlab-Meta: {"correlation_id":"7e815ab626b3ec958eb45b614106a759","version":"1"}
+X-Page: 1
+X-Runtime: 0.130064
+Gitlab-Lb: haproxy-main-38-lb-gprd
[{"id":43524600,"iid":2,"project_id":15578026,"title":"Test branch","description":"do not merge this PR","state":"opened","created_at":"2019-11-28T15:56:54.104Z","updated_at":"2020-04-19T19:24:21.108Z","web_url":"https://gitlab.com/gitea/test_repo/-/merge_requests/2"}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_1_approvals b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_1_approvals
index 80df508bc3..7a3ab6b858 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_1_approvals
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_1_approvals
@@ -1,22 +1,17 @@
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:51 GMT
-Ratelimit-Limit: 2000
-Content-Security-Policy: default-src 'none'
-X-Gitlab-Meta: {"correlation_id":"0a1a7339f3527e175a537afe058a6ac7","version":"1"}
-Ratelimit-Observed: 21
Cache-Control: max-age=0, private, must-revalidate
-Gitlab-Lb: haproxy-main-38-lb-gprd
-X-Frame-Options: SAMEORIGIN
+Content-Security-Policy: default-src 'none'
Strict-Transport-Security: max-age=31536000
-Cf-Cache-Status: MISS
-Content-Type: application/json
-Etag: W/"19aa54b7d4531bd5ab98282e0b772f20"
X-Content-Type-Options: nosniff
-Set-Cookie: _cfuvid=J2edW64FLja6v0MZCh5tVbLYO42.VvIsTqQ.uj1Gr_k-1701333891171-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Ratelimit-Reset: 1701333951
-Gitlab-Sv: localhost
+X-Frame-Options: SAMEORIGIN
+Set-Cookie: _cfuvid=z0y3rhqnpB208dDD5k02RKi_y6HV6.i7lc65_MGJIHM-1709516935718-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Content-Type: application/json
Vary: Origin, Accept-Encoding
-Ratelimit-Remaining: 1979
-X-Runtime: 0.155712
+Gitlab-Sv: api-gke-us-east1-d
Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Lb: haproxy-main-38-lb-gprd
+Cf-Cache-Status: MISS
+Etag: W/"632b3d0f41fe1650d82b84feaa7b125d"
+X-Gitlab-Meta: {"correlation_id":"68a6a29f5330b299ef95868936bd1b4b","version":"1"}
+X-Runtime: 0.150028
-{"id":43486906,"iid":1,"project_id":15578026,"title":"Update README.md","description":"add warning to readme","state":"merged","created_at":"2019-11-28T08:54:41.034Z","updated_at":"2019-11-28T16:02:08.377Z","merge_status":"can_be_merged","approved":true,"approvals_required":0,"approvals_left":0,"require_password_to_approve":false,"approved_by":[{"user":{"id":527793,"username":"axifive","name":"Alexey Terentyev","state":"active","locked":false,"avatar_url":"https://secure.gravatar.com/avatar/06683cd6b2e2c2ce0ab00fb80cc0729f?s=80\u0026d=identicon","web_url":"https://gitlab.com/axifive"}},{"user":{"id":4102996,"username":"zeripath","name":"zeripath","state":"active","locked":false,"avatar_url":"https://secure.gravatar.com/avatar/1ae18535c2b1aed798da090448997248?s=80\u0026d=identicon","web_url":"https://gitlab.com/zeripath"}}],"suggested_approvers":[],"approvers":[],"approver_groups":[],"user_has_approved":false,"user_can_approve":false,"approval_rules_left":[],"has_approval_rules":true,"merge_request_approvers_available":false,"multiple_approval_rules_available":false,"invalid_approvers_rules":[]} \ No newline at end of file
+{"id":43486906,"iid":1,"project_id":15578026,"title":"Update README.md","description":"add warning to readme","state":"merged","created_at":"2019-11-28T08:54:41.034Z","updated_at":"2019-11-28T16:02:08.377Z","merge_status":"can_be_merged","approved":true,"approvals_required":0,"approvals_left":0,"require_password_to_approve":false,"approved_by":[{"user":{"id":527793,"username":"axifive","name":"Alexey Terentyev","state":"active","locked":false,"avatar_url":"https://secure.gravatar.com/avatar/b5eee878c9129969b55d221a823fd15e55aad8dc15d521f4170e3c93728e02b6?s=80\u0026d=identicon","web_url":"https://gitlab.com/axifive"}},{"user":{"id":4102996,"username":"zeripath","name":"zeripath","state":"active","locked":false,"avatar_url":"https://secure.gravatar.com/avatar/3bad2cdad37aa0bbb3ad276ce8f77e32a1a9567a7083f0866d8df8ed0e92e5b5?s=80\u0026d=identicon","web_url":"https://gitlab.com/zeripath"}}],"suggested_approvers":[],"approvers":[],"approver_groups":[],"user_has_approved":false,"user_can_approve":false,"approval_rules_left":[],"has_approval_rules":true,"merge_request_approvers_available":false,"multiple_approval_rules_available":false,"invalid_approvers_rules":[]} \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2
index 7119342f6c..73441c917c 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2
@@ -1,22 +1,17 @@
-Etag: W/"914149155d75f8d8f7ed2e5351f0fadb"
-X-Runtime: 0.234286
-Ratelimit-Remaining: 1983
-Strict-Transport-Security: max-age=31536000
-Referrer-Policy: strict-origin-when-cross-origin
-Gitlab-Sv: localhost
-Set-Cookie: _cfuvid=aYLZ68TRL8gsnraUk.zZIxRvuv981nIhZNIO9vVpgbU-1701333890175-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options: nosniff
+X-Gitlab-Meta: {"correlation_id":"d351bb99dc07c885c71d8f5299208320","version":"1"}
+Gitlab-Lb: haproxy-main-56-lb-gprd
X-Frame-Options: SAMEORIGIN
-Ratelimit-Observed: 17
Content-Type: application/json
+Referrer-Policy: strict-origin-when-cross-origin
+X-Runtime: 0.237643
+Strict-Transport-Security: max-age=31536000
+Gitlab-Sv: api-gke-us-east1-d
Cache-Control: max-age=0, private, must-revalidate
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:50 GMT
-Ratelimit-Limit: 2000
-Vary: Origin, Accept-Encoding
Content-Security-Policy: default-src 'none'
-Gitlab-Lb: haproxy-main-33-lb-gprd
+Etag: W/"914149155d75f8d8f7ed2e5351f0fadb"
+Vary: Origin, Accept-Encoding
Cf-Cache-Status: MISS
-Ratelimit-Reset: 1701333950
-X-Gitlab-Meta: {"correlation_id":"10d576ab8e82b745b7202a6daec3c5e1","version":"1"}
+Set-Cookie: _cfuvid=yE9p3NWSIseWCeQl9amdJ0bfdfTyf7TIEOGJSzjcxTQ-1709516933254-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
{"id":43524600,"iid":2,"project_id":15578026,"title":"Test branch","description":"do not merge this PR","state":"opened","created_at":"2019-11-28T15:56:54.104Z","updated_at":"2020-04-19T19:24:21.108Z","merged_by":null,"merge_user":null,"merged_at":null,"closed_by":null,"closed_at":null,"target_branch":"master","source_branch":"feat/test","user_notes_count":0,"upvotes":1,"downvotes":0,"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"assignees":[],"assignee":null,"reviewers":[],"source_project_id":15578026,"target_project_id":15578026,"labels":["bug"],"draft":false,"work_in_progress":false,"milestone":{"id":1082926,"iid":1,"project_id":15578026,"title":"1.0.0","description":"","state":"closed","created_at":"2019-11-28T08:42:30.301Z","updated_at":"2019-11-28T15:57:52.401Z","due_date":null,"start_date":null,"expired":false,"web_url":"https://gitlab.com/gitea/test_repo/-/milestones/1"},"merge_when_pipeline_succeeds":false,"merge_status":"can_be_merged","detailed_merge_status":"mergeable","sha":"9f733b96b98a4175276edf6a2e1231489c3bdd23","merge_commit_sha":null,"squash_commit_sha":null,"discussion_locked":null,"should_remove_source_branch":null,"force_remove_source_branch":true,"prepared_at":"2019-11-28T15:56:54.104Z","reference":"!2","references":{"short":"!2","relative":"!2","full":"gitea/test_repo!2"},"web_url":"https://gitlab.com/gitea/test_repo/-/merge_requests/2","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"squash":true,"squash_on_merge":true,"task_completion_status":{"count":0,"completed_count":0},"has_conflicts":false,"blocking_discussions_resolved":true,"approvals_before_merge":null,"subscribed":false,"changes_count":"1","latest_build_started_at":null,"latest_build_finished_at":null,"first_deployed_to_production_at":null,"pipeline":null,"head_pipeline":null,"diff_refs":{"base_sha":"c59c9b451acca9d106cc19d61d87afe3fbbb8b83","head_sha":"9f733b96b98a4175276edf6a2e1231489c3bdd23","start_sha":"c59c9b451acca9d106cc19d61d87afe3fbbb8b83"},"merge_error":null,"first_contribution":false,"user":{"can_merge":false}} \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_approvals b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_approvals
index 02a1deae29..e9e5f3ad0c 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_approvals
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_approvals
@@ -1,22 +1,17 @@
-Vary: Origin, Accept-Encoding
-Ratelimit-Remaining: 1978
-Gitlab-Lb: haproxy-main-04-lb-gprd
-Set-Cookie: _cfuvid=cKUtcpJODQwk9SDRn91k1DY8CY5Tg238DXGgT0a2go0-1701333891493-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Gitlab-Sv: api-gke-us-east1-c
Content-Type: application/json
-Cf-Cache-Status: MISS
-Etag: W/"ce2f774c1b05c5c8a14ec9274444cba3"
-Ratelimit-Limit: 2000
+Vary: Origin, Accept-Encoding
+Gitlab-Lb: haproxy-main-49-lb-gprd
+X-Gitlab-Meta: {"correlation_id":"ea044fc89155ed7f76093b9cc3a7d4ea","version":"1"}
+X-Runtime: 0.144068
+Strict-Transport-Security: max-age=31536000
+Etag: W/"58109b687618e6b9e49ff812d5a911df"
X-Content-Type-Options: nosniff
Cache-Control: max-age=0, private, must-revalidate
-X-Gitlab-Meta: {"correlation_id":"98ee1da556bdb3d764679ebab9ab5312","version":"1"}
-Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: SAMEORIGIN
-Gitlab-Sv: localhost
+Set-Cookie: _cfuvid=bjDdu13341ZREKL1340bXPm8TFCQkeafZBecRxoqNv0-1709516936936-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Cf-Cache-Status: MISS
Content-Security-Policy: default-src 'none'
-X-Runtime: 0.165471
-Strict-Transport-Security: max-age=31536000
-Ratelimit-Observed: 22
-Ratelimit-Reset: 1701333951
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:51 GMT
+Referrer-Policy: strict-origin-when-cross-origin
-{"id":43524600,"iid":2,"project_id":15578026,"title":"Test branch","description":"do not merge this PR","state":"opened","created_at":"2019-11-28T15:56:54.104Z","updated_at":"2020-04-19T19:24:21.108Z","merge_status":"can_be_merged","approved":true,"approvals_required":0,"approvals_left":0,"require_password_to_approve":false,"approved_by":[{"user":{"id":4575606,"username":"real6543","name":"6543","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/4575606/avatar.png","web_url":"https://gitlab.com/real6543"}}],"suggested_approvers":[],"approvers":[],"approver_groups":[{"group":{"id":3181312,"web_url":"https://gitlab.com/groups/gitea","name":"gitea","path":"gitea","description":"Mirror of Gitea source code repositories","visibility":"public","share_with_group_lock":false,"require_two_factor_authentication":false,"two_factor_grace_period":48,"project_creation_level":"maintainer","auto_devops_enabled":null,"subgroup_creation_level":"owner","emails_disabled":false,"emails_enabled":true,"mentions_disabled":null,"lfs_enabled":true,"default_branch_protection":2,"default_branch_protection_defaults":{"allowed_to_push":[{"access_level":30}],"allow_force_push":true,"allowed_to_merge":[{"access_level":30}]},"avatar_url":"https://gitlab.com/uploads/-/system/group/avatar/3181312/gitea.png","request_access_enabled":true,"full_name":"gitea","full_path":"gitea","created_at":"2018-07-04T16:32:10.176Z","parent_id":null,"shared_runners_setting":"enabled","ldap_cn":null,"ldap_access":null,"wiki_access_level":"enabled"}}],"user_has_approved":false,"user_can_approve":false,"approval_rules_left":[],"has_approval_rules":true,"merge_request_approvers_available":false,"multiple_approval_rules_available":false,"invalid_approvers_rules":[]} \ No newline at end of file
+{"id":43524600,"iid":2,"project_id":15578026,"title":"Test branch","description":"do not merge this PR","state":"opened","created_at":"2019-11-28T15:56:54.104Z","updated_at":"2020-04-19T19:24:21.108Z","merge_status":"can_be_merged","approved":true,"approvals_required":0,"approvals_left":0,"require_password_to_approve":false,"approved_by":[{"user":{"id":4575606,"username":"real6543","name":"6543","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/4575606/avatar.png","web_url":"https://gitlab.com/real6543"}}],"suggested_approvers":[],"approvers":[],"approver_groups":[{"group":{"id":3181312,"web_url":"https://gitlab.com/groups/gitea","name":"gitea","path":"gitea","description":"Mirror of Gitea source code repositories","visibility":"public","share_with_group_lock":false,"require_two_factor_authentication":false,"two_factor_grace_period":48,"project_creation_level":"maintainer","auto_devops_enabled":null,"subgroup_creation_level":"owner","emails_disabled":false,"emails_enabled":true,"mentions_disabled":null,"lfs_enabled":true,"math_rendering_limits_enabled":true,"lock_math_rendering_limits_enabled":false,"default_branch_protection":2,"default_branch_protection_defaults":{"allowed_to_push":[{"access_level":30}],"allow_force_push":true,"allowed_to_merge":[{"access_level":30}]},"avatar_url":"https://gitlab.com/uploads/-/system/group/avatar/3181312/gitea.png","request_access_enabled":true,"full_name":"gitea","full_path":"gitea","created_at":"2018-07-04T16:32:10.176Z","parent_id":null,"organization_id":1,"shared_runners_setting":"enabled","ldap_cn":null,"ldap_access":null,"wiki_access_level":"enabled"}}],"user_has_approved":false,"user_can_approve":false,"approval_rules_left":[],"has_approval_rules":true,"merge_request_approvers_available":false,"multiple_approval_rules_available":false,"invalid_approvers_rules":[]} \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=1&per_page=1 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=1&per_page=1
index aab7a74df8..3d99cfbe24 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=1&per_page=1
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=1&per_page=1
@@ -1,29 +1,24 @@
-X-Prev-Page:
-X-Runtime: 0.066211
-Strict-Transport-Security: max-age=31536000
-Content-Security-Policy: default-src 'none'
-X-Per-Page: 1
-X-Total: 2
-Ratelimit-Reset: 1701333950
-Ratelimit-Limit: 2000
-Cf-Cache-Status: MISS
-X-Content-Type-Options: nosniff
-X-Gitlab-Meta: {"correlation_id":"d0f8c843558e938161d7307b686f1cd9","version":"1"}
-Gitlab-Sv: localhost
-Set-Cookie: _cfuvid=WFMplweUX3zWl6uoteYRHeDcpElbTNYhWrIBbNEVC3A-1701333890399-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Content-Type: application/json
-X-Total-Pages: 2
+Set-Cookie: _cfuvid=2_c1M0pqgnG1D4bNm2QluJ9AGXZ7FyB14t_v4ittTjY-1709516933765-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Etag: W/"798718b23a2ec66b16cce20cb7155116"
-X-Next-Page: 2
+X-Runtime: 0.125829
+X-Total-Pages: 2
+Gitlab-Sv: api-gke-us-east1-b
+Cf-Cache-Status: MISS
+X-Prev-Page:
+Cache-Control: max-age=0, private, must-revalidate
Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=2&per_page=1>; rel="next", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=2&per_page=1>; rel="last"
+Content-Type: application/json
+X-Content-Type-Options: nosniff
+X-Gitlab-Meta: {"correlation_id":"9d8976ef2244076825f1e8a8bae3a090","version":"1"}
Vary: Origin, Accept-Encoding
-Ratelimit-Observed: 18
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:50 GMT
+Strict-Transport-Security: max-age=31536000
+X-Total: 2
X-Frame-Options: SAMEORIGIN
-Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Remaining: 1982
-Gitlab-Lb: haproxy-main-31-lb-gprd
-Cache-Control: max-age=0, private, must-revalidate
+X-Next-Page: 2
X-Page: 1
+X-Per-Page: 1
+Content-Security-Policy: default-src 'none'
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Lb: haproxy-main-45-lb-gprd
[{"id":5541414,"name":"thumbsup","user":{"id":4575606,"username":"real6543","name":"6543","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/4575606/avatar.png","web_url":"https://gitlab.com/real6543"},"created_at":"2020-09-02T23:42:34.310Z","updated_at":"2020-09-02T23:42:34.310Z","awardable_id":43524600,"awardable_type":"MergeRequest","url":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=2&per_page=1 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=2&per_page=1
index 5d85a567e8..9981fc1c38 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=2&per_page=1
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=2&per_page=1
@@ -1,29 +1,24 @@
-Cf-Cache-Status: MISS
+X-Content-Type-Options: nosniff
+Gitlab-Lb: haproxy-main-32-lb-gprd
+Cache-Control: max-age=0, private, must-revalidate
Etag: W/"e6776aaa57e6a81bf8a2d8823272cc70"
-X-Frame-Options: SAMEORIGIN
-X-Gitlab-Meta: {"correlation_id":"db01aae11b0cf7febcf051706159faae","version":"1"}
-X-Total-Pages: 2
-Strict-Transport-Security: max-age=31536000
-Gitlab-Lb: haproxy-main-51-lb-gprd
-X-Total: 2
+X-Prev-Page: 1
+X-Runtime: 0.066771
Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Limit: 2000
-Cache-Control: max-age=0, private, must-revalidate
-X-Next-Page:
-Set-Cookie: _cfuvid=X0n26HdiufQTXsshb4pvCyuf0jDSstPZ8GnIiyx57YU-1701333890628-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="prev", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=2&per_page=1>; rel="last"
-Ratelimit-Observed: 19
-Ratelimit-Reset: 1701333950
-Content-Type: application/json
+Content-Security-Policy: default-src 'none'
Vary: Origin, Accept-Encoding
+X-Frame-Options: SAMEORIGIN
+X-Next-Page:
X-Per-Page: 1
-X-Runtime: 0.067511
-Gitlab-Sv: localhost
-X-Prev-Page: 1
-Ratelimit-Remaining: 1981
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:50 GMT
-Content-Security-Policy: default-src 'none'
-X-Content-Type-Options: nosniff
+Set-Cookie: _cfuvid=XlmPD5BVPxHofXNdPbazM3JF2i5DbLlQUVqNW9K6Y28-1709516934208-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+X-Gitlab-Meta: {"correlation_id":"e51679dffc5216e7c77a018a26343380","version":"1"}
+X-Total: 2
+X-Total-Pages: 2
+Content-Type: application/json
X-Page: 2
+Strict-Transport-Security: max-age=31536000
+Cf-Cache-Status: MISS
+Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="prev", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=2&per_page=1>; rel="last"
+Gitlab-Sv: api-gke-us-east1-d
[{"id":5541415,"name":"tada","user":{"id":4575606,"username":"real6543","name":"6543","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/4575606/avatar.png","web_url":"https://gitlab.com/real6543"},"created_at":"2020-09-02T23:42:59.060Z","updated_at":"2020-09-02T23:42:59.060Z","awardable_id":43524600,"awardable_type":"MergeRequest","url":null}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=3&per_page=1 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=3&per_page=1
index aa5a50e45b..07ff6e5ba4 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=3&per_page=1
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_merge_requests_2_award_emoji!page=3&per_page=1
@@ -1,31 +1,26 @@
-X-Page: 3
-Strict-Transport-Security: max-age=31536000
-Accept-Ranges: bytes
-Set-Cookie: _cfuvid=CBSpRhUuajZbJ9Mc_r7SkVmZawoSi5ofuts2TGyHgRk-1701333890842-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Cache-Control: max-age=0, private, must-revalidate
-X-Prev-Page:
-X-Total-Pages: 2
-Ratelimit-Reset: 1701333950
-Gitlab-Sv: localhost
X-Content-Type-Options: nosniff
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:50 GMT
-Gitlab-Lb: haproxy-main-05-lb-gprd
+X-Prev-Page:
+Accept-Ranges: bytes
+Gitlab-Sv: api-gke-us-east1-d
+X-Gitlab-Meta: {"correlation_id":"e19c4433df21888b10c912bab5311ecd","version":"1"}
+X-Next-Page:
+Strict-Transport-Security: max-age=31536000
+Gitlab-Lb: haproxy-main-26-lb-gprd
Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5"
-Vary: Origin, Accept-Encoding
-X-Frame-Options: SAMEORIGIN
-X-Gitlab-Meta: {"correlation_id":"36817edd7cae21d5d6b875faf173ce80","version":"1"}
+Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=2&per_page=1>; rel="last"
X-Per-Page: 1
+Set-Cookie: _cfuvid=Lv9tmhZRx2Sa.lToTQ.C73MDyRvwOtmVmgEi4cbTrkQ-1709516935278-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+X-Total-Pages: 2
+Cf-Cache-Status: MISS
+Content-Length: 2
+X-Page: 3
X-Total: 2
+X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
-Content-Security-Policy: default-src 'none'
-Link: <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=1&per_page=1>; rel="first", <https://gitlab.com/api/v4/projects/15578026/merge_requests/2/award_emoji?id=15578026&merge_request_iid=2&page=2&per_page=1>; rel="last"
-X-Next-Page:
-X-Runtime: 0.061075
-Ratelimit-Limit: 2000
-Ratelimit-Observed: 20
-Cf-Cache-Status: MISS
Content-Type: application/json
-Content-Length: 2
-Ratelimit-Remaining: 1980
+Cache-Control: max-age=0, private, must-revalidate
+Vary: Origin, Accept-Encoding
+X-Runtime: 0.056300
+Content-Security-Policy: default-src 'none'
[] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_milestones!page=1&per_page=100&state=all b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_milestones!page=1&per_page=100&state=all
index 78310e123d..14a40dc505 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_milestones!page=1&per_page=100&state=all
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_milestones!page=1&per_page=100&state=all
@@ -1,29 +1,24 @@
+X-Total: 2
+Referrer-Policy: strict-origin-when-cross-origin
+Gitlab-Sv: api-gke-us-east1-d
X-Content-Type-Options: nosniff
-X-Next-Page:
-Ratelimit-Observed: 5
X-Frame-Options: SAMEORIGIN
-X-Per-Page: 100
-Ratelimit-Limit: 2000
+X-Next-Page:
+X-Total-Pages: 1
Cf-Cache-Status: MISS
+Content-Type: application/json
+Cache-Control: max-age=0, private, must-revalidate
+Link: <https://gitlab.com/api/v4/projects/15578026/milestones?id=15578026&include_ancestors=false&page=1&per_page=100&state=all>; rel="first", <https://gitlab.com/api/v4/projects/15578026/milestones?id=15578026&include_ancestors=false&page=1&per_page=100&state=all>; rel="last"
+Gitlab-Lb: haproxy-main-02-lb-gprd
+Vary: Origin, Accept-Encoding
+X-Per-Page: 100
+X-Runtime: 0.072314
Strict-Transport-Security: max-age=31536000
-Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:46 GMT
+Set-Cookie: _cfuvid=AAzb4a45dTRraCeBWB2eYtD0LUdZnyMdcLZpKLKFKQY-1709516922946-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+X-Page: 1
Content-Security-Policy: default-src 'none'
-Link: <https://gitlab.com/api/v4/projects/15578026/milestones?id=15578026&include_parent_milestones=false&page=1&per_page=100&state=all>; rel="first", <https://gitlab.com/api/v4/projects/15578026/milestones?id=15578026&include_parent_milestones=false&page=1&per_page=100&state=all>; rel="last"
-X-Gitlab-Meta: {"correlation_id":"4f72373995f8681ce127c62d384745a3","version":"1"}
-Gitlab-Sv: localhost
-X-Runtime: 0.073691
-Ratelimit-Remaining: 1995
-Ratelimit-Reset: 1701333946
-Content-Type: application/json
Etag: W/"c8e2d3a5f05ee29c58b665c86684f9f9"
-X-Page: 1
-Gitlab-Lb: haproxy-main-47-lb-gprd
-Vary: Origin, Accept-Encoding
+X-Gitlab-Meta: {"correlation_id":"3786d93aa260a78e86bd229427022c67","version":"1"}
X-Prev-Page:
-X-Total: 2
-Cache-Control: max-age=0, private, must-revalidate
-X-Total-Pages: 1
-Set-Cookie: _cfuvid=ZfjvK5rh2nTUjEDt1Guwzd8zrl6uCDplfE8NBPbdJ7c-1701333886832-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
[{"id":1082927,"iid":2,"project_id":15578026,"title":"1.1.0","description":"","state":"active","created_at":"2019-11-28T08:42:44.575Z","updated_at":"2019-11-28T08:42:44.575Z","due_date":null,"start_date":null,"expired":false,"web_url":"https://gitlab.com/gitea/test_repo/-/milestones/2"},{"id":1082926,"iid":1,"project_id":15578026,"title":"1.0.0","description":"","state":"closed","created_at":"2019-11-28T08:42:30.301Z","updated_at":"2019-11-28T15:57:52.401Z","due_date":null,"start_date":null,"expired":false,"web_url":"https://gitlab.com/gitea/test_repo/-/milestones/1"}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_releases!page=1&per_page=100 b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_releases!page=1&per_page=100
index 9be0b74729..5e0f064cde 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_releases!page=1&per_page=100
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_15578026_releases!page=1&per_page=100
@@ -1,29 +1,24 @@
-Strict-Transport-Security: max-age=31536000
-Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Reset: 1701333947
-X-Total: 1
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:47 GMT
-Ratelimit-Limit: 2000
-X-Runtime: 0.178411
-Gitlab-Lb: haproxy-main-15-lb-gprd
-Vary: Origin, Accept-Encoding
+Gitlab-Lb: haproxy-main-38-lb-gprd
+X-Gitlab-Meta: {"correlation_id":"fe487506ab79b2641f2798820a003e65","version":"1"}
+X-Runtime: 0.126232
+X-Total-Pages: 1
+X-Prev-Page:
+Cache-Control: max-age=0, private, must-revalidate
+Link: <https://gitlab.com/api/v4/projects/15578026/releases?id=15578026&order_by=released_at&page=1&per_page=100&sort=desc>; rel="first", <https://gitlab.com/api/v4/projects/15578026/releases?id=15578026&order_by=released_at&page=1&per_page=100&sort=desc>; rel="last"
X-Page: 1
+X-Per-Page: 100
+Content-Type: application/json
+Vary: Origin, Accept-Encoding
X-Frame-Options: SAMEORIGIN
-Ratelimit-Observed: 7
+X-Next-Page:
+Gitlab-Sv: api-gke-us-east1-d
+X-Content-Type-Options: nosniff
+Referrer-Policy: strict-origin-when-cross-origin
Cf-Cache-Status: MISS
+Strict-Transport-Security: max-age=31536000
+Set-Cookie: _cfuvid=2dextQvrlcispQRNmodfvb.IH__P1bCF5jvS5aFrRjY-1709516924499-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
Etag: W/"dccc7159dc4b46989d13128a7d6ee859"
-X-Content-Type-Options: nosniff
-Ratelimit-Remaining: 1993
-X-Gitlab-Meta: {"correlation_id":"0044a3de3ede2f913cabe6e464dd73c2","version":"1"}
-X-Total-Pages: 1
-X-Next-Page:
-X-Per-Page: 100
-Content-Type: application/json
Content-Security-Policy: default-src 'none'
-Set-Cookie: _cfuvid=h1ayMNs6W_kFPoFe28IpiaFUz1ZAPvY6npUWxARRx4I-1701333887452-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Link: <https://gitlab.com/api/v4/projects/15578026/releases?id=15578026&order_by=released_at&page=1&per_page=100&sort=desc>; rel="first", <https://gitlab.com/api/v4/projects/15578026/releases?id=15578026&order_by=released_at&page=1&per_page=100&sort=desc>; rel="last"
-Gitlab-Sv: localhost
-Cache-Control: max-age=0, private, must-revalidate
-X-Prev-Page:
+X-Total: 1
[{"name":"First Release","tag_name":"v0.9.99","description":"A test release","created_at":"2019-11-28T09:09:48.840Z","released_at":"2019-11-28T09:09:48.836Z","upcoming_release":false,"author":{"id":1241334,"username":"lafriks","name":"Lauris BH","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/1241334/avatar.png","web_url":"https://gitlab.com/lafriks"},"commit":{"id":"0720a3ec57c1f843568298117b874319e7deee75","short_id":"0720a3ec","created_at":"2019-11-28T08:49:16.000+00:00","parent_ids":["93ea21ce45d35690c35e80961d239645139e872c"],"title":"Add new file","message":"Add new file","author_name":"Lauris BH","author_email":"lauris@nix.lv","authored_date":"2019-11-28T08:49:16.000+00:00","committer_name":"Lauris BH","committer_email":"lauris@nix.lv","committed_date":"2019-11-28T08:49:16.000+00:00","trailers":{},"extended_trailers":{},"web_url":"https://gitlab.com/gitea/test_repo/-/commit/0720a3ec57c1f843568298117b874319e7deee75"},"commit_path":"/gitea/test_repo/-/commit/0720a3ec57c1f843568298117b874319e7deee75","tag_path":"/gitea/test_repo/-/tags/v0.9.99","assets":{"count":4,"sources":[{"format":"zip","url":"https://gitlab.com/gitea/test_repo/-/archive/v0.9.99/test_repo-v0.9.99.zip"},{"format":"tar.gz","url":"https://gitlab.com/gitea/test_repo/-/archive/v0.9.99/test_repo-v0.9.99.tar.gz"},{"format":"tar.bz2","url":"https://gitlab.com/gitea/test_repo/-/archive/v0.9.99/test_repo-v0.9.99.tar.bz2"},{"format":"tar","url":"https://gitlab.com/gitea/test_repo/-/archive/v0.9.99/test_repo-v0.9.99.tar"}],"links":[]},"evidences":[{"sha":"89f1223473ee01f192a83d0cb89f4d1eac1de74f01ad","filepath":"https://gitlab.com/gitea/test_repo/-/releases/v0.9.99/evidences/52147.json","collected_at":"2019-11-28T09:09:48.888Z"}],"_links":{"closed_issues_url":"https://gitlab.com/gitea/test_repo/-/issues?release_tag=v0.9.99\u0026scope=all\u0026state=closed","closed_merge_requests_url":"https://gitlab.com/gitea/test_repo/-/merge_requests?release_tag=v0.9.99\u0026scope=all\u0026state=closed","merged_merge_requests_url":"https://gitlab.com/gitea/test_repo/-/merge_requests?release_tag=v0.9.99\u0026scope=all\u0026state=merged","opened_issues_url":"https://gitlab.com/gitea/test_repo/-/issues?release_tag=v0.9.99\u0026scope=all\u0026state=opened","opened_merge_requests_url":"https://gitlab.com/gitea/test_repo/-/merge_requests?release_tag=v0.9.99\u0026scope=all\u0026state=opened","self":"https://gitlab.com/gitea/test_repo/-/releases/v0.9.99"}}] \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_gitea%2Ftest_repo b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_gitea%2Ftest_repo
index 07fed52a81..490eebe791 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_projects_gitea%2Ftest_repo
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_projects_gitea%2Ftest_repo
@@ -1,22 +1,17 @@
-Content-Security-Policy: default-src 'none'
+X-Frame-Options: SAMEORIGIN
+X-Gitlab-Meta: {"correlation_id":"d08798c744b97af051e81bc1f6fecabe","version":"1"}
+Cf-Cache-Status: MISS
Vary: Origin, Accept-Encoding
+X-Runtime: 0.282076
+Gitlab-Lb: haproxy-main-43-lb-gprd
+Etag: W/"8db4917b3be5f4ca0d101a702179b75a"
Referrer-Policy: strict-origin-when-cross-origin
-Gitlab-Sv: localhost
+Set-Cookie: _cfuvid=q8qrvxAlkuGzqRsYQXzKrbLTHH6CWOF_x.icF64i9VQ-1709516921514-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+Content-Security-Policy: default-src 'none'
+Cache-Control: max-age=0, private, must-revalidate
X-Content-Type-Options: nosniff
-Ratelimit-Reset: 1701333946
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:46 GMT
-X-Runtime: 0.144599
-Content-Type: application/json
-X-Gitlab-Meta: {"correlation_id":"919887b868b11ed34c5917e98b4be40d","version":"1"}
-Ratelimit-Observed: 2
-Gitlab-Lb: haproxy-main-42-lb-gprd
Strict-Transport-Security: max-age=31536000
-Cf-Cache-Status: MISS
-Ratelimit-Limit: 2000
-Set-Cookie: _cfuvid=BENIrMVlxs_tt.JplEkDKbUrMpOF_kjRRLJOifNTLqY-1701333886061-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-Etag: W/"3cacfe29f44a69e84a577337eac55d89"
-X-Frame-Options: SAMEORIGIN
-Cache-Control: max-age=0, private, must-revalidate
-Ratelimit-Remaining: 1998
+Gitlab-Sv: api-gke-us-east1-c
+Content-Type: application/json
-{"id":15578026,"description":"Test repository for testing migration from gitlab to gitea","name":"test_repo","name_with_namespace":"gitea / test_repo","path":"test_repo","path_with_namespace":"gitea/test_repo","created_at":"2019-11-28T08:20:33.019Z","default_branch":"master","tag_list":["migration","test"],"topics":["migration","test"],"ssh_url_to_repo":"git@gitlab.com:gitea/test_repo.git","http_url_to_repo":"https://gitlab.com/gitea/test_repo.git","web_url":"https://gitlab.com/gitea/test_repo","readme_url":"https://gitlab.com/gitea/test_repo/-/blob/master/README.md","forks_count":1,"avatar_url":null,"star_count":0,"last_activity_at":"2020-04-19T19:46:04.527Z","namespace":{"id":3181312,"name":"gitea","path":"gitea","kind":"group","full_path":"gitea","parent_id":null,"avatar_url":"/uploads/-/system/group/avatar/3181312/gitea.png","web_url":"https://gitlab.com/groups/gitea"},"container_registry_image_prefix":"registry.gitlab.com/gitea/test_repo","_links":{"self":"https://gitlab.com/api/v4/projects/15578026","issues":"https://gitlab.com/api/v4/projects/15578026/issues","merge_requests":"https://gitlab.com/api/v4/projects/15578026/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/15578026/repository/branches","labels":"https://gitlab.com/api/v4/projects/15578026/labels","events":"https://gitlab.com/api/v4/projects/15578026/events","members":"https://gitlab.com/api/v4/projects/15578026/members","cluster_agents":"https://gitlab.com/api/v4/projects/15578026/cluster_agents"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"public","resolve_outdated_diff_discussions":false,"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"container_registry_enabled":true,"service_desk_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","analytics_access_level":"enabled","container_registry_access_level":"enabled","security_and_compliance_access_level":"private","releases_access_level":"enabled","environments_access_level":"enabled","feature_flags_access_level":"enabled","infrastructure_access_level":"enabled","monitor_access_level":"enabled","model_experiments_access_level":"enabled","emails_disabled":false,"emails_enabled":true,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":1241334,"import_status":"none","open_issues_count":0,"description_html":"\u003cp data-sourcepos=\"1:1-1:58\" dir=\"auto\"\u003eTest repository for testing migration from gitlab to gitea\u003c/p\u003e","updated_at":"2022-08-26T19:41:46.691Z","ci_config_path":null,"public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"ff","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":null,"merge_commit_template":null,"squash_commit_template":null,"issue_branch_template":null,"autoclose_referenced_issues":true,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":false,"compliance_frameworks":[],"permissions":{"project_access":null,"group_access":null}} \ No newline at end of file
+{"id":15578026,"description":"Test repository for testing migration from gitlab to gitea","name":"test_repo","name_with_namespace":"gitea / test_repo","path":"test_repo","path_with_namespace":"gitea/test_repo","created_at":"2019-11-28T08:20:33.019Z","default_branch":"master","tag_list":["migration","test"],"topics":["migration","test"],"ssh_url_to_repo":"git@gitlab.com:gitea/test_repo.git","http_url_to_repo":"https://gitlab.com/gitea/test_repo.git","web_url":"https://gitlab.com/gitea/test_repo","readme_url":"https://gitlab.com/gitea/test_repo/-/blob/master/README.md","forks_count":1,"avatar_url":null,"star_count":0,"last_activity_at":"2020-04-19T19:46:04.527Z","namespace":{"id":3181312,"name":"gitea","path":"gitea","kind":"group","full_path":"gitea","parent_id":null,"avatar_url":"/uploads/-/system/group/avatar/3181312/gitea.png","web_url":"https://gitlab.com/groups/gitea"},"container_registry_image_prefix":"registry.gitlab.com/gitea/test_repo","_links":{"self":"https://gitlab.com/api/v4/projects/15578026","issues":"https://gitlab.com/api/v4/projects/15578026/issues","merge_requests":"https://gitlab.com/api/v4/projects/15578026/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/15578026/repository/branches","labels":"https://gitlab.com/api/v4/projects/15578026/labels","events":"https://gitlab.com/api/v4/projects/15578026/events","members":"https://gitlab.com/api/v4/projects/15578026/members","cluster_agents":"https://gitlab.com/api/v4/projects/15578026/cluster_agents"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"public","resolve_outdated_diff_discussions":false,"repository_object_format":"sha1","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"container_registry_enabled":true,"service_desk_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","analytics_access_level":"enabled","container_registry_access_level":"enabled","security_and_compliance_access_level":"private","releases_access_level":"enabled","environments_access_level":"enabled","feature_flags_access_level":"enabled","infrastructure_access_level":"enabled","monitor_access_level":"enabled","model_experiments_access_level":"enabled","model_registry_access_level":"enabled","emails_disabled":false,"emails_enabled":true,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":1241334,"import_status":"none","open_issues_count":0,"description_html":"\u003cp data-sourcepos=\"1:1-1:58\" dir=\"auto\"\u003eTest repository for testing migration from gitlab to gitea\u003c/p\u003e","updated_at":"2024-01-11T01:23:21.057Z","ci_config_path":null,"public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"ff","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":null,"merge_commit_template":null,"squash_commit_template":null,"issue_branch_template":null,"warn_about_potentially_unwanted_characters":true,"autoclose_referenced_issues":true,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":false,"compliance_frameworks":[],"permissions":{"project_access":null,"group_access":null}} \ No newline at end of file
diff --git a/services/migrations/testdata/gitlab/full_download/_api_v4_version b/services/migrations/testdata/gitlab/full_download/_api_v4_version
index 7c2cd320ad..e61313f6bc 100644
--- a/services/migrations/testdata/gitlab/full_download/_api_v4_version
+++ b/services/migrations/testdata/gitlab/full_download/_api_v4_version
@@ -1,22 +1,17 @@
-Etag: W/"4e5c0a031c3aacb6ba0a3c19e67d7592"
-Ratelimit-Observed: 1
-Content-Type: application/json
-Ratelimit-Remaining: 1999
-Set-Cookie: _cfuvid=qtYbzv8YeGg4q7XaV0aAE2.YqWIp_xrYPGilXrlecsk-1701333885742-0-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
-X-Gitlab-Meta: {"correlation_id":"c7c75f0406e1b1b9705a6d7e9bdb06a5","version":"1"}
-X-Runtime: 0.039264
+Etag: W/"796348ca31c2f886c4bf67753358302b"
+X-Content-Type-Options: nosniff
+Gitlab-Lb: haproxy-main-22-lb-gprd
+Set-Cookie: _cfuvid=XONUYaYMv2vYBZLhOZoclracol_W8SXVwL7kwoXROjM-1709516920902-0.0.1.1-604800000; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None
+X-Gitlab-Meta: {"correlation_id":"0defa7748a7bd70616af6bd0f338094c","version":"1"}
+Strict-Transport-Security: max-age=31536000
+Gitlab-Sv: api-gke-us-east1-c
Cf-Cache-Status: MISS
+Content-Type: application/json
+Cache-Control: max-age=0, private, must-revalidate
Content-Security-Policy: default-src 'none'
-Ratelimit-Reset: 1701333945
-Gitlab-Sv: localhost
-Strict-Transport-Security: max-age=31536000
+X-Frame-Options: SAMEORIGIN
+X-Runtime: 0.035674
Vary: Origin, Accept-Encoding
-X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
-Ratelimit-Resettime: Thu, 30 Nov 2023 08:45:45 GMT
-Gitlab-Lb: haproxy-main-23-lb-gprd
-Cache-Control: max-age=0, private, must-revalidate
-X-Frame-Options: SAMEORIGIN
-Ratelimit-Limit: 2000
-{"version":"16.7.0-pre","revision":"acd848a9228","kas":{"enabled":true,"externalUrl":"wss://kas.gitlab.com","version":"v16.7.0-rc2"},"enterprise":true} \ No newline at end of file
+{"version":"16.10.0-pre","revision":"432cc3c7389","kas":{"enabled":true,"externalUrl":"wss://kas.gitlab.com","version":"v16.10.0-rc1"},"enterprise":true} \ No newline at end of file
diff --git a/services/packages/cleanup/cleanup.go b/services/packages/cleanup/cleanup.go
index 0ff8077bc9..5d5120c6a0 100644
--- a/services/packages/cleanup/cleanup.go
+++ b/services/packages/cleanup/cleanup.go
@@ -12,8 +12,8 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
- "code.gitea.io/gitea/modules/util"
packages_service "code.gitea.io/gitea/services/packages"
alpine_service "code.gitea.io/gitea/services/packages/alpine"
cargo_service "code.gitea.io/gitea/services/packages/cargo"
@@ -60,7 +60,7 @@ func ExecuteCleanupRules(outerCtx context.Context) error {
for _, p := range packages {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
PackageID: p.ID,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
Sort: packages_model.SortCreatedDesc,
Paginator: db.NewAbsoluteListOptions(pcr.KeepCount, 200),
})
diff --git a/services/packages/container/cleanup.go b/services/packages/container/cleanup.go
index dd3f158dbf..3f5f43bbc0 100644
--- a/services/packages/container/cleanup.go
+++ b/services/packages/container/cleanup.go
@@ -9,8 +9,8 @@ import (
packages_model "code.gitea.io/gitea/models/packages"
container_model "code.gitea.io/gitea/models/packages/container"
+ "code.gitea.io/gitea/modules/optional"
container_module "code.gitea.io/gitea/modules/packages/container"
- "code.gitea.io/gitea/modules/util"
packages_service "code.gitea.io/gitea/services/packages"
digest "github.com/opencontainers/go-digest"
@@ -59,8 +59,8 @@ func cleanupExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) e
ExactMatch: true,
Value: container_model.UploadVersion,
},
- IsInternal: util.OptionalBoolTrue,
- HasFiles: util.OptionalBoolFalse,
+ IsInternal: optional.Some(true),
+ HasFiles: optional.Some(false),
})
if err != nil {
return err
diff --git a/services/packages/packages.go b/services/packages/packages.go
index 56d5cc04de..64b1ddd869 100644
--- a/services/packages/packages.go
+++ b/services/packages/packages.go
@@ -18,10 +18,10 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
- "code.gitea.io/gitea/modules/util"
notify_service "code.gitea.io/gitea/services/notify"
)
@@ -330,7 +330,7 @@ func CheckCountQuotaExceeded(ctx context.Context, doer, owner *user_model.User)
if setting.Packages.LimitTotalOwnerCount > -1 {
totalCount, err := packages_model.CountVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: owner.ID,
- IsInternal: util.OptionalBoolFalse,
+ IsInternal: optional.Some(false),
})
if err != nil {
log.Error("CountVersions failed: %v", err)
@@ -640,7 +640,7 @@ func RemoveAllPackages(ctx context.Context, userID int64) (int, error) {
Page: 1,
},
OwnerID: userID,
- IsInternal: util.OptionalBoolNone,
+ IsInternal: optional.None[bool](),
})
if err != nil {
return count, fmt.Errorf("GetOwnedPackages[%d]: %w", userID, err)
diff --git a/services/pull/pull.go b/services/pull/pull.go
index ef6c589a2f..34f3391a63 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -21,7 +21,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/graceful"
@@ -31,6 +30,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/util"
+ gitea_context "code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
notify_service "code.gitea.io/gitea/services/notify"
)
diff --git a/services/pull/review.go b/services/pull/review.go
index 39644479f9..1220d54728 100644
--- a/services/pull/review.go
+++ b/services/pull/review.go
@@ -18,8 +18,8 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
notify_service "code.gitea.io/gitea/services/notify"
)
@@ -56,7 +56,7 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis
ListAll: true,
},
Type: issues_model.CommentTypeCode,
- Invalidated: util.OptionalBoolFalse,
+ Invalidated: optional.Some(false),
IssueIDs: issueIDs,
})
if err != nil {
@@ -327,7 +327,7 @@ func DismissApprovalReviews(ctx context.Context, doer *user_model.User, pull *is
},
IssueID: pull.IssueID,
Type: issues_model.ReviewTypeApprove,
- Dismissed: util.OptionalBoolFalse,
+ Dismissed: optional.Some(false),
})
if err != nil {
return err
@@ -394,7 +394,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
reviews, err := issues_model.FindReviews(ctx, issues_model.FindReviewOptions{
IssueID: review.IssueID,
ReviewerID: review.ReviewerID,
- Dismissed: util.OptionalBoolFalse,
+ Dismissed: optional.Some(false),
})
if err != nil {
return nil, err
diff --git a/services/repository/archiver/archiver_test.go b/services/repository/archiver/archiver_test.go
index 5deec259da..ec6e9dfac3 100644
--- a/services/repository/archiver/archiver_test.go
+++ b/services/repository/archiver/archiver_test.go
@@ -10,7 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
+ "code.gitea.io/gitea/services/contexttest"
_ "code.gitea.io/gitea/models/actions"
diff --git a/services/repository/branch.go b/services/repository/branch.go
index 39be3984ae..c3a7282f43 100644
--- a/services/repository/branch.go
+++ b/services/repository/branch.go
@@ -23,7 +23,6 @@ import (
"code.gitea.io/gitea/modules/queue"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
notify_service "code.gitea.io/gitea/services/notify"
files_service "code.gitea.io/gitea/services/repository/files"
@@ -52,7 +51,7 @@ type Branch struct {
}
// LoadBranches loads branches from the repository limited by page & pageSize.
-func LoadBranches(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, isDeletedBranch util.OptionalBool, keyword string, page, pageSize int) (*Branch, []*Branch, int64, error) {
+func LoadBranches(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, isDeletedBranch optional.Option[bool], keyword string, page, pageSize int) (*Branch, []*Branch, int64, error) {
defaultDBBranch, err := git_model.GetBranch(ctx, repo.ID, repo.DefaultBranch)
if err != nil {
return nil, nil, 0, err
@@ -60,7 +59,7 @@ func LoadBranches(ctx context.Context, repo *repo_model.Repository, gitRepo *git
branchOpts := git_model.FindBranchOptions{
RepoID: repo.ID,
- IsDeletedBranch: isDeletedBranch.ToGeneric(),
+ IsDeletedBranch: isDeletedBranch,
ListOptions: db.ListOptions{
Page: page,
PageSize: pageSize,
diff --git a/services/repository/commit.go b/services/repository/commit.go
index 2497910a83..e8c0262ef4 100644
--- a/services/repository/commit.go
+++ b/services/repository/commit.go
@@ -7,8 +7,8 @@ import (
"context"
"fmt"
- gitea_ctx "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
+ gitea_ctx "code.gitea.io/gitea/services/context"
)
type ContainedLinks struct { // TODO: better name?
diff --git a/services/repository/create.go b/services/repository/create.go
index c3b50ae747..9bc0b93eff 100644
--- a/services/repository/create.go
+++ b/services/repository/create.go
@@ -157,7 +157,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re
}
// Apply changes and commit.
- if err = repo_module.InitRepoCommit(ctx, tmpDir, repo, u, opts.DefaultBranch); err != nil {
+ if err = initRepoCommit(ctx, tmpDir, repo, u, opts.DefaultBranch); err != nil {
return fmt.Errorf("initRepoCommit: %w", err)
}
}
diff --git a/services/repository/files/content_test.go b/services/repository/files/content_test.go
index d50847789a..4811f9d327 100644
--- a/services/repository/files/content_test.go
+++ b/services/repository/files/content_test.go
@@ -7,9 +7,9 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/gitrepo"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/contexttest"
_ "code.gitea.io/gitea/models/actions"
diff --git a/services/repository/files/diff_test.go b/services/repository/files/diff_test.go
index fbd2f3e70f..7cec979d72 100644
--- a/services/repository/files/diff_test.go
+++ b/services/repository/files/diff_test.go
@@ -8,8 +8,8 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/services/contexttest"
"code.gitea.io/gitea/services/gitdiff"
"github.com/stretchr/testify/assert"
diff --git a/services/repository/files/file_test.go b/services/repository/files/file_test.go
index 675ddbddb3..a5b3aad91e 100644
--- a/services/repository/files/file_test.go
+++ b/services/repository/files/file_test.go
@@ -7,10 +7,10 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/services/repository/files/search_test.go b/services/repository/files/search_test.go
index c24bb731a8..959ddaa9f9 100644
--- a/services/repository/files/search_test.go
+++ b/services/repository/files/search_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/services/repository/files/tree_test.go b/services/repository/files/tree_test.go
index 528ef500df..508f20090d 100644
--- a/services/repository/files/tree_test.go
+++ b/services/repository/files/tree_test.go
@@ -7,8 +7,8 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
diff --git a/modules/repository/generate.go b/services/repository/generate.go
index f622383bb5..c444b60b2c 100644
--- a/modules/repository/generate.go
+++ b/services/repository/generate.go
@@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
+ repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/util"
"github.com/gobwas/glob"
@@ -242,7 +243,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
defaultBranch = templateRepo.DefaultBranch
}
- return InitRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch)
+ return initRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch)
}
func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *repo_model.Repository) (err error) {
@@ -292,7 +293,7 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_mo
return err
}
- if err := UpdateRepoSize(ctx, generateRepo); err != nil {
+ if err := repo_module.UpdateRepoSize(ctx, generateRepo); err != nil {
return fmt.Errorf("failed to update size for repository: %w", err)
}
@@ -323,8 +324,8 @@ func (gro GenerateRepoOptions) IsValid() bool {
gro.IssueLabels || gro.ProtectedBranch // or other items as they are added
}
-// GenerateRepository generates a repository from a template
-func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts GenerateRepoOptions) (_ *repo_model.Repository, err error) {
+// generateRepository generates a repository from a template
+func generateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts GenerateRepoOptions) (_ *repo_model.Repository, err error) {
generateRepo := &repo_model.Repository{
OwnerID: owner.ID,
Owner: owner,
@@ -341,7 +342,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
ObjectFormatName: templateRepo.ObjectFormatName,
}
- if err = CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil {
+ if err = repo_module.CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil {
return nil, err
}
@@ -358,11 +359,11 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
}
}
- if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name, generateRepo.ObjectFormatName); err != nil {
+ if err = repo_module.CheckInitRepository(ctx, owner.Name, generateRepo.Name, generateRepo.ObjectFormatName); err != nil {
return generateRepo, err
}
- if err = CheckDaemonExportOK(ctx, generateRepo); err != nil {
+ if err = repo_module.CheckDaemonExportOK(ctx, generateRepo); err != nil {
return generateRepo, fmt.Errorf("checkDaemonExportOK: %w", err)
}
diff --git a/modules/repository/generate_test.go b/services/repository/generate_test.go
index b0f97d0ffb..b0f97d0ffb 100644
--- a/modules/repository/generate_test.go
+++ b/services/repository/generate_test.go
diff --git a/services/repository/init.go b/services/repository/init.go
new file mode 100644
index 0000000000..817fa4abd7
--- /dev/null
+++ b/services/repository/init.go
@@ -0,0 +1,83 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repository
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "time"
+
+ repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ repo_module "code.gitea.io/gitea/modules/repository"
+ "code.gitea.io/gitea/modules/setting"
+ asymkey_service "code.gitea.io/gitea/services/asymkey"
+)
+
+// initRepoCommit temporarily changes with work directory.
+func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Repository, u *user_model.User, defaultBranch string) (err error) {
+ commitTimeStr := time.Now().Format(time.RFC3339)
+
+ sig := u.NewGitSig()
+ // Because this may call hooks we should pass in the environment
+ env := append(os.Environ(),
+ "GIT_AUTHOR_NAME="+sig.Name,
+ "GIT_AUTHOR_EMAIL="+sig.Email,
+ "GIT_AUTHOR_DATE="+commitTimeStr,
+ "GIT_COMMITTER_DATE="+commitTimeStr,
+ )
+ committerName := sig.Name
+ committerEmail := sig.Email
+
+ if stdout, _, err := git.NewCommand(ctx, "add", "--all").
+ SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)).
+ RunStdString(&git.RunOpts{Dir: tmpPath}); err != nil {
+ log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err)
+ return fmt.Errorf("git add --all: %w", err)
+ }
+
+ cmd := git.NewCommand(ctx, "commit", "--message=Initial commit").
+ AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)
+
+ sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u)
+ if sign {
+ cmd.AddOptionFormat("-S%s", keyID)
+
+ if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
+ // need to set the committer to the KeyID owner
+ committerName = signer.Name
+ committerEmail = signer.Email
+ }
+ } else {
+ cmd.AddArguments("--no-gpg-sign")
+ }
+
+ env = append(env,
+ "GIT_COMMITTER_NAME="+committerName,
+ "GIT_COMMITTER_EMAIL="+committerEmail,
+ )
+
+ if stdout, _, err := cmd.
+ SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)).
+ RunStdString(&git.RunOpts{Dir: tmpPath, Env: env}); err != nil {
+ log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.String(), stdout, err)
+ return fmt.Errorf("git commit: %w", err)
+ }
+
+ if len(defaultBranch) == 0 {
+ defaultBranch = setting.Repository.DefaultBranch
+ }
+
+ if stdout, _, err := git.NewCommand(ctx, "push", "origin").AddDynamicArguments("HEAD:" + defaultBranch).
+ SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)).
+ RunStdString(&git.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil {
+ log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err)
+ return fmt.Errorf("git push: %w", err)
+ }
+
+ return nil
+}
diff --git a/services/repository/template.go b/services/repository/template.go
index 06cf05026f..36a680c8e2 100644
--- a/services/repository/template.go
+++ b/services/repository/template.go
@@ -11,7 +11,6 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- repo_module "code.gitea.io/gitea/modules/repository"
notify_service "code.gitea.io/gitea/services/notify"
)
@@ -63,7 +62,7 @@ func GenerateProtectedBranch(ctx context.Context, templateRepo, generateRepo *re
}
// GenerateRepository generates a repository from a template
-func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) {
+func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts GenerateRepoOptions) (_ *repo_model.Repository, err error) {
if !doer.IsAdmin && !owner.CanCreateRepo() {
return nil, repo_model.ErrReachLimitOfRepo{
Limit: owner.MaxRepoCreation,
@@ -72,14 +71,14 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
var generateRepo *repo_model.Repository
if err = db.WithTx(ctx, func(ctx context.Context) error {
- generateRepo, err = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts)
+ generateRepo, err = generateRepository(ctx, doer, owner, templateRepo, opts)
if err != nil {
return err
}
// Git Content
if opts.GitContent && !templateRepo.IsEmpty {
- if err = repo_module.GenerateGitContent(ctx, templateRepo, generateRepo); err != nil {
+ if err = GenerateGitContent(ctx, templateRepo, generateRepo); err != nil {
return err
}
}
diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go
index 068be29ccb..996942d1e5 100644
--- a/services/webhook/webhook.go
+++ b/services/webhook/webhook.go
@@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
@@ -225,7 +226,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu
if source.Repository != nil {
repoHooks, err := db.Find[webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{
RepoID: source.Repository.ID,
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
})
if err != nil {
return fmt.Errorf("ListWebhooksByOpts: %w", err)
@@ -239,7 +240,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu
if owner != nil {
ownerHooks, err := db.Find[webhook_model.Webhook](ctx, webhook_model.ListWebhookOptions{
OwnerID: owner.ID,
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
})
if err != nil {
return fmt.Errorf("ListWebhooksByOpts: %w", err)
@@ -248,7 +249,7 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu
}
// Add any admin-defined system webhooks
- systemHooks, err := webhook_model.GetSystemWebhooks(ctx, util.OptionalBoolTrue)
+ systemHooks, err := webhook_model.GetSystemWebhooks(ctx, optional.Some(true))
if err != nil {
return fmt.Errorf("GetSystemWebhooks: %w", err)
}
diff --git a/tailwind.config.js b/tailwind.config.js
index 8c474c33a8..7f36822001 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -6,6 +6,7 @@ const isProduction = env.NODE_ENV !== 'development';
export default {
prefix: 'tw-',
+ important: true, // the frameworks are mixed together, so tailwind needs to override other framework's styles
content: [
isProduction && '!./templates/devtest/**/*',
isProduction && '!./web_src/js/standalone/devtest.js',
diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl
index 8088315f17..53a12cbe27 100644
--- a/templates/admin/dashboard.tmpl
+++ b/templates/admin/dashboard.tmpl
@@ -2,7 +2,7 @@
<div class="admin-setting-content">
{{if .NeedUpdate}}
<div class="ui negative message flash-error">
- <p>{{(ctx.Locale.Tr "admin.dashboard.new_version_hint" .RemoteVersion AppVer) | Str2html}}</p>
+ <p>{{(ctx.Locale.Tr "admin.dashboard.new_version_hint" .RemoteVersion AppVer) | SanitizeHTML}}</p>
</div>
{{end}}
<h4 class="ui top attached header">
diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl
index e11247aed4..e977c8307c 100644
--- a/templates/admin/repo/list.tmpl
+++ b/templates/admin/repo/list.tmpl
@@ -7,7 +7,7 @@
</div>
</h4>
<div class="ui attached segment">
- {{template "admin/repo/search" .}}
+ {{template "shared/repo_search" .}}
</div>
<div class="ui attached table segment">
<table class="ui very basic striped table unstackable">
diff --git a/templates/admin/repo/search.tmpl b/templates/admin/repo/search.tmpl
deleted file mode 100644
index 247ec5491a..0000000000
--- a/templates/admin/repo/search.tmpl
+++ /dev/null
@@ -1,29 +0,0 @@
-<div class="ui secondary filter menu gt-ac gt-mx-0">
- <form class="ui form ignore-dirty gt-f1">
- <div class="ui fluid action input">
- {{template "shared/searchinput" dict "Value" .Keyword}}
- <button class="ui primary button">{{ctx.Locale.Tr "explore.search"}}</button>
- </div>
- </form>
- <!-- Sort -->
- <div class="ui dropdown type jump item gt-mr-0">
- <span class="text">
- {{ctx.Locale.Tr "repo.issues.filter_sort"}}
- </span>
- {{svg "octicon-triangle-down" 14 "dropdown icon"}}
- <div class="menu">
- <a class="{{if or (eq .SortType "oldest") (not .SortType)}}active {{end}}item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
- <a class="{{if eq .SortType "newest"}}active {{end}}item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
- <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
- <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
- <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
- <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
- <a class="{{if eq .SortType "moststars"}}active {{end}}item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.moststars"}}</a>
- <a class="{{if eq .SortType "feweststars"}}active {{end}}item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.feweststars"}}</a>
- <a class="{{if eq .SortType "mostforks"}}active {{end}}item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostforks"}}</a>
- <a class="{{if eq .SortType "fewestforks"}}active {{end}}item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.fewestforks"}}</a>
- <a class="{{if eq .SortType "size"}}active {{end}}item" href="{{$.Link}}?sort=size&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.by_size"}}</a>
- <a class="{{if eq .SortType "reversesize"}}active {{end}}item" href="{{$.Link}}?sort=reversesize&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_by_size"}}</a>
- </div>
- </div>
-</div>
diff --git a/templates/admin/self_check.tmpl b/templates/admin/self_check.tmpl
index 6bca01ec65..fafaf9242d 100644
--- a/templates/admin/self_check.tmpl
+++ b/templates/admin/self_check.tmpl
@@ -20,7 +20,7 @@
{{if .DatabaseCheckInconsistentCollationColumns}}
<div class="ui red message">
{{ctx.Locale.Tr "admin.self_check.database_inconsistent_collation_columns" .DatabaseCheckResult.DatabaseCollation}}
- <ul class="gt-w-full">
+ <ul class="tw-w-full">
{{range .DatabaseCheckInconsistentCollationColumns}}
<li>{{.}}</li>
{{end}}
diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl
index fcb8ce0827..159c821099 100644
--- a/templates/admin/user/edit.tmpl
+++ b/templates/admin/user/edit.tmpl
@@ -70,6 +70,21 @@
<input id="password" name="password" type="password" autocomplete="new-password">
<p class="help">{{ctx.Locale.Tr "admin.users.password_helper"}}</p>
</div>
+
+ <div class="field {{if .Err_Language}}error{{end}}">
+ <label for="language">{{ctx.Locale.Tr "settings.language"}}</label>
+ <div class="ui selection dropdown">
+ <input name="language" type="hidden" value="{{.User.Language}}">
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="text">{{range .AllLangs}}{{if eq $.User.Language .Lang}}{{.Name}}{{end}}{{end}}</div>
+ <div class="menu">
+ {{range .AllLangs}}
+ <div class="item{{if eq $.User.Language .Lang}} active selected{{end}}" data-value="{{.Lang}}">{{.Name}}</div>
+ {{end}}
+ </div>
+ </div>
+ </div>
+
<div class="field {{if .Err_Website}}error{{end}}">
<label for="website">{{ctx.Locale.Tr "settings.website"}}</label>
<input id="website" name="website" type="url" value="{{.User.Website}}" placeholder="http://mydomain.com or https://mydomain.com" maxlength="255">
diff --git a/templates/admin/user/view_details.tmpl b/templates/admin/user/view_details.tmpl
index 21425eecb4..be2f32b5ec 100644
--- a/templates/admin/user/view_details.tmpl
+++ b/templates/admin/user/view_details.tmpl
@@ -48,6 +48,14 @@
{{svg "octicon-x"}}
{{end}}
</div>
+ {{if .User.Language}}
+ <div class="flex-item-body">
+ <span class="flex-text-inline">
+ <b>{{ctx.Locale.Tr "settings.language"}}:</b>
+ {{range .AllLangs}}{{if eq $.User.Language .Lang}}{{.Name}}{{end}}{{end}}
+ </span>
+ </div>
+ {{end}}
{{if .User.Location}}
<div class="flex-item-body">
<span class="flex-text-inline">{{svg "octicon-location"}}{{.User.Location}}</span>
diff --git a/templates/base/alert.tmpl b/templates/base/alert.tmpl
index 160584f769..760d3bfa2c 100644
--- a/templates/base/alert.tmpl
+++ b/templates/base/alert.tmpl
@@ -1,20 +1,20 @@
{{if .Flash.ErrorMsg}}
<div class="ui negative message flash-message flash-error">
- <p>{{.Flash.ErrorMsg | Str2html}}</p>
+ <p>{{.Flash.ErrorMsg | SanitizeHTML}}</p>
</div>
{{end}}
{{if .Flash.SuccessMsg}}
<div class="ui positive message flash-message flash-success">
- <p>{{.Flash.SuccessMsg | Str2html}}</p>
+ <p>{{.Flash.SuccessMsg | SanitizeHTML}}</p>
</div>
{{end}}
{{if .Flash.InfoMsg}}
<div class="ui info message flash-message flash-info">
- <p>{{.Flash.InfoMsg | Str2html}}</p>
+ <p>{{.Flash.InfoMsg | SanitizeHTML}}</p>
</div>
{{end}}
{{if .Flash.WarningMsg}}
<div class="ui warning message flash-message flash-warning">
- <p>{{.Flash.WarningMsg | Str2html}}</p>
+ <p>{{.Flash.WarningMsg | SanitizeHTML}}</p>
</div>
{{end}}
diff --git a/templates/base/alert_details.tmpl b/templates/base/alert_details.tmpl
index 1d7ec15dc0..6801c8240f 100644
--- a/templates/base/alert_details.tmpl
+++ b/templates/base/alert_details.tmpl
@@ -2,6 +2,6 @@
<details>
<summary>{{.Summary}}</summary>
<code>
- {{.Details | Str2html}}
+ {{.Details | SanitizeHTML}}
</code>
</details>
diff --git a/templates/base/head_navbar.tmpl b/templates/base/head_navbar.tmpl
index fb0301aeb1..06fc5913d0 100644
--- a/templates/base/head_navbar.tmpl
+++ b/templates/base/head_navbar.tmpl
@@ -13,14 +13,14 @@
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
<div class="ui secondary menu item navbar-mobile-right">
{{if .IsSigned}}
- <a id="mobile-notifications-icon" class="item gt-w-auto gt-p-3" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
+ <a id="mobile-notifications-icon" class="item tw-w-auto gt-p-3" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
<div class="gt-relative">
{{svg "octicon-bell"}}
<span class="notification_count{{if not $notificationUnreadCount}} gt-hidden{{end}}">{{$notificationUnreadCount}}</span>
</div>
</a>
{{end}}
- <button class="item gt-w-auto ui icon mini button gt-p-3 gt-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "toggle_menu"}}">{{svg "octicon-three-bars"}}</button>
+ <button class="item tw-w-auto ui icon mini button gt-p-3 gt-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "toggle_menu"}}">{{svg "octicon-three-bars"}}</button>
</div>
<!-- navbar links non-mobile -->
diff --git a/templates/base/paginate.tmpl b/templates/base/paginate.tmpl
index 503817c339..ef7d0b341b 100644
--- a/templates/base/paginate.tmpl
+++ b/templates/base/paginate.tmpl
@@ -1,13 +1,15 @@
-{{$paginationLink := .Page.GetParams}}
+{{$paginationParams := .Page.GetParams}}
+{{$paginationLink := $.Link}}
+{{if eq $paginationLink AppSubUrl}}{{$paginationLink = print $paginationLink "/"}}{{end}}
{{with .Page.Paginater}}
{{if gt .TotalPages 1}}
<div class="center page buttons">
<div class="ui borderless pagination menu">
- <a class="{{if .IsFirst}}disabled{{end}} item navigation" {{if not .IsFirst}}href="{{$.Link}}{{if $paginationLink}}?{{$paginationLink}}{{end}}"{{end}}>
+ <a class="{{if .IsFirst}}disabled{{end}} item navigation" {{if not .IsFirst}}href="{{$paginationLink}}{{if $paginationParams}}?{{$paginationParams}}{{end}}"{{end}}>
{{svg "gitea-double-chevron-left" 16 "gt-mr-2"}}
<span class="navigation_label">{{ctx.Locale.Tr "admin.first_page"}}</span>
</a>
- <a class="{{if not .HasPrevious}}disabled{{end}} item navigation" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>
+ <a class="{{if not .HasPrevious}}disabled{{end}} item navigation" {{if .HasPrevious}}href="{{$paginationLink}}?page={{.Previous}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>
{{svg "octicon-chevron-left" 16 "gt-mr-2"}}
<span class="navigation_label">{{ctx.Locale.Tr "repo.issues.previous"}}</span>
</a>
@@ -15,14 +17,14 @@
{{if eq .Num -1}}
<a class="disabled item">...</a>
{{else}}
- <a class="{{if .IsCurrent}}active {{end}}item gt-content-center" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>{{.Num}}</a>
+ <a class="{{if .IsCurrent}}active {{end}}item gt-content-center" {{if not .IsCurrent}}href="{{$paginationLink}}?page={{.Num}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>{{.Num}}</a>
{{end}}
{{end}}
- <a class="{{if not .HasNext}}disabled{{end}} item navigation" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>
+ <a class="{{if not .HasNext}}disabled{{end}} item navigation" {{if .HasNext}}href="{{$paginationLink}}?page={{.Next}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>
<span class="navigation_label">{{ctx.Locale.Tr "repo.issues.next"}}</span>
{{svg "octicon-chevron-right" 16 "gt-ml-2"}}
</a>
- <a class="{{if .IsLast}}disabled{{end}} item navigation" {{if not .IsLast}}href="{{$.Link}}?page={{.TotalPages}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>
+ <a class="{{if .IsLast}}disabled{{end}} item navigation" {{if not .IsLast}}href="{{$paginationLink}}?page={{.TotalPages}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>
<span class="navigation_label">{{ctx.Locale.Tr "admin.last_page"}}</span>
{{svg "gitea-double-chevron-right" 16 "gt-ml-2"}}
</a>
diff --git a/templates/devtest/fomantic-modal.tmpl b/templates/devtest/fomantic-modal.tmpl
index eda169a043..0b4199a197 100644
--- a/templates/devtest/fomantic-modal.tmpl
+++ b/templates/devtest/fomantic-modal.tmpl
@@ -5,7 +5,7 @@
<div id="test-modal-form-1" class="ui mini modal">
<div class="header">Form dialog (layout 1)</div>
<form class="content" method="post">
- <div class="ui input gt-w-full"><input name="user_input"></div>
+ <div class="ui input tw-w-full"><input name="user_input"></div>
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
</form>
</div>
@@ -14,7 +14,7 @@
<div class="header">Form dialog (layout 2)</div>
<form method="post">
<div class="content">
- <div class="ui input gt-w-full"><input name="user_input"></div>
+ <div class="ui input tw-w-full"><input name="user_input"></div>
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
</div>
</form>
@@ -24,7 +24,7 @@
<div class="header">Form dialog (layout 3)</div>
<form method="post">
<div class="content">
- <div class="ui input gt-w-full"><input name="user_input"></div>
+ <div class="ui input tw-w-full"><input name="user_input"></div>
</div>
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
</form>
@@ -33,7 +33,7 @@
<div id="test-modal-form-4" class="ui mini modal">
<div class="header">Form dialog (layout 4)</div>
<div class="content">
- <div class="ui input gt-w-full"><input name="user_input"></div>
+ <div class="ui input tw-w-full"><input name="user_input"></div>
</div>
<form method="post">
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
diff --git a/templates/explore/repo_search.tmpl b/templates/explore/repo_search.tmpl
deleted file mode 100644
index 96f34d508a..0000000000
--- a/templates/explore/repo_search.tmpl
+++ /dev/null
@@ -1,45 +0,0 @@
-<div class="ui secondary filter menu gt-ac gt-mx-0">
- <form class="ui form ignore-dirty gt-f1">
- <input type="hidden" name="sort" value="{{$.SortType}}">
- <input type="hidden" name="language" value="{{$.Language}}">
- <input type="hidden" name="topic" value="{{$.TopicOnly}}">
- <div class="ui fluid action input">
- {{template "shared/searchinput" dict "Value" .Keyword}}
- {{if .PageIsExploreRepositories}}
- <input type="hidden" name="only_show_relevant" value="{{.OnlyShowRelevant}}">
- {{else if .TabName}}
- <input type="hidden" name="tab" value="{{.TabName}}">
- {{end}}
- <button class="ui primary button">{{ctx.Locale.Tr "explore.search"}}</button>
- </div>
- </form>
- <!-- Sort -->
- <div class="ui dropdown type jump item gt-mr-0">
- <span class="text">
- {{ctx.Locale.Tr "repo.issues.filter_sort"}}
- </span>
- {{svg "octicon-triangle-down" 14 "dropdown icon"}}
- <div class="menu">
- <a class="{{if eq .SortType "newest"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=newest&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a>
- <a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=oldest&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
- <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=alphabetically&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
- <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=reversealphabetically&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
- <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=recentupdate&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
- <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=leastupdate&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
- {{if not .DisableStars}}
- <a class="{{if eq .SortType "moststars"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=moststars&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.moststars"}}</a>
- <a class="{{if eq .SortType "feweststars"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=feweststars&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.feweststars"}}</a>
- {{end}}
- {{if not .DisableForks}}
- <a class="{{if eq .SortType "mostforks"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=mostforks&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.mostforks"}}</a>
- <a class="{{if eq .SortType "fewestforks"}}active {{end}}item" href="{{$.Link}}?tab={{$.TabName}}&sort=fewestforks&q={{$.Keyword}}&language={{$.Language}}">{{ctx.Locale.Tr "repo.issues.filter_sort.fewestforks"}}</a>
- {{end}}
- </div>
- </div>
-</div>
-{{if and .PageIsExploreRepositories .OnlyShowRelevant}}
- <div class="ui message explore-relevancy-note">
- <span data-tooltip-content="{{ctx.Locale.Tr "explore.relevant_repositories_tooltip"}}">{{ctx.Locale.Tr "explore.relevant_repositories" (printf "?only_show_relevant=0&sort=%s&q=%s&language=%s" $.SortType (QueryEscape $.Keyword) (QueryEscape $.Language))}}</span>
- </div>
-{{end}}
-<div class="divider"></div>
diff --git a/templates/explore/repos.tmpl b/templates/explore/repos.tmpl
index dfede2ffcc..53742bf0d9 100644
--- a/templates/explore/repos.tmpl
+++ b/templates/explore/repos.tmpl
@@ -2,7 +2,7 @@
<div role="main" aria-label="{{.Title}}" class="page-content explore repositories">
{{template "explore/navbar" .}}
<div class="ui container">
- {{template "explore/repo_search" .}}
+ {{template "shared/repo_search" .}}
{{template "explore/repo_list" .}}
{{template "base/paginate" .}}
</div>
diff --git a/templates/explore/search.tmpl b/templates/explore/search.tmpl
index 74b80436dc..2bb5f319d1 100644
--- a/templates/explore/search.tmpl
+++ b/templates/explore/search.tmpl
@@ -16,8 +16,6 @@
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
- <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
- <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div>
</div>
</div>
diff --git a/templates/home.tmpl b/templates/home.tmpl
index 78364431e9..393525dcd4 100644
--- a/templates/home.tmpl
+++ b/templates/home.tmpl
@@ -17,7 +17,7 @@
{{svg "octicon-flame"}} {{ctx.Locale.Tr "startpage.install"}}
</h1>
<p class="large">
- {{ctx.Locale.Tr "startpage.install_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.install_desc" | SanitizeHTML}}
</p>
</div>
<div class="eight wide center column">
@@ -25,7 +25,7 @@
{{svg "octicon-device-desktop"}} {{ctx.Locale.Tr "startpage.platform"}}
</h1>
<p class="large">
- {{ctx.Locale.Tr "startpage.platform_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.platform_desc" | SanitizeHTML}}
</p>
</div>
</div>
@@ -35,7 +35,7 @@
{{svg "octicon-rocket"}} {{ctx.Locale.Tr "startpage.lightweight"}}
</h1>
<p class="large">
- {{ctx.Locale.Tr "startpage.lightweight_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.lightweight_desc" | SanitizeHTML}}
</p>
</div>
<div class="eight wide center column">
@@ -43,7 +43,7 @@
{{svg "octicon-code"}} {{ctx.Locale.Tr "startpage.license"}}
</h1>
<p class="large">
- {{ctx.Locale.Tr "startpage.license_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.license_desc" | SanitizeHTML}}
</p>
</div>
</div>
diff --git a/templates/mail/auth/activate.tmpl b/templates/mail/auth/activate.tmpl
index a15afe3d49..c50717d315 100644
--- a/templates/mail/auth/activate.tmpl
+++ b/templates/mail/auth/activate.tmpl
@@ -8,8 +8,8 @@
{{$activate_url := printf "%suser/activate?code=%s" AppUrl (QueryEscape .Code)}}
<body>
- <p>{{.locale.Tr "mail.activate_account.text_1" (.DisplayName|DotEscape) AppName | Str2html}}</p><br>
- <p>{{.locale.Tr "mail.activate_account.text_2" .ActiveCodeLives | Str2html}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
+ <p>{{.locale.Tr "mail.activate_account.text_1" (.DisplayName|DotEscape) AppName | SanitizeHTML}}</p><br>
+ <p>{{.locale.Tr "mail.activate_account.text_2" .ActiveCodeLives | SanitizeHTML}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
<p>{{.locale.Tr "mail.link_not_working_do_paste"}}</p>
<p>© <a target="_blank" rel="noopener noreferrer" href="{{AppUrl}}">{{AppName}}</a></p>
diff --git a/templates/mail/auth/activate_email.tmpl b/templates/mail/auth/activate_email.tmpl
index b15cc2a68a..30fcb99ab8 100644
--- a/templates/mail/auth/activate_email.tmpl
+++ b/templates/mail/auth/activate_email.tmpl
@@ -8,8 +8,8 @@
{{$activate_url := printf "%suser/activate_email?code=%s&email=%s" AppUrl (QueryEscape .Code) (QueryEscape .Email)}}
<body>
- <p>{{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}</p><br>
- <p>{{.locale.Tr "mail.activate_email.text" .ActiveCodeLives | Str2html}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
+ <p>{{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | SanitizeHTML}}</p><br>
+ <p>{{.locale.Tr "mail.activate_email.text" .ActiveCodeLives | SanitizeHTML}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
<p>{{.locale.Tr "mail.link_not_working_do_paste"}}</p>
<p>© <a target="_blank" rel="noopener noreferrer" href="{{AppUrl}}">{{AppName}}</a></p>
diff --git a/templates/mail/auth/register_notify.tmpl b/templates/mail/auth/register_notify.tmpl
index 224c845452..27c685e58f 100644
--- a/templates/mail/auth/register_notify.tmpl
+++ b/templates/mail/auth/register_notify.tmpl
@@ -8,7 +8,7 @@
{{$set_pwd_url := printf "%[1]suser/forgot_password" AppUrl}}
<body>
- <p>{{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}</p><br>
+ <p>{{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | SanitizeHTML}}</p><br>
<p>{{.locale.Tr "mail.register_notify.text_1" AppName}}</p><br>
<p>{{.locale.Tr "mail.register_notify.text_2" .Username}}</p><p><a href="{{AppUrl}}user/login">{{AppUrl}}user/login</a></p><br>
<p>{{.locale.Tr "mail.register_notify.text_3" $set_pwd_url}}</p><br>
diff --git a/templates/mail/auth/reset_passwd.tmpl b/templates/mail/auth/reset_passwd.tmpl
index 172844c954..e1af5b483c 100644
--- a/templates/mail/auth/reset_passwd.tmpl
+++ b/templates/mail/auth/reset_passwd.tmpl
@@ -8,8 +8,8 @@
{{$recover_url := printf "%suser/recover_account?code=%s" AppUrl (QueryEscape .Code)}}
<body>
- <p>{{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}</p><br>
- <p>{{.locale.Tr "mail.reset_password.text" .ResetPwdCodeLives | Str2html}}</p><p><a href="{{$recover_url}}">{{$recover_url}}</a></p><br>
+ <p>{{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | SanitizeHTML}}</p><br>
+ <p>{{.locale.Tr "mail.reset_password.text" .ResetPwdCodeLives | SanitizeHTML}}</p><p><a href="{{$recover_url}}">{{$recover_url}}</a></p><br>
<p>{{.locale.Tr "mail.link_not_working_do_paste"}}</p>
<p>© <a target="_blank" rel="noopener noreferrer" href="{{AppUrl}}">{{AppName}}</a></p>
diff --git a/templates/mail/issue/default.tmpl b/templates/mail/issue/default.tmpl
index 49887e1e1d..796dc403b7 100644
--- a/templates/mail/issue/default.tmpl
+++ b/templates/mail/issue/default.tmpl
@@ -16,7 +16,7 @@
</head>
<body>
- {{if .IsMention}}<p>{{.locale.Tr "mail.issue.x_mentioned_you" .Doer.Name | Str2html}}</p>{{end}}
+ {{if .IsMention}}<p>{{.locale.Tr "mail.issue.x_mentioned_you" .Doer.Name | SanitizeHTML}}</p>{{end}}
{{if eq .ActionName "push"}}
<p>
{{if .Comment.IsForcePush}}
@@ -30,7 +30,7 @@
{{.locale.Tr "mail.issue.action.force_push" .Doer.Name .Comment.Issue.PullRequest.HeadBranch $oldCommitLink $newCommitLink}}
{{else}}
- {{.locale.TrN (len .Comment.Commits) "mail.issue.action.push_1" "mail.issue.action.push_n" .Doer.Name .Comment.Issue.PullRequest.HeadBranch (len .Comment.Commits) | Str2html}}
+ {{.locale.TrN (len .Comment.Commits) "mail.issue.action.push_1" "mail.issue.action.push_n" .Doer.Name .Comment.Issue.PullRequest.HeadBranch (len .Comment.Commits) | SanitizeHTML}}
{{end}}
</p>
{{end}}
@@ -58,14 +58,14 @@
{{.locale.Tr "mail.issue.action.new" .Doer.Name .Issue.Index}}
{{end}}
{{else}}
- {{.Body | Str2html}}
+ {{.Body | SanitizeHTML}}
{{end -}}
{{- range .ReviewComments}}
<hr>
{{$.locale.Tr "mail.issue.in_tree_path" .TreePath}}
<div class="review">
<pre>{{.Patch}}</pre>
- <div>{{.RenderedContent | SafeHTML}}</div>
+ <div>{{.RenderedContent}}</div>
</div>
{{end -}}
{{if eq .ActionName "push"}}
diff --git a/templates/mail/notify/admin_new_user.tmpl b/templates/mail/notify/admin_new_user.tmpl
index 34d1584f60..04f90b61ab 100644
--- a/templates/mail/notify/admin_new_user.tmpl
+++ b/templates/mail/notify/admin_new_user.tmpl
@@ -13,9 +13,9 @@
<body>
<ul>
- <h3>{{.Locale.Tr "mail.admin.new_user.user_info" | Str2html}}: <a href="{{.NewUserUrl}}">@{{.NewUser.Name}}</a></h3>
- <li>{{.Locale.Tr "admin.users.created" | Str2html}}: {{DateTime "full" .NewUser.CreatedUnix}}</li>
+ <h3>{{.Locale.Tr "mail.admin.new_user.user_info" | SanitizeHTML}}: <a href="{{.NewUserUrl}}">@{{.NewUser.Name}}</a></h3>
+ <li>{{.Locale.Tr "admin.users.created" | SanitizeHTML}}: {{DateTime "full" .NewUser.CreatedUnix}}</li>
</ul>
- <p> {{.Body | Str2html}} </p>
+ <p> {{.Body | SanitizeHTML}} </p>
</body>
</html>
diff --git a/templates/mail/notify/repo_transfer.tmpl b/templates/mail/notify/repo_transfer.tmpl
index 597048ddf4..8c8b276484 100644
--- a/templates/mail/notify/repo_transfer.tmpl
+++ b/templates/mail/notify/repo_transfer.tmpl
@@ -5,7 +5,7 @@
<title>{{.Subject}}</title>
</head>
-{{$url := HTMLFormat "<a href='%[1]s'>%[2]s</a>" .Link .Repo)}}
+{{$url := HTMLFormat "<a href='%[1]s'>%[2]s</a>" .Link .Repo}}
<body>
<p>{{.Subject}}.
{{.locale.Tr "mail.repo.transfer.body" $url}}
diff --git a/templates/mail/release.tmpl b/templates/mail/release.tmpl
index 62a16573c6..90a3caa4c5 100644
--- a/templates/mail/release.tmpl
+++ b/templates/mail/release.tmpl
@@ -22,7 +22,7 @@
{{.locale.Tr "mail.release.note"}}<br>
{{- if eq .Release.RenderedNote ""}}
{{else}}
- {{.Release.RenderedNote | Str2html}}
+ {{.Release.RenderedNote}}
{{end -}}
</p>
<br><br>
diff --git a/templates/mail/team_invite.tmpl b/templates/mail/team_invite.tmpl
index d21b7843ec..67b368f348 100644
--- a/templates/mail/team_invite.tmpl
+++ b/templates/mail/team_invite.tmpl
@@ -5,7 +5,7 @@
<meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no">
</head>
<body>
- <p>{{.locale.Tr "mail.team_invite.text_1" (DotEscape .Inviter.DisplayName) (DotEscape .Team.Name) (DotEscape .Organization.DisplayName) | Str2html}}</p>
+ <p>{{.locale.Tr "mail.team_invite.text_1" (DotEscape .Inviter.DisplayName) (DotEscape .Team.Name) (DotEscape .Organization.DisplayName) | SanitizeHTML}}</p>
<p>{{.locale.Tr "mail.team_invite.text_2"}}</p><p><a href="{{.InviteURL}}">{{.InviteURL}}</a></p>
<p>{{.locale.Tr "mail.link_not_working_do_paste"}}</p>
<p>{{.locale.Tr "mail.team_invite.text_3" .Invite.Email}}</p>
diff --git a/templates/org/header.tmpl b/templates/org/header.tmpl
index 8423fd7d3b..efbbc43b1d 100644
--- a/templates/org/header.tmpl
+++ b/templates/org/header.tmpl
@@ -18,7 +18,7 @@
{{end}}
</span>
</div>
- {{if .RenderedDescription}}<div class="render-content markup">{{.RenderedDescription | Str2html}}</div>{{end}}
+ {{if .RenderedDescription}}<div class="render-content markup">{{.RenderedDescription}}</div>{{end}}
<div class="text light meta gt-mt-2">
{{if .Org.Location}}<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="flex-text-block">{{svg "octicon-link"}} <a class="muted" target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl
index 1c8a083aed..d0a39c04fc 100644
--- a/templates/org/home.tmpl
+++ b/templates/org/home.tmpl
@@ -11,9 +11,9 @@
<div class="ui mobile reversed stackable grid">
<div class="ui {{if .ShowMemberAndTeamTab}}eleven wide{{end}} column">
{{if .ProfileReadme}}
- <div id="readme_profile" class="markup">{{.ProfileReadme | Str2html}}</div>
+ <div id="readme_profile" class="markup">{{.ProfileReadme}}</div>
{{end}}
- {{template "explore/repo_search" .}}
+ {{template "shared/repo_search" .}}
{{template "explore/repo_list" .}}
{{template "base/paginate" .}}
</div>
diff --git a/templates/org/settings/delete.tmpl b/templates/org/settings/delete.tmpl
index 2cf8238f57..8c93e7548d 100644
--- a/templates/org/settings/delete.tmpl
+++ b/templates/org/settings/delete.tmpl
@@ -6,7 +6,7 @@
</h4>
<div class="ui attached error segment">
<div class="ui red message">
- <p class="text left">{{svg "octicon-alert"}} {{ctx.Locale.Tr "org.settings.delete_prompt" | Str2html}}</p>
+ <p class="text left">{{svg "octicon-alert"}} {{ctx.Locale.Tr "org.settings.delete_prompt" | SanitizeHTML}}</p>
</div>
<form class="ui form ignore-dirty" id="delete-form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
diff --git a/templates/org/settings/labels.tmpl b/templates/org/settings/labels.tmpl
index b12ea8d9f4..56931def82 100644
--- a/templates/org/settings/labels.tmpl
+++ b/templates/org/settings/labels.tmpl
@@ -2,7 +2,7 @@
<div class="org-setting-content">
<div class="gt-df gt-ac">
<div class="gt-f1">
- {{ctx.Locale.Tr "org.settings.labels_desc" | Str2html}}
+ {{ctx.Locale.Tr "org.settings.labels_desc" | SanitizeHTML}}
</div>
<button class="ui small primary new-label button">{{ctx.Locale.Tr "repo.issues.new_label"}}</button>
</div>
diff --git a/templates/org/team/invite.tmpl b/templates/org/team/invite.tmpl
index e003d14757..5a8780c205 100644
--- a/templates/org/team/invite.tmpl
+++ b/templates/org/team/invite.tmpl
@@ -7,7 +7,7 @@
{{ctx.AvatarUtils.Avatar .Organization 140}}
</div>
<div class="content">
- <div class="header">{{ctx.Locale.Tr "org.teams.invite.title" .Team.Name .Organization.Name | Str2html}}</div>
+ <div class="header">{{ctx.Locale.Tr "org.teams.invite.title" .Team.Name .Organization.Name | SanitizeHTML}}</div>
<div class="meta">{{ctx.Locale.Tr "org.teams.invite.by" .Inviter.Name}}</div>
<div class="description">{{ctx.Locale.Tr "org.teams.invite.description"}}</div>
</div>
diff --git a/templates/org/team/new.tmpl b/templates/org/team/new.tmpl
index 0178a20fbb..99b16ee22d 100644
--- a/templates/org/team/new.tmpl
+++ b/templates/org/team/new.tmpl
@@ -32,14 +32,14 @@
<div class="ui radio checkbox">
<input type="radio" name="repo_access" value="specific" {{if not .Team.IncludesAllRepositories}}checked{{end}}>
<label>{{ctx.Locale.Tr "org.teams.specific_repositories"}}</label>
- <span class="help">{{ctx.Locale.Tr "org.teams.specific_repositories_helper" | Str2html}}</span>
+ <span class="help">{{ctx.Locale.Tr "org.teams.specific_repositories_helper" | SanitizeHTML}}</span>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="repo_access" value="all" {{if .Team.IncludesAllRepositories}}checked{{end}}>
<label>{{ctx.Locale.Tr "org.teams.all_repositories"}}</label>
- <span class="help">{{ctx.Locale.Tr "org.teams.all_repositories_helper" | Str2html}}</span>
+ <span class="help">{{ctx.Locale.Tr "org.teams.all_repositories_helper" | SanitizeHTML}}</span>
</div>
</div>
diff --git a/templates/org/team/sidebar.tmpl b/templates/org/team/sidebar.tmpl
index 509c6382d8..e59c0e5613 100644
--- a/templates/org/team/sidebar.tmpl
+++ b/templates/org/team/sidebar.tmpl
@@ -27,16 +27,16 @@
</div>
{{if eq .Team.LowerName "owners"}}
<div class="item">
- {{ctx.Locale.Tr "org.teams.owners_permission_desc" | Str2html}}
+ {{ctx.Locale.Tr "org.teams.owners_permission_desc" | SanitizeHTML}}
</div>
{{else}}
<div class="item">
<h3>{{ctx.Locale.Tr "org.team_access_desc"}}</h3>
<ul>
{{if .Team.IncludesAllRepositories}}
- <li>{{ctx.Locale.Tr "org.teams.all_repositories" | Str2html}}</li>
+ <li>{{ctx.Locale.Tr "org.teams.all_repositories" | SanitizeHTML}}</li>
{{else}}
- <li>{{ctx.Locale.Tr "org.teams.specific_repositories" | Str2html}}</li>
+ <li>{{ctx.Locale.Tr "org.teams.specific_repositories" | SanitizeHTML}}</li>
{{end}}
{{if .Team.CanCreateOrgRepo}}
<li>{{ctx.Locale.Tr "org.teams.can_create_org_repo"}}</li>
@@ -44,10 +44,10 @@
</ul>
{{if (eq .Team.AccessMode 2)}}
<h3>{{ctx.Locale.Tr "org.settings.permission"}}</h3>
- {{ctx.Locale.Tr "org.teams.write_permission_desc" | Str2html}}
+ {{ctx.Locale.Tr "org.teams.write_permission_desc" | SanitizeHTML}}
{{else if (eq .Team.AccessMode 3)}}
<h3>{{ctx.Locale.Tr "org.settings.permission"}}</h3>
- {{ctx.Locale.Tr "org.teams.admin_permission_desc" | Str2html}}
+ {{ctx.Locale.Tr "org.teams.admin_permission_desc" | SanitizeHTML}}
{{else}}
<table class="ui table">
<thead>
diff --git a/templates/package/content/nuget.tmpl b/templates/package/content/nuget.tmpl
index f4807b0ad9..d56f50cb22 100644
--- a/templates/package/content/nuget.tmpl
+++ b/templates/package/content/nuget.tmpl
@@ -20,7 +20,7 @@
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
<div class="ui attached segment">
{{if .PackageDescriptor.Metadata.Description}}{{.PackageDescriptor.Metadata.Description}}{{end}}
- {{if .PackageDescriptor.Metadata.ReleaseNotes}}{{Str2html .PackageDescriptor.Metadata.ReleaseNotes}}{{end}}
+ {{if .PackageDescriptor.Metadata.ReleaseNotes}}{{.PackageDescriptor.Metadata.ReleaseNotes}}{{end}}
</div>
{{end}}
diff --git a/templates/projects/list.tmpl b/templates/projects/list.tmpl
index cbff82dd70..30fbd498a4 100644
--- a/templates/projects/list.tmpl
+++ b/templates/projects/list.tmpl
@@ -75,7 +75,7 @@
</div>
{{if .Description}}
<div class="content">
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
</div>
{{end}}
</li>
diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl
index b3ad03c354..3792ccca0e 100644
--- a/templates/projects/view.tmpl
+++ b/templates/projects/view.tmpl
@@ -58,7 +58,7 @@
{{end}}
</div>
- <div class="content">{{$.Project.RenderedContent|Str2html}}</div>
+ <div class="content">{{$.Project.RenderedContent}}</div>
<div class="divider"></div>
</div>
diff --git a/templates/repo/blame.tmpl b/templates/repo/blame.tmpl
index 3bd5e36949..75104cdcd2 100644
--- a/templates/repo/blame.tmpl
+++ b/templates/repo/blame.tmpl
@@ -2,11 +2,11 @@
{{$revsFileLink := URLJoin .RepoLink "src" .BranchNameSubURL "/.git-blame-ignore-revs"}}
{{if .UsesIgnoreRevs}}
<div class="ui info message">
- <p>{{ctx.Locale.Tr "repo.blame.ignore_revs" $revsFileLink (print $revsFileLink "?bypass-blame-ignore=true") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.blame.ignore_revs" $revsFileLink (print $revsFileLink "?bypass-blame-ignore=true") | SanitizeHTML}}</p>
</div>
{{else}}
<div class="ui error message">
- <p>{{ctx.Locale.Tr "repo.blame.ignore_revs.failed" $revsFileLink | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.blame.ignore_revs.failed" $revsFileLink | SanitizeHTML}}</p>
</div>
{{end}}
{{end}}
diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl
index 8ae7301c4a..4aa0e22b78 100644
--- a/templates/repo/branch/list.tmpl
+++ b/templates/repo/branch/list.tmpl
@@ -210,7 +210,7 @@
{{ctx.Locale.Tr "repo.branch.delete_html"}} <span class="name"></span>
</div>
<div class="content">
- <p>{{ctx.Locale.Tr "repo.branch.delete_desc" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.branch.delete_desc" | SanitizeHTML}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
diff --git a/templates/repo/clone_script.tmpl b/templates/repo/clone_script.tmpl
index 9ff826bc93..46e49e7f85 100644
--- a/templates/repo/clone_script.tmpl
+++ b/templates/repo/clone_script.tmpl
@@ -24,14 +24,22 @@
const btn = isSSH ? sshBtn : httpsBtn;
if (!btn) return;
- let link = btn.getAttribute('data-link');
- if (link.startsWith('http://') || link.startsWith('https://')) {
- // use current protocol/host as the clone link
- const url = new URL(link);
- url.protocol = window.location.protocol;
- url.host = window.location.host;
- link = url.toString();
+ // NOTE: Keep this function in sync with the one in the js folder
+ function toOriginUrl(urlStr) {
+ try {
+ if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) {
+ const {origin, protocol, hostname, port} = window.location;
+ const url = new URL(urlStr, origin);
+ url.protocol = protocol;
+ url.hostname = hostname;
+ url.port = port || (protocol === 'https:' ? '443' : '80');
+ return url.toString();
+ }
+ } catch {}
+ return urlStr;
}
+ const link = toOriginUrl(btn.getAttribute('data-link'));
+
for (const el of document.getElementsByClassName('js-clone-url')) {
el[el.nodeName === 'INPUT' ? 'value' : 'textContent'] = link;
}
diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl
index 115ee92955..7892a57163 100644
--- a/templates/repo/commit_page.tmpl
+++ b/templates/repo/commit_page.tmpl
@@ -276,7 +276,7 @@
<span class="text grey" id="note-authored-time">{{TimeSince .NoteCommit.Author.When ctx.Locale}}</span>
</div>
<div class="ui bottom attached info segment git-notes">
- <pre class="commit-body">{{.NoteRendered | Str2html}}</pre>
+ <pre class="commit-body">{{.NoteRendered | SanitizeHTML}}</pre>
</div>
{{end}}
{{template "repo/diff/box" .}}
diff --git a/templates/repo/create.tmpl b/templates/repo/create.tmpl
index d6ff22b7ab..1ddf2c4808 100644
--- a/templates/repo/create.tmpl
+++ b/templates/repo/create.tmpl
@@ -158,7 +158,7 @@
{{end}}
</div>
</div>
- <span class="help">{{ctx.Locale.Tr "repo.license_helper_desc" "https://choosealicense.com/" | Str2html}}</span>
+ <span class="help">{{ctx.Locale.Tr "repo.license_helper_desc" "https://choosealicense.com/" | SanitizeHTML}}</span>
</div>
<div class="inline field">
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl
index 9dcc59cea7..f9f18208e5 100644
--- a/templates/repo/diff/box.tmpl
+++ b/templates/repo/diff/box.tmpl
@@ -19,7 +19,7 @@
{{end}}
{{if not .DiffNotAvailable}}
<div class="diff-detail-stats gt-df gt-ac gt-fw">
- {{svg "octicon-diff" 16 "gt-mr-2"}}{{ctx.Locale.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}}
+ {{svg "octicon-diff" 16 "gt-mr-2"}}{{ctx.Locale.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | SanitizeHTML}}
</div>
{{end}}
</div>
@@ -206,7 +206,7 @@
{{if $showFileViewToggle}}
{{/* for image or CSV, it can have a horizontal scroll bar, there won't be review comment context menu (position absolute) which would be clipped by "overflow" */}}
<div id="diff-rendered-{{$file.NameHash}}" class="file-body file-code {{if $.IsSplitStyle}}code-diff-split{{else}}code-diff-unified{{end}} gt-overflow-x-scroll">
- <table class="chroma gt-w-full">
+ <table class="chroma tw-w-full">
{{if $isImage}}
{{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead "sniffedTypeBase" $sniffedTypeBase "sniffedTypeHead" $sniffedTypeHead}}
{{else}}
diff --git a/templates/repo/diff/comments.tmpl b/templates/repo/diff/comments.tmpl
index e567417fa6..0bb577deba 100644
--- a/templates/repo/diff/comments.tmpl
+++ b/templates/repo/diff/comments.tmpl
@@ -55,7 +55,7 @@
<div class="ui attached segment comment-body">
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
{{if .RenderedContent}}
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
@@ -63,7 +63,7 @@
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.root.RepoLink}}/comments/{{.ID}}" data-context="{{$.root.RepoLink}}" data-attachment-url="{{$.root.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
- {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
+ {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl
index 65b85b9686..17e0d3e712 100644
--- a/templates/repo/diff/compare.tmpl
+++ b/templates/repo/diff/compare.tmpl
@@ -11,14 +11,6 @@
{{ctx.Locale.Tr "action.compare_commits_general"}}
{{end}}
</h2>
- {{if .Flash.WarningMsg}}
- {{/*
- There's already an importing of alert.tmpl in new_form.tmpl,
- but only the negative message will be displayed within forms for some reasons, see semantic.css:10659.
- To avoid repeated negative messages, the importing here if for .Flash.WarningMsg only.
- */}}
- {{template "base/alert" .}}
- {{end}}
{{$BaseCompareName := $.BaseName -}}
{{- $HeadCompareName := $.HeadRepo.OwnerName -}}
{{- if and (eq $.BaseName $.HeadRepo.OwnerName) (ne $.Repository.Name $.HeadRepo.Name) -}}
diff --git a/templates/repo/diff/stats.tmpl b/templates/repo/diff/stats.tmpl
index db468ab6c8..64ee17a7c5 100644
--- a/templates/repo/diff/stats.tmpl
+++ b/templates/repo/diff/stats.tmpl
@@ -1,5 +1,5 @@
{{Eval .file.Addition "+" .file.Deletion}}
-<span class="diff-stats-bar gt-mx-3" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.stats_desc_file" (Eval .file.Addition "+" .file.Deletion) .file.Addition .file.Deletion | Str2html}}">
+<span class="diff-stats-bar gt-mx-3" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.stats_desc_file" (Eval .file.Addition "+" .file.Deletion) .file.Addition .file.Deletion | SanitizeHTML}}">
{{/* if the denominator is zero, then the float result is "width: NaNpx", as before, it just works */}}
<div class="diff-stats-add-bar" style="width: {{Eval 100 "*" .file.Addition "/" "(" .file.Addition "+" .file.Deletion "+" 0.0 ")"}}%"></div>
</span>
diff --git a/templates/repo/empty.tmpl b/templates/repo/empty.tmpl
index 62194abe50..7a0e6926c0 100644
--- a/templates/repo/empty.tmpl
+++ b/templates/repo/empty.tmpl
@@ -24,7 +24,7 @@
</h4>
<div class="ui attached guide table segment empty-repo-guide">
<div class="item">
- <h3>{{ctx.Locale.Tr "repo.clone_this_repo"}} <small>{{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository" | Str2html}}</small></h3>
+ <h3>{{ctx.Locale.Tr "repo.clone_this_repo"}} <small>{{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository" | SanitizeHTML}}</small></h3>
<div class="repo-button-row">
{{if and .CanWriteCode (not .Repository.IsArchived)}}
diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl
index 7fb3d82827..5e524079c8 100644
--- a/templates/repo/issue/card.tmpl
+++ b/templates/repo/issue/card.tmpl
@@ -6,7 +6,7 @@
{{end}}
</div>
{{end}}
- <div class="content gt-p-0 gt-w-full">
+ <div class="content gt-p-0 tw-w-full">
<div class="gt-df gt-items-start">
<div class="issue-card-icon">
{{template "shared/issueicon" .}}
diff --git a/templates/repo/issue/fields/checkboxes.tmpl b/templates/repo/issue/fields/checkboxes.tmpl
index 237f2eb5dd..b928b2be58 100644
--- a/templates/repo/issue/fields/checkboxes.tmpl
+++ b/templates/repo/issue/fields/checkboxes.tmpl
@@ -1,8 +1,8 @@
-<div class="field">
+<div class="field {{if not .item.VisibleOnForm}}gt-hidden{{end}}">
{{template "repo/issue/fields/header" .}}
{{range $i, $opt := .item.Attributes.options}}
<div class="field inline">
- <div class="ui checkbox gt-mr-0">
+ <div class="ui checkbox gt-mr-0 {{if and ($opt.visible) (not (SliceUtils.Contains $opt.visible "form"))}}gt-hidden{{end}}">
<input type="checkbox" name="form-field-{{$.item.ID}}-{{$i}}" {{if $opt.required}}required{{end}}>
<label>{{RenderMarkdownToHtml $.context $opt.label}}</label>
</div>
diff --git a/templates/repo/issue/fields/dropdown.tmpl b/templates/repo/issue/fields/dropdown.tmpl
index 23aa373cd2..b8df6908e3 100644
--- a/templates/repo/issue/fields/dropdown.tmpl
+++ b/templates/repo/issue/fields/dropdown.tmpl
@@ -1,4 +1,4 @@
-<div class="field">
+<div class="field {{if not .item.VisibleOnForm}}gt-hidden{{end}}">
{{template "repo/issue/fields/header" .}}
{{/* FIXME: required validation */}}
<div class="ui fluid selection dropdown {{if .item.Attributes.multiple}}multiple clearable{{end}}">
diff --git a/templates/repo/issue/fields/input.tmpl b/templates/repo/issue/fields/input.tmpl
index 3fc8a86510..ad0fe3d783 100644
--- a/templates/repo/issue/fields/input.tmpl
+++ b/templates/repo/issue/fields/input.tmpl
@@ -1,4 +1,4 @@
-<div class="field">
+<div class="field {{if not .item.VisibleOnForm}}gt-hidden{{end}}">
{{template "repo/issue/fields/header" .}}
<input type="{{if .item.Validations.is_number}}number{{else}}text{{end}}" name="form-field-{{.item.ID}}" placeholder="{{.item.Attributes.placeholder}}" value="{{.item.Attributes.value}}" {{if .item.Validations.required}}required{{end}} {{if .item.Validations.regex}}pattern="{{.item.Validations.regex}}" title="{{.item.Validations.regex}}"{{end}}>
</div>
diff --git a/templates/repo/issue/fields/markdown.tmpl b/templates/repo/issue/fields/markdown.tmpl
index fd5b6afd22..97813cc1d8 100644
--- a/templates/repo/issue/fields/markdown.tmpl
+++ b/templates/repo/issue/fields/markdown.tmpl
@@ -1,3 +1,3 @@
-<div class="field">
+<div class="field {{if not .item.VisibleOnForm}}gt-hidden{{end}}">
<div>{{RenderMarkdownToHtml .Context .item.Attributes.value}}</div>
</div>
diff --git a/templates/repo/issue/fields/textarea.tmpl b/templates/repo/issue/fields/textarea.tmpl
index 55adeb28d0..4f68b4038b 100644
--- a/templates/repo/issue/fields/textarea.tmpl
+++ b/templates/repo/issue/fields/textarea.tmpl
@@ -1,5 +1,5 @@
{{$useMarkdownEditor := not .item.Attributes.render}}
-<div class="field {{if $useMarkdownEditor}}combo-editor-dropzone{{end}}">
+<div class="field {{if not .item.VisibleOnForm}}gt-hidden{{end}} {{if $useMarkdownEditor}}combo-editor-dropzone{{end}}">
{{template "repo/issue/fields/header" .}}
{{/* the real form element to provide the value */}}
diff --git a/templates/repo/issue/labels/label_list.tmpl b/templates/repo/issue/labels/label_list.tmpl
index 9a6065a407..252b5816b3 100644
--- a/templates/repo/issue/labels/label_list.tmpl
+++ b/templates/repo/issue/labels/label_list.tmpl
@@ -61,7 +61,7 @@
<li class="item">
<div class="ui grid middle aligned">
<div class="ten wide column">
- {{ctx.Locale.Tr "repo.org_labels_desc" | Str2html}}
+ {{ctx.Locale.Tr "repo.org_labels_desc" | SanitizeHTML}}
{{if .IsOrganizationOwner}}
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
{{end}}
diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl
index d9495d9b77..35a8a77680 100644
--- a/templates/repo/issue/milestone_issues.tmpl
+++ b/templates/repo/issue/milestone_issues.tmpl
@@ -22,7 +22,7 @@
</div>
{{if .Milestone.RenderedContent}}
<div class="markup content gt-mb-4">
- {{.Milestone.RenderedContent|Str2html}}
+ {{.Milestone.RenderedContent}}
</div>
{{end}}
<div class="gt-df gt-fc gt-gap-3">
diff --git a/templates/repo/issue/milestones.tmpl b/templates/repo/issue/milestones.tmpl
index 698e3fffba..363ba7e3a2 100644
--- a/templates/repo/issue/milestones.tmpl
+++ b/templates/repo/issue/milestones.tmpl
@@ -82,7 +82,7 @@
</div>
{{if .Content}}
<div class="markup content">
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
</div>
{{end}}
</li>
diff --git a/templates/repo/issue/new.tmpl b/templates/repo/issue/new.tmpl
index 780e874bc6..ccd45fdebe 100644
--- a/templates/repo/issue/new.tmpl
+++ b/templates/repo/issue/new.tmpl
@@ -2,14 +2,6 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository new issue">
{{template "repo/header" .}}
<div class="ui container">
- {{if .Flash.WarningMsg}}
- {{/*
- There's already an importing of alert.tmpl in new_form.tmpl,
- but only the negative message will be displayed within forms for some reasons, see semantic.css:10659.
- To avoid repeated negative messages, the importing here if for .Flash.WarningMsg only.
- */}}
- {{template "base/alert" .}}
- {{end}}
{{template "repo/issue/new_form" .}}
</div>
</div>
diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl
index 8e4310f0bb..e67314bfd5 100644
--- a/templates/repo/issue/new_form.tmpl
+++ b/templates/repo/issue/new_form.tmpl
@@ -1,10 +1,8 @@
+{{if .Flash}}
+{{template "base/alert" .}}
+{{end}}
<form class="issue-content ui comment form form-fetch-action" id="new-issue" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
- {{if .Flash}}
- <div class="sixteen wide column">
- {{template "base/alert" .}}
- </div>
- {{end}}
<div class="issue-content-left">
<div class="ui comments">
<div class="comment">
diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl
index 91db68c810..f06f9137cd 100644
--- a/templates/repo/issue/view_content.tmpl
+++ b/templates/repo/issue/view_content.tmpl
@@ -54,7 +54,7 @@
<div class="ui attached segment comment-body" role="article">
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission $.IsIssuePoster}}data-can-edit="true"{{end}}>
{{if .Issue.RenderedContent}}
- {{.Issue.RenderedContent|Str2html}}
+ {{.Issue.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
@@ -62,7 +62,7 @@
<div id="issue-{{.Issue.ID}}-raw" class="raw-content gt-hidden">{{.Issue.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/content" data-context="{{.RepoLink}}" data-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/attachments" data-view-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/view-attachments"></div>
{{if .Issue.Attachments}}
- {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}}
+ {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Issue.Attachments "RenderedContent" .Issue.RenderedContent}}
{{end}}
</div>
{{$reactions := .Issue.Reactions.GroupByType}}
@@ -181,7 +181,7 @@
{{ctx.Locale.Tr "repo.branch.delete" .HeadTarget}}
</div>
<div class="content">
- <p>{{ctx.Locale.Tr "repo.branch.delete_desc" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.branch.delete_desc" | SanitizeHTML}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
diff --git a/templates/repo/issue/view_content/attachments.tmpl b/templates/repo/issue/view_content/attachments.tmpl
index 1fb6f2f2c2..2c3a47d670 100644
--- a/templates/repo/issue/view_content/attachments.tmpl
+++ b/templates/repo/issue/view_content/attachments.tmpl
@@ -8,7 +8,7 @@
<div class="gt-f1 gt-p-3">
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title="{{ctx.Locale.Tr "repo.issues.attachment.open_tab" .Name}}">
{{if FilenameIsImage .Name}}
- {{if not (StringUtils.Contains $.Content .UUID)}}
+ {{if not (StringUtils.Contains (StringUtils.ToString $.RenderedContent) .UUID)}}
{{$hasThumbnails = true}}
{{end}}
{{svg "octicon-file"}}
@@ -29,7 +29,7 @@
<div class="ui small thumbnails">
{{- range .Attachments -}}
{{if FilenameIsImage .Name}}
- {{if not (StringUtils.Contains $.Content .UUID)}}
+ {{if not (StringUtils.Contains (StringUtils.ToString $.RenderedContent) .UUID)}}
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}">
<img alt="{{.Name}}" src="{{.DownloadURL}}" title="{{ctx.Locale.Tr "repo.issues.attachment.open_tab" .Name}}">
</a>
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index b37d1e069f..45cc65478f 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -61,7 +61,7 @@
<div class="ui attached segment comment-body" role="article">
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
{{if .RenderedContent}}
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
@@ -69,7 +69,7 @@
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
- {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
+ {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
@@ -81,9 +81,11 @@
{{else if eq .Type 1}}
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge gt-bg-green gt-text-white">{{svg "octicon-dot-fill"}}</span>
- {{template "shared/user/avatarlink" dict "user" .Poster}}
+ {{if not .OriginalAuthor}}
+ {{template "shared/user/avatarlink" dict "user" .Poster}}
+ {{end}}
<span class="text grey muted-links">
- {{template "shared/user/authorlink" .Poster}}
+ {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{if .Issue.IsPull}}
{{ctx.Locale.Tr "repo.pulls.reopened_at" .EventTag $createdStr}}
{{else}}
@@ -94,9 +96,11 @@
{{else if eq .Type 2}}
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge gt-bg-red gt-text-white">{{svg "octicon-circle-slash"}}</span>
- {{template "shared/user/avatarlink" dict "user" .Poster}}
+ {{if not .OriginalAuthor}}
+ {{template "shared/user/avatarlink" dict "user" .Poster}}
+ {{end}}
<span class="text grey muted-links">
- {{template "shared/user/authorlink" .Poster}}
+ {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{if .Issue.IsPull}}
{{ctx.Locale.Tr "repo.pulls.closed_at" .EventTag $createdStr}}
{{else}}
@@ -107,9 +111,11 @@
{{else if eq .Type 28}}
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge gt-bg-purple gt-text-white">{{svg "octicon-git-merge"}}</span>
- {{template "shared/user/avatarlink" dict "user" .Poster}}
+ {{if not .OriginalAuthor}}
+ {{template "shared/user/avatarlink" dict "user" .Poster}}
+ {{end}}
<span class="text grey muted-links">
- {{template "shared/user/authorlink" .Poster}}
+ {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{$link := printf "%s/commit/%s" $.Repository.Link ($.Issue.PullRequest.MergedCommitID|PathEscape)}}
{{if eq $.Issue.PullRequest.Status 3}}
{{ctx.Locale.Tr "repo.issues.comment_manually_pull_merged_at" (HTMLFormat `<a class="ui sha" href="%[1]s"><b>%[2]s</b></a>` $link (ShortSha $.Issue.PullRequest.MergedCommitID)) (HTMLFormat "<b>%[1]s</b>" $.BaseTarget) $createdStr}}
@@ -160,7 +166,7 @@
</span>
<div class="detail">
{{svg "octicon-git-commit"}}
- <span class="text grey muted-links">{{.Content | Str2html}}</span>
+ <span class="text grey muted-links">{{.Content | SanitizeHTML}}</span>
</div>
</div>
{{else if eq .Type 7}}
@@ -379,18 +385,7 @@
{{end}}
<span class="badge{{if eq .Review.Type 1}} gt-bg-green gt-text-white{{else if eq .Review.Type 3}} gt-bg-red gt-text-white{{end}}">{{svg (printf "octicon-%s" .Review.Type.Icon)}}</span>
<span class="text grey muted-links">
- {{if .OriginalAuthor}}
- <span class="text black">
- {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
- {{.OriginalAuthor}}
- </span>
- {{if $.Repository.OriginalURL}}
- <span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname}})</span>
- {{end}}
- {{else}}
- {{template "shared/user/authorlink" .Poster}}
- {{end}}
-
+ {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{if eq .Review.Type 1}}
{{ctx.Locale.Tr "repo.issues.review.approve" $createdStr}}
{{else if eq .Review.Type 2}}
@@ -441,7 +436,7 @@
<div class="ui attached segment comment-body">
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
{{if .RenderedContent}}
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
@@ -449,7 +444,7 @@
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
- {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
+ {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
@@ -502,17 +497,7 @@
{{template "shared/user/avatarlink" dict "user" .Poster}}
{{end}}
<span class="text grey muted-links">
- {{if .OriginalAuthor}}
- <span class="text black">
- {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
- {{.OriginalAuthor}}
- </span>
- {{if $.Repository.OriginalURL}}
- <span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname}})</span>
- {{end}}
- {{else}}
- {{template "shared/user/authorlink" .Poster}}
- {{end}}
+ {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{ctx.Locale.Tr "repo.pulls.change_target_branch_at" .OldRef .NewRef $createdStr}}
</span>
</div>
@@ -650,7 +635,7 @@
<div class="ui attached segment">
<div class="render-content markup">
{{if .RenderedContent}}
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
@@ -679,17 +664,7 @@
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge">{{svg "octicon-git-merge" 16}}</span>
<span class="text grey muted-links">
- {{if .OriginalAuthor}}
- <span class="text black">
- {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
- {{.OriginalAuthor}}
- </span>
- {{if $.Repository.OriginalURL}}
- <span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname}})</span>
- {{end}}
- {{else}}
- {{template "shared/user/authorlink" .Poster}}
- {{end}}
+ {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{if eq .Type 34}}{{ctx.Locale.Tr "repo.pulls.auto_merge_newly_scheduled_comment" $createdStr}}
{{else}}{{ctx.Locale.Tr "repo.pulls.auto_merge_canceled_schedule_comment" $createdStr}}{{end}}
</span>
diff --git a/templates/repo/issue/view_content/comments_authorlink.tmpl b/templates/repo/issue/view_content/comments_authorlink.tmpl
new file mode 100644
index 0000000000..f652a0bec3
--- /dev/null
+++ b/templates/repo/issue/view_content/comments_authorlink.tmpl
@@ -0,0 +1,11 @@
+{{if .comment.OriginalAuthor}}
+ <span class="text black">
+ {{svg (MigrationIcon .ctxData.Repository.GetOriginalURLHostname)}}
+ {{.comment.OriginalAuthor}}
+ </span>
+ {{if .ctxData.Repository.OriginalURL}}
+ <span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" .ctxData.Repository.OriginalURL .ctxData.Repository.GetOriginalURLHostname}})</span>
+ {{end}}
+{{else}}
+ {{template "shared/user/authorlink" .comment.Poster}}
+{{end}}
diff --git a/templates/repo/issue/view_content/conversation.tmpl b/templates/repo/issue/view_content/conversation.tmpl
index 1bad0e9b55..5bb99d1db6 100644
--- a/templates/repo/issue/view_content/conversation.tmpl
+++ b/templates/repo/issue/view_content/conversation.tmpl
@@ -87,7 +87,7 @@
<div class="text comment-content">
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
{{if .RenderedContent}}
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
@@ -95,7 +95,7 @@
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
- {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
+ {{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
diff --git a/templates/repo/migrate/options.tmpl b/templates/repo/migrate/options.tmpl
index 1bc30b886d..d0235a0f85 100644
--- a/templates/repo/migrate/options.tmpl
+++ b/templates/repo/migrate/options.tmpl
@@ -17,7 +17,7 @@
<span id="lfs_settings" class="gt-hidden">(<a id="lfs_settings_show" href="#">{{ctx.Locale.Tr "repo.settings.advanced_settings"}}</a>)</span>
</div>
<div id="lfs_endpoint" class="gt-hidden">
- <span class="help">{{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.description" "https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md#server-discovery" | Str2html}}{{if .ContextUser.CanImportLocal}} {{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.description.local"}}{{end}}</span>
+ <span class="help">{{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.description" "https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md#server-discovery" | SanitizeHTML}}{{if .ContextUser.CanImportLocal}} {{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.description.local"}}{{end}}</span>
<div class="inline field {{if .Err_LFSEndpoint}}error{{end}}">
<label>{{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.label"}}</label>
<input name="lfs_endpoint" value="{{.lfs_endpoint}}" placeholder="{{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.placeholder"}}">
diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl
index d533cf6757..541af86ff5 100644
--- a/templates/repo/release/list.tmpl
+++ b/templates/repo/release/list.tmpl
@@ -54,11 +54,11 @@
<span class="time">{{TimeSinceUnix $release.CreatedUnix ctx.Locale}}</span>
{{end}}
{{if and (not $release.IsDraft) ($.Permission.CanRead $.UnitTypeCode)}}
- | <span class="ahead"><a href="{{$.RepoLink}}/compare/{{$release.TagName | PathEscapeSegments}}...{{$release.TargetBehind | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.release.ahead.commits" $release.NumCommitsBehind | Str2html}}</a> {{ctx.Locale.Tr "repo.release.ahead.target" $release.TargetBehind}}</span>
+ | <span class="ahead"><a href="{{$.RepoLink}}/compare/{{$release.TagName | PathEscapeSegments}}...{{$release.TargetBehind | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.release.ahead.commits" $release.NumCommitsBehind | SanitizeHTML}}</a> {{ctx.Locale.Tr "repo.release.ahead.target" $release.TargetBehind}}</span>
{{end}}
</p>
<div class="markup desc">
- {{Str2html $release.Note}}
+ {{$release.RenderedNote}}
</div>
<div class="divider"></div>
<details class="download" {{if eq $idx 0}}open{{end}}>
diff --git a/templates/repo/release_tag_header.tmpl b/templates/repo/release_tag_header.tmpl
index 6f3d28e7ad..fe978a9680 100644
--- a/templates/repo/release_tag_header.tmpl
+++ b/templates/repo/release_tag_header.tmpl
@@ -13,7 +13,7 @@
</div>
{{if .EnableFeed}}
<a class="ui small button" href="{{.RepoLink}}/{{if .PageIsTagList}}tags{{else}}releases{{end}}.rss">
- {{svg "octicon-rss" 18}} {{ctx.Locale.Tr "rss_feed"}}
+ {{svg "octicon-rss" 16}} {{ctx.Locale.Tr "rss_feed"}}
</a>
{{end}}
{{if and (not .PageIsTagList) .CanCreateRelease}}
diff --git a/templates/repo/settings/deploy_keys.tmpl b/templates/repo/settings/deploy_keys.tmpl
index 3ea854ef88..0b0f56520b 100644
--- a/templates/repo/settings/deploy_keys.tmpl
+++ b/templates/repo/settings/deploy_keys.tmpl
@@ -31,7 +31,7 @@
<label for="is_writable">
{{ctx.Locale.Tr "repo.settings.is_writable"}}
</label>
- <small style="padding-left: 26px;">{{ctx.Locale.Tr "repo.settings.is_writable_info" | Str2html}}</small>
+ <small style="padding-left: 26px;">{{ctx.Locale.Tr "repo.settings.is_writable_info" | SanitizeHTML}}</small>
</div>
</div>
<button class="ui primary button">
diff --git a/templates/repo/settings/githooks.tmpl b/templates/repo/settings/githooks.tmpl
index 389d381f30..03dd639671 100644
--- a/templates/repo/settings/githooks.tmpl
+++ b/templates/repo/settings/githooks.tmpl
@@ -6,7 +6,7 @@
<div class="ui attached segment">
<div class="ui list">
<div class="item">
- {{ctx.Locale.Tr "repo.settings.githooks_desc" | Str2html}}
+ {{ctx.Locale.Tr "repo.settings.githooks_desc" | SanitizeHTML}}
</div>
{{range .Hooks}}
<div class="item truncated-item-container">
diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl
index 9541dd12d8..fe2764aa83 100644
--- a/templates/repo/settings/options.tmpl
+++ b/templates/repo/settings/options.tmpl
@@ -191,7 +191,7 @@
<div class="field {{if .Err_LFSEndpoint}}error{{end}}">
<label for="mirror_lfs_endpoint">{{ctx.Locale.Tr "repo.mirror_lfs_endpoint"}}</label>
<input id="mirror_lfs_endpoint" name="mirror_lfs_endpoint" value="{{.PullMirror.LFSEndpoint}}" placeholder="{{ctx.Locale.Tr "repo.migrate_options_lfs_endpoint.placeholder"}}">
- <p class="help">{{ctx.Locale.Tr "repo.mirror_lfs_endpoint_desc" "https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md#server-discovery" | Str2html}}</p>
+ <p class="help">{{ctx.Locale.Tr "repo.mirror_lfs_endpoint_desc" "https://github.com/git-lfs/git-lfs/blob/main/docs/api/server-discovery.md#server-discovery" | SanitizeHTML}}</p>
</div>
{{end}}
<div class="field">
diff --git a/templates/repo/settings/units/issues.tmpl b/templates/repo/settings/units/issues.tmpl
index a09b8edb2e..7ddafd1c6a 100644
--- a/templates/repo/settings/units/issues.tmpl
+++ b/templates/repo/settings/units/issues.tmpl
@@ -61,7 +61,7 @@
<div class="field">
<label for="tracker_url_format">{{ctx.Locale.Tr "repo.settings.tracker_url_format"}}</label>
<input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="https://github.com/{user}/{repo}/issues/{index}">
- <p class="help">{{ctx.Locale.Tr "repo.settings.tracker_url_format_desc" | Str2html}}</p>
+ <p class="help">{{ctx.Locale.Tr "repo.settings.tracker_url_format_desc" | SanitizeHTML}}</p>
</div>
<div class="inline fields">
<label for="issue_style">{{ctx.Locale.Tr "repo.settings.tracker_issue_style"}}</label>
@@ -89,7 +89,7 @@
<div class="field {{if ne $externalTrackerStyle "regexp"}}disabled{{end}}" id="tracker-issue-style-regex-box">
<label for="external_tracker_regexp_pattern">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern"}}</label>
<input id="external_tracker_regexp_pattern" name="external_tracker_regexp_pattern" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerRegexpPattern}}">
- <p class="help">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern_desc" | Str2html}}</p>
+ <p class="help">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern_desc" | SanitizeHTML}}</p>
</div>
</div>
</div>
diff --git a/templates/repo/settings/webhook/base_list.tmpl b/templates/repo/settings/webhook/base_list.tmpl
index 5a3fc0e7b8..00f9a48ba7 100644
--- a/templates/repo/settings/webhook/base_list.tmpl
+++ b/templates/repo/settings/webhook/base_list.tmpl
@@ -10,7 +10,7 @@
<div class="ui attached segment">
<div class="ui list">
<div class="item">
- {{.Description | Str2html}}
+ {{.Description | SanitizeHTML}}
</div>
{{range .Webhooks}}
<div class="item truncated-item-container">
diff --git a/templates/repo/settings/webhook/dingtalk.tmpl b/templates/repo/settings/webhook/dingtalk.tmpl
index 32ca0d0807..a620d9e241 100644
--- a/templates/repo/settings/webhook/dingtalk.tmpl
+++ b/templates/repo/settings/webhook/dingtalk.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "dingtalk"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://dingtalk.com" (ctx.Locale.Tr "repo.settings.web_hook_name_dingtalk") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://dingtalk.com" (ctx.Locale.Tr "repo.settings.web_hook_name_dingtalk") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/dingtalk/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
diff --git a/templates/repo/settings/webhook/discord.tmpl b/templates/repo/settings/webhook/discord.tmpl
index 9a1ebf8377..ff1ca75d3f 100644
--- a/templates/repo/settings/webhook/discord.tmpl
+++ b/templates/repo/settings/webhook/discord.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "discord"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://discord.com" (ctx.Locale.Tr "repo.settings.web_hook_name_discord") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://discord.com" (ctx.Locale.Tr "repo.settings.web_hook_name_discord") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/discord/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
diff --git a/templates/repo/settings/webhook/feishu.tmpl b/templates/repo/settings/webhook/feishu.tmpl
index 9683427fbf..1acb42c76c 100644
--- a/templates/repo/settings/webhook/feishu.tmpl
+++ b/templates/repo/settings/webhook/feishu.tmpl
@@ -1,6 +1,6 @@
{{if eq .HookType "feishu"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://feishu.cn" (ctx.Locale.Tr "repo.settings.web_hook_name_feishu") | Str2html}}</p>
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://larksuite.com" (ctx.Locale.Tr "repo.settings.web_hook_name_larksuite") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://feishu.cn" (ctx.Locale.Tr "repo.settings.web_hook_name_feishu") | SanitizeHTML}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://larksuite.com" (ctx.Locale.Tr "repo.settings.web_hook_name_larksuite") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/feishu/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
diff --git a/templates/repo/settings/webhook/forgejo.tmpl b/templates/repo/settings/webhook/forgejo.tmpl
index 494d0ef747..0045f27616 100644
--- a/templates/repo/settings/webhook/forgejo.tmpl
+++ b/templates/repo/settings/webhook/forgejo.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "forgejo"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_forgejo") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_forgejo") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/forgejo/{{or .Webhook.ID "new"}}" method="post">
{{template "base/disable_form_autofill"}}
{{.CsrfTokenHtml}}
diff --git a/templates/repo/settings/webhook/gitea.tmpl b/templates/repo/settings/webhook/gitea.tmpl
index 743c5169cf..cb2e789459 100644
--- a/templates/repo/settings/webhook/gitea.tmpl
+++ b/templates/repo/settings/webhook/gitea.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "gitea"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_gitea") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_gitea") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/gitea/{{or .Webhook.ID "new"}}" method="post">
{{template "base/disable_form_autofill"}}
{{.CsrfTokenHtml}}
diff --git a/templates/repo/settings/webhook/gogs.tmpl b/templates/repo/settings/webhook/gogs.tmpl
index 62ca2e1d99..a81b15fd5b 100644
--- a/templates/repo/settings/webhook/gogs.tmpl
+++ b/templates/repo/settings/webhook/gogs.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "gogs"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_gogs") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_gogs") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/gogs/{{or .Webhook.ID "new"}}" method="post">
{{template "base/disable_form_autofill"}}
{{.CsrfTokenHtml}}
diff --git a/templates/repo/settings/webhook/matrix.tmpl b/templates/repo/settings/webhook/matrix.tmpl
index a2a9921d7b..662beeaccb 100644
--- a/templates/repo/settings/webhook/matrix.tmpl
+++ b/templates/repo/settings/webhook/matrix.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "matrix"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://matrix.org/" (ctx.Locale.Tr "repo.settings.web_hook_name_matrix") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://matrix.org/" (ctx.Locale.Tr "repo.settings.web_hook_name_matrix") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/matrix/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_HomeserverURL}}error{{end}}">
diff --git a/templates/repo/settings/webhook/msteams.tmpl b/templates/repo/settings/webhook/msteams.tmpl
index 0097209db1..08e381de38 100644
--- a/templates/repo/settings/webhook/msteams.tmpl
+++ b/templates/repo/settings/webhook/msteams.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "msteams"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://teams.microsoft.com" (ctx.Locale.Tr "repo.settings.web_hook_name_msteams") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://teams.microsoft.com" (ctx.Locale.Tr "repo.settings.web_hook_name_msteams") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/msteams/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
diff --git a/templates/repo/settings/webhook/packagist.tmpl b/templates/repo/settings/webhook/packagist.tmpl
index 667a4d4318..48a4ecce6d 100644
--- a/templates/repo/settings/webhook/packagist.tmpl
+++ b/templates/repo/settings/webhook/packagist.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "packagist"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://packagist.org" (ctx.Locale.Tr "repo.settings.web_hook_name_packagist") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://packagist.org" (ctx.Locale.Tr "repo.settings.web_hook_name_packagist") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/packagist/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_Username}}error{{end}}">
diff --git a/templates/repo/settings/webhook/settings.tmpl b/templates/repo/settings/webhook/settings.tmpl
index 6836e695ed..a3764371e2 100644
--- a/templates/repo/settings/webhook/settings.tmpl
+++ b/templates/repo/settings/webhook/settings.tmpl
@@ -5,19 +5,19 @@
<div class="field">
<div class="ui radio non-events checkbox">
<input name="events" type="radio" value="push_only" {{if or $isNew .Webhook.PushOnly}}checked{{end}}>
- <label>{{ctx.Locale.Tr "repo.settings.event_push_only" | Str2html}}</label>
+ <label>{{ctx.Locale.Tr "repo.settings.event_push_only" | SanitizeHTML}}</label>
</div>
</div>
<div class="field">
<div class="ui radio non-events checkbox">
<input name="events" type="radio" value="send_everything" {{if .Webhook.SendEverything}}checked{{end}}>
- <label>{{ctx.Locale.Tr "repo.settings.event_send_everything" | Str2html}}</label>
+ <label>{{ctx.Locale.Tr "repo.settings.event_send_everything" | SanitizeHTML}}</label>
</div>
</div>
<div class="field">
<div class="ui radio events checkbox">
<input name="events" type="radio" value="choose_events" {{if .Webhook.ChooseEvents}}checked{{end}}>
- <label>{{ctx.Locale.Tr "repo.settings.event_choose" | Str2html}}</label>
+ <label>{{ctx.Locale.Tr "repo.settings.event_choose" | SanitizeHTML}}</label>
</div>
</div>
</div>
@@ -255,7 +255,7 @@
<div class="field">
<label for="branch_filter">{{ctx.Locale.Tr "repo.settings.branch_filter"}}</label>
<input id="branch_filter" name="branch_filter" type="text" value="{{or .Webhook.BranchFilter "*"}}">
- <span class="help">{{ctx.Locale.Tr "repo.settings.branch_filter_desc" | Str2html}}</span>
+ <span class="help">{{ctx.Locale.Tr "repo.settings.branch_filter_desc" | SanitizeHTML}}</span>
</div>
<!-- Authorization Header -->
diff --git a/templates/repo/settings/webhook/slack.tmpl b/templates/repo/settings/webhook/slack.tmpl
index 3fdea3bfd2..5dfc7a67b7 100644
--- a/templates/repo/settings/webhook/slack.tmpl
+++ b/templates/repo/settings/webhook/slack.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "slack"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://slack.com" (ctx.Locale.Tr "repo.settings.web_hook_name_slack") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://slack.com" (ctx.Locale.Tr "repo.settings.web_hook_name_slack") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/slack/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
diff --git a/templates/repo/settings/webhook/telegram.tmpl b/templates/repo/settings/webhook/telegram.tmpl
index 92bbbef3fd..62cac464b6 100644
--- a/templates/repo/settings/webhook/telegram.tmpl
+++ b/templates/repo/settings/webhook/telegram.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "telegram"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://core.telegram.org/bots" (ctx.Locale.Tr "repo.settings.web_hook_name_telegram") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://core.telegram.org/bots" (ctx.Locale.Tr "repo.settings.web_hook_name_telegram") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/telegram/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_BotToken}}error{{end}}">
diff --git a/templates/repo/settings/webhook/wechatwork.tmpl b/templates/repo/settings/webhook/wechatwork.tmpl
index 65f12998b1..95c4cefe64 100644
--- a/templates/repo/settings/webhook/wechatwork.tmpl
+++ b/templates/repo/settings/webhook/wechatwork.tmpl
@@ -1,5 +1,5 @@
{{if eq .HookType "wechatwork"}}
- <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://work.weixin.qq.com" (ctx.Locale.Tr "repo.settings.web_hook_name_wechatwork") | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://work.weixin.qq.com" (ctx.Locale.Tr "repo.settings.web_hook_name_wechatwork") | SanitizeHTML}}</p>
<form class="ui form" action="{{.BaseLink}}/wechatwork/{{or .Webhook.ID "new"}}" method="post">
{{.CsrfTokenHtml}}
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
diff --git a/templates/repo/unicode_escape_prompt.tmpl b/templates/repo/unicode_escape_prompt.tmpl
index d0730f23c1..9fe458f97b 100644
--- a/templates/repo/unicode_escape_prompt.tmpl
+++ b/templates/repo/unicode_escape_prompt.tmpl
@@ -5,9 +5,9 @@
<div class="header">
{{ctx.Locale.Tr "repo.invisible_runes_header"}}
</div>
- <p>{{ctx.Locale.Tr "repo.invisible_runes_description" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.invisible_runes_description" | SanitizeHTML}}</p>
{{if .EscapeStatus.HasAmbiguous}}
- <p>{{ctx.Locale.Tr "repo.ambiguous_runes_description" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.ambiguous_runes_description" | SanitizeHTML}}</p>
{{end}}
</div>
{{else if .EscapeStatus.HasAmbiguous}}
@@ -16,7 +16,7 @@
<div class="header">
{{ctx.Locale.Tr "repo.ambiguous_runes_header"}}
</div>
- <p>{{ctx.Locale.Tr "repo.ambiguous_runes_description" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "repo.ambiguous_runes_description" | SanitizeHTML}}</p>
</div>
{{end}}
{{end}}
diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl
index c1ef4ff4cb..988a5ddd50 100644
--- a/templates/repo/view_list.tmpl
+++ b/templates/repo/view_list.tmpl
@@ -1,7 +1,7 @@
-<table id="repo-files-table" class="ui single line table gt-mt-0" data-last-commit-loader-url="{{.LastCommitLoaderURL}}">
+<table id="repo-files-table" class="ui single line table gt-mt-0" {{if .HasFilesWithoutLatestCommit}}hx-indicator="tr.notready td.message span" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
<thead>
<tr class="commit-list">
- <th colspan="2" {{if not .LatestCommit}}class="notready"{{end}}>
+ <th colspan="2">
{{template "repo/latest_commit" .}}
</th>
<th class="text grey right age">{{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When ctx.Locale}}{{end}}{{end}}</th>
@@ -55,7 +55,7 @@
{{$commitLink := printf "%s/commit/%s" $.RepoLink (PathEscape $commit.ID.String)}}
{{RenderCommitMessageLinkSubject $.Context $commit.Message $commitLink ($.Repository.ComposeMetas ctx)}}
{{else}}
- <div class="ui active tiny slow centered inline">…</div>
+ <div class="ui active tiny slow centered inline"></div>
{{end}}
</span>
</td>
diff --git a/templates/shared/repo_search.tmpl b/templates/shared/repo_search.tmpl
new file mode 100644
index 0000000000..2ea4bfaad7
--- /dev/null
+++ b/templates/shared/repo_search.tmpl
@@ -0,0 +1,67 @@
+<div class="ui secondary filter menu">
+ <form id="repo-search-form" class="ui form ignore-dirty tw-flex-1 tw-flex tw-flex-row tw-gap-x-2">
+ {{if .Language}}<input hidden name="language" value="{{.Language}}">{{end}}
+ <div class="ui fluid action input tw-flex-1">
+ {{template "shared/searchinput" dict "Value" .Keyword}}
+ {{if .PageIsExploreRepositories}}
+ <input type="hidden" name="only_show_relevant" value="{{.OnlyShowRelevant}}">
+ {{else if .TabName}}
+ <input type="hidden" name="tab" value="{{.TabName}}">
+ {{end}}
+ <button class="ui primary button">{{ctx.Locale.Tr "explore.search"}}</button>
+ </div>
+ <!-- Filter -->
+ <div class="ui dropdown type jump item tw-mr-0">
+ <span class="text">
+ {{ctx.Locale.Tr "filter"}}
+ </span>
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="menu">
+ <label class="item"><input type="radio" name="clear-filter"> {{ctx.Locale.Tr "filter.clear"}}</label>
+ <div class="divider"></div>
+ <label class="item"><input type="radio" name="archived" {{if .IsArchived.Value}}checked{{end}} value="1"> {{ctx.Locale.Tr "filter.is_archived"}}</label>
+ <label class="item"><input type="radio" name="archived" {{if (not (.IsArchived.ValueOrDefault true))}}checked{{end}} value="0"> {{ctx.Locale.Tr "filter.not_archived"}}</label>
+ <div class="divider"></div>
+ <label class="item"><input type="radio" name="fork" {{if .IsFork.Value}}checked{{end}} value="1"> {{ctx.Locale.Tr "filter.is_fork"}}</label>
+ <label class="item"><input type="radio" name="fork" {{if (not (.IsFork.ValueOrDefault true))}}checked{{end}} value="0"> {{ctx.Locale.Tr "filter.not_fork"}}</label>
+ <div class="divider"></div>
+ <label class="item"><input type="radio" name="mirror" {{if .IsMirror.Value}}checked{{end}} value="1"> {{ctx.Locale.Tr "filter.is_mirror"}}</label>
+ <label class="item"><input type="radio" name="mirror" {{if (not (.IsMirror.ValueOrDefault true))}}checked{{end}} value="0"> {{ctx.Locale.Tr "filter.not_mirror"}}</label>
+ <div class="divider"></div>
+ <label class="item"><input type="radio" name="template" {{if .IsTemplate.Value}}checked{{end}} value="1"> {{ctx.Locale.Tr "filter.is_template"}}</label>
+ <label class="item"><input type="radio" name="template" {{if (not (.IsTemplate.ValueOrDefault true))}}checked{{end}} value="0"> {{ctx.Locale.Tr "filter.not_template"}}</label>
+ <div class="divider"></div>
+ <label class="item"><input type="radio" name="private" {{if .IsPrivate.Value}}checked{{end}} value="1"> {{ctx.Locale.Tr "filter.private"}}</label>
+ <label class="item"><input type="radio" name="private" {{if (not (.IsPrivate.ValueOrDefault true))}}checked{{end}} value="0"> {{ctx.Locale.Tr "filter.public"}}</label>
+ </div>
+ </div>
+ <!-- Sort -->
+ <div class="ui dropdown type jump item gt-mr-0">
+ <span class="text">
+ {{ctx.Locale.Tr "repo.issues.filter_sort"}}
+ </span>
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="menu">
+ <label class="{{if eq .SortType "newest"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "newest"}}checked{{end}} value="newest"> {{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</label>
+ <label class="{{if eq .SortType "oldest"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "oldest"}}checked{{end}} value="oldest"> {{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</label>
+ <label class="{{if eq .SortType "alphabetically"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "alphabetically"}}checked{{end}} value="alphabetically"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</label>
+ <label class="{{if eq .SortType "reversealphabetically"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "reversealphabetically"}}checked{{end}} value="reversealphabetically"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</label>
+ <label class="{{if eq .SortType "recentupdate"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "recentupdate"}}checked{{end}} value="recentupdate"> {{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</label>
+ <label class="{{if eq .SortType "leastupdate"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "leastupdate"}}checked{{end}} value="leastupdate"> {{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</label>
+ {{if not .DisableStars}}
+ <label class="{{if eq .SortType "moststars"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "moststars"}}checked{{end}} value="moststars"> {{ctx.Locale.Tr "repo.issues.filter_sort.moststars"}}</label>
+ <label class="{{if eq .SortType "feweststars"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "feweststars"}}checked{{end}} value="feweststars"> {{ctx.Locale.Tr "repo.issues.filter_sort.feweststars"}}</label>
+ {{end}}
+ <label class="{{if eq .SortType "mostforks"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "mostforks"}}checked{{end}} value="mostforks"> {{ctx.Locale.Tr "repo.issues.filter_sort.mostforks"}}</label>
+ <label class="{{if eq .SortType "fewestforks"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "fewestforks"}}checked{{end}} value="fewestforks"> {{ctx.Locale.Tr "repo.issues.filter_sort.fewestforks"}}</label>
+ <label class="{{if eq .SortType "size"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "size"}}checked{{end}} value="size"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.by_size"}}</label>
+ <label class="{{if eq .SortType "reversesize"}}active {{end}}item"><input hidden type="radio" name="sort" {{if eq .SortType "reversesize"}}checked{{end}} value="reversesize"> {{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_by_size"}}</label>
+ </div>
+ </div>
+ </form>
+</div>
+{{if and .PageIsExploreRepositories .OnlyShowRelevant}}
+ <div class="ui message explore-relevancy-note">
+ <span data-tooltip-content="{{ctx.Locale.Tr "explore.relevant_repositories_tooltip"}}">{{ctx.Locale.Tr "explore.relevant_repositories" (printf "?only_show_relevant=0&sort=%s&q=%s&language=%s" $.SortType (QueryEscape $.Keyword) (QueryEscape $.Language))}}</span>
+ </div>
+{{end}}
diff --git a/templates/shared/user/profile_big_avatar.tmpl b/templates/shared/user/profile_big_avatar.tmpl
index f1b0560b3b..4e25a53737 100644
--- a/templates/shared/user/profile_big_avatar.tmpl
+++ b/templates/shared/user/profile_big_avatar.tmpl
@@ -70,7 +70,7 @@
{{end}}
{{if $.RenderedDescription}}
<li>
- <div class="render-content markup">{{$.RenderedDescription|Str2html}}</div>
+ <div class="render-content markup">{{$.RenderedDescription}}</div>
</li>
{{end}}
{{range .OpenIDs}}
diff --git a/templates/status/404.tmpl b/templates/status/404.tmpl
index 289b9ea654..9e961e1b84 100644
--- a/templates/status/404.tmpl
+++ b/templates/status/404.tmpl
@@ -1,5 +1,5 @@
{{template "base/head" .}}
-<div role="main" aria-label="{{.Title}}" class="page-content ui center gt-w-screen {{if .IsRepo}}repository{{end}}">
+<div role="main" aria-label="{{.Title}}" class="page-content ui center tw-w-screen {{if .IsRepo}}repository{{end}}">
{{if .IsRepo}}{{template "repo/header" .}}{{end}}
<div class="ui container center">
<h1 style="margin-top: 100px" class="error-code">404</h1>
diff --git a/templates/status/500.tmpl b/templates/status/500.tmpl
index d0c8746148..c04b4af805 100644
--- a/templates/status/500.tmpl
+++ b/templates/status/500.tmpl
@@ -1,5 +1,5 @@
{{/* This page should only depend the minimal template functions/variables, to avoid triggering new panics.
-* base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, ThemeName, Str2html
+* base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, ThemeName, SanitizeHTML
* ctx.Locale
* .Flash
* .ErrorMsg
@@ -45,7 +45,7 @@
{{end}}
<div class="center gt-mt-5">
{{if or .SignedUser.IsAdmin .ShowFooterVersion}}<p>{{ctx.Locale.Tr "admin.config.app_ver"}}: {{AppVer}}</p>{{end}}
- {{if .SignedUser.IsAdmin}}<p>{{ctx.Locale.Tr "error.report_message" | Str2html}}</p>{{end}}
+ {{if .SignedUser.IsAdmin}}<p>{{ctx.Locale.Tr "error.report_message" | SanitizeHTML}}</p>{{end}}
</div>
</div>
</div>
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index ef292f2d65..04f71835ca 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -12828,7 +12828,8 @@
},
"post": {
"consumes": [
- "multipart/form-data"
+ "multipart/form-data",
+ "application/octet-stream"
],
"produces": [
"application/json"
@@ -12871,8 +12872,7 @@
"type": "file",
"description": "attachment to upload",
"name": "attachment",
- "in": "formData",
- "required": true
+ "in": "formData"
}
],
"responses": {
@@ -21225,6 +21225,13 @@
"type": "object",
"additionalProperties": {},
"x-go-name": "Validations"
+ },
+ "visible": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/IssueFormFieldVisible"
+ },
+ "x-go-name": "Visible"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
@@ -21234,6 +21241,11 @@
"title": "IssueFormFieldType defines issue form field type, can be \"markdown\", \"textarea\", \"input\", \"dropdown\" or \"checkboxes\"",
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
+ "IssueFormFieldVisible": {
+ "description": "IssueFormFieldVisible defines issue form field visible",
+ "type": "string",
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
"IssueLabelsOption": {
"description": "IssueLabelsOption a collection of labels",
"type": "object",
diff --git a/templates/user/auth/finalize_openid.tmpl b/templates/user/auth/finalize_openid.tmpl
index 7449e3beda..f7da41d16c 100644
--- a/templates/user/auth/finalize_openid.tmpl
+++ b/templates/user/auth/finalize_openid.tmpl
@@ -35,7 +35,7 @@
{{if .ShowRegistrationButton}}
<div class="inline field">
<label></label>
- <a href="{{AppSubUrl}}/user/sign_up">{{ctx.Locale.Tr "auth.sign_up_now" | Str2html}}</a>
+ <a href="{{AppSubUrl}}/user/sign_up">{{ctx.Locale.Tr "auth.sign_up_now" | SanitizeHTML}}</a>
</div>
{{end}}
</form>
diff --git a/templates/user/auth/grant.tmpl b/templates/user/auth/grant.tmpl
index 9c0bf33e28..d56692ccce 100644
--- a/templates/user/auth/grant.tmpl
+++ b/templates/user/auth/grant.tmpl
@@ -9,11 +9,11 @@
{{template "base/alert" .}}
<p>
<b>{{ctx.Locale.Tr "auth.authorize_application_description"}}</b><br>
- {{ctx.Locale.Tr "auth.authorize_application_created_by" .ApplicationCreatorLinkHTML | Str2html}}
+ {{ctx.Locale.Tr "auth.authorize_application_created_by" .ApplicationCreatorLinkHTML | SanitizeHTML}}
</p>
</div>
<div class="ui attached segment">
- <p>{{ctx.Locale.Tr "auth.authorize_redirect_notice" .ApplicationRedirectDomainHTML | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "auth.authorize_redirect_notice" .ApplicationRedirectDomainHTML | SanitizeHTML}}</p>
</div>
<div class="ui attached segment">
<form method="post" action="{{AppSubUrl}}/login/oauth/grant">
diff --git a/templates/user/auth/reset_passwd.tmpl b/templates/user/auth/reset_passwd.tmpl
index 2f470df441..c0bf693f46 100644
--- a/templates/user/auth/reset_passwd.tmpl
+++ b/templates/user/auth/reset_passwd.tmpl
@@ -34,7 +34,7 @@
<h4 class="ui dividing header">
{{ctx.Locale.Tr "twofa"}}
</h4>
- <div class="ui warning visible message">{{ctx.Locale.Tr "settings.twofa_is_enrolled" | Str2html}}</div>
+ <div class="ui warning visible message">{{ctx.Locale.Tr "settings.twofa_is_enrolled" | SanitizeHTML}}</div>
{{if .scratch_code}}
<div class="required inline field {{if .Err_Token}}error{{end}}">
<label for="token">{{ctx.Locale.Tr "auth.scratch_code"}}</label>
@@ -53,11 +53,11 @@
<label></label>
<button class="ui primary button">{{ctx.Locale.Tr "auth.reset_password_helper"}}</button>
{{if and .has_two_factor (not .scratch_code)}}
- <a href="{{.Link}}?code={{.Code}}&amp;scratch_code=true">{{ctx.Locale.Tr "auth.use_scratch_code" | Str2html}}</a>
+ <a href="{{.Link}}?code={{.Code}}&amp;scratch_code=true">{{ctx.Locale.Tr "auth.use_scratch_code" | SanitizeHTML}}</a>
{{end}}
</div>
{{else}}
- <p class="center">{{ctx.Locale.Tr "auth.invalid_code_forgot_password" (printf "%s/user/forgot_password" AppSubUrl) | Str2html}}</p>
+ <p class="center">{{ctx.Locale.Tr "auth.invalid_code_forgot_password" (printf "%s/user/forgot_password" AppSubUrl) | SanitizeHTML}}</p>
{{end}}
</div>
</form>
diff --git a/templates/user/auth/signin_inner.tmpl b/templates/user/auth/signin_inner.tmpl
index 40e54ec8fa..15733eb9bf 100644
--- a/templates/user/auth/signin_inner.tmpl
+++ b/templates/user/auth/signin_inner.tmpl
@@ -48,7 +48,7 @@
{{if .ShowRegistrationButton}}
<div class="inline field">
<label></label>
- <a href="{{AppSubUrl}}/user/sign_up">{{ctx.Locale.Tr "auth.sign_up_now" | Str2html}}</a>
+ <a href="{{AppSubUrl}}/user/sign_up">{{ctx.Locale.Tr "auth.sign_up_now" | SanitizeHTML}}</a>
</div>
{{end}}
diff --git a/templates/user/auth/twofa.tmpl b/templates/user/auth/twofa.tmpl
index d325114155..8a898c7dd8 100644
--- a/templates/user/auth/twofa.tmpl
+++ b/templates/user/auth/twofa.tmpl
@@ -17,7 +17,7 @@
<div class="inline field">
<label></label>
<button class="ui primary button">{{ctx.Locale.Tr "auth.verify"}}</button>
- <a href="{{AppSubUrl}}/user/two_factor/scratch">{{ctx.Locale.Tr "auth.use_scratch_code" | Str2html}}</a>
+ <a href="{{AppSubUrl}}/user/two_factor/scratch">{{ctx.Locale.Tr "auth.use_scratch_code" | SanitizeHTML}}</a>
</div>
</div>
</form>
diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl
index 6dec610e93..0e7371ad83 100644
--- a/templates/user/dashboard/feeds.tmpl
+++ b/templates/user/dashboard/feeds.tmpl
@@ -7,7 +7,7 @@
<div class="flex-item-main gt-gap-3">
<div>
{{if gt .ActUser.ID 0}}
- <a href="{{AppSubUrl}}/{{(.GetActUserName ctx) | PathEscape}}" title="{{.GetDisplayNameTitle ctx}}">{{.GetDisplayName ctx}}</a>
+ <a href="{{AppSubUrl}}/{{(.GetActUserName ctx) | PathEscape}}" title="{{.GetActDisplayNameTitle ctx}}">{{.GetActDisplayName ctx}}</a>
{{else}}
{{.ShortActUserName ctx}}
{{end}}
diff --git a/templates/user/dashboard/milestones.tmpl b/templates/user/dashboard/milestones.tmpl
index 1829021ff4..737a0f7e2b 100644
--- a/templates/user/dashboard/milestones.tmpl
+++ b/templates/user/dashboard/milestones.tmpl
@@ -141,7 +141,7 @@
</div>
{{if .Content}}
<div class="markup content">
- {{.RenderedContent|Str2html}}
+ {{.RenderedContent}}
</div>
{{end}}
</li>
diff --git a/templates/user/notification/notification_subscriptions.tmpl b/templates/user/notification/notification_subscriptions.tmpl
index ec40d3afea..a37f0c352e 100644
--- a/templates/user/notification/notification_subscriptions.tmpl
+++ b/templates/user/notification/notification_subscriptions.tmpl
@@ -69,7 +69,7 @@
{{template "shared/issuelist" dict "." . "listType" "dashboard"}}
{{end}}
{{else}}
- {{template "explore/repo_search" .}}
+ {{template "shared/repo_search" .}}
{{template "explore/repo_list" .}}
{{template "base/paginate" .}}
{{end}}
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index ed35389097..da68d50ab9 100644
--- a/templates/user/profile.tmpl
+++ b/templates/user/profile.tmpl
@@ -21,7 +21,7 @@
{{template "user/dashboard/feeds" .}}
{{else if eq .TabName "stars"}}
<div class="stars">
- {{template "explore/repo_search" .}}
+ {{template "shared/repo_search" .}}
{{template "explore/repo_list" .}}
{{template "base/paginate" .}}
</div>
@@ -30,9 +30,9 @@
{{else if eq .TabName "followers"}}
{{template "repo/user_cards" .}}
{{else if eq .TabName "overview"}}
- <div id="readme_profile" class="markup">{{.ProfileReadme | Str2html}}</div>
+ <div id="readme_profile" class="markup">{{.ProfileReadme}}</div>
{{else}}
- {{template "explore/repo_search" .}}
+ {{template "shared/repo_search" .}}
{{template "explore/repo_list" .}}
{{template "base/paginate" .}}
{{end}}
diff --git a/templates/user/settings/account.tmpl b/templates/user/settings/account.tmpl
index c7bf3c0a41..b9dc3a9ce4 100644
--- a/templates/user/settings/account.tmpl
+++ b/templates/user/settings/account.tmpl
@@ -134,9 +134,9 @@
</h4>
<div class="ui attached error segment">
<div class="ui red message">
- <p class="text left">{{svg "octicon-alert"}} {{ctx.Locale.Tr "settings.delete_prompt" | Str2html}}</p>
+ <p class="text left">{{svg "octicon-alert"}} {{ctx.Locale.Tr "settings.delete_prompt" | SanitizeHTML}}</p>
{{if .UserDeleteWithComments}}
- <p class="text left gt-font-semibold">{{ctx.Locale.Tr "settings.delete_with_all_comments" .UserDeleteWithCommentsMaxTime | Str2html}}</p>
+ <p class="text left gt-font-semibold">{{ctx.Locale.Tr "settings.delete_with_all_comments" .UserDeleteWithCommentsMaxTime | SanitizeHTML}}</p>
{{end}}
</div>
<form class="ui form ignore-dirty" id="delete-form" action="{{AppSubUrl}}/user/settings/account/delete" method="post">
diff --git a/templates/user/settings/keys.tmpl b/templates/user/settings/keys.tmpl
index 93037e7e28..a44bf50048 100644
--- a/templates/user/settings/keys.tmpl
+++ b/templates/user/settings/keys.tmpl
@@ -2,6 +2,8 @@
<div class="user-setting-content">
{{template "user/settings/keys_ssh" .}}
{{template "user/settings/keys_principal" .}}
+ {{if not ($.UserDisabledFeatures.Contains "manage_gpg_keys")}}
{{template "user/settings/keys_gpg" .}}
+ {{end}}
</div>
{{template "user/settings/layout_footer" .}}
diff --git a/templates/user/settings/keys_gpg.tmpl b/templates/user/settings/keys_gpg.tmpl
index 981cfd8106..3ab066c954 100644
--- a/templates/user/settings/keys_gpg.tmpl
+++ b/templates/user/settings/keys_gpg.tmpl
@@ -43,7 +43,7 @@
<div class="flex-item">
<p>
{{ctx.Locale.Tr "settings.gpg_desc"}}<br>
- {{ctx.Locale.Tr "settings.gpg_helper" "https://docs.codeberg.org/security/gpg-key/" | Str2html}}
+ {{ctx.Locale.Tr "settings.gpg_helper" "https://docs.codeberg.org/security/gpg-key/" | SanitizeHTML}}
</p>
</div>
{{range .GPGKeys}}
diff --git a/templates/user/settings/keys_ssh.tmpl b/templates/user/settings/keys_ssh.tmpl
index dc3179fdd0..9045b6c27c 100644
--- a/templates/user/settings/keys_ssh.tmpl
+++ b/templates/user/settings/keys_ssh.tmpl
@@ -31,7 +31,7 @@
<div class="flex-item">
<p>
{{ctx.Locale.Tr "settings.ssh_desc"}}<br>
- {{ctx.Locale.Tr "settings.ssh_helper" "https://docs.codeberg.org/security/ssh-key/" "https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/troubleshooting-ssh" | Str2html}}
+ {{ctx.Locale.Tr "settings.ssh_helper" "https://docs.codeberg.org/security/ssh-key/" "https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/troubleshooting-ssh" | SanitizeHTML}}
</p>
</div>
{{if .DisableSSH}}
diff --git a/templates/user/settings/security/twofa.tmpl b/templates/user/settings/security/twofa.tmpl
index 2f15fe13f1..87cc90e477 100644
--- a/templates/user/settings/security/twofa.tmpl
+++ b/templates/user/settings/security/twofa.tmpl
@@ -4,7 +4,7 @@
<div class="ui attached segment">
<p>{{ctx.Locale.Tr "settings.twofa_desc"}}</p>
{{if .TOTPEnrolled}}
- <p>{{ctx.Locale.Tr "settings.twofa_is_enrolled" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "settings.twofa_is_enrolled" | SanitizeHTML}}</p>
<form class="ui form" action="{{AppSubUrl}}/user/settings/security/two_factor/regenerate_scratch" method="post" enctype="multipart/form-data">
{{.CsrfTokenHtml}}
<p>{{ctx.Locale.Tr "settings.regenerate_scratch_token_desc"}}</p>
diff --git a/templates/user/settings/security/webauthn.tmpl b/templates/user/settings/security/webauthn.tmpl
index e582b801da..a7fa04a521 100644
--- a/templates/user/settings/security/webauthn.tmpl
+++ b/templates/user/settings/security/webauthn.tmpl
@@ -1,6 +1,6 @@
<h4 class="ui top attached header">{{ctx.Locale.Tr "settings.webauthn"}}</h4>
<div class="ui attached segment">
- <p>{{ctx.Locale.Tr "settings.webauthn_desc" | Str2html}}</p>
+ <p>{{ctx.Locale.Tr "settings.webauthn_desc" | SanitizeHTML}}</p>
<p>{{ctx.Locale.Tr "settings.webauthn_key_loss_warning"}} {{ctx.Locale.Tr "settings.webauthn_alternative_tip"}}</p>
{{template "user/auth/webauthn_error" .}}
<div class="flex-list">
diff --git a/tests/integration/api_actions_artifact_v4_test.go b/tests/integration/api_actions_artifact_v4_test.go
new file mode 100644
index 0000000000..f58f876849
--- /dev/null
+++ b/tests/integration/api_actions_artifact_v4_test.go
@@ -0,0 +1,224 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "encoding/hex"
+ "io"
+ "net/http"
+ "strings"
+ "testing"
+ "time"
+
+ "code.gitea.io/gitea/routers/api/actions"
+ actions_service "code.gitea.io/gitea/services/actions"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+ "google.golang.org/protobuf/encoding/protojson"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/known/timestamppb"
+ "google.golang.org/protobuf/types/known/wrapperspb"
+)
+
+func toProtoJSON(m protoreflect.ProtoMessage) io.Reader {
+ resp, _ := protojson.Marshal(m)
+ buf := bytes.Buffer{}
+ buf.Write(resp)
+ return &buf
+}
+
+func TestActionsArtifactV4UploadSingleFile(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
+ assert.NoError(t, err)
+
+ // acquire artifact upload url
+ req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact", toProtoJSON(&actions.CreateArtifactRequest{
+ Version: 4,
+ Name: "artifact",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp actions.CreateArtifactResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &uploadResp)
+ assert.True(t, uploadResp.Ok)
+ assert.Contains(t, uploadResp.SignedUploadUrl, "/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact")
+
+ // get upload url
+ idx := strings.Index(uploadResp.SignedUploadUrl, "/twirp/")
+ url := uploadResp.SignedUploadUrl[idx:] + "&comp=block"
+
+ // upload artifact chunk
+ body := strings.Repeat("A", 1024)
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body))
+ MakeRequest(t, req, http.StatusCreated)
+
+ t.Logf("Create artifact confirm")
+
+ sha := sha256.Sum256([]byte(body))
+
+ // confirm artifact upload
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact", toProtoJSON(&actions.FinalizeArtifactRequest{
+ Name: "artifact",
+ Size: 1024,
+ Hash: wrapperspb.String("sha256:" + hex.EncodeToString(sha[:])),
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ var finalizeResp actions.FinalizeArtifactResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &finalizeResp)
+ assert.True(t, finalizeResp.Ok)
+}
+
+func TestActionsArtifactV4UploadSingleFileWrongChecksum(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
+ assert.NoError(t, err)
+
+ // acquire artifact upload url
+ req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact", toProtoJSON(&actions.CreateArtifactRequest{
+ Version: 4,
+ Name: "artifact-invalid-checksum",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp actions.CreateArtifactResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &uploadResp)
+ assert.True(t, uploadResp.Ok)
+ assert.Contains(t, uploadResp.SignedUploadUrl, "/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact")
+
+ // get upload url
+ idx := strings.Index(uploadResp.SignedUploadUrl, "/twirp/")
+ url := uploadResp.SignedUploadUrl[idx:] + "&comp=block"
+
+ // upload artifact chunk
+ body := strings.Repeat("B", 1024)
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body))
+ MakeRequest(t, req, http.StatusCreated)
+
+ t.Logf("Create artifact confirm")
+
+ sha := sha256.Sum256([]byte(strings.Repeat("A", 1024)))
+
+ // confirm artifact upload
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact", toProtoJSON(&actions.FinalizeArtifactRequest{
+ Name: "artifact-invalid-checksum",
+ Size: 1024,
+ Hash: wrapperspb.String("sha256:" + hex.EncodeToString(sha[:])),
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusInternalServerError)
+}
+
+func TestActionsArtifactV4UploadSingleFileWithRetentionDays(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
+ assert.NoError(t, err)
+
+ // acquire artifact upload url
+ req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact", toProtoJSON(&actions.CreateArtifactRequest{
+ Version: 4,
+ ExpiresAt: timestamppb.New(time.Now().Add(5 * 24 * time.Hour)),
+ Name: "artifactWithRetentionDays",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp actions.CreateArtifactResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &uploadResp)
+ assert.True(t, uploadResp.Ok)
+ assert.Contains(t, uploadResp.SignedUploadUrl, "/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact")
+
+ // get upload url
+ idx := strings.Index(uploadResp.SignedUploadUrl, "/twirp/")
+ url := uploadResp.SignedUploadUrl[idx:] + "&comp=block"
+
+ // upload artifact chunk
+ body := strings.Repeat("A", 1024)
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body))
+ MakeRequest(t, req, http.StatusCreated)
+
+ t.Logf("Create artifact confirm")
+
+ sha := sha256.Sum256([]byte(body))
+
+ // confirm artifact upload
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact", toProtoJSON(&actions.FinalizeArtifactRequest{
+ Name: "artifactWithRetentionDays",
+ Size: 1024,
+ Hash: wrapperspb.String("sha256:" + hex.EncodeToString(sha[:])),
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ var finalizeResp actions.FinalizeArtifactResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &finalizeResp)
+ assert.True(t, finalizeResp.Ok)
+}
+
+func TestActionsArtifactV4DownloadSingle(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
+ assert.NoError(t, err)
+
+ // acquire artifact upload url
+ req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/ListArtifacts", toProtoJSON(&actions.ListArtifactsRequest{
+ NameFilter: wrapperspb.String("artifact"),
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp actions.ListArtifactsResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.Len(t, listResp.Artifacts, 1)
+
+ // confirm artifact upload
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/GetSignedArtifactURL", toProtoJSON(&actions.GetSignedArtifactURLRequest{
+ Name: "artifact",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ var finalizeResp actions.GetSignedArtifactURLResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &finalizeResp)
+ assert.NotEmpty(t, finalizeResp.SignedUrl)
+
+ req = NewRequest(t, "GET", finalizeResp.SignedUrl)
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("A", 1024)
+ assert.Equal(t, resp.Body.String(), body)
+}
+
+func TestActionsArtifactV4Delete(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
+ assert.NoError(t, err)
+
+ // delete artifact by name
+ req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/DeleteArtifact", toProtoJSON(&actions.DeleteArtifactRequest{
+ Name: "artifact",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var deleteResp actions.DeleteArtifactResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &deleteResp)
+ assert.True(t, deleteResp.Ok)
+}
diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go
index 5b1ab76ce9..49aa4c4e1b 100644
--- a/tests/integration/api_releases_test.go
+++ b/tests/integration/api_releases_test.go
@@ -262,24 +262,60 @@ func TestAPIUploadAssetRelease(t *testing.T) {
filename := "image.png"
buff := generateImg()
- body := &bytes.Buffer{}
- writer := multipart.NewWriter(body)
- part, err := writer.CreateFormFile("attachment", filename)
- assert.NoError(t, err)
- _, err = io.Copy(part, &buff)
- assert.NoError(t, err)
- err = writer.Close()
- assert.NoError(t, err)
+ assetURL := fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d/assets", owner.Name, repo.Name, r.ID)
- req := NewRequestWithBody(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d/assets?name=test-asset", owner.Name, repo.Name, r.ID), body).
- AddTokenAuth(token)
- req.Header.Add("Content-Type", writer.FormDataContentType())
- resp := MakeRequest(t, req, http.StatusCreated)
+ t.Run("multipart/form-data", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ body := &bytes.Buffer{}
+
+ writer := multipart.NewWriter(body)
+ part, err := writer.CreateFormFile("attachment", filename)
+ assert.NoError(t, err)
+ _, err = io.Copy(part, bytes.NewReader(buff.Bytes()))
+ assert.NoError(t, err)
+ err = writer.Close()
+ assert.NoError(t, err)
+
+ req := NewRequestWithBody(t, http.MethodPost, assetURL, bytes.NewReader(body.Bytes())).
+ AddTokenAuth(token).
+ SetHeader("Content-Type", writer.FormDataContentType())
+ resp := MakeRequest(t, req, http.StatusCreated)
+
+ var attachment *api.Attachment
+ DecodeJSON(t, resp, &attachment)
+
+ assert.EqualValues(t, filename, attachment.Name)
+ assert.EqualValues(t, 104, attachment.Size)
+
+ req = NewRequestWithBody(t, http.MethodPost, assetURL+"?name=test-asset", bytes.NewReader(body.Bytes())).
+ AddTokenAuth(token).
+ SetHeader("Content-Type", writer.FormDataContentType())
+ resp = MakeRequest(t, req, http.StatusCreated)
+
+ var attachment2 *api.Attachment
+ DecodeJSON(t, resp, &attachment2)
+
+ assert.EqualValues(t, "test-asset", attachment2.Name)
+ assert.EqualValues(t, 104, attachment2.Size)
+ })
+
+ t.Run("application/octet-stream", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequestWithBody(t, http.MethodPost, assetURL, bytes.NewReader(buff.Bytes())).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusBadRequest)
+
+ req = NewRequestWithBody(t, http.MethodPost, assetURL+"?name=stream.bin", bytes.NewReader(buff.Bytes())).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusCreated)
- var attachment *api.Attachment
- DecodeJSON(t, resp, &attachment)
+ var attachment *api.Attachment
+ DecodeJSON(t, resp, &attachment)
- assert.EqualValues(t, "test-asset", attachment.Name)
- assert.EqualValues(t, 104, attachment.Size)
+ assert.EqualValues(t, "stream.bin", attachment.Name)
+ assert.EqualValues(t, 104, attachment.Size)
+ })
}
diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go
index 0d192a1fe8..41ad7211ff 100644
--- a/tests/integration/api_repo_file_create_test.go
+++ b/tests/integration/api_repo_file_create_test.go
@@ -17,10 +17,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"github.com/stretchr/testify/assert"
)
diff --git a/tests/integration/api_repo_file_update_test.go b/tests/integration/api_repo_file_update_test.go
index 195a1090c7..ac28e0c0a2 100644
--- a/tests/integration/api_repo_file_update_test.go
+++ b/tests/integration/api_repo_file_update_test.go
@@ -16,10 +16,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"github.com/stretchr/testify/assert"
)
diff --git a/tests/integration/api_repo_files_change_test.go b/tests/integration/api_repo_files_change_test.go
index ab5cf19a9c..fb3ae5e4dd 100644
--- a/tests/integration/api_repo_files_change_test.go
+++ b/tests/integration/api_repo_files_change_test.go
@@ -15,10 +15,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/context"
"github.com/stretchr/testify/assert"
)
diff --git a/tests/integration/block_test.go b/tests/integration/block_test.go
index 96e9d5d3e3..8f40ed13e8 100644
--- a/tests/integration/block_test.go
+++ b/tests/integration/block_test.go
@@ -17,8 +17,8 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- forgejo_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/translation"
+ forgejo_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
diff --git a/tests/integration/branches_test.go b/tests/integration/branches_test.go
index 26bed8c90a..e0482b6f2e 100644
--- a/tests/integration/branches_test.go
+++ b/tests/integration/branches_test.go
@@ -12,7 +12,7 @@ import (
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- gitea_context "code.gitea.io/gitea/modules/context"
+ gitea_context "code.gitea.io/gitea/services/context"
"github.com/stretchr/testify/assert"
)
diff --git a/tests/integration/editor_test.go b/tests/integration/editor_test.go
index f2b2716a80..f2f312b8a4 100644
--- a/tests/integration/editor_test.go
+++ b/tests/integration/editor_test.go
@@ -17,10 +17,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/translation"
+ gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
diff --git a/tests/integration/explore_repos_test.go b/tests/integration/explore_repos_test.go
index fda376b96f..26fd1dde64 100644
--- a/tests/integration/explore_repos_test.go
+++ b/tests/integration/explore_repos_test.go
@@ -8,7 +8,6 @@ import (
"testing"
"code.gitea.io/gitea/tests"
- "github.com/stretchr/testify/assert"
)
func TestExploreRepos(t *testing.T) {
@@ -16,16 +15,4 @@ func TestExploreRepos(t *testing.T) {
req := NewRequest(t, "GET", "/explore/repos")
MakeRequest(t, req, http.StatusOK)
-
- t.Run("Persistent parameters", func(t *testing.T) {
- defer tests.PrintCurrentTest(t)()
-
- req := NewRequest(t, "GET", "/explore/repos?topic=1&language=Go&sort=moststars")
- resp := MakeRequest(t, req, http.StatusOK)
- htmlDoc := NewHTMLParser(t, resp.Body)
-
- assert.EqualValues(t, "moststars", htmlDoc.Find("input[type='hidden'][name='sort']").AttrOr("value", "not found"))
- assert.EqualValues(t, "Go", htmlDoc.Find("input[type='hidden'][name='language']").AttrOr("value", "not found"))
- assert.EqualValues(t, "true", htmlDoc.Find("input[type='hidden'][name='topic']").AttrOr("value", "not found"))
- })
}
diff --git a/tests/integration/explore_user_test.go b/tests/integration/explore_user_test.go
new file mode 100644
index 0000000000..046caf378e
--- /dev/null
+++ b/tests/integration/explore_user_test.go
@@ -0,0 +1,44 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "net/http"
+ "testing"
+
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestExploreUser(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ cases := []struct{ sortOrder, expected string }{
+ {"", "/explore/users?sort=newest&q="},
+ {"newest", "/explore/users?sort=newest&q="},
+ {"oldest", "/explore/users?sort=oldest&q="},
+ {"alphabetically", "/explore/users?sort=alphabetically&q="},
+ {"reversealphabetically", "/explore/users?sort=reversealphabetically&q="},
+ }
+ for _, c := range cases {
+ req := NewRequest(t, "GET", "/explore/users?sort="+c.sortOrder)
+ resp := MakeRequest(t, req, http.StatusOK)
+ h := NewHTMLParser(t, resp.Body)
+ href, _ := h.Find(`.ui.dropdown .menu a.active.item[href^="/explore/users"]`).Attr("href")
+ assert.Equal(t, c.expected, href)
+ }
+
+ // these sort orders shouldn't be supported, to avoid leaking user activity
+ cases404 := []string{
+ "/explore/users?sort=lastlogin",
+ "/explore/users?sort=reverselastlogin",
+ "/explore/users?sort=leastupdate",
+ "/explore/users?sort=reverseleastupdate",
+ }
+ for _, c := range cases404 {
+ req := NewRequest(t, "GET", c).SetHeader("Accept", "text/html")
+ MakeRequest(t, req, http.StatusNotFound)
+ }
+}
diff --git a/tests/integration/forgejo_confirmation_repo_test.go b/tests/integration/forgejo_confirmation_repo_test.go
index c63d0ae75c..53bd32f1a6 100644
--- a/tests/integration/forgejo_confirmation_repo_test.go
+++ b/tests/integration/forgejo_confirmation_repo_test.go
@@ -8,8 +8,8 @@ import (
"net/http/httptest"
"testing"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/translation"
+ gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
diff --git a/tests/integration/git_test.go b/tests/integration/git_test.go
index ff5421d93a..e0a8246719 100644
--- a/tests/integration/git_test.go
+++ b/tests/integration/git_test.go
@@ -25,12 +25,12 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ gitea_context "code.gitea.io/gitea/services/context"
files_service "code.gitea.io/gitea/services/repository/files"
"code.gitea.io/gitea/tests"
diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go
index 33e507e5c6..0a2003447a 100644
--- a/tests/integration/integration_test.go
+++ b/tests/integration/integration_test.go
@@ -30,7 +30,6 @@ import (
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/json"
@@ -40,6 +39,7 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers"
+ gitea_context "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
files_service "code.gitea.io/gitea/services/repository/files"
user_service "code.gitea.io/gitea/services/user"
diff --git a/tests/integration/mirror_push_test.go b/tests/integration/mirror_push_test.go
index 4263f12f95..7fb6414b4f 100644
--- a/tests/integration/mirror_push_test.go
+++ b/tests/integration/mirror_push_test.go
@@ -15,10 +15,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
+ gitea_context "code.gitea.io/gitea/services/context"
doctor "code.gitea.io/gitea/services/doctor"
"code.gitea.io/gitea/services/migrations"
mirror_service "code.gitea.io/gitea/services/mirror"
diff --git a/tests/integration/pull_reopen_test.go b/tests/integration/pull_reopen_test.go
index 51f208794e..a4be38ab64 100644
--- a/tests/integration/pull_reopen_test.go
+++ b/tests/integration/pull_reopen_test.go
@@ -18,9 +18,9 @@ import (
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/translation"
+ gitea_context "code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
diff --git a/tests/integration/repo_settings_test.go b/tests/integration/repo_settings_test.go
index 3076148156..771aa9ad8e 100644
--- a/tests/integration/repo_settings_test.go
+++ b/tests/integration/repo_settings_test.go
@@ -14,8 +14,8 @@ import (
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
+ gitea_context "code.gitea.io/gitea/services/context"
repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go
index 19fbd1754c..49abeb83fb 100644
--- a/tests/integration/repofiles_change_test.go
+++ b/tests/integration/repofiles_change_test.go
@@ -12,11 +12,11 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/contexttest"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/services/contexttest"
files_service "code.gitea.io/gitea/services/repository/files"
"github.com/stretchr/testify/assert"
diff --git a/web_src/css/base.css b/web_src/css/base.css
index bb45c8d325..976f2f9f33 100644
--- a/web_src/css/base.css
+++ b/web_src/css/base.css
@@ -1587,7 +1587,7 @@ a.ui.active.label:hover {
.lines-commit {
vertical-align: top;
- color: var(--color-grey);
+ color: var(--color-text-light-2);
padding: 0 !important;
background: var(--color-code-sidebar-bg);
width: 1%;
@@ -1630,6 +1630,10 @@ a.ui.active.label:hover {
border-top: 1px solid var(--color-secondary);
}
+.code-view tr.top-line-blame:first-of-type {
+ border-top: none;
+}
+
.lines-code .bottom-line,
.lines-commit .bottom-line {
border-bottom: 1px solid var(--color-secondary);
diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css
index da94ebb486..3579c193b1 100644
--- a/web_src/css/helpers.css
+++ b/web_src/css/helpers.css
@@ -73,12 +73,6 @@ Gitea's private styles use `g-` prefix.
.gt-overflow-x-scroll { overflow-x: scroll !important; }
.gt-overflow-y-hidden { overflow-y: hidden !important; }
-.gt-h-screen { height: 100vh !important; }
-.gt-h-full { height: 100% !important; }
-.gt-w-auto { width: auto !important; }
-.gt-w-screen { width: 100vw !important; }
-.gt-w-full { width: 100% !important; }
-
.gt-float-left { float: left !important; }
.gt-float-right { float: right !important; }
.gt-clear-both { clear: both !important; }
diff --git a/web_src/css/modules/button.css b/web_src/css/modules/button.css
index b772a4c14e..3c80eb99c0 100644
--- a/web_src/css/modules/button.css
+++ b/web_src/css/modules/button.css
@@ -87,6 +87,13 @@ It needs some tricks to tweak the left/right borders with active state */
box-shadow: none;
}
+/* apply the vertical padding of .compact to non-compact buttons when they contain a svg as they
+ would otherwise appear too large. Seen on "RSS Feed" button on repo releases tab. */
+.ui.small.button:not(.compact):has(.svg) {
+ padding-top: 0.58928571em;
+ padding-bottom: 0.58928571em;
+}
+
.ui.labeled.button.disabled > .button,
.ui.basic.buttons .button,
.ui.basic.button {
diff --git a/web_src/css/themes/theme-gitea-dark.css b/web_src/css/themes/theme-gitea-dark.css
index bac002e3db..ac77b7bbd9 100644
--- a/web_src/css/themes/theme-gitea-dark.css
+++ b/web_src/css/themes/theme-gitea-dark.css
@@ -3,72 +3,72 @@
:root {
--is-dark-theme: true;
- --color-primary: #87ab63;
+ --color-primary: #4183c4;
--color-primary-contrast: #ffffff;
- --color-primary-dark-1: #93b373;
- --color-primary-dark-2: #9fbc82;
- --color-primary-dark-3: #abc492;
- --color-primary-dark-4: #b7cda1;
- --color-primary-dark-5: #cfddc1;
- --color-primary-dark-6: #e7eee0;
- --color-primary-dark-7: #f8faf6;
- --color-primary-light-1: #7a9e55;
- --color-primary-light-2: #6c8c4c;
- --color-primary-light-3: #5f7b42;
- --color-primary-light-4: #516939;
- --color-primary-light-5: #364626;
- --color-primary-light-6: #1b2313;
- --color-primary-light-7: #080b06;
- --color-primary-alpha-10: #87ab6319;
- --color-primary-alpha-20: #87ab6333;
- --color-primary-alpha-30: #87ab634b;
- --color-primary-alpha-40: #87ab6366;
- --color-primary-alpha-50: #87ab6380;
- --color-primary-alpha-60: #87ab6399;
- --color-primary-alpha-70: #87ab63b3;
- --color-primary-alpha-80: #87ab63cc;
- --color-primary-alpha-90: #87ab63e1;
+ --color-primary-dark-1: #548fca;
+ --color-primary-dark-2: #679cd0;
+ --color-primary-dark-3: #7aa8d6;
+ --color-primary-dark-4: #8db5dc;
+ --color-primary-dark-5: #b3cde7;
+ --color-primary-dark-6: #d9e6f3;
+ --color-primary-dark-7: #f4f8fb;
+ --color-primary-light-1: #3876b3;
+ --color-primary-light-2: #31699f;
+ --color-primary-light-3: #2b5c8b;
+ --color-primary-light-4: #254f77;
+ --color-primary-light-5: #193450;
+ --color-primary-light-6: #0c1a28;
+ --color-primary-light-7: #04080c;
+ --color-primary-alpha-10: #4183c419;
+ --color-primary-alpha-20: #4183c433;
+ --color-primary-alpha-30: #4183c44b;
+ --color-primary-alpha-40: #4183c466;
+ --color-primary-alpha-50: #4183c480;
+ --color-primary-alpha-60: #4183c499;
+ --color-primary-alpha-70: #4183c4b3;
+ --color-primary-alpha-80: #4183c4cc;
+ --color-primary-alpha-90: #4183c4e1;
--color-primary-hover: var(--color-primary-light-1);
--color-primary-active: var(--color-primary-light-2);
- --color-secondary: #525767;
- --color-secondary-dark-1: #5c6374;
- --color-secondary-dark-2: #666e81;
- --color-secondary-dark-3: #7c8497;
- --color-secondary-dark-4: #8990a1;
- --color-secondary-dark-5: #959cab;
- --color-secondary-dark-6: #a2a8b5;
- --color-secondary-dark-7: #afb4c0;
- --color-secondary-dark-8: #bcc0ca;
- --color-secondary-dark-9: #c9cbd4;
- --color-secondary-dark-10: #d6d7de;
- --color-secondary-dark-11: #e2e3e8;
- --color-secondary-dark-12: #eeeff2;
- --color-secondary-dark-13: #fbfbfc;
- --color-secondary-light-1: #454a57;
- --color-secondary-light-2: #383c47;
- --color-secondary-light-3: #2c2f37;
- --color-secondary-light-4: #1f2226;
- --color-secondary-alpha-10: #52576719;
- --color-secondary-alpha-20: #52576733;
- --color-secondary-alpha-30: #5257674b;
- --color-secondary-alpha-40: #52576766;
- --color-secondary-alpha-50: #52576780;
- --color-secondary-alpha-60: #52576799;
- --color-secondary-alpha-70: #525767b3;
- --color-secondary-alpha-80: #525767cc;
- --color-secondary-alpha-90: #525767e1;
+ --color-secondary: #3f4346;
+ --color-secondary-dark-1: #464a4d;
+ --color-secondary-dark-2: #4f5356;
+ --color-secondary-dark-3: #5f6366;
+ --color-secondary-dark-4: #72767a;
+ --color-secondary-dark-5: #7f8488;
+ --color-secondary-dark-6: #8d9297;
+ --color-secondary-dark-7: #999ea3;
+ --color-secondary-dark-8: #a6abaf;
+ --color-secondary-dark-9: #aeb3b8;
+ --color-secondary-dark-10: #babfc4;
+ --color-secondary-dark-11: #c5cbd0;
+ --color-secondary-dark-12: #ced4da;
+ --color-secondary-dark-13: #d1d7dd;
+ --color-secondary-light-1: #313538;
+ --color-secondary-light-2: #272b2e;
+ --color-secondary-light-3: #1e2225;
+ --color-secondary-light-4: #171b1e;
+ --color-secondary-alpha-10: #3f434619;
+ --color-secondary-alpha-20: #3f434633;
+ --color-secondary-alpha-30: #3f43464b;
+ --color-secondary-alpha-40: #3f434666;
+ --color-secondary-alpha-50: #3f434680;
+ --color-secondary-alpha-60: #3f434699;
+ --color-secondary-alpha-70: #3f4346b3;
+ --color-secondary-alpha-80: #3f4346cc;
+ --color-secondary-alpha-90: #3f4346e1;
--color-secondary-button: var(--color-secondary-dark-4);
--color-secondary-hover: var(--color-secondary-dark-3);
--color-secondary-active: var(--color-secondary-dark-2);
/* console colors - used for actions console and console files */
- --color-console-fg: #eeeff2;
- --color-console-fg-subtle: #959cab;
- --color-console-bg: #262936;
- --color-console-border: #383c47;
+ --color-console-fg: #d9dde2;
+ --color-console-fg-subtle: #95989c;
+ --color-console-bg: #1c2023;
+ --color-console-border: #272b2e;
--color-console-hover-bg: #ffffff16;
- --color-console-active-bg: #454a57;
- --color-console-menu-bg: #383c47;
- --color-console-menu-border: #5c6374;
+ --color-console-active-bg: #313538;
+ --color-console-menu-bg: #272b2e;
+ --color-console-menu-border: #464a4d;
/* named colors */
--color-red: #cc4848;
--color-orange: #cc580c;
@@ -81,7 +81,7 @@
--color-purple: #b259d0;
--color-pink: #d22e8b;
--color-brown: #a47252;
- --color-black: #2e323e;
+ --color-black: #1f2326;
/* light variants - produced via Sass scale-color(color, $lightness: +10%) */
--color-red-light: #d15a5a;
--color-orange-light: #f6a066;
@@ -94,7 +94,7 @@
--color-purple-light: #ba6ad5;
--color-pink-light: #d74397;
--color-brown-light: #b08061;
- --color-black-light: #3f4555;
+ --color-black-light: #46494d;
/* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */
--color-red-dark-1: #c23636;
--color-orange-dark-1: #f38236;
@@ -107,7 +107,7 @@
--color-purple-dark-1: #a742c9;
--color-pink-dark-1: #be297d;
--color-brown-dark-1: #94674a;
- --color-black-dark-1: #292d38;
+ --color-black-dark-1: #2c2f35;
/* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */
--color-red-dark-2: #ad3030;
--color-orange-dark-2: #f16e17;
@@ -120,7 +120,7 @@
--color-purple-dark-2: #9834b9;
--color-pink-dark-2: #a9246f;
--color-brown-dark-2: #835b42;
- --color-black-dark-2: #252832;
+ --color-black-dark-2: #292a2e;
/* ansi colors used for actions console and console files */
--color-ansi-black: var(--color-black);
--color-ansi-red: var(--color-red);
@@ -139,8 +139,8 @@
--color-ansi-bright-cyan: var(--color-teal-light);
--color-ansi-bright-white: var(--color-console-fg);
/* other colors */
- --color-grey: #505665;
- --color-grey-light: #a1a6b7;
+ --color-grey: #3c4043;
+ --color-grey-light: #898e92;
--color-gold: #b1983b;
--color-white: #ffffff;
--color-diff-removed-word-bg: #6f3333;
@@ -151,7 +151,7 @@
--color-diff-removed-row-border: #634343;
--color-diff-moved-row-border: #bcca6f;
--color-diff-added-row-border: #314a37;
- --color-diff-inactive: #353846;
+ --color-diff-inactive: #24282b;
--color-error-border: #a04141;
--color-error-bg: #522;
--color-error-bg-active: #744;
@@ -180,40 +180,40 @@
--color-orange-badge-hover-bg: #f2711c4d;
--color-git: #f05133;
/* target-based colors */
- --color-body: #2e323e;
- --color-box-header: #303340;
- --color-box-body: #222733;
- --color-box-body-highlight: #262b36;
- --color-text-dark: #dbe0ea;
- --color-text: #cbd0da;
- --color-text-light: #bbbfca;
- --color-text-light-1: #aaafb9;
- --color-text-light-2: #9a9ea9;
- --color-text-light-3: #8a8e99;
- --color-footer: #232834;
- --color-timeline: #4c525e;
- --color-input-text: #dfe3ec;
- --color-input-background: #1e252e;
- --color-input-toggle-background: #454a57;
+ --color-body: #1f2326;
+ --color-box-header: #202427;
+ --color-box-body: #191d20;
+ --color-box-body-highlight: #1d2124;
+ --color-text-dark: #f8f8f9;
+ --color-text: #ced2d5;
+ --color-text-light: #bec4c8;
+ --color-text-light-1: #acb3b8;
+ --color-text-light-2: #8d969c;
+ --color-text-light-3: #747f87;
+ --color-footer: var(--color-nav-bg);
+ --color-timeline: #383c3f;
+ --color-input-text: var(--color-text-dark);
+ --color-input-background: #161a1d;
+ --color-input-toggle-background: #313538;
--color-input-border: var(--color-secondary);
--color-input-border-hover: var(--color-secondary-dark-1);
- --color-header-wrapper: #202430;
+ --color-header-wrapper: #191d20;
--color-light: #00000028;
--color-light-mimic-enabled: rgba(0, 0, 0, calc(40 / 255 * 222 / 255 / var(--opacity-disabled)));
--color-light-border: #ffffff28;
--color-hover: #ffffff19;
--color-active: #ffffff24;
- --color-menu: #1e252e;
- --color-card: #1e252e;
+ --color-menu: #161a1d;
+ --color-card: #161a1d;
--color-markup-table-row: #ffffff06;
--color-markup-code-block: #ffffff16;
- --color-button: #1e252e;
- --color-code-bg: #222733;
- --color-code-sidebar-bg: #232834;
+ --color-button: #161a1d;
+ --color-code-bg: #191d20;
+ --color-code-sidebar-bg: #1b1f22;
--color-shadow: #00000058;
- --color-secondary-bg: #2a2e3a;
- --color-expand-button: #3c404d;
- --color-placeholder-text: #8a8e99;
+ --color-secondary-bg: #2f3135;
+ --color-expand-button: #414348;
+ --color-placeholder-text: var(--color-text-light-3);
--color-editor-line-highlight: var(--color-primary-light-5);
--color-project-board-bg: var(--color-secondary-light-2);
--color-project-board-dark-label: #111111;
@@ -224,13 +224,13 @@
--color-reaction-active-bg: var(--color-primary-light-5);
--color-tooltip-text: #ffffff;
--color-tooltip-bg: #000000f0;
- --color-nav-bg: #232834;
- --color-nav-hover-bg: #383c47;
+ --color-nav-bg: #1b1f22;
+ --color-nav-hover-bg: #272b2e;
--color-nav-text: var(--color-text);
- --color-label-text: #dfe3ec;
- --color-label-bg: #7c84974b;
- --color-label-hover-bg: #7c8497a0;
- --color-label-active-bg: #7c8497ff;
+ --color-label-text: var(--color-text);
+ --color-label-bg: #7a7f834b;
+ --color-label-hover-bg: #7a7f83a0;
+ --color-label-active-bg: #7a7f83ff;
--color-accent: var(--color-primary-light-1);
--color-small-accent: var(--color-primary-light-5);
--color-active-line: #534d1b;
diff --git a/web_src/css/themes/theme-gitea-light.css b/web_src/css/themes/theme-gitea-light.css
index ca5d15cd25..5c375712d8 100644
--- a/web_src/css/themes/theme-gitea-light.css
+++ b/web_src/css/themes/theme-gitea-light.css
@@ -190,9 +190,9 @@
--color-text-light-1: #6a6a6a;
--color-text-light-2: #808080;
--color-text-light-3: #a0a0a0;
- --color-footer: #ffffff;
+ --color-footer: var(--color-nav-bg);
--color-timeline: #ececec;
- --color-input-text: #212121;
+ --color-input-text: var(--color-text-dark);
--color-input-background: #fafafa;
--color-input-toggle-background: #dedede;
--color-input-border: var(--color-secondary);
@@ -213,7 +213,7 @@
--color-shadow: #00000026;
--color-secondary-bg: #f4f4f4;
--color-expand-button: #d8efff;
- --color-placeholder-text: #aaa;
+ --color-placeholder-text: var(--color-text-light-3);
--color-editor-line-highlight: var(--color-primary-light-6);
--color-project-board-bg: var(--color-secondary-light-4);
--color-project-board-dark-label: #111111;
@@ -227,7 +227,7 @@
--color-nav-bg: #ffffff;
--color-nav-hover-bg: #ebebeb;
--color-nav-text: var(--color-text);
- --color-label-text: #232323;
+ --color-label-text: var(--color-text);
--color-label-bg: #cacaca5b;
--color-label-hover-bg: #cacacaa0;
--color-label-active-bg: #cacacaff;
diff --git a/web_src/js/bootstrap.js b/web_src/js/bootstrap.js
index e46c91e5e6..c0047b0ac2 100644
--- a/web_src/js/bootstrap.js
+++ b/web_src/js/bootstrap.js
@@ -1,5 +1,6 @@
// DO NOT IMPORT window.config HERE!
-// to make sure the error handler always works, we should never import `window.config`, because some user's custom template breaks it.
+// to make sure the error handler always works, we should never import `window.config`, because
+// some user's custom template breaks it.
// This sets up the URL prefix used in webpack's chunk loading.
// This file must be imported before any lazy-loading is being attempted.
@@ -26,29 +27,42 @@ export function showGlobalErrorMessage(msg) {
}
/**
- * @param {ErrorEvent} e
+ * @param {ErrorEvent|PromiseRejectionEvent} event - Event
+ * @param {string} event.message - Only present on ErrorEvent
+ * @param {string} event.error - Only present on ErrorEvent
+ * @param {string} event.type - Only present on ErrorEvent
+ * @param {string} event.filename - Only present on ErrorEvent
+ * @param {number} event.lineno - Only present on ErrorEvent
+ * @param {number} event.colno - Only present on ErrorEvent
+ * @param {string} event.reason - Only present on PromiseRejectionEvent
+ * @param {number} event.promise - Only present on PromiseRejectionEvent
*/
-function processWindowErrorEvent(e) {
- const err = e.error ?? e.reason;
+function processWindowErrorEvent({error, reason, message, type, filename, lineno, colno}) {
+ const err = error ?? reason;
const assetBaseUrl = String(new URL(__webpack_public_path__, window.location.origin));
+ const {runModeIsProd} = window.config ?? {};
- // error is likely from browser extension or inline script. Do not show these in production builds.
- if (!err.stack?.includes(assetBaseUrl) && window.config?.runModeIsProd) return;
-
- let message;
- if (e.type === 'unhandledrejection') {
- message = `JavaScript promise rejection: ${err.message}.`;
- } else {
- message = `JavaScript error: ${e.message} (${e.filename} @ ${e.lineno}:${e.colno}).`;
+ // `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likly a
+ // non-critical event from the browser. We log them but don't show them to users. Examples:
+ // - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
+ // - https://github.com/mozilla-mobile/firefox-ios/issues/10817
+ // - https://github.com/go-gitea/gitea/issues/20240
+ if (!err) {
+ if (message) console.error(new Error(message));
+ if (runModeIsProd) return;
}
- if (!e.error && e.lineno === 0 && e.colno === 0 && e.filename === '' && window.navigator.userAgent.includes('FxiOS/')) {
- // At the moment, Firefox (iOS) (10x) has an engine bug. See https://github.com/go-gitea/gitea/issues/20240
- // If a script inserts a newly created (and content changed) element into DOM, there will be a nonsense error event reporting: Script error: line 0, col 0.
- return; // ignore such nonsense error event
+ // If the error stack trace does not include the base URL of our script assets, it likely came
+ // from a browser extension or inline script. Do not show such errors in production.
+ if (err instanceof Error && !err.stack?.includes(assetBaseUrl) && runModeIsProd) {
+ return;
}
- showGlobalErrorMessage(`${message} Open browser console to see more details.`);
+ let msg = err?.message ?? message;
+ if (lineno) msg += ` (${filename} @ ${lineno}:${colno})`;
+ const dot = msg.endsWith('.') ? '' : '.';
+ const renderedType = type === 'unhandledrejection' ? 'promise rejection' : type;
+ showGlobalErrorMessage(`JavaScript ${renderedType}: ${msg}${dot} Open browser console to see more details.`);
}
function initGlobalErrorHandler() {
@@ -59,13 +73,14 @@ function initGlobalErrorHandler() {
if (!window.config) {
showGlobalErrorMessage(`Gitea JavaScript code couldn't run correctly, please check your custom templates`);
}
- // we added an event handler for window error at the very beginning of <script> of page head
- // the handler calls `_globalHandlerErrors.push` (array method) to record all errors occur before this init
- // then in this init, we can collect all error events and show them
+ // we added an event handler for window error at the very beginning of <script> of page head the
+ // handler calls `_globalHandlerErrors.push` (array method) to record all errors occur before
+ // this init then in this init, we can collect all error events and show them.
for (const e of window._globalHandlerErrors || []) {
processWindowErrorEvent(e);
}
- // then, change _globalHandlerErrors to an object with push method, to process further error events directly
+ // then, change _globalHandlerErrors to an object with push method, to process further error
+ // events directly
window._globalHandlerErrors = {_inited: true, push: (e) => processWindowErrorEvent(e)};
}
diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js
index cd0fc6d6a9..c53d43cbb2 100644
--- a/web_src/js/features/common-global.js
+++ b/web_src/js/features/common-global.js
@@ -11,7 +11,7 @@ import {htmlEscape} from 'escape-goat';
import {showTemporaryTooltip} from '../modules/tippy.js';
import {confirmModal} from './comp/ConfirmModal.js';
import {showErrorToast} from '../modules/toast.js';
-import {request, POST} from '../modules/fetch.js';
+import {request, POST, GET} from '../modules/fetch.js';
import '../htmx.js';
const {appUrl, appSubUrl, csrfToken, i18n} = window.config;
@@ -37,11 +37,10 @@ export function initHeadNavbarContentToggle() {
}
export function initFootLanguageMenu() {
- function linkLanguageAction() {
+ async function linkLanguageAction() {
const $this = $(this);
- $.get($this.data('url')).always(() => {
- window.location.reload();
- });
+ await GET($this.data('url'));
+ window.location.reload();
}
$('.language-menu a[lang]').on('click', linkLanguageAction);
@@ -92,19 +91,24 @@ async function fetchActionDoRequest(actionElem, url, opt) {
} else {
window.location.reload();
}
+ return;
} else if (resp.status >= 400 && resp.status < 500) {
const data = await resp.json();
// the code was quite messy, sometimes the backend uses "err", sometimes it uses "error", and even "user_error"
// but at the moment, as a new approach, we only use "errorMessage" here, backend can use JSONError() to respond.
- showErrorToast(data.errorMessage || `server error: ${resp.status}`);
+ if (data.errorMessage) {
+ showErrorToast(data.errorMessage, {useHtmlBody: data.renderFormat === 'html'});
+ } else {
+ showErrorToast(`server error: ${resp.status}`);
+ }
} else {
showErrorToast(`server error: ${resp.status}`);
}
} catch (e) {
console.error('error when doRequest', e);
- actionElem.classList.remove('is-loading', 'small-loading-icon');
- showErrorToast(i18n.network_error);
+ showErrorToast(`${i18n.network_error} ${e}`);
}
+ actionElem.classList.remove('is-loading', 'small-loading-icon');
}
async function formFetchAction(e) {
@@ -309,27 +313,26 @@ export function initGlobalLinkActions() {
dialog.modal({
closable: false,
- onApprove() {
+ onApprove: async () => {
if ($this.data('type') === 'form') {
$($this.data('form')).trigger('submit');
return;
}
-
- const postData = {
- _csrf: csrfToken,
- };
+ const postData = new FormData();
for (const [key, value] of Object.entries(dataArray)) {
if (key && key.startsWith('data')) {
- postData[key.slice(4)] = value;
+ postData.append(key.slice(4), value);
}
if (key === 'id') {
- postData['id'] = value;
+ postData.append('id', value);
}
}
- $.post($this.data('url'), postData).done((data) => {
+ const response = await POST($this.data('url'), {data: postData});
+ if (response.ok) {
+ const data = await response.json();
window.location.href = data.redirect;
- });
+ }
}
}).modal('show');
}
diff --git a/web_src/js/features/pull-view-file.js b/web_src/js/features/pull-view-file.js
index 90881ee989..2472e5a0bd 100644
--- a/web_src/js/features/pull-view-file.js
+++ b/web_src/js/features/pull-view-file.js
@@ -43,9 +43,11 @@ export function initViewedCheckboxListenerFor() {
// Mark the file as viewed visually - will especially change the background
if (this.checked) {
form.classList.add(viewedStyleClass);
+ checkbox.setAttribute('checked', '');
prReview.numberOfViewedFiles++;
} else {
form.classList.remove(viewedStyleClass);
+ checkbox.removeAttribute('checked');
prReview.numberOfViewedFiles--;
}
diff --git a/web_src/js/features/repo-commit.js b/web_src/js/features/repo-commit.js
index 7e2f6fa58e..f61ea08a42 100644
--- a/web_src/js/features/repo-commit.js
+++ b/web_src/js/features/repo-commit.js
@@ -1,7 +1,5 @@
import {createTippy} from '../modules/tippy.js';
import {toggleElem} from '../utils/dom.js';
-import {parseDom} from '../utils.js';
-import {POST} from '../modules/fetch.js';
export function initRepoEllipsisButton() {
for (const button of document.querySelectorAll('.js-toggle-commit-body')) {
@@ -14,47 +12,6 @@ export function initRepoEllipsisButton() {
}
}
-export async function initRepoCommitLastCommitLoader() {
- const entryMap = {};
-
- const entries = Array.from(document.querySelectorAll('table#repo-files-table tr.notready'), (el) => {
- const entryName = el.getAttribute('data-entryname');
- entryMap[entryName] = el;
- return entryName;
- });
-
- if (entries.length === 0) {
- return;
- }
-
- const lastCommitLoaderURL = document.querySelector('table#repo-files-table').getAttribute('data-last-commit-loader-url');
-
- if (entries.length > 200) {
- // For more than 200 entries, replace the entire table
- const response = await POST(lastCommitLoaderURL);
- const data = await response.text();
- document.querySelector('table#repo-files-table').outerHTML = data;
- return;
- }
-
- // For fewer entries, update individual rows
- const response = await POST(lastCommitLoaderURL, {data: {'f': entries}});
- const data = await response.text();
- const doc = parseDom(data, 'text/html');
- for (const row of doc.querySelectorAll('tr')) {
- if (row.className === 'commit-list') {
- document.querySelector('table#repo-files-table .commit-list')?.replaceWith(row);
- continue;
- }
- // there are other <tr> rows in response (eg: <tr class="has-parent">)
- // at the moment only the "data-entryname" rows should be processed
- const entryName = row.getAttribute('data-entryname');
- if (entryName) {
- entryMap[entryName]?.replaceWith(row);
- }
- }
-}
-
export function initCommitStatuses() {
for (const element of document.querySelectorAll('[data-tippy="commit-statuses"]')) {
const top = document.querySelector('.repository.file.list') || document.querySelector('.repository.diff');
diff --git a/web_src/js/features/repo-findfile.js b/web_src/js/features/repo-findfile.js
index 158732acc2..cb03d9e803 100644
--- a/web_src/js/features/repo-findfile.js
+++ b/web_src/js/features/repo-findfile.js
@@ -1,13 +1,11 @@
-import $ from 'jquery';
import {svg} from '../svg.js';
import {toggleElem} from '../utils/dom.js';
import {pathEscapeSegments} from '../utils/url.js';
-
-const {csrf} = window.config;
+import {GET} from '../modules/fetch.js';
const threshold = 50;
let files = [];
-let $repoFindFileInput, $repoFindFileTableBody, $repoFindFileNoResult;
+let repoFindFileInput, repoFindFileTableBody, repoFindFileNoResult;
// return the case-insensitive sub-match result as an array: [unmatched, matched, unmatched, matched, ...]
// res[even] is unmatched, res[odd] is matched, see unit tests for examples
@@ -74,46 +72,46 @@ export function filterRepoFilesWeighted(files, filter) {
}
function filterRepoFiles(filter) {
- const treeLink = $repoFindFileInput.attr('data-url-tree-link');
- $repoFindFileTableBody.empty();
+ const treeLink = repoFindFileInput.getAttribute('data-url-tree-link');
+ repoFindFileTableBody.innerHTML = '';
const filterResult = filterRepoFilesWeighted(files, filter);
- const tmplRow = `<tr><td><a></a></td></tr>`;
- toggleElem($repoFindFileNoResult, filterResult.length === 0);
+ toggleElem(repoFindFileNoResult, filterResult.length === 0);
for (const r of filterResult) {
- const $row = $(tmplRow);
- const $a = $row.find('a');
- $a.attr('href', `${treeLink}/${pathEscapeSegments(r.matchResult.join(''))}`);
- const $octiconFile = $(svg('octicon-file')).addClass('gt-mr-3');
- $a.append($octiconFile);
- // if the target file path is "abc/xyz", to search "bx", then the matchResult is ['a', 'b', 'c/', 'x', 'yz']
- // the matchResult[odd] is matched and highlighted to red.
- for (let j = 0; j < r.matchResult.length; j++) {
- if (!r.matchResult[j]) continue;
- const $span = $('<span>').text(r.matchResult[j]);
- if (j % 2 === 1) $span.addClass('ui text red');
- $a.append($span);
+ const row = document.createElement('tr');
+ const cell = document.createElement('td');
+ const a = document.createElement('a');
+ a.setAttribute('href', `${treeLink}/${pathEscapeSegments(r.matchResult.join(''))}`);
+ a.innerHTML = svg('octicon-file', 16, 'gt-mr-3');
+ row.append(cell);
+ cell.append(a);
+ for (const [index, part] of r.matchResult.entries()) {
+ const span = document.createElement('span');
+ // safely escape by using textContent
+ span.textContent = part;
+ // if the target file path is "abc/xyz", to search "bx", then the matchResult is ['a', 'b', 'c/', 'x', 'yz']
+ // the matchResult[odd] is matched and highlighted to red.
+ if (index % 2 === 1) span.classList.add('ui', 'text', 'red');
+ a.append(span);
}
- $repoFindFileTableBody.append($row);
+ repoFindFileTableBody.append(row);
}
}
async function loadRepoFiles() {
- files = await $.ajax({
- url: $repoFindFileInput.attr('data-url-data-link'),
- headers: {'X-Csrf-Token': csrf}
- });
- filterRepoFiles($repoFindFileInput.val());
+ const response = await GET(repoFindFileInput.getAttribute('data-url-data-link'));
+ files = await response.json();
+ filterRepoFiles(repoFindFileInput.value);
}
export function initFindFileInRepo() {
- $repoFindFileInput = $('#repo-file-find-input');
- if (!$repoFindFileInput.length) return;
+ repoFindFileInput = document.getElementById('repo-file-find-input');
+ if (!repoFindFileInput) return;
- $repoFindFileTableBody = $('#repo-find-file-table tbody');
- $repoFindFileNoResult = $('#repo-find-file-no-result');
- $repoFindFileInput.on('input', () => filterRepoFiles($repoFindFileInput.val()));
+ repoFindFileTableBody = document.querySelector('#repo-find-file-table tbody');
+ repoFindFileNoResult = document.getElementById('repo-find-file-no-result');
+ repoFindFileInput.addEventListener('input', () => filterRepoFiles(repoFindFileInput.value));
loadRepoFiles();
}
diff --git a/web_src/js/features/repo-home.js b/web_src/js/features/repo-home.js
index 3603fae2e9..bbba7b103e 100644
--- a/web_src/js/features/repo-home.js
+++ b/web_src/js/features/repo-home.js
@@ -1,8 +1,9 @@
import $ from 'jquery';
import {stripTags} from '../utils.js';
import {hideElem, showElem} from '../utils/dom.js';
+import {POST} from '../modules/fetch.js';
-const {appSubUrl, csrfToken} = window.config;
+const {appSubUrl} = window.config;
export function initRepoTopicBar() {
const mgrBtn = $('#manage_topic');
@@ -30,50 +31,50 @@ export function initRepoTopicBar() {
mgrBtn.focus();
});
- saveBtn.on('click', () => {
+ saveBtn.on('click', async () => {
const topics = $('input[name=topics]').val();
- $.post(saveBtn.attr('data-link'), {
- _csrf: csrfToken,
- topics
- }, (_data, _textStatus, xhr) => {
- if (xhr.responseJSON.status === 'ok') {
+ const data = new FormData();
+ data.append('topics', topics);
+
+ const response = await POST(saveBtn.attr('data-link'), {data});
+
+ if (response.ok) {
+ const responseData = await response.json();
+ if (responseData.status === 'ok') {
viewDiv.children('.topic').remove();
if (topics.length) {
const topicArray = topics.split(',');
topicArray.sort();
- for (let i = 0; i < topicArray.length; i++) {
+ for (const topic of topicArray) {
const link = $('<a class="ui repo-topic large label topic gt-m-0"></a>');
- link.attr('href', `${appSubUrl}/explore/repos?q=${encodeURIComponent(topicArray[i])}&topic=1`);
- link.text(topicArray[i]);
+ link.attr('href', `${appSubUrl}/explore/repos?q=${encodeURIComponent(topic)}&topic=1`);
+ link.text(topic);
link.insertBefore(mgrBtn); // insert all new topics before manage button
}
}
hideElem(editDiv);
showElem(viewDiv);
}
- }).fail((xhr) => {
- if (xhr.status === 422) {
- if (xhr.responseJSON.invalidTopics.length > 0) {
- topicPrompts.formatPrompt = xhr.responseJSON.message;
-
- const {invalidTopics} = xhr.responseJSON;
- const topicLabels = topicDropdown.children('a.ui.label');
-
- for (const [index, value] of topics.split(',').entries()) {
- for (let i = 0; i < invalidTopics.length; i++) {
- if (invalidTopics[i] === value) {
- topicLabels.eq(index).removeClass('green').addClass('red');
- }
- }
+ } else if (response.status === 422) {
+ const responseData = await response.json();
+ if (responseData.invalidTopics.length > 0) {
+ topicPrompts.formatPrompt = responseData.message;
+
+ const {invalidTopics} = responseData;
+ const topicLabels = topicDropdown.children('a.ui.label');
+ for (const [index, value] of topics.split(',').entries()) {
+ if (invalidTopics.includes(value)) {
+ topicLabels.eq(index).removeClass('green').addClass('red');
}
- } else {
- topicPrompts.countPrompt = xhr.responseJSON.message;
}
+ } else {
+ topicPrompts.countPrompt = responseData.message;
}
- }).always(() => {
- topicForm.form('validate form');
- });
+ }
+
+ // Always validate the form
+ topicForm.form('validate form');
});
topicDropdown.dropdown({
diff --git a/web_src/js/features/repo-search.js b/web_src/js/features/repo-search.js
new file mode 100644
index 0000000000..185f6119d9
--- /dev/null
+++ b/web_src/js/features/repo-search.js
@@ -0,0 +1,22 @@
+export function initRepositorySearch() {
+ const repositorySearchForm = document.querySelector('#repo-search-form');
+ if (!repositorySearchForm) return;
+
+ repositorySearchForm.addEventListener('change', (e) => {
+ e.preventDefault();
+
+ const formData = new FormData(repositorySearchForm);
+ const params = new URLSearchParams(formData);
+
+ if (e.target.name === 'clear-filter') {
+ params.delete('archived');
+ params.delete('fork');
+ params.delete('mirror');
+ params.delete('template');
+ params.delete('private');
+ }
+
+ params.delete('clear-filter');
+ window.location.search = params.toString();
+ });
+}
diff --git a/web_src/js/index.js b/web_src/js/index.js
index b7f3ba99a0..abf0d469d1 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -33,11 +33,7 @@ import {
initRepoPullRequestAllowMaintainerEdit,
initRepoPullRequestReview, initRepoIssueSidebarList, initArchivedLabelHandler,
} from './features/repo-issue.js';
-import {
- initRepoEllipsisButton,
- initRepoCommitLastCommitLoader,
- initCommitStatuses,
-} from './features/repo-commit.js';
+import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.js';
import {
initFootLanguageMenu,
initGlobalButtonClickOnEnter,
@@ -88,6 +84,7 @@ import {initRepoCodeFrequency} from './features/code-frequency.js';
import {initRepoRecentCommits} from './features/recent-commits.js';
import {initRepoDiffCommitBranchesAndTags} from './features/repo-diff-commit.js';
import {initDirAuto} from './modules/dirauto.js';
+import {initRepositorySearch} from './features/repo-search.js';
// Init Gitea's Fomantic settings
initGiteaFomantic();
@@ -148,7 +145,6 @@ onDomReady(() => {
initRepoCommentForm();
initRepoEllipsisButton();
initRepoDiffCommitBranchesAndTags();
- initRepoCommitLastCommitLoader();
initRepoEditor();
initRepoGraphGit();
initRepoIssueContentHistory();
@@ -175,6 +171,7 @@ onDomReady(() => {
initRepoWikiForm();
initRepository();
initRepositoryActionView();
+ initRepositorySearch();
initRepoContributors();
initRepoCodeFrequency();
initRepoRecentCommits();
diff --git a/web_src/js/modules/toast.js b/web_src/js/modules/toast.js
index fa075aed48..d64359799c 100644
--- a/web_src/js/modules/toast.js
+++ b/web_src/js/modules/toast.js
@@ -21,13 +21,12 @@ const levels = {
};
// See https://github.com/apvarun/toastify-js#api for options
-function showToast(message, level, {gravity, position, duration, ...other} = {}) {
+function showToast(message, level, {gravity, position, duration, useHtmlBody, ...other} = {}) {
const {icon, background, duration: levelDuration} = levels[level ?? 'info'];
-
const toast = Toastify({
text: `
<div class='toast-icon'>${svg(icon)}</div>
- <div class='toast-body'>${htmlEscape(message)}</div>
+ <div class='toast-body'>${useHtmlBody ? message : htmlEscape(message)}</div>
<button class='toast-close'>${svg('octicon-x')}</button>
`,
escapeMarkup: false,
diff --git a/web_src/js/webcomponents/GiteaOriginUrl.js b/web_src/js/webcomponents/GiteaOriginUrl.js
index 5d71d95c60..6e6f84d739 100644
--- a/web_src/js/webcomponents/GiteaOriginUrl.js
+++ b/web_src/js/webcomponents/GiteaOriginUrl.js
@@ -1,7 +1,8 @@
-// Convert an absolute or relative URL to an absolute URL with the current origin
+// Convert an absolute or relative URL to an absolute URL with the current origin. It only
+// processes absolute HTTP/HTTPS URLs or relative URLs like '/xxx' or '//host/xxx'.
+// NOTE: Keep this function in sync with clone_script.tmpl
export function toOriginUrl(urlStr) {
try {
- // only process absolute HTTP/HTTPS URL or relative URLs ('/xxx' or '//host/xxx')
if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) {
const {origin, protocol, hostname, port} = window.location;
const url = new URL(urlStr, origin);