0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-07-20 01:48:28 +02:00

Merge branch 'main' into non-text-edit

# Conflicts:
#	routers/web/repo/editor.go
This commit is contained in:
bytedream 2025-05-05 01:40:21 +02:00
commit 96bbf81700
11 changed files with 134 additions and 34 deletions

View File

@ -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

18
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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)

View File

@ -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
}

View File

@ -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"
@ -146,22 +145,27 @@ func editFile(ctx *context.Context, isNewFile bool) {
}
blob := entry.Blob()
dataRc, err := blob.DataAsync()
if err != nil {
if blob.Size() >= setting.UI.MaxDisplayFileSize {
ctx.NotFound(err)
return
}
buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, blob)
if err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound(err)
} else {
ctx.ServerError("getFileReader", err)
}
return
}
defer dataRc.Close()
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.
ctx.Data["IsFileEditable"] = typesniffer.DetectContentType(buf).IsRepresentableAsText()
ctx.Data["IsFileEditable"] = fInfo.isTextFile && !fInfo.isLFSFile
if blob.Size() >= setting.UI.MaxDisplayFileSize {
ctx.Data["IsFileTooLarge"] = true

View File

@ -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
}

View File

@ -101,8 +101,8 @@
{{end}}
</div>
<span class="file tw-flex tw-items-center tw-font-mono tw-flex-1"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}}{{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}}{{end}}{{$file.Name}}</a>
{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
{{if .IsLFSFile}}<span class="ui label">LFS</span>{{end}}
{{if $file.IsGenerated}}
<span class="ui label">{{ctx.Locale.Tr "repo.diff.generated"}}</span>
{{end}}

View File

@ -11,7 +11,7 @@
{{end}}
{{if ne .FileSize nil}}
<div class="file-info-entry">
{{FileSize .FileSize}}{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
{{FileSize .FileSize}}{{if .IsLFSFile}}<span class="ui label">LFS</span>{{end}}
</div>
{{end}}
{{if .LFSLock}}

View File

@ -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)
})
}

View File

@ -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 <img> 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")