mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-04 00:01:16 -04:00
Compare commits
36 Commits
6d96ca45cf
...
a38279c270
Author | SHA1 | Date | |
---|---|---|---|
|
a38279c270 | ||
|
23e534d723 | ||
|
a8ef5d5125 | ||
|
180386b0d6 | ||
|
e442ab15b1 | ||
|
f4a0fe369f | ||
|
b9102f532e | ||
|
688fc78e78 | ||
|
2905d354fc | ||
|
e9fac73bcf | ||
|
c80f0b9d46 | ||
|
d784a0f25d | ||
|
3274b844c6 | ||
|
17c860e97d | ||
|
a9c8ce990e | ||
|
2bcb546ca3 | ||
|
180c1b075e | ||
|
acb57e5031 | ||
|
f86ddd53f0 | ||
|
bfa2d101c4 | ||
|
4d7ea0d931 | ||
|
a3c29538f1 | ||
|
016c2f3025 | ||
|
c6acfc1491 | ||
|
7f72fe9ef9 | ||
|
4e2434b438 | ||
|
b46d3141ca | ||
|
a7aaa79a64 | ||
|
bcc4ade3e7 | ||
|
104eecc710 | ||
|
e11a3398b6 | ||
|
ac251501d3 | ||
|
54d37d1e7b | ||
|
5cc1bda7c9 | ||
|
f2a2acf146 | ||
|
8d799c236c |
@ -18,4 +18,5 @@ type CompareInfo struct {
|
||||
BaseBranch string
|
||||
HeadBranch string
|
||||
DirectComparison bool
|
||||
RawDiffType git.RawDiffType
|
||||
}
|
||||
|
@ -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, ""
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user