From 5a5c6d062fbdaef0d7f8e891d40e6ddbd6274367 Mon Sep 17 00:00:00 2001 From: yystopf Date: Thu, 7 Nov 2024 13:53:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=20commit\compare=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8F=98=E5=8A=A8=E6=8E=A5=E5=8F=A3=E6=8B=86=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routers/hat/hat.go | 13 +++- routers/hat/repo/commits.go | 98 ++++++++++++++++++++++++++ routers/hat/repo/repo.go | 137 +++++++++++++++++++++++++++++++----- 3 files changed, 228 insertions(+), 20 deletions(-) diff --git a/routers/hat/hat.go b/routers/hat/hat.go index 21dffa4..d7f4b5b 100644 --- a/routers/hat/hat.go +++ b/routers/hat/hat.go @@ -145,6 +145,10 @@ func Routers() *web.Route { }, reqRepoReader(unit_model.TypeCode)) m.Group("/commits", func() { m.Get("/{sha}/diff", repo.GetCommitDiff) + m.Group("/{sha}/files", func() { + m.Get("", repo.GetCommitFiles) + m.Get("/*", repo.GetCommitFilesByPath) + }) }, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode)) m.Group("/tags", func() { m.Get("", repo.ListTags) @@ -159,7 +163,14 @@ func Routers() *web.Route { }) m.Get("/commits_slice", repo.GetAllCommitsSliceByTime) m.Get("/recent_commits", context.ReferencesGitRepo(), repo.GetRecentCommits) - m.Get("/compare/*", reqRepoReader(unit_model.TypeCode), repo.CompareDiff) + // m.Get("/compare/*", reqRepoReader(unit_model.TypeCode), repo.CompareDiff) + m.Group("/compare/{shaFrom}...{shaTo}", func() { + m.Get("", repo.CompareDiff) + m.Group("/files", func() { + m.Get("", repo.CompareFiles) + m.Get("/*", repo.CompareFilesByPath) + }) + }, reqRepoReader(unit_model.TypeCode)) m.Group("/pulls", func() { m.Group("/{index}", func() { m.Combo("").Get(repo.GetPullRequest). diff --git a/routers/hat/repo/commits.go b/routers/hat/repo/commits.go index 2e508d3..748138a 100644 --- a/routers/hat/repo/commits.go +++ b/routers/hat/repo/commits.go @@ -312,6 +312,104 @@ func GetSingleCommit(ctx *context.APIContext) { ctx.JSON(http.StatusOK, json) } +func GetCommitFiles(ctx *context.APIContext) { + commitID := ctx.Params(":sha") + gitRepo := ctx.Repo.GitRepo + + commit, err := gitRepo.GetCommit(commitID) + if err != nil { + if git.IsErrNotExist(err) { + ctx.NotFound(commitID) + return + } + ctx.Error(http.StatusInternalServerError, "gitRepo.GetCommit", err) + return + } + + if len(commitID) != 40 { + commitID = commit.ID.String() + } + + diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ + AfterCommitID: commitID, + SkipTo: ctx.FormString("skip-to"), + MaxLines: setting.Git.MaxGitDiffLines, + MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, + MaxFiles: -1, + WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.FormString("whitespace")), + }) + if err != nil { + ctx.NotFound("GetDIff", err) + return + } + listOptions := utils.GetListOptions(ctx) + + totalNumberOfFiles := diff.NumFiles + totalNumberOfPages := int(math.Ceil(float64(totalNumberOfFiles) / float64(listOptions.PageSize))) + + start, end := listOptions.GetStartEnd() + + if end > totalNumberOfFiles { + end = totalNumberOfFiles + } + + lenFiles := end - start + if lenFiles < 0 { + lenFiles = 0 + } + + apiFiles := make([]*api.ChangedFile, 0, lenFiles) + for i := start; i < end; i++ { + apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], ctx.Repo.Repository, commitID)) + } + + ctx.SetLinkHeader(totalNumberOfFiles, listOptions.PageSize) + ctx.SetTotalCountHeader(int64(totalNumberOfFiles)) + + ctx.RespHeader().Set("X-Page", strconv.Itoa(listOptions.Page)) + ctx.RespHeader().Set("X-PerPage", strconv.Itoa(listOptions.PageSize)) + ctx.RespHeader().Set("X-PageCount", strconv.Itoa(totalNumberOfPages)) + ctx.RespHeader().Set("X-HasMore", strconv.FormatBool(listOptions.Page < totalNumberOfPages)) + ctx.AppendAccessControlExposeHeaders("X-Page", "X-PerPage", "X-PageCount", "X-HasMore") + + ctx.JSON(http.StatusOK, &apiFiles) +} + +func GetCommitFilesByPath(ctx *context.APIContext) { + commitID := ctx.Params(":sha") + gitRepo := ctx.Repo.GitRepo + path := ctx.Params("*") + commit, err := gitRepo.GetCommit(commitID) + if err != nil { + if git.IsErrNotExist(err) { + ctx.NotFound(commitID) + return + } + ctx.Error(http.StatusInternalServerError, "gitRepo.GetCommit", err) + return + } + + if len(commitID) != 40 { + commitID = commit.ID.String() + } + + diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ + AfterCommitID: commitID, + SkipTo: ctx.FormString("skip-to"), + MaxLines: setting.Git.MaxGitDiffLines, + MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, + MaxFiles: -1, + WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.FormString("whitespace")), + }, path) + if err != nil { + ctx.NotFound("GetDIff", err) + return + } + + ctx.JSON(http.StatusOK, &diff) + +} + func GetCommitDiff(ctx *context.APIContext) { commitID := ctx.Params(":sha") gitRepo := ctx.Repo.GitRepo diff --git a/routers/hat/repo/repo.go b/routers/hat/repo/repo.go index 824b052..1908a13 100644 --- a/routers/hat/repo/repo.go +++ b/routers/hat/repo/repo.go @@ -2,7 +2,9 @@ package repo import ( "fmt" + "math" "net/http" + "strconv" "strings" "time" @@ -17,7 +19,9 @@ import ( "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/gitdiff" hat_git "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git" hat_repo_service "code.gitlink.org.cn/Gitlink/gitea_hat.git/services/repository" @@ -29,7 +33,7 @@ func PrepareComapreDiff( headRepo *repo_model.Repository, headGitRepo *gitea_git.Repository, compareInfo *gitea_git.CompareInfo, - baseBranch, headBranch string) bool { + baseBranch, headBranch string, path ...string) bool { var ( err error ) @@ -62,12 +66,14 @@ func PrepareComapreDiff( defer gitRepo.Close() diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ - BeforeCommitID: compareInfo.MergeBase, - AfterCommitID: headCommitID, - MaxLines: setting.Git.MaxGitDiffLines, - MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, - MaxFiles: setting.Git.MaxGitDiffFiles, - }) + BeforeCommitID: compareInfo.MergeBase, + AfterCommitID: headCommitID, + SkipTo: ctx.FormString("skip-to"), + MaxLines: setting.Git.MaxGitDiffLines, + MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, + MaxFiles: -1, + WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.FormString("whitespace")), + }, path...) if err != nil { ctx.Error(http.StatusInternalServerError, "GetDiff", err) @@ -128,6 +134,107 @@ func CompareDiff(ctx *context.APIContext) { ctx.JSON(http.StatusOK, different) } +func CompareFiles(ctx *context.APIContext) { + headUser, headRepo, headGitRepo, compareInfo, _, headBranch := ParseCompareInfo(ctx) + if ctx.Written() { + return + } + defer headGitRepo.Close() + + headCommitID := headBranch + + repoPath := repo_model.RepoPath(headUser.Name, headRepo.Name) + + gitRepo, _ := gitea_git.OpenRepository(ctx, repoPath) + defer gitRepo.Close() + + diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ + BeforeCommitID: compareInfo.MergeBase, + AfterCommitID: headCommitID, + SkipTo: ctx.FormString("skip-to"), + MaxLines: setting.Git.MaxGitDiffLines, + MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, + MaxFiles: -1, + WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.FormString("whitespace")), + }) + + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetDiff", err) + return + } + + listOptions := utils.GetListOptions(ctx) + + totalNumberOfFiles := diff.NumFiles + totalNumberOfPages := int(math.Ceil(float64(totalNumberOfFiles) / float64(listOptions.PageSize))) + + start, end := listOptions.GetStartEnd() + + if end > totalNumberOfFiles { + end = totalNumberOfFiles + } + + lenFiles := end - start + if lenFiles < 0 { + lenFiles = 0 + } + + apiFiles := make([]*api.ChangedFile, 0, lenFiles) + for i := start; i < end; i++ { + apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], ctx.Repo.Repository, headCommitID)) + } + + ctx.SetLinkHeader(totalNumberOfFiles, listOptions.PageSize) + ctx.SetTotalCountHeader(int64(totalNumberOfFiles)) + + ctx.RespHeader().Set("X-Page", strconv.Itoa(listOptions.Page)) + ctx.RespHeader().Set("X-PerPage", strconv.Itoa(listOptions.PageSize)) + ctx.RespHeader().Set("X-PageCount", strconv.Itoa(totalNumberOfPages)) + ctx.RespHeader().Set("X-HasMore", strconv.FormatBool(listOptions.Page < totalNumberOfPages)) + ctx.AppendAccessControlExposeHeaders("X-Page", "X-PerPage", "X-PageCount", "X-HasMore") + + ctx.JSON(http.StatusOK, &apiFiles) + +} + +func CompareFilesByPath(ctx *context.APIContext) { + path := ctx.Params("*") + headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := ParseCompareInfo(ctx) + if ctx.Written() { + return + } + defer headGitRepo.Close() + + _ = PrepareComapreDiff(ctx, headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch, path) + + result := make([]CompareCommit, 0) + for _, commit := range compareInfo.Commits { + compareCommit := CompareCommit{ + Commit: commit, + Sha: commit.ID.String(), + } + for _, p := range commit.Parents { + compareCommit.ParentShas = append(compareCommit.ParentShas, p.String()) + } + result = append(result, compareCommit) + } + + different := struct { + Commits []CompareCommit + Diff interface{} + CommitsCount int + Latestsha string + }{ + Commits: result, + Diff: ctx.Data["Diff"], + } + + different.CommitsCount = len(compareInfo.Commits) + different.Latestsha = compareInfo.HeadCommitID + + ctx.JSON(http.StatusOK, different) +} + func ParseCompareInfo(ctx *context.APIContext) (*user_model.User, *repo_model.Repository, *gitea_git.Repository, *gitea_git.CompareInfo, string, string) { baseRepo := ctx.Repo.Repository @@ -136,25 +243,17 @@ func ParseCompareInfo(ctx *context.APIContext) (*user_model.User, *repo_model.Re headRepo *repo_model.Repository headBranch string isSameRepo bool - infoPath string err error directComparison bool ) - infoPath = ctx.Params("*") + shaFrom := ctx.Params("shaFrom") + shaTo := ctx.Params("shaTo") var infos []string - if infoPath == "" { + if shaFrom == "" || shaTo == "" { infos = []string{baseRepo.DefaultBranch, baseRepo.DefaultBranch} } else { - infos = strings.SplitN(infoPath, "...", 2) - if len(infos) != 2 { - if infos = strings.SplitN(infoPath, "..", 2); len(infos) == 2 { - directComparison = true - ctx.Data["PageIsComparePull"] = false - } else { - infos = []string{baseRepo.DefaultBranch, infoPath} - } - } + infos = []string{shaFrom, shaTo} } ctx.Data["BaseName"] = baseRepo.OwnerName