-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Showing
8 changed files
with
250 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright 2024 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package structs | ||
|
||
// Compare represents a comparison between two commits. | ||
type Compare struct { | ||
TotalCommits int `json:"total_commits"` // Total number of commits in the comparison. | ||
Commits []*Commit `json:"commits"` // List of commits in the comparison. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright 2024 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package integration | ||
|
||
import ( | ||
"net/http" | ||
"testing" | ||
|
||
auth_model "code.gitea.io/gitea/models/auth" | ||
"code.gitea.io/gitea/models/unittest" | ||
user_model "code.gitea.io/gitea/models/user" | ||
api "code.gitea.io/gitea/modules/structs" | ||
"code.gitea.io/gitea/tests" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestAPICompareBranches(t *testing.T) { | ||
defer tests.PrepareTestEnv(t)() | ||
|
||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) | ||
// Login as User2. | ||
session := loginUser(t, user.Name) | ||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) | ||
|
||
repoName := "repo20" | ||
|
||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/%s/compare/add-csv...remove-files-b", repoName). | ||
AddTokenAuth(token) | ||
resp := MakeRequest(t, req, http.StatusOK) | ||
|
||
var apiResp *api.Compare | ||
DecodeJSON(t, resp, &apiResp) | ||
|
||
assert.Equal(t, 2, apiResp.TotalCommits) | ||
assert.Len(t, apiResp.Commits, 2) | ||
} |