Skip to content

Commit 9634f56

Browse files
committed
Add API to get file comment history
1 parent ab13797 commit 9634f56

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

integrations/api_repo_git_commits_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,20 @@ func TestDownloadCommitDiffOrPatch(t *testing.T) {
132132
resp.Body.String())
133133

134134
}
135+
136+
func TestGetFileHistory(t *testing.T) {
137+
user := db.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
138+
// Login as User2.
139+
session := loginUser(t, user.Name)
140+
token := getTokenForLoggedInUser(t, session)
141+
142+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo16/git/history/readme.md?token="+token+"&sha=good-sign", user.Name)
143+
resp := session.MakeRequest(t, req, http.StatusOK)
144+
145+
var apiData []api.Commit
146+
DecodeJSON(t, resp, &apiData)
147+
148+
assert.Len(t, apiData, 3)
149+
assert.Equal(t, "69554a64c1e6030f051e5c3f94bfbd773cd6a324", apiData[0].CommitMeta.SHA)
150+
compareCommitFiles(t, []string{"readme.md"}, apiData[0].Files)
151+
}

routers/api/v1/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route {
965965
m.Get("/blobs/{sha}", context.RepoRefForAPI, repo.GetBlob)
966966
m.Get("/tags/{sha}", context.RepoRefForAPI, repo.GetAnnotatedTag)
967967
m.Get("/notes/{sha}", repo.GetNote)
968+
m.Get("/history/*", context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetFileHistory)
968969
}, reqRepoReader(unit.TypeCode))
969970
m.Group("/contents", func() {
970971
m.Get("", repo.GetContentsList)

routers/api/v1/repo/file.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import (
1414
"code.gitea.io/gitea/models"
1515
"code.gitea.io/gitea/models/unit"
1616
"code.gitea.io/gitea/modules/context"
17+
"code.gitea.io/gitea/modules/convert"
1718
"code.gitea.io/gitea/modules/git"
1819
"code.gitea.io/gitea/modules/repofiles"
20+
"code.gitea.io/gitea/modules/setting"
1921
api "code.gitea.io/gitea/modules/structs"
2022
"code.gitea.io/gitea/modules/web"
2123
"code.gitea.io/gitea/routers/common"
@@ -597,3 +599,86 @@ func GetContentsList(ctx *context.APIContext) {
597599
// same as GetContents(), this function is here because swagger fails if path is empty in GetContents() interface
598600
GetContents(ctx)
599601
}
602+
603+
// GetFileHistory get a file's commit history
604+
func GetFileHistory(ctx *context.APIContext) {
605+
// swagger:operation GET /repos/{owner}/{repo}/git/history/{filepath} repository repoGetFileHistory
606+
// ---
607+
// summary: Get a file's commit history
608+
// produces:
609+
// - application/json
610+
// parameters:
611+
// - name: owner
612+
// in: path
613+
// description: owner of the repo
614+
// type: string
615+
// required: true
616+
// - name: repo
617+
// in: path
618+
// description: name of the repo
619+
// type: string
620+
// required: true
621+
// - name: filepath
622+
// in: path
623+
// description: filepath of the file to get
624+
// type: string
625+
// required: true
626+
// - name: ref
627+
// in: query
628+
// description: "The name of the commit/branch/tag. Default the repository’s default branch (usually master)"
629+
// type: string
630+
// required: false
631+
// - name: page
632+
// in: query
633+
// description: page number of results to return (1-based)
634+
// type: integer
635+
// responses:
636+
// "200":
637+
// "$ref": "#/responses/CommitList"
638+
// "404":
639+
// "$ref": "#/responses/notFound"
640+
641+
if ctx.Repo.Repository.IsEmpty {
642+
ctx.NotFound()
643+
return
644+
}
645+
646+
ref := ctx.FormTrim("ref")
647+
if len(ref) < 1 {
648+
ref = ctx.Repo.Repository.DefaultBranch
649+
}
650+
651+
page := ctx.FormInt("page")
652+
if page <= 1 {
653+
page = 1
654+
}
655+
656+
commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(ref, ctx.Repo.TreePath)
657+
if err != nil {
658+
ctx.Error(http.StatusInternalServerError, "FileCommitsCount", err)
659+
return
660+
} else if commitsCount == 0 {
661+
ctx.NotFound("FileCommitsCount", nil)
662+
return
663+
}
664+
665+
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(ref, ctx.Repo.TreePath, page)
666+
if err != nil {
667+
ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRange", err)
668+
return
669+
}
670+
apiCommits := make([]*api.Commit, len(commits))
671+
for i, commit := range commits {
672+
// Create json struct
673+
apiCommits[i], err = convert.ToCommit(ctx.Repo.Repository, commit, make(map[string]*models.User))
674+
if err != nil {
675+
ctx.Error(http.StatusInternalServerError, "toCommit", err)
676+
return
677+
}
678+
}
679+
680+
ctx.SetLinkHeader(int(commitsCount), setting.Git.CommitsRangeSize)
681+
ctx.SetTotalCountHeader(commitsCount)
682+
683+
ctx.JSON(http.StatusOK, &apiCommits)
684+
}

templates/swagger/v1_json.tmpl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3652,6 +3652,61 @@
36523652
}
36533653
}
36543654
},
3655+
"/repos/{owner}/{repo}/git/history/{filepath}": {
3656+
"get": {
3657+
"produces": [
3658+
"application/json"
3659+
],
3660+
"tags": [
3661+
"repository"
3662+
],
3663+
"summary": "Get a file's commit history",
3664+
"operationId": "repoGetFileHistory",
3665+
"parameters": [
3666+
{
3667+
"type": "string",
3668+
"description": "owner of the repo",
3669+
"name": "owner",
3670+
"in": "path",
3671+
"required": true
3672+
},
3673+
{
3674+
"type": "string",
3675+
"description": "name of the repo",
3676+
"name": "repo",
3677+
"in": "path",
3678+
"required": true
3679+
},
3680+
{
3681+
"type": "string",
3682+
"description": "filepath of the file to get",
3683+
"name": "filepath",
3684+
"in": "path",
3685+
"required": true
3686+
},
3687+
{
3688+
"type": "string",
3689+
"description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
3690+
"name": "ref",
3691+
"in": "query"
3692+
},
3693+
{
3694+
"type": "integer",
3695+
"description": "page number of results to return (1-based)",
3696+
"name": "page",
3697+
"in": "query"
3698+
}
3699+
],
3700+
"responses": {
3701+
"200": {
3702+
"$ref": "#/responses/CommitList"
3703+
},
3704+
"404": {
3705+
"$ref": "#/responses/notFound"
3706+
}
3707+
}
3708+
}
3709+
},
36553710
"/repos/{owner}/{repo}/git/notes/{sha}": {
36563711
"get": {
36573712
"produces": [

0 commit comments

Comments
 (0)