diff options
author | Bo-Yi Wu <appleboy.tw@gmail.com> | 2024-04-16 11:45:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-16 11:45:04 +0800 |
commit | c70e442ce4b99e2a1f1bf216afcfa1ad78d1925a (patch) | |
tree | e4bff85f5ce22a3d57371814d9fb3c261e9f70dc /routers | |
parent | 3b045ee165c8ba06c99c28d57b849fb53a502e84 (diff) | |
download | gitea-c70e442ce4b99e2a1f1bf216afcfa1ad78d1925a.tar.gz gitea-c70e442ce4b99e2a1f1bf216afcfa1ad78d1925a.zip |
feat(api): implement branch/commit comparison API (#30349)
- Add new `Compare` struct to represent comparison between two commits
- Introduce new API endpoint `/compare/*` to get commit comparison
information
- Create new file `repo_compare.go` with the `Compare` struct definition
- Add new file `compare.go` in `routers/api/v1/repo` to handle
comparison logic
- Add new file `compare.go` in `routers/common` to define `CompareInfo`
struct
- Refactor `ParseCompareInfo` function to use `common.CompareInfo`
struct
- Update Swagger documentation to include the new API endpoint for
commit comparison
- Remove duplicate `CompareInfo` struct from
`routers/web/repo/compare.go`
- Adjust base path in Swagger template to be relative (`/api/v1`)
GitHub API
https://docs.github.com/en/rest/commits/commits?apiVersion=2022-11-28#compare-two-commits
---------
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/api.go | 2 | ||||
-rw-r--r-- | routers/api/v1/repo/compare.go | 99 | ||||
-rw-r--r-- | routers/api/v1/swagger/repo.go | 6 | ||||
-rw-r--r-- | routers/common/compare.go | 21 | ||||
-rw-r--r-- | routers/web/repo/compare.go | 18 |
5 files changed, 132 insertions, 14 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e870378c4b..1fc7682966 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1066,6 +1066,8 @@ func Routes() *web.Route { m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate) m.Group("/{username}/{reponame}", func() { + m.Get("/compare/*", reqRepoReader(unit.TypeCode), repo.CompareDiff) + m.Combo("").Get(reqAnyRepoReader(), repo.Get). Delete(reqToken(), reqOwner(), repo.Delete). Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit) diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go new file mode 100644 index 0000000000..549b9b7fa9 --- /dev/null +++ b/routers/api/v1/repo/compare.go @@ -0,0 +1,99 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repo + +import ( + "net/http" + "strings" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/gitrepo" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/convert" +) + +// CompareDiff compare two branches or commits +func CompareDiff(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/compare/{basehead} Get commit comparison information + // --- + // summary: Get commit comparison information + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: basehead + // in: path + // description: compare two branches or commits + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/Compare" + // "404": + // "$ref": "#/responses/notFound" + + if ctx.Repo.GitRepo == nil { + gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository) + if err != nil { + ctx.Error(http.StatusInternalServerError, "OpenRepository", err) + return + } + ctx.Repo.GitRepo = gitRepo + defer gitRepo.Close() + } + + infoPath := ctx.Params("*") + infos := []string{ctx.Repo.Repository.DefaultBranch, ctx.Repo.Repository.DefaultBranch} + if infoPath != "" { + infos = strings.SplitN(infoPath, "...", 2) + if len(infos) != 2 { + if infos = strings.SplitN(infoPath, "..", 2); len(infos) != 2 { + infos = []string{ctx.Repo.Repository.DefaultBranch, infoPath} + } + } + } + + _, _, headGitRepo, ci, _, _ := parseCompareInfo(ctx, api.CreatePullRequestOption{ + Base: infos[0], + Head: infos[1], + }) + if ctx.Written() { + return + } + defer headGitRepo.Close() + + verification := ctx.FormString("verification") == "" || ctx.FormBool("verification") + files := ctx.FormString("files") == "" || ctx.FormBool("files") + + apiCommits := make([]*api.Commit, 0, len(ci.Commits)) + userCache := make(map[string]*user_model.User) + for i := 0; i < len(ci.Commits); i++ { + apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, ci.Commits[i], userCache, + convert.ToCommitOptions{ + Stat: true, + Verification: verification, + Files: files, + }) + if err != nil { + ctx.ServerError("toCommit", err) + return + } + apiCommits = append(apiCommits, apiCommit) + } + + ctx.JSON(http.StatusOK, &api.Compare{ + TotalCommits: len(ci.Commits), + Commits: apiCommits, + }) +} diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index 3e23aa4d5a..c3219f28d6 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -414,3 +414,9 @@ type swaggerRepoNewIssuePinsAllowed struct { // in:body Body api.NewIssuePinsAllowed `json:"body"` } + +// swagger:response Compare +type swaggerCompare struct { + // in:body + Body api.Compare `json:"body"` +} diff --git a/routers/common/compare.go b/routers/common/compare.go new file mode 100644 index 0000000000..4d1cc2f0d8 --- /dev/null +++ b/routers/common/compare.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package common + +import ( + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" +) + +// CompareInfo represents the collected results from ParseCompareInfo +type CompareInfo struct { + HeadUser *user_model.User + HeadRepo *repo_model.Repository + HeadGitRepo *git.Repository + CompareInfo *git.CompareInfo + BaseBranch string + HeadBranch string + DirectComparison bool +} diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index cfb0e859bd..035a92f228 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -35,6 +35,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context/upload" "code.gitea.io/gitea/services/gitdiff" @@ -185,21 +186,10 @@ func setCsvCompareContext(ctx *context.Context) { } } -// CompareInfo represents the collected results from ParseCompareInfo -type CompareInfo struct { - HeadUser *user_model.User - HeadRepo *repo_model.Repository - HeadGitRepo *git.Repository - CompareInfo *git.CompareInfo - BaseBranch string - HeadBranch string - DirectComparison bool -} - // ParseCompareInfo parse compare info between two commit for preparing comparing references -func ParseCompareInfo(ctx *context.Context) *CompareInfo { +func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { baseRepo := ctx.Repo.Repository - ci := &CompareInfo{} + ci := &common.CompareInfo{} fileOnly := ctx.FormBool("file-only") @@ -576,7 +566,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { // PrepareCompareDiff renders compare diff page func PrepareCompareDiff( ctx *context.Context, - ci *CompareInfo, + ci *common.CompareInfo, whitespaceBehavior git.TrustedCmdArgs, ) bool { var ( |