From 3446f14ba0afc4934a091ef117130765be10a981 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Sat, 3 May 2025 20:31:16 +0300 Subject: [PATCH 1/5] Bump `@github/relative-time-element` to v4.4.6 (#34352) Tested, it works as before. Changelog: https://github.com/github/relative-time-element/releases/tag/v4.4.6 Signed-off-by: Yarden Shoham --- package-lock.json | 18 +++++++++++++----- package.json | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ab429628e..e374bcdc7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", - "@github/relative-time-element": "4.4.5", + "@github/relative-time-element": "4.4.6", "@github/text-expander-element": "2.9.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "19.15.1", @@ -1149,10 +1149,18 @@ "license": "MIT" }, "node_modules/@github/relative-time-element": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.5.tgz", - "integrity": "sha512-9ejPtayBDIJfEU8x1fg/w2o5mahHkkp1SC6uObDtoKs4Gn+2a1vNK8XIiNDD8rMeEfpvDjydgSZZ+uk+7N0VsQ==", - "license": "MIT" + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.6.tgz", + "integrity": "sha512-KgrkxVWb/qcBBSDumGhRzieqtSzGJyyEF4D5to+OVJf/nTExU5sSlPKiNEzN8Nh6Kj0SGlq8UdIJjEgPxZzUhQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "18 || 19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, "node_modules/@github/text-expander-element": { "version": "2.9.1", diff --git a/package.json b/package.json index 4874ad450d..bc11e4d398 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", - "@github/relative-time-element": "4.4.5", + "@github/relative-time-element": "4.4.6", "@github/text-expander-element": "2.9.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "19.15.1", From 180aa00abf4a7647e46b8cd8ed35dc5be43166b9 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 4 May 2025 20:23:28 +0200 Subject: [PATCH 2/5] Fix LFS files being editable in web UI (#34356) It's possible to edit "raw" lfs files in the web UI when accessing the path manually. ![image](https://github.com/user-attachments/assets/62610e9e-24db-45ec-ad04-28062073164c) --- routers/web/repo/editor.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index c925b61151..514eb0ebfe 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -20,7 +20,6 @@ import ( "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" - "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/utils" @@ -151,9 +150,13 @@ func editFile(ctx *context.Context, isNewFile bool) { return } - dataRc, err := blob.DataAsync() + buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, blob) if err != nil { - ctx.NotFound(err) + if git.IsErrNotExist(err) { + ctx.NotFound(err) + } else { + ctx.ServerError("getFileReader", err) + } return } @@ -161,12 +164,8 @@ func editFile(ctx *context.Context, isNewFile bool) { ctx.Data["FileSize"] = blob.Size() - buf := make([]byte, 1024) - n, _ := util.ReadAtMost(dataRc, buf) - buf = buf[:n] - // Only some file types are editable online as text. - if !typesniffer.DetectContentType(buf).IsRepresentableAsText() { + if !fInfo.isTextFile || fInfo.isLFSFile { ctx.NotFound(nil) return } From 41f3d062a2c3bb42cbcc75f1d8a6a68246e417ff Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 May 2025 11:52:00 -0700 Subject: [PATCH 3/5] Fix bug when visiting comparation page (#34334) The `ci.HeadGitRepo` was opened and closed in the function `ParseCompareInfo` but reused in the function `PrepareCompareDiff`. --- routers/web/repo/compare.go | 10 ++-------- routers/web/repo/pull.go | 5 ----- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 34d9710acb..8b99dd95da 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -402,12 +402,11 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { ci.HeadRepo = ctx.Repo.Repository ci.HeadGitRepo = ctx.Repo.GitRepo } else if has { - ci.HeadGitRepo, err = gitrepo.OpenRepository(ctx, ci.HeadRepo) + ci.HeadGitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ci.HeadRepo) if err != nil { - ctx.ServerError("OpenRepository", err) + ctx.ServerError("RepositoryFromRequestContextOrOpen", err) return nil } - defer ci.HeadGitRepo.Close() } else { ctx.NotFound(nil) return nil @@ -726,11 +725,6 @@ func getBranchesAndTagsForRepo(ctx gocontext.Context, repo *repo_model.Repositor // CompareDiff show different from one commit to another commit func CompareDiff(ctx *context.Context) { ci := ParseCompareInfo(ctx) - defer func() { - if ci != nil && ci.HeadGitRepo != nil { - ci.HeadGitRepo.Close() - } - }() if ctx.Written() { return } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 6a63240269..43ddc265cf 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1296,11 +1296,6 @@ func CompareAndPullRequestPost(ctx *context.Context) { ) ci := ParseCompareInfo(ctx) - defer func() { - if ci != nil && ci.HeadGitRepo != nil { - ci.HeadGitRepo.Close() - } - }() if ctx.Written() { return } From 51aafb427802803e9a97806afed07f488e032d83 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 May 2025 12:17:17 -0700 Subject: [PATCH 4/5] Fix bug when API get pull changed files for deleted head repository (#34333) --- routers/api/v1/repo/pull.go | 4 +- tests/integration/api_pull_test.go | 98 ++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 04d9b10787..c0ab381bc8 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -1632,7 +1632,9 @@ func GetPullRequestFiles(ctx *context.APIContext) { apiFiles := make([]*api.ChangedFile, 0, limit) for i := start; i < start+limit; i++ { - apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], pr.HeadRepo, endCommitID)) + // refs/pull/1/head stores the HEAD commit ID, allowing all related commits to be found in the base repository. + // The head repository might have been deleted, so we should not rely on it here. + apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], pr.BaseRepo, endCommitID)) } ctx.SetLinkHeader(totalNumberOfFiles, listOptions.PageSize) diff --git a/tests/integration/api_pull_test.go b/tests/integration/api_pull_test.go index f3165c6fc5..f2df6021e1 100644 --- a/tests/integration/api_pull_test.go +++ b/tests/integration/api_pull_test.go @@ -8,7 +8,10 @@ import ( "fmt" "io" "net/http" + "net/url" + "strings" "testing" + "time" auth_model "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" @@ -17,11 +20,15 @@ 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/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/gitdiff" issue_service "code.gitea.io/gitea/services/issue" + pull_service "code.gitea.io/gitea/services/pull" + files_service "code.gitea.io/gitea/services/repository/files" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" @@ -424,3 +431,94 @@ func TestAPICommitPullRequest(t *testing.T) { req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/commits/%s/pull", owner.Name, repo.Name, invalidCommitSHA).AddTokenAuth(ctx.Token) ctx.Session.MakeRequest(t, req, http.StatusNotFound) } + +func TestAPIViewPullFilesWithHeadRepoDeleted(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + + ctx := NewAPITestContext(t, "user1", baseRepo.Name, auth_model.AccessTokenScopeAll) + + doAPIForkRepository(ctx, "user2")(t) + + forkedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ForkID: baseRepo.ID, OwnerName: "user1"}) + + // add a new file to the forked repo + addFileToForkedResp, err := files_service.ChangeRepoFiles(git.DefaultContext, forkedRepo, user1, &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "file_1.txt", + ContentReader: strings.NewReader("file1"), + }, + }, + Message: "add file1", + OldBranch: "master", + NewBranch: "fork-branch-1", + Author: &files_service.IdentityOptions{ + GitUserName: user1.Name, + GitUserEmail: user1.Email, + }, + Committer: &files_service.IdentityOptions{ + GitUserName: user1.Name, + GitUserEmail: user1.Email, + }, + Dates: &files_service.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }) + assert.NoError(t, err) + assert.NotEmpty(t, addFileToForkedResp) + + // create Pull + pullIssue := &issues_model.Issue{ + RepoID: baseRepo.ID, + Title: "Test pull-request-target-event", + PosterID: user1.ID, + Poster: user1, + IsPull: true, + } + pullRequest := &issues_model.PullRequest{ + HeadRepoID: forkedRepo.ID, + BaseRepoID: baseRepo.ID, + HeadBranch: "fork-branch-1", + BaseBranch: "master", + HeadRepo: forkedRepo, + BaseRepo: baseRepo, + Type: issues_model.PullRequestGitea, + } + + prOpts := &pull_service.NewPullRequestOptions{Repo: baseRepo, Issue: pullIssue, PullRequest: pullRequest} + err = pull_service.NewPullRequest(git.DefaultContext, prOpts) + assert.NoError(t, err) + pr := convert.ToAPIPullRequest(t.Context(), pullRequest, user1) + + ctx = NewAPITestContext(t, "user2", baseRepo.Name, auth_model.AccessTokenScopeAll) + doAPIGetPullFiles(ctx, pr, func(t *testing.T, files []*api.ChangedFile) { + if assert.Len(t, files, 1) { + assert.Equal(t, "file_1.txt", files[0].Filename) + assert.Empty(t, files[0].PreviousFilename) + assert.Equal(t, 1, files[0].Additions) + assert.Equal(t, 1, files[0].Changes) + assert.Equal(t, 0, files[0].Deletions) + assert.Equal(t, "added", files[0].Status) + } + })(t) + + // delete the head repository of the pull request + forkCtx := NewAPITestContext(t, "user1", forkedRepo.Name, auth_model.AccessTokenScopeAll) + doAPIDeleteRepository(forkCtx)(t) + + doAPIGetPullFiles(ctx, pr, func(t *testing.T, files []*api.ChangedFile) { + if assert.Len(t, files, 1) { + assert.Equal(t, "file_1.txt", files[0].Filename) + assert.Empty(t, files[0].PreviousFilename) + assert.Equal(t, 1, files[0].Additions) + assert.Equal(t, 1, files[0].Changes) + assert.Equal(t, 0, files[0].Deletions) + assert.Equal(t, "added", files[0].Status) + } + })(t) + }) +} From 62f73491f36eff06ab42bca4aa66f2fc9dfc673d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 May 2025 14:07:29 -0700 Subject: [PATCH 5/5] Use lfs label for lfs file rather than a long description (#34363) Before ![image](https://github.com/user-attachments/assets/ed6c9221-5a6a-4717-8178-e5528fd180bf) After ![image](https://github.com/user-attachments/assets/baa94350-ead4-46bf-b4b7-1bfd3aa5dcac) --- options/locale/locale_en-US.ini | 1 - templates/repo/diff/box.tmpl | 2 +- templates/repo/file_info.tmpl | 2 +- tests/integration/lfs_view_test.go | 6 +++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index a8fabc9ca1..4db4964afb 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1305,7 +1305,6 @@ file_copy_permalink = Copy Permalink view_git_blame = View Git Blame video_not_supported_in_browser = Your browser does not support the HTML5 'video' tag. audio_not_supported_in_browser = Your browser does not support the HTML5 'audio' tag. -stored_lfs = Stored with Git LFS symbolic_link = Symbolic link executable_file = Executable File vendored = Vendored diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index f8d0804bf0..fa96d2f0e2 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -101,8 +101,8 @@ {{end}} {{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}} - {{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}} + {{if .IsLFSFile}}LFS{{end}} {{if $file.IsGenerated}} {{ctx.Locale.Tr "repo.diff.generated"}} {{end}} diff --git a/templates/repo/file_info.tmpl b/templates/repo/file_info.tmpl index b63af68973..38133bde2b 100644 --- a/templates/repo/file_info.tmpl +++ b/templates/repo/file_info.tmpl @@ -11,7 +11,7 @@ {{end}} {{if ne .FileSize nil}}
- {{FileSize .FileSize}}{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}} + {{FileSize .FileSize}}{{if .IsLFSFile}}LFS{{end}}
{{end}} {{if .LFSLock}} diff --git a/tests/integration/lfs_view_test.go b/tests/integration/lfs_view_test.go index 153050dd5e..64ffebaa78 100644 --- a/tests/integration/lfs_view_test.go +++ b/tests/integration/lfs_view_test.go @@ -38,7 +38,7 @@ func TestLFSRender(t *testing.T) { doc := NewHTMLParser(t, resp.Body).doc fileInfo := doc.Find("div.file-info-entry").First().Text() - assert.Contains(t, fileInfo, "Stored with Git LFS") + assert.Contains(t, fileInfo, "LFS") content := doc.Find("div.file-view").Text() assert.Contains(t, content, "Testing documents in LFS") @@ -54,7 +54,7 @@ func TestLFSRender(t *testing.T) { doc := NewHTMLParser(t, resp.Body).doc fileInfo := doc.Find("div.file-info-entry").First().Text() - assert.Contains(t, fileInfo, "Stored with Git LFS") + assert.Contains(t, fileInfo, "LFS") src, exists := doc.Find(".file-view img").Attr("src") assert.True(t, exists, "The image should be in an tag") @@ -71,7 +71,7 @@ func TestLFSRender(t *testing.T) { doc := NewHTMLParser(t, resp.Body).doc fileInfo := doc.Find("div.file-info-entry").First().Text() - assert.Contains(t, fileInfo, "Stored with Git LFS") + assert.Contains(t, fileInfo, "LFS") rawLink, exists := doc.Find("div.file-view > div.view-raw > a").Attr("href") assert.True(t, exists, "Download link should render instead of content because this is a binary file")