Compare commits

...

36 Commits

Author SHA1 Message Date
badhezi
a38279c270
Merge 23e534d723a12b8287f5257df972d968fafb5fb9 into f3364ec57f58eee0fb3a894eb43858b5f26e043f 2025-07-01 08:43:29 +08:00
badhezi
23e534d723
Merge branch 'main' into dev/hezi/add-raw-diff-patch 2025-06-02 15:35:07 +03:00
badhezi
a8ef5d5125 make head repo selection clearer 2025-06-02 11:53:01 +03:00
wxiaoguang
180386b0d6 FIXME: how to correctly choose the head repository? 2025-06-01 23:48:39 +08:00
wxiaoguang
e442ab15b1 revert unnecessary change 2025-06-01 23:30:44 +08:00
badhezi
f4a0fe369f
Merge branch 'main' into dev/hezi/add-raw-diff-patch 2025-05-31 12:23:20 +03:00
badhezi
b9102f532e remove redundant line 2025-05-30 13:17:16 +03:00
badhezi
688fc78e78 move revParse to testing code only 2025-05-30 13:05:52 +03:00
badhezi
2905d354fc add more test cases to cover different compare patterns 2025-05-30 12:58:16 +03:00
badhezi
e9fac73bcf cover all head ref format cases 2025-05-29 16:04:16 +03:00
badhezi
c80f0b9d46 fix lint and typos 2025-05-28 10:48:55 +03:00
badhezi
d784a0f25d add download links to raw diff and patch in diff box options dropdown 2025-05-28 10:48:55 +03:00
badhezi
3274b844c6 support tag and branch names with ends with .diff and .patch 2025-05-28 10:48:55 +03:00
badhezi
17c860e97d fix timezone adjustment in TestCompareRawDiffPatch 2025-05-28 10:48:55 +03:00
badhezi
a9c8ce990e formatting 2025-05-28 10:48:55 +03:00
badhezi
2bcb546ca3 Add tests and RevParse() function 2025-05-28 10:48:55 +03:00
badhezi
180c1b075e integration tests: WIP 2025-05-28 10:48:55 +03:00
badhezi
acb57e5031 lint, err handle 2025-05-28 10:48:55 +03:00
badhezi
f86ddd53f0 parse .raw and .diff optional compare parameters 2025-05-28 10:48:55 +03:00
badhezi
bfa2d101c4
Merge branch 'go-gitea:main' into main 2025-05-28 10:05:30 +03:00
badhezi
4d7ea0d931
Merge branch 'go-gitea:main' into main 2025-05-20 09:57:11 +03:00
badhezi
a3c29538f1
Merge branch 'go-gitea:main' into main 2025-05-13 22:52:08 +03:00
badhezi
016c2f3025
Merge branch 'go-gitea:main' into main 2025-05-12 16:39:04 +03:00
badhezi
c6acfc1491
Merge branch 'go-gitea:main' into main 2025-05-11 09:18:01 +03:00
badhezi
7f72fe9ef9
Merge branch 'go-gitea:main' into main 2025-05-02 11:07:53 +03:00
badhezi
4e2434b438
Merge branch 'go-gitea:main' into main 2025-04-29 15:15:26 +03:00
badhezi
b46d3141ca
Merge branch 'go-gitea:main' into main 2025-04-28 17:07:29 +03:00
badhezi
a7aaa79a64
Merge branch 'go-gitea:main' into main 2025-04-27 16:14:49 +03:00
badhezi
bcc4ade3e7
Merge branch 'go-gitea:main' into main 2025-04-22 08:19:13 +03:00
badhezi
104eecc710
Merge branch 'go-gitea:main' into main 2025-04-21 22:30:05 +03:00
badhezi
e11a3398b6
Merge branch 'go-gitea:main' into main 2025-04-20 20:33:21 +03:00
badhezi
ac251501d3
Merge branch 'go-gitea:main' into main 2025-04-16 10:34:28 +03:00
Giteabot
54d37d1e7b
Merge branch 'main' into main 2025-04-16 15:05:54 +08:00
Giteabot
5cc1bda7c9
Merge branch 'main' into main 2025-04-16 14:52:59 +08:00
badhezi
f2a2acf146
Merge branch 'main' into main 2025-04-15 20:07:40 +03:00
badhezi
8d799c236c use the correct context data for PR link template in issue card 2025-04-15 19:56:19 +03:00
4 changed files with 267 additions and 15 deletions

View File

@ -18,4 +18,5 @@ type CompareInfo struct {
BaseBranch string
HeadBranch string
DirectComparison bool
RawDiffType git.RawDiffType
}

View File

@ -221,13 +221,9 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {
// base<-head: master...head:feature
// same repo: master...feature
var (
isSameRepo bool
infoPath string
err error
)
var isSameRepo bool
infoPath = ctx.PathParam("*")
infoPath := ctx.PathParam("*")
var infos []string
if infoPath == "" {
infos = []string{baseRepo.DefaultBranch, baseRepo.DefaultBranch}
@ -247,15 +243,17 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {
ci.BaseBranch = infos[0]
ctx.Data["BaseBranch"] = ci.BaseBranch
// If there is no head repository, it means compare between same repository.
var err error
// If there is no head repository, it means compare between the same repository.
headInfos := strings.Split(infos[1], ":")
if len(headInfos) == 1 {
if len(headInfos) == 1 { // {:headBranch} case, guaranteed baseRepo is headRepo
isSameRepo = true
ci.HeadUser = ctx.Repo.Owner
ci.HeadBranch = headInfos[0]
} else if len(headInfos) == 2 {
ci.HeadBranch, ci.RawDiffType = parseRefForRawDiff(ctx, baseRepo, headInfos[0])
} else if len(headInfos) == 2 { // {:headOwner}:{:headBranch} or {:headOwner}/{:headRepoName}:{:headBranch} case
headInfosSplit := strings.Split(headInfos[0], "/")
if len(headInfosSplit) == 1 {
if len(headInfosSplit) == 1 { // {:headOwner}:{:headBranch} case, guaranteed baseRepo.Name is headRepo.Name
ci.HeadUser, err = user_model.GetUserByName(ctx, headInfos[0])
if err != nil {
if user_model.IsErrUserNotExist(err) {
@ -265,12 +263,23 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {
}
return nil
}
ci.HeadBranch = headInfos[1]
headRepo, err := repo_model.GetRepositoryByOwnerAndName(ctx, ci.HeadUser.Name, baseRepo.Name)
if err != nil {
if repo_model.IsErrRepoNotExist(err) {
ctx.NotFound(nil)
} else {
ctx.ServerError("GetRepositoryByOwnerAndName", err)
}
return nil
}
ci.HeadBranch, ci.RawDiffType = parseRefForRawDiff(ctx, headRepo, headInfos[1])
isSameRepo = ci.HeadUser.ID == ctx.Repo.Owner.ID
if isSameRepo {
if isSameRepo { // not a fork
ci.HeadRepo = baseRepo
}
} else {
} else { // {:headOwner}/{:headRepoName}:{:headBranch} case, across forks
ci.HeadRepo, err = repo_model.GetRepositoryByOwnerAndName(ctx, headInfosSplit[0], headInfosSplit[1])
if err != nil {
if repo_model.IsErrRepoNotExist(err) {
@ -288,7 +297,7 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {
}
return nil
}
ci.HeadBranch = headInfos[1]
ci.HeadBranch, ci.RawDiffType = parseRefForRawDiff(ctx, ci.HeadRepo, headInfos[1])
ci.HeadUser = ci.HeadRepo.Owner
isSameRepo = ci.HeadRepo.ID == ctx.Repo.Repository.ID
}
@ -735,6 +744,7 @@ func CompareDiff(ctx *context.Context) {
return
}
ctx.Data["PageIsCompareDiff"] = true
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
ctx.Data["DirectComparison"] = ci.DirectComparison
ctx.Data["OtherCompareSeparator"] = ".."
@ -749,6 +759,15 @@ func CompareDiff(ctx *context.Context) {
return
}
if ci.RawDiffType != "" {
err := git.GetRepoRawDiffForFile(ci.HeadGitRepo, ci.BaseBranch, ci.HeadBranch, ci.RawDiffType, "", ctx.Resp)
if err != nil {
ctx.ServerError("GetRepoRawDiffForFile", err)
return
}
return
}
baseTags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
if err != nil {
ctx.ServerError("GetTagNamesByRepoID", err)
@ -990,3 +1009,20 @@ func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chu
}
return diffLines, nil
}
func parseRefForRawDiff(ctx *context.Context, refRepo *repo_model.Repository, refShortName string) (string, git.RawDiffType) {
if !strings.HasSuffix(refShortName, ".diff") && !strings.HasSuffix(refShortName, ".patch") {
return refShortName, ""
}
if gitrepo.IsBranchExist(ctx, refRepo, refShortName) || gitrepo.IsTagExist(ctx, refRepo, refShortName) {
return refShortName, ""
}
if s, ok := strings.CutSuffix(refShortName, ".diff"); ok {
return s, git.RawDiffNormal
} else if s, ok = strings.CutSuffix(refShortName, ".patch"); ok {
return s, git.RawDiffPatch
}
return refShortName, ""
}

View File

@ -10,6 +10,9 @@
{{else if .Commit.ID.String}}
<a class="item" href="{{$.RepoLink}}/commit/{{PathEscape .Commit.ID.String}}.patch" download="{{ShortSha .Commit.ID.String}}.patch">{{ctx.Locale.Tr "repo.diff.download_patch"}}</a>
<a class="item" href="{{$.RepoLink}}/commit/{{PathEscape .Commit.ID.String}}.diff" download="{{ShortSha .Commit.ID.String}}.diff">{{ctx.Locale.Tr "repo.diff.download_diff"}}</a>
{{else if $.PageIsCompareDiff}}
<a class="item" href="{{$.Link}}.patch" download="{{$.BaseBranch}}...{{$.HeadBranch}}.patch">{{ctx.Locale.Tr "repo.diff.download_patch"}}</a>
<a class="item" href="{{$.Link}}.diff" download="{{$.BaseBranch}}...{{$.HeadBranch}}.diff">{{ctx.Locale.Tr "repo.diff.download_diff"}}</a>
{{end}}
<a id="expand-files-btn" class="item">{{ctx.Locale.Tr "repo.pulls.expand_files"}}</a>
<a id="collapse-files-btn" class="item">{{ctx.Locale.Tr "repo.pulls.collapse_files"}}</a>

View File

@ -9,10 +9,13 @@ import (
"net/url"
"strings"
"testing"
"time"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
git_module "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/test"
repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
@ -158,3 +161,212 @@ func TestCompareCodeExpand(t *testing.T) {
}
})
}
func TestCompareRawDiffNormal(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
repo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user1, user1, repo_service.CreateRepoOptions{
Name: "test_raw_diff",
Readme: "Default",
AutoInit: true,
DefaultBranch: "main",
}, true)
assert.NoError(t, err)
session := loginUser(t, user1.Name)
r, _ := gitrepo.OpenRepository(db.DefaultContext, repo)
oldRef, _ := r.GetBranchCommit(repo.DefaultBranch)
oldBlobRef, _ := revParse(r, oldRef.ID.String(), "README.md")
testEditFile(t, session, user1.Name, repo.Name, "main", "README.md", strings.Repeat("a\n", 2))
newRef, _ := r.GetBranchCommit(repo.DefaultBranch)
newBlobRef, _ := revParse(r, newRef.ID.String(), "README.md")
req := NewRequest(t, "GET", fmt.Sprintf("/user1/test_raw_diff/compare/%s...%s.diff", oldRef.ID.String(), newRef.ID.String()))
resp := session.MakeRequest(t, req, http.StatusOK)
expected := fmt.Sprintf(`diff --git a/README.md b/README.md
index %s..%s 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# test_raw_diff
-
+a
+a
`, oldBlobRef[:7], newBlobRef[:7])
assert.Equal(t, expected, resp.Body.String())
})
}
func TestCompareRawDiffPatch(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
repo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user1, user1, repo_service.CreateRepoOptions{
Name: "test_raw_diff",
Readme: "Default",
AutoInit: true,
DefaultBranch: "main",
}, true)
assert.NoError(t, err)
session := loginUser(t, user1.Name)
r, _ := gitrepo.OpenRepository(db.DefaultContext, repo)
// Get the old commit and blob reference
oldRef, _ := r.GetBranchCommit(repo.DefaultBranch)
oldBlobRef, _ := revParse(r, oldRef.ID.String(), "README.md")
resp := testEditFile(t, session, user1.Name, repo.Name, "main", "README.md", strings.Repeat("a\n", 2))
newRef, _ := r.GetBranchCommit(repo.DefaultBranch)
newBlobRef, _ := revParse(r, newRef.ID.String(), "README.md")
// Get the last modified time from the response header
respTs, _ := time.Parse(time.RFC1123, resp.Result().Header.Get("Last-Modified"))
respTs = respTs.In(time.Local)
// Format the timestamp to match the expected format in the patch
customFormat := "Mon, 2 Jan 2006 15:04:05 -0700"
respTsStr := respTs.Format(customFormat)
req := NewRequest(t, "GET", fmt.Sprintf("/user1/test_raw_diff/compare/%s...%s.patch", oldRef.ID.String(), newRef.ID.String()))
resp = session.MakeRequest(t, req, http.StatusOK)
expected := fmt.Sprintf(`From %s Mon Sep 17 00:00:00 2001
From: User One <user1@example.com>
Date: %s
Subject: [PATCH] Update README.md
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index %s..%s 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# test_raw_diff
-
+a
+a
`, newRef.ID.String(), respTsStr, oldBlobRef[:7], newBlobRef[:7])
assert.Equal(t, expected, resp.Body.String())
})
}
func TestCompareRawDiffNormalSameOwnerDifferentRepo(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
repo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user1, user1, repo_service.CreateRepoOptions{
Name: "test_raw_diff",
Readme: "Default",
AutoInit: true,
DefaultBranch: "main",
}, true)
assert.NoError(t, err)
session := loginUser(t, user1.Name)
headRepo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user1, user1, repo_service.CreateRepoOptions{
Name: "test_raw_diff_head",
Readme: "Default",
AutoInit: true,
DefaultBranch: "main",
}, true)
assert.NoError(t, err)
r, _ := gitrepo.OpenRepository(db.DefaultContext, repo)
hr, _ := gitrepo.OpenRepository(db.DefaultContext, headRepo)
oldRef, _ := r.GetBranchCommit(repo.DefaultBranch)
oldBlobRef, _ := revParse(r, oldRef.ID.String(), "README.md")
testEditFile(t, session, user1.Name, headRepo.Name, "main", "README.md", strings.Repeat("a\n", 2))
newRef, _ := hr.GetBranchCommit(headRepo.DefaultBranch)
newBlobRef, _ := revParse(hr, newRef.ID.String(), "README.md")
req := NewRequest(t, "GET", fmt.Sprintf("/user1/test_raw_diff/compare/%s...%s/%s:%s.diff", oldRef.ID.String(), user1.LowerName, headRepo.LowerName, newRef.ID.String()))
resp := session.MakeRequest(t, req, http.StatusOK)
expected := fmt.Sprintf(`diff --git a/README.md b/README.md
index %s..%s 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# test_raw_diff
-
+a
+a
`, oldBlobRef[:7], newBlobRef[:7])
assert.Equal(t, expected, resp.Body.String())
})
}
func TestCompareRawDiffNormalAcrossForks(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user1, user1, repo_service.CreateRepoOptions{
Name: "test_raw_diff",
Readme: "Default",
AutoInit: true,
DefaultBranch: "main",
}, true)
assert.NoError(t, err)
headRepo, err := repo_service.ForkRepository(db.DefaultContext, user2, user2, repo_service.ForkRepoOptions{
BaseRepo: repo,
Name: repo.Name,
Description: repo.Description,
SingleBranch: "",
})
assert.NoError(t, err)
session := loginUser(t, user2.Name)
r, _ := gitrepo.OpenRepository(db.DefaultContext, repo)
hr, _ := gitrepo.OpenRepository(db.DefaultContext, headRepo)
oldRef, _ := r.GetBranchCommit(repo.DefaultBranch)
oldBlobRef, _ := revParse(r, oldRef.ID.String(), "README.md")
testEditFile(t, session, user2.Name, headRepo.Name, "main", "README.md", strings.Repeat("a\n", 2))
newRef, _ := hr.GetBranchCommit(headRepo.DefaultBranch)
newBlobRef, _ := revParse(hr, newRef.ID.String(), "README.md")
session = loginUser(t, user1.Name)
req := NewRequest(t, "GET", fmt.Sprintf("/user1/test_raw_diff/compare/%s...%s:%s.diff", oldRef.ID.String(), user2.LowerName, newRef.ID.String()))
resp := session.MakeRequest(t, req, http.StatusOK)
expected := fmt.Sprintf(`diff --git a/README.md b/README.md
index %s..%s 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# test_raw_diff
-
+a
+a
`, oldBlobRef[:7], newBlobRef[:7])
assert.Equal(t, expected, resp.Body.String())
})
}
// helper function to use rev-parse
// revParse resolves a revision reference to other git-related objects
func revParse(repo *git_module.Repository, ref, file string) (string, error) {
stdout, _, err := git_module.NewCommand("rev-parse").
AddDynamicArguments(ref+":"+file).
RunStdString(repo.Ctx, &git_module.RunOpts{Dir: repo.Path})
if err != nil {
return "", err
}
return strings.TrimSpace(stdout), nil
}