From 994920c677b04a720726d982e4d6212664b82a43 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 15 Apr 2024 10:24:36 +0200 Subject: [PATCH 01/59] Kill all gitea processes before air build (#30477) So it happened to me multiple times that air leaves zombie processes after termination. I think ultimately it's some kind of bug in air, but we can work around. The change in the delay is unrelated to the zombie processes but seems to help a bit with duplicate changes resulting in duplicate `make generate` as seen here: Screenshot 2024-04-14 at 17 05 47 --------- Co-authored-by: delvh --- .air.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.air.toml b/.air.toml index de97bd8b29..3740c4d4aa 100644 --- a/.air.toml +++ b/.air.toml @@ -2,9 +2,10 @@ root = "." tmp_dir = ".air" [build] +pre_cmd = ["killall -9 gitea 2>/dev/null || true"] # kill off potential zombie processes from previous runs cmd = "make --no-print-directory backend" bin = "gitea" -delay = 1000 +delay = 2000 include_ext = ["go", "tmpl"] include_file = ["main.go"] include_dir = ["cmd", "models", "modules", "options", "routers", "services"] From 1508a85f6235814271ea927d651bcbcd8c9f5f18 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 15 Apr 2024 10:49:48 +0200 Subject: [PATCH 02/59] Fix overflow on issue dependency (#30484) Small tweak here to prevent this and likely other events from overflowing in the timeline: Screenshot 2024-04-14 at 22 53 17 Co-authored-by: Giteabot --- web_src/css/repo.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 887789115e..0f6bf482b5 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -1063,6 +1063,12 @@ td .commit-summary { margin-left: 15px; } +.repository.view.issue .comment-list .event .detail .text { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + .repository.view.issue .comment-list .event .segments { box-shadow: none; } From c63060b130d34e3f03f28f4dccbf04d381a95c17 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 15 Apr 2024 22:11:07 +0800 Subject: [PATCH 03/59] Fix code owners will not be mentioned when a pull request comes from a forked repository (#30476) Fix #30277 Caused by #29783 --- services/issue/pull.go | 8 ++++---- tests/integration/pull_create_test.go | 25 +++++++++++++++++++++++++ tests/integration/pull_review_test.go | 10 +++++++++- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/services/issue/pull.go b/services/issue/pull.go index b7b63a7024..4a0009e82f 100644 --- a/services/issue/pull.go +++ b/services/issue/pull.go @@ -51,14 +51,14 @@ func PullRequestCodeOwnersReview(ctx context.Context, issue *issues_model.Issue, return nil, err } - if pr.HeadRepo.IsFork { - return nil, nil - } - if err := pr.LoadBaseRepo(ctx); err != nil { return nil, err } + if pr.BaseRepo.IsFork { + return nil, nil + } + repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { return nil, err diff --git a/tests/integration/pull_create_test.go b/tests/integration/pull_create_test.go index 029ea65d71..609bd73fd5 100644 --- a/tests/integration/pull_create_test.go +++ b/tests/integration/pull_create_test.go @@ -4,6 +4,7 @@ package integration import ( + "fmt" "net/http" "net/http/httptest" "net/url" @@ -57,6 +58,30 @@ func testPullCreate(t *testing.T, session *TestSession, user, repo string, toSel return resp } +func testPullCreateDirectly(t *testing.T, session *TestSession, baseRepoOwner, baseRepoName, baseBranch, headRepoOwner, headRepoName, headBranch, title string) *httptest.ResponseRecorder { + headCompare := headBranch + if headRepoOwner != "" { + if headRepoName != "" { + headCompare = fmt.Sprintf("%s/%s:%s", headRepoOwner, headRepoName, headBranch) + } else { + headCompare = fmt.Sprintf("%s:%s", headRepoOwner, headBranch) + } + } + req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/compare/%s...%s", baseRepoOwner, baseRepoName, baseBranch, headCompare)) + resp := session.MakeRequest(t, req, http.StatusOK) + + // Submit the form for creating the pull + htmlDoc := NewHTMLParser(t, resp.Body) + link, exists := htmlDoc.doc.Find("form.ui.form").Attr("action") + assert.True(t, exists, "The template has changed") + req = NewRequestWithValues(t, "POST", link, map[string]string{ + "_csrf": htmlDoc.GetCSRF(), + "title": title, + }) + resp = session.MakeRequest(t, req, http.StatusOK) + return resp +} + func TestPullCreate(t *testing.T) { onGiteaRun(t, func(t *testing.T, u *url.URL) { session := loginUser(t, "user1") diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go index 9a5877697c..2d8b3cb4ab 100644 --- a/tests/integration/pull_review_test.go +++ b/tests/integration/pull_review_test.go @@ -161,10 +161,18 @@ func TestPullView_CodeOwner(t *testing.T) { assert.NoError(t, err) session := loginUser(t, "user5") - testPullCreate(t, session, "user5", "test_codeowner", true, forkedRepo.DefaultBranch, "codeowner-basebranch-forked", "Test Pull Request2") + + // create a pull request on the forked repository, code reviewers should not be mentioned + testPullCreateDirectly(t, session, "user5", "test_codeowner", forkedRepo.DefaultBranch, "", "", "codeowner-basebranch-forked", "Test Pull Request on Forked Repository") pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: forkedRepo.ID, HeadBranch: "codeowner-basebranch-forked"}) unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 8}) + + // create a pull request to base repository, code reviewers should be mentioned + testPullCreateDirectly(t, session, repo.OwnerName, repo.Name, repo.DefaultBranch, forkedRepo.OwnerName, forkedRepo.Name, "codeowner-basebranch-forked", "Test Pull Request3") + + pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadRepoID: forkedRepo.ID, HeadBranch: "codeowner-basebranch-forked"}) + unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 8}) }) }) } From 2dc7e9e5fe66a361021e41046f7a88e61a45300b Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 15 Apr 2024 19:20:32 +0200 Subject: [PATCH 04/59] Fix button color on red and green buttons (#30500) Previously these colors were provided by fomantic css. I missed them. Fixes: https://github.com/go-gitea/gitea/issues/30499 Regressed by: https://github.com/go-gitea/gitea/pull/30475 --- web_src/css/modules/button.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_src/css/modules/button.css b/web_src/css/modules/button.css index 47f55df7fa..87b9ddf292 100644 --- a/web_src/css/modules/button.css +++ b/web_src/css/modules/button.css @@ -249,6 +249,7 @@ .ui.red.button, .ui.red.buttons .button { + color: var(--color-white); background: var(--color-red); } @@ -283,6 +284,7 @@ .ui.green.button, .ui.green.buttons .button { + color: var(--color-white); background: var(--color-green); } From 3b40ebf895307a705738df3c5aba31843f0be74d Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 15 Apr 2024 20:22:53 +0200 Subject: [PATCH 05/59] Remove active border on pointing menu (#30486) It looks better when these menus don't flash a border-bottom on click. --- web_src/css/modules/menu.css | 1 - 1 file changed, 1 deletion(-) diff --git a/web_src/css/modules/menu.css b/web_src/css/modules/menu.css index 2581d8fab2..a392ffb5e9 100644 --- a/web_src/css/modules/menu.css +++ b/web_src/css/modules/menu.css @@ -588,7 +588,6 @@ .ui.secondary.pointing.menu .dropdown.item:active, .ui.secondary.pointing.menu a.item:active { background-color: transparent; - border-color: var(--color-secondary); } .ui.secondary.pointing.menu .active.item { From 2c80421243ed1fd6f53c3e1a84c06648524f7c66 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Tue, 16 Apr 2024 04:08:31 +0900 Subject: [PATCH 06/59] Convert max file name length to 255 (#30489) Quick/Partly fix #29907 In Linux and MacOS, by default the max file name length is 255. In windows, it depends on the version and settings, and has no file name length limitation, but has path length limitation. By default it is 260, considering path length is longer than filename, so I think it is ok to do this. For Windows, see https://learn.microsoft.com/windows/win32/fileio/maximum-file-path-limitation?tabs=registry For Linux, see https://github.com/torvalds/linux/blob/master/include/uapi/linux/limits.h#L12-L13 For MacOS, see https://discussions.apple.com/thread/254788848?sortBy=best --- templates/repo/editor/edit.tmpl | 2 +- templates/repo/editor/upload.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/repo/editor/edit.tmpl b/templates/repo/editor/edit.tmpl index 46f82c47d4..d52e5a047a 100644 --- a/templates/repo/editor/edit.tmpl +++ b/templates/repo/editor/edit.tmpl @@ -15,7 +15,7 @@ {{range $i, $v := .TreeNames}} {{if eq $i $l}} - + {{svg "octicon-info"}} {{else}} {{$v}} diff --git a/templates/repo/editor/upload.tmpl b/templates/repo/editor/upload.tmpl index 0a7c49dae3..5725020406 100644 --- a/templates/repo/editor/upload.tmpl +++ b/templates/repo/editor/upload.tmpl @@ -13,7 +13,7 @@ {{range $i, $v := .TreeNames}} {{if eq $i $l}} - + {{svg "octicon-info"}} {{else}} {{$v}} From b9f69b4a4d1d6b5b1f94852f6dfcae41b30658ff Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 15 Apr 2024 21:46:52 +0200 Subject: [PATCH 07/59] Fix various overflows on actions view (#30344) Fix a number of text overflow issues in actions view and run list. Also improve mobile view of run list. Fixes: https://github.com/go-gitea/gitea/issues/30328 Screenshot 2024-04-08 at 23 10 16 Screenshot 2024-04-08 at 23 17 46 Screenshot 2024-04-08 at 23 49 05 Screenshot 2024-04-08 at 23 55 30 --- templates/repo/actions/runs_list.tmpl | 14 ++++++------- web_src/css/actions.css | 26 +++++++++++++++++++++++- web_src/js/components/RepoActionView.vue | 16 ++++++++++----- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/templates/repo/actions/runs_list.tmpl b/templates/repo/actions/runs_list.tmpl index ac5049cf56..20330b5d62 100644 --- a/templates/repo/actions/runs_list.tmpl +++ b/templates/repo/actions/runs_list.tmpl @@ -1,4 +1,4 @@ -
+
{{if not .Runs}}
{{svg "octicon-no-entry" 48}} @@ -28,14 +28,14 @@
{{if .RefLink}} - {{.PrettyRef}} + {{.PrettyRef}} {{else}} - {{.PrettyRef}} + {{.PrettyRef}} {{end}} -
-
-
{{svg "octicon-calendar" 16}}{{TimeSinceUnix .Updated ctx.Locale}}
-
{{svg "octicon-stopwatch" 16}}{{.Duration}}
+
+
{{svg "octicon-calendar" 16}}{{TimeSinceUnix .Updated ctx.Locale}}
+
{{svg "octicon-stopwatch" 16}}{{.Duration}}
+
{{end}} diff --git a/web_src/css/actions.css b/web_src/css/actions.css index 1d5bea2395..0ab09f537a 100644 --- a/web_src/css/actions.css +++ b/web_src/css/actions.css @@ -44,9 +44,10 @@ } .run-list-item-right { - flex: 0 0 min(20%, 130px); + width: 130px; display: flex; flex-direction: column; + flex-shrink: 0; gap: 3px; color: var(--color-text-light); } @@ -57,3 +58,26 @@ gap: .25rem; align-items: center; } + +.run-list .flex-item-trailing { + flex-wrap: nowrap; + width: 280px; + flex: 0 0 280px; +} + +.run-list-ref { + display: inline-block !important; +} + +@media (max-width: 767.98px) { + .run-list .flex-item-trailing { + flex-direction: column; + align-items: flex-end; + width: auto; + flex-basis: auto; + } + .run-list-item-right, + .run-list-ref { + max-width: 110px; + } +} diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 06c42f0b35..16ce3fc80d 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -377,7 +377,7 @@ export function initRepositoryActionView() { -
@@ -386,8 +386,8 @@ export function initRepositoryActionView() { {{ run.commit.shortSHA }} {{ run.commit.localePushedBy }} {{ run.commit.pusher.displayName }} - - {{ run.commit.branch.name }} + + {{ run.commit.branch.name }} @@ -426,8 +426,8 @@ export function initRepositoryActionView() {
-
-

+
+

{{ currentJob.title }}

@@ -503,6 +503,7 @@ export function initRepositoryActionView() { display: flex; align-items: center; justify-content: space-between; + gap: 8px; } .action-info-summary-title { @@ -513,6 +514,7 @@ export function initRepositoryActionView() { font-size: 20px; margin: 0 0 0 8px; flex: 1; + overflow-wrap: anywhere; } .action-commit-summary { @@ -728,6 +730,10 @@ export function initRepositoryActionView() { font-size: 12px; } +.job-info-header-left { + flex: 1; +} + .job-step-container { max-height: 100%; border-radius: 0 0 var(--border-radius) var(--border-radius); From 3b045ee165c8ba06c99c28d57b849fb53a502e84 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Tue, 16 Apr 2024 00:23:51 +0000 Subject: [PATCH 08/59] [skip ci] Updated translations via Crowdin --- options/locale/locale_ja-JP.ini | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 0edd6c5dd7..74ff775cc8 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -25,6 +25,7 @@ enable_javascript=このウェブサイトにはJavaScriptが必要です。 toc=目次 licenses=ライセンス return_to_gitea=Giteaに戻る +more_items=その他の項目 username=ユーザー名 email=メールアドレス @@ -1003,6 +1004,7 @@ fork_visibility_helper=フォークしたリポジトリの公開/非公開は fork_branch=フォークにクローンされるブランチ all_branches=すべてのブランチ fork_no_valid_owners=このリポジトリには有効なオーナーがいないため、フォークできません。 +fork.blocked_user=リポジトリのオーナーがあなたをブロックしているため、リポジトリをフォークできません。 use_template=このテンプレートを使用 open_with_editor=%s で開く download_zip=ZIPファイルをダウンロード @@ -1179,6 +1181,7 @@ watch=ウォッチ unstar=スター取消 star=スター fork=フォーク +action.blocked_user=リポジトリのオーナーがあなたをブロックしているため、アクションを実行できません。 download_archive=リポジトリをダウンロード more_operations=その他の操作 @@ -1427,6 +1430,8 @@ issues.new.assignees=担当者 issues.new.clear_assignees=担当者をクリア issues.new.no_assignees=担当者なし issues.new.no_reviewers=レビューアなし +issues.new.blocked_user=リポジトリのオーナーがあなたをブロックしているため、イシューを作成できません。 +issues.edit.blocked_user=投稿者またはリポジトリのオーナーがあなたをブロックしているため、内容を編集できません。 issues.choose.get_started=始める issues.choose.open_external_link=オープン issues.choose.blank=デフォルト @@ -1541,6 +1546,7 @@ issues.close_comment_issue=コメントしてクローズ issues.reopen_issue=再オープンする issues.reopen_comment_issue=コメントして再オープン issues.create_comment=コメントする +issues.comment.blocked_user=投稿者またはリポジトリのオーナーがあなたをブロックしているため、コメントの作成や編集はできません。 issues.closed_at=`がイシューをクローズ %[2]s` issues.reopened_at=`がイシューを再オープン %[2]s` issues.commit_ref_at=`がコミットでこのイシューを参照 %[2]s` @@ -1739,6 +1745,7 @@ compare.compare_head=比較 pulls.desc=プルリクエストとコードレビューの有効化。 pulls.new=新しいプルリクエスト +pulls.new.blocked_user=リポジトリのオーナーがあなたをブロックしているため、プルリクエストを作成できません。 pulls.view=プルリクエストを表示 pulls.compare_changes=新規プルリクエスト pulls.allow_edits_from_maintainers=メンテナーからの編集を許可する @@ -1960,6 +1967,7 @@ wiki.original_git_entry_tooltip=フレンドリーリンクを使用する代わ activity=アクティビティ activity.navbar.pulse=Pulse +activity.navbar.code_frequency=コード更新頻度 activity.navbar.contributors=貢献者 activity.navbar.recent_commits=最近のコミット activity.period.filter_label=期間: @@ -2080,6 +2088,8 @@ settings.branches.add_new_rule=新しいルールを追加 settings.advanced_settings=拡張設定 settings.wiki_desc=Wikiを有効にする settings.use_internal_wiki=ビルトインのWikiを使用する +settings.default_wiki_branch_name=デフォルトのWikiブランチ名 +settings.failed_to_change_default_wiki_branch=デフォルトのWikiブランチを変更できませんでした。 settings.use_external_wiki=外部のWikiを使用する settings.external_wiki_url=外部WikiのURL settings.external_wiki_url_error=外部WikiのURLが有効なURLではありません。 @@ -2110,6 +2120,9 @@ settings.pulls.default_allow_edits_from_maintainers=デフォルトでメンテ settings.releases_desc=リリースを有効にする settings.packages_desc=リポジトリパッケージレジストリを有効にする settings.projects_desc=プロジェクトを有効にする +settings.projects_mode_desc=プロジェクト モード (表示するプロジェクトの種類) +settings.projects_mode_repo=リポジトリのプロジェクトのみ +settings.projects_mode_owner=ユーザーや組織のプロジェクトのみ settings.projects_mode_all=すべてのプロジェクト settings.actions_desc=Actionsを有効にする settings.admin_settings=管理者用設定 @@ -2136,6 +2149,7 @@ settings.convert_fork_succeed=フォークを通常のリポジトリに変換 settings.transfer=オーナー移転 settings.transfer.rejected=リポジトリの移転は拒否されました。 settings.transfer.success=リポジトリの移転が成功しました。 +settings.transfer.blocked_user=新しいオーナーがあなたをブロックしているため、リポジトリを移転できません。 settings.transfer_abort=転送をキャンセル settings.transfer_abort_invalid=存在しないリポジトリの移転はキャンセルできません。 settings.transfer_abort_success=%s へのリポジトリ移転は正常にキャンセルされました。 @@ -2181,6 +2195,7 @@ settings.add_collaborator_success=共同作業者を追加しました。 settings.add_collaborator_inactive_user=アクティベートされていないユーザーを共同作業者として追加することはできません。 settings.add_collaborator_owner=共同作業者としてオーナーを追加することはできません。 settings.add_collaborator_duplicate=共同作業者として既にこのリポジトリに追加されています。 +settings.add_collaborator.blocked_user=共同作業者がリポジトリのオーナーによってブロックされているか、またはブロックしています。 settings.delete_collaborator=削除 settings.collaborator_deletion=共同作業者の削除 settings.collaborator_deletion_desc=共同作業者を削除し、このリポジトリへのアクセス権を取り消します。 続行しますか? @@ -2619,12 +2634,14 @@ find_file.no_matching=一致するファイルが見つかりません error.csv.too_large=このファイルは大きすぎるため表示できません。 error.csv.unexpected=このファイルは %d 行目の %d 文字目に予期しない文字が含まれているため表示できません。 error.csv.invalid_field_count=このファイルは %d 行目のフィールドの数が正しくないため表示できません。 +error.broken_git_hook=このリポジトリのGitフックが壊れているようです。 ドキュメントに従って修正し、その後いくつかのコミットをプッシュして状態を最新にしてください。 [graphs] component_loading=%sを読み込み中... component_loading_failed=%sを読み込めませんでした component_loading_info=少し時間がかかるかもしれません… component_failed_to_load=予期しないエラーが発生しました。 +code_frequency.what=コード更新頻度 contributors.what=実績 recent_commits.what=最近のコミット @@ -2753,6 +2770,7 @@ teams.invite.by=%s からの招待 teams.invite.description=下のボタンをクリックしてチームに参加してください。 [admin] +maintenance=メンテナンス dashboard=ダッシュボード self_check=セルフチェック identity_access=アイデンティティとアクセス @@ -2776,6 +2794,7 @@ settings=管理設定 dashboard.new_version_hint=Gitea %s が入手可能になりました。 現在実行しているのは %s です。 詳細は ブログ を確認してください。 dashboard.statistic=サマリー +dashboard.maintenance_operations=メンテナンス操作 dashboard.system_status=システム状況 dashboard.operation_name=操作の名称 dashboard.operation_switch=切り替え @@ -3282,6 +3301,7 @@ notices.op=操作 notices.delete_success=システム通知を削除しました。 self_check.no_problem_found=今のところ問題は見つかっていません。 +self_check.startup_warnings=起動時の警告: self_check.database_collation_mismatch=データベースに想定される照合順序: %s self_check.database_collation_case_insensitive=データベースは照合順序 %s を使用しており、大文字小文字を区別しません。 Giteaはその照合順序でも動作するかもしれませんが、まれに期待どおり動作しないケースがあるかもしれません。 self_check.database_inconsistent_collation_columns=データベースは照合順序 %s を使用していますが、以下のカラムはそれと一致しない照合順序を使用しており、予期せぬ問題を引き起こす可能性があります。 From c70e442ce4b99e2a1f1bf216afcfa1ad78d1925a Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Tue, 16 Apr 2024 11:45:04 +0800 Subject: [PATCH 09/59] feat(api): implement branch/commit comparison API (#30349) - Add new `Compare` struct to represent comparison between two commits - Introduce new API endpoint `/compare/*` to get commit comparison information - Create new file `repo_compare.go` with the `Compare` struct definition - Add new file `compare.go` in `routers/api/v1/repo` to handle comparison logic - Add new file `compare.go` in `routers/common` to define `CompareInfo` struct - Refactor `ParseCompareInfo` function to use `common.CompareInfo` struct - Update Swagger documentation to include the new API endpoint for commit comparison - Remove duplicate `CompareInfo` struct from `routers/web/repo/compare.go` - Adjust base path in Swagger template to be relative (`/api/v1`) GitHub API https://docs.github.com/en/rest/commits/commits?apiVersion=2022-11-28#compare-two-commits --------- Signed-off-by: Bo-Yi Wu Co-authored-by: Lunny Xiao --- modules/structs/repo_compare.go | 10 +++ routers/api/v1/api.go | 2 + routers/api/v1/repo/compare.go | 99 ++++++++++++++++++++++ routers/api/v1/swagger/repo.go | 6 ++ routers/common/compare.go | 21 +++++ routers/web/repo/compare.go | 18 +--- templates/swagger/v1_json.tmpl | 70 +++++++++++++++ tests/integration/api_repo_compare_test.go | 38 +++++++++ 8 files changed, 250 insertions(+), 14 deletions(-) create mode 100644 modules/structs/repo_compare.go create mode 100644 routers/api/v1/repo/compare.go create mode 100644 routers/common/compare.go create mode 100644 tests/integration/api_repo_compare_test.go diff --git a/modules/structs/repo_compare.go b/modules/structs/repo_compare.go new file mode 100644 index 0000000000..8a12498705 --- /dev/null +++ b/modules/structs/repo_compare.go @@ -0,0 +1,10 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +// Compare represents a comparison between two commits. +type Compare struct { + TotalCommits int `json:"total_commits"` // Total number of commits in the comparison. + Commits []*Commit `json:"commits"` // List of commits in the comparison. +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e870378c4b..1fc7682966 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1066,6 +1066,8 @@ func Routes() *web.Route { m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate) m.Group("/{username}/{reponame}", func() { + m.Get("/compare/*", reqRepoReader(unit.TypeCode), repo.CompareDiff) + m.Combo("").Get(reqAnyRepoReader(), repo.Get). Delete(reqToken(), reqOwner(), repo.Delete). Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit) diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go new file mode 100644 index 0000000000..549b9b7fa9 --- /dev/null +++ b/routers/api/v1/repo/compare.go @@ -0,0 +1,99 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repo + +import ( + "net/http" + "strings" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/gitrepo" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/convert" +) + +// CompareDiff compare two branches or commits +func CompareDiff(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/compare/{basehead} Get commit comparison information + // --- + // summary: Get commit comparison information + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: basehead + // in: path + // description: compare two branches or commits + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/Compare" + // "404": + // "$ref": "#/responses/notFound" + + if ctx.Repo.GitRepo == nil { + gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository) + if err != nil { + ctx.Error(http.StatusInternalServerError, "OpenRepository", err) + return + } + ctx.Repo.GitRepo = gitRepo + defer gitRepo.Close() + } + + infoPath := ctx.Params("*") + infos := []string{ctx.Repo.Repository.DefaultBranch, ctx.Repo.Repository.DefaultBranch} + if infoPath != "" { + infos = strings.SplitN(infoPath, "...", 2) + if len(infos) != 2 { + if infos = strings.SplitN(infoPath, "..", 2); len(infos) != 2 { + infos = []string{ctx.Repo.Repository.DefaultBranch, infoPath} + } + } + } + + _, _, headGitRepo, ci, _, _ := parseCompareInfo(ctx, api.CreatePullRequestOption{ + Base: infos[0], + Head: infos[1], + }) + if ctx.Written() { + return + } + defer headGitRepo.Close() + + verification := ctx.FormString("verification") == "" || ctx.FormBool("verification") + files := ctx.FormString("files") == "" || ctx.FormBool("files") + + apiCommits := make([]*api.Commit, 0, len(ci.Commits)) + userCache := make(map[string]*user_model.User) + for i := 0; i < len(ci.Commits); i++ { + apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, ci.Commits[i], userCache, + convert.ToCommitOptions{ + Stat: true, + Verification: verification, + Files: files, + }) + if err != nil { + ctx.ServerError("toCommit", err) + return + } + apiCommits = append(apiCommits, apiCommit) + } + + ctx.JSON(http.StatusOK, &api.Compare{ + TotalCommits: len(ci.Commits), + Commits: apiCommits, + }) +} diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index 3e23aa4d5a..c3219f28d6 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -414,3 +414,9 @@ type swaggerRepoNewIssuePinsAllowed struct { // in:body Body api.NewIssuePinsAllowed `json:"body"` } + +// swagger:response Compare +type swaggerCompare struct { + // in:body + Body api.Compare `json:"body"` +} diff --git a/routers/common/compare.go b/routers/common/compare.go new file mode 100644 index 0000000000..4d1cc2f0d8 --- /dev/null +++ b/routers/common/compare.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package common + +import ( + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" +) + +// CompareInfo represents the collected results from ParseCompareInfo +type CompareInfo struct { + HeadUser *user_model.User + HeadRepo *repo_model.Repository + HeadGitRepo *git.Repository + CompareInfo *git.CompareInfo + BaseBranch string + HeadBranch string + DirectComparison bool +} diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index cfb0e859bd..035a92f228 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -35,6 +35,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context/upload" "code.gitea.io/gitea/services/gitdiff" @@ -185,21 +186,10 @@ func setCsvCompareContext(ctx *context.Context) { } } -// CompareInfo represents the collected results from ParseCompareInfo -type CompareInfo struct { - HeadUser *user_model.User - HeadRepo *repo_model.Repository - HeadGitRepo *git.Repository - CompareInfo *git.CompareInfo - BaseBranch string - HeadBranch string - DirectComparison bool -} - // ParseCompareInfo parse compare info between two commit for preparing comparing references -func ParseCompareInfo(ctx *context.Context) *CompareInfo { +func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { baseRepo := ctx.Repo.Repository - ci := &CompareInfo{} + ci := &common.CompareInfo{} fileOnly := ctx.FormBool("file-only") @@ -576,7 +566,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { // PrepareCompareDiff renders compare diff page func PrepareCompareDiff( ctx *context.Context, - ci *CompareInfo, + ci *common.CompareInfo, whitespaceBehavior git.TrustedCmdArgs, ) bool { var ( diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index b5677c77e0..254b7daf17 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -5340,6 +5340,51 @@ } } }, + "/repos/{owner}/{repo}/compare/{basehead}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Get", + "commit", + "comparison" + ], + "summary": "Get commit comparison information", + "operationId": "information", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "compare two branches or commits", + "name": "basehead", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/Compare" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, "/repos/{owner}/{repo}/contents": { "get": { "produces": [ @@ -18717,6 +18762,25 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "Compare": { + "type": "object", + "title": "Compare represents a comparison between two commits.", + "properties": { + "commits": { + "type": "array", + "items": { + "$ref": "#/definitions/Commit" + }, + "x-go-name": "Commits" + }, + "total_commits": { + "type": "integer", + "format": "int64", + "x-go-name": "TotalCommits" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "ContentsResponse": { "description": "ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content", "type": "object", @@ -24678,6 +24742,12 @@ } } }, + "Compare": { + "description": "", + "schema": { + "$ref": "#/definitions/Compare" + } + }, "ContentsListResponse": { "description": "ContentsListResponse", "schema": { diff --git a/tests/integration/api_repo_compare_test.go b/tests/integration/api_repo_compare_test.go new file mode 100644 index 0000000000..f3188eb49f --- /dev/null +++ b/tests/integration/api_repo_compare_test.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "net/http" + "testing" + + auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPICompareBranches(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + // Login as User2. + session := loginUser(t, user.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + + repoName := "repo20" + + req := NewRequestf(t, "GET", "/api/v1/repos/user2/%s/compare/add-csv...remove-files-b", repoName). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusOK) + + var apiResp *api.Compare + DecodeJSON(t, resp, &apiResp) + + assert.Equal(t, 2, apiResp.TotalCommits) + assert.Len(t, apiResp.Commits, 2) +} From cf9061f44a439aa7775e301a7467dbda22a06eaa Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Tue, 16 Apr 2024 14:13:00 +0900 Subject: [PATCH 10/59] Fix empty field `login_name` in API response JSON when creating user (#30511) Fix #30508 ps: if `sourceID` is not set, `LoginName` will be ignored --- routers/api/v1/admin/user.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 87a5b28fad..be907805d6 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -30,7 +30,7 @@ import ( user_service "code.gitea.io/gitea/services/user" ) -func parseAuthSource(ctx *context.APIContext, u *user_model.User, sourceID int64, loginName string) { +func parseAuthSource(ctx *context.APIContext, u *user_model.User, sourceID int64) { if sourceID == 0 { return } @@ -47,7 +47,6 @@ func parseAuthSource(ctx *context.APIContext, u *user_model.User, sourceID int64 u.LoginType = source.Type u.LoginSource = source.ID - u.LoginName = loginName } // CreateUser create a user @@ -83,12 +82,13 @@ func CreateUser(ctx *context.APIContext) { Passwd: form.Password, MustChangePassword: true, LoginType: auth.Plain, + LoginName: form.LoginName, } if form.MustChangePassword != nil { u.MustChangePassword = *form.MustChangePassword } - parseAuthSource(ctx, u, form.SourceID, form.LoginName) + parseAuthSource(ctx, u, form.SourceID) if ctx.Written() { return } From 6ba0c371c21237376c292ee92ec067b4a1ef1218 Mon Sep 17 00:00:00 2001 From: SimonErm <33630884+SimonErm@users.noreply.github.com> Date: Tue, 16 Apr 2024 07:41:39 +0200 Subject: [PATCH 11/59] Allow `preferred_username` as username source for OIDC (#30454) This PR adds the preferred_username claim as a possible username source for the oauth2_client. Closes #21518 --- custom/conf/app.example.ini | 3 ++- docs/content/administration/config-cheat-sheet.en-us.md | 5 +++-- modules/setting/oauth2.go | 4 +++- routers/web/auth/auth.go | 7 +++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 918252044b..32b51fd7c6 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1553,8 +1553,9 @@ LEVEL = Info ;; The source of the username for new oauth2 accounts: ;; userid = use the userid / sub attribute ;; nickname = use the nickname attribute +;; preferred_username = use the preferred_username attribute ;; email = use the username part of the email attribute -;; Note: `nickname` and `email` options will normalize input strings using the following criteria: +;; Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria: ;; - diacritics are removed ;; - the characters in the set `['´\x60]` are removed ;; - the characters in the set `[\s~+]` are replaced with `-` diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index 9de7511964..ff8bcb066c 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -608,9 +608,10 @@ And the following unique queues: - `ENABLE_AUTO_REGISTRATION`: **false**: Automatically create user accounts for new oauth2 users. - `USERNAME`: **nickname**: The source of the username for new oauth2 accounts: - `userid` - use the userid / sub attribute - - `nickname` - use the nickname attribute + - `nickname` - use the nickname + - `preferred_username` - use the preferred_username - `email` - use the username part of the email attribute - - Note: `nickname` and `email` options will normalize input strings using the following criteria: + - Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria: - diacritics are removed - the characters in the set `['´\x60]` are removed - the characters in the set `[\s~+]` are replaced with `-` diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go index 830472db32..6930197b22 100644 --- a/modules/setting/oauth2.go +++ b/modules/setting/oauth2.go @@ -22,11 +22,13 @@ const ( OAuth2UsernameNickname OAuth2UsernameType = "nickname" // OAuth2UsernameEmail username of oauth2 email field will be used as gitea name OAuth2UsernameEmail OAuth2UsernameType = "email" + // OAuth2UsernameEmail username of oauth2 preferred_username field will be used as gitea name + OAuth2UsernamePreferredUsername OAuth2UsernameType = "preferred_username" ) func (username OAuth2UsernameType) isValid() bool { switch username { - case OAuth2UsernameUserid, OAuth2UsernameNickname, OAuth2UsernameEmail: + case OAuth2UsernameUserid, OAuth2UsernameNickname, OAuth2UsernameEmail, OAuth2UsernamePreferredUsername: return true } return false diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go index 8b5cd986b8..9ef32ebdb1 100644 --- a/routers/web/auth/auth.go +++ b/routers/web/auth/auth.go @@ -386,6 +386,13 @@ func getUserName(gothUser *goth.User) (string, error) { switch setting.OAuth2Client.Username { case setting.OAuth2UsernameEmail: return user_model.NormalizeUserName(strings.Split(gothUser.Email, "@")[0]) + case setting.OAuth2UsernamePreferredUsername: + preferredUsername, exists := gothUser.RawData["preferred_username"] + if exists { + return user_model.NormalizeUserName(preferredUsername.(string)) + } else { + return "", fmt.Errorf("preferred_username is missing in received user data but configured as username source for user_id %q. Check if OPENID_CONNECT_SCOPES contains profile", gothUser.UserID) + } case setting.OAuth2UsernameNickname: return user_model.NormalizeUserName(gothUser.NickName) default: // OAuth2UsernameUserid From 58b204b813cd3a97db904d889d552e64a7e398ff Mon Sep 17 00:00:00 2001 From: Tobias Balle-Petersen Date: Tue, 16 Apr 2024 08:08:48 +0200 Subject: [PATCH 12/59] Update API to return 'source_id' for users (#29718) Using the API, a user's _source_id_ can be set in the _CreateUserOption_ model, but the field is not returned in the _User_ model. This PR updates the _User_ model to include the field _source_id_ (The ID of the Authentication Source). --- modules/structs/user.go | 2 ++ services/convert/user.go | 1 + templates/swagger/v1_json.tmpl | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/modules/structs/user.go b/modules/structs/user.go index 21ecc1479e..ca6ab79944 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -20,6 +20,8 @@ type User struct { // the user's authentication sign-in name. // default: empty LoginName string `json:"login_name"` + // The ID of the user's Authentication Source + SourceID int64 `json:"source_id"` // the user's full name FullName string `json:"full_name"` // swagger:strfmt email diff --git a/services/convert/user.go b/services/convert/user.go index 3521dd2f90..1a2733d91e 100644 --- a/services/convert/user.go +++ b/services/convert/user.go @@ -75,6 +75,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap if authed { result.IsAdmin = user.IsAdmin result.LoginName = user.LoginName + result.SourceID = user.LoginSource result.LastLogin = user.LastLoginUnix.AsTime() result.Language = user.Language result.IsActive = user.IsActive diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 254b7daf17..532b8880bc 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -24260,6 +24260,12 @@ "type": "boolean", "x-go-name": "Restricted" }, + "source_id": { + "description": "The ID of the user's Authentication Source", + "type": "integer", + "format": "int64", + "x-go-name": "SourceID" + }, "starred_repos_count": { "type": "integer", "format": "int64", From a658e2f277af435517f022355af697bdf588708e Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 16 Apr 2024 10:52:45 +0200 Subject: [PATCH 13/59] Fix long branch name overflows (#30345) Fixes: https://github.com/go-gitea/gitea/issues/27971 Fixes: https://github.com/go-gitea/gitea/pull/28010 Screenshot 2024-04-09 at 00 19 57 Also fixes a similar issue in issue list where CSS was there but not active because of missing `display: block`. Screenshot 2024-04-09 at 00 18 25 --- templates/repo/branch_dropdown.tmpl | 4 ++-- .../repo/issue/branch_selector_field.tmpl | 6 +++--- templates/repo/issue/view_title.tmpl | 2 +- templates/shared/issuelist.tmpl | 15 ++++++++------ web_src/css/base.css | 2 ++ web_src/css/repo.css | 20 ++++++------------- web_src/css/repo/issue-list.css | 6 ++++-- .../js/components/RepoBranchTagSelector.vue | 4 ++-- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/templates/repo/branch_dropdown.tmpl b/templates/repo/branch_dropdown.tmpl index 6c2e08a985..7b39830df8 100644 --- a/templates/repo/branch_dropdown.tmpl +++ b/templates/repo/branch_dropdown.tmpl @@ -71,7 +71,7 @@ {{/* show dummy elements before Vue componment is mounted, this code must match the code in BranchTagSelector.vue */}}