From 876a08fe063a72a6833ecd9d84d3568c14b6e143 Mon Sep 17 00:00:00 2001 From: hang Date: Mon, 6 Dec 2021 13:56:39 +0800 Subject: [PATCH] add:file_commit --- modules/git/commit.go | 5 ++ routers/api/v1/api.go | 3 + routers/api/v1/repo/commits.go | 139 +++++++++++++++++++++++++++++++++ routers/api/v1/swagger/repo.go | 22 ++++++ templates/swagger/v1_json.tmpl | 99 +++++++++++++++++++++++ 5 files changed, 268 insertions(+) diff --git a/modules/git/commit.go b/modules/git/commit.go index 3ce2b0388..d63b71a87 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -191,6 +191,11 @@ func (c *Commit) CommitsByRange(page, pageSize int) (*list.List, error) { return c.repo.commitsByRange(c.ID, page, pageSize) } +// CommitsByFileAndRange returns the specific page page commits before current revision and file, every page's number default by CommitsRangeSize +func (c *Commit) CommitsByFileAndRange(file string, page, pageSize int) (*list.List, error) { + return c.repo.CommitsByFileAndRange(c.ID.String(), file, page) +} + // CommitsBefore returns all the commits before current revision func (c *Commit) CommitsBefore() (*list.List, error) { return c.repo.getCommitsBefore(c.ID) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 38eca05c8..73338e51b 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -768,6 +768,9 @@ func Routes() *web.Route { m.Group("/count", func() { m.Get("", viewfile.GetCommitCount) //**** }) + m.Group("/file_commits", func() { + m.Get("/*", repo.GetFileAllCommits) + }) m.Group("/hooks", func() { m.Combo("").Get(repo.ListHooks). Post(bind(api.CreateHookOption{}), repo.CreateHook) diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go index 7d5a9aed1..e4dd16095 100644 --- a/routers/api/v1/repo/commits.go +++ b/routers/api/v1/repo/commits.go @@ -396,3 +396,142 @@ func GetCommitsCount(ctx *context.APIContext) { } ctx.JSON(http.StatusOK, &ctx.Repo) } + +// GetFileAllCommits get all commits by path on a repository +func GetFileAllCommits(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/file_commits/{filepath} repository repoGetFileAllCommits + // --- + // summary: Get a list of all commits by filepath from a repository *** + // 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: filepath + // in: path + // description: filepath of the file to get + // type: string + // required: true + // - name: sha + // in: query + // description: SHA or branch to start listing commits from (usually 'master') + // type: string + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer + // responses: + // "200": + // "$ref": "#/responses/FileCommitList" + // "404": + // "$ref": "#/responses/notFound" + // "409": + // "$ref": "#/responses/EmptyRepository" + + if ctx.Repo.Repository.IsEmpty { + ctx.JSON(http.StatusConflict, api.APIError{ + Message: "Git Repository is empty", + URL: setting.API.SwaggerURL, + }) + return + } + gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath()) + if err != nil { + ctx.Error(http.StatusInternalServerError, "Get the GitRepo", err) + return + } + defer gitRepo.Close() + + listOptions := utils.GetListOptions(ctx) + if listOptions.Page <= 0 { + listOptions.Page = 1 + } + + if listOptions.PageSize > setting.Git.CommitsRangeSize { + listOptions.PageSize = setting.Git.CommitsRangeSize + } + + sha := ctx.Query("sha") + treePath := ctx.Params(":*") + + var baseCommit *git.Commit + var commitsCountTotal int64 + if len(sha) == 0 { + head, err := gitRepo.GetHEADBranch() + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetHeadBranch", err) + return + + } + baseCommit, err = gitRepo.GetBranchCommit(head.Name) + if err != nil { + + ctx.Error(http.StatusInternalServerError, "Getcommit ", err) + return + } + + commitsCountTotal, err = git.CommitsCountFiles(gitRepo.Path, []string{head.Name}, []string{treePath}) // get th commmit count by file + if err != nil { + ctx.Error(http.StatusInternalServerError, "CommmisCountFiles", err) + return + } + } else { + baseCommit, err = gitRepo.GetCommit(sha) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetCommit", err) + return + } + commitsCountTotal, err = git.CommitsCountFiles(gitRepo.Path, []string{sha}, []string{treePath}) + if err != nil { + ctx.Error(http.StatusInternalServerError, "CommitsCountFiles", err) + return + } + + } + pageCount := int(math.Ceil(float64(commitsCountTotal) / float64(listOptions.PageSize))) + commits, err := baseCommit.CommitsByFileAndRange(treePath, listOptions.Page, listOptions.PageSize) + if err != nil { + ctx.Error(http.StatusInternalServerError, "CommitByFileAndRange", err) + return + } + userCache := make(map[string]*models.User) + apiCommits := make([]*api.Commit, commits.Len()) + + i := 0 + + for commitPointer := commits.Front(); commitPointer != nil; commitPointer = commitPointer.Next() { + commit := commitPointer.Value.(*git.Commit) + + // Create json struct + apiCommits[i], err = convert.ToCommit(ctx.Repo.Repository, commit, userCache) + if err != nil { + ctx.Error(http.StatusInternalServerError, "toCommit", err) + return + } + + i++ + } + // kept for backwards compatibility + ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page)) + ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize)) + ctx.Header().Set("X-Total", strconv.FormatInt(commitsCountTotal, 10)) + ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount)) + ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < pageCount)) + + ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize) + ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", commitsCountTotal)) + + ctx.JSON(http.StatusOK, apiCommits) +} diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index 4eb110908..0226ee205 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -283,6 +283,28 @@ type swaggerCommitList struct { Body []api.Commit `json:"body"` } +// FileCommitList +// swagger:response FileCommitList +type swaggerFileCommitList struct { + // The current page + Page int `json:"X-Page"` + + // Commits per page + PerPage int `json:"X-PerPage"` + + // Total commit count + Total int `json:"X-Total"` + + // Total number of pages + PageCount int `json:"X-PageCount"` + + // True if there is another page + HasMore bool `json:"X-HasMore"` + + // in: body + Body []api.Commit `json:"body"` +} + // EmptyRepository // swagger:response EmptyRepository type swaggerEmptyRepository struct { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 8dfcb63c0..57f2ffcc0 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -3706,6 +3706,70 @@ } } }, + "/repos/{owner}/{repo}/file_commits/{filepath}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Get a list of all commits by filepath from a repository ***", + "operationId": "repoGetFileAllCommits", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "filepath of the file to get", + "name": "filepath", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "SHA or branch to start listing commits from (usually 'master')", + "name": "sha", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/FileCommitList" + }, + "404": { + "$ref": "#/responses/notFound" + }, + "409": { + "$ref": "#/responses/EmptyRepository" + } + } + } + }, "/repos/{owner}/{repo}/find": { "get": { "produces": [ @@ -18384,6 +18448,41 @@ "$ref": "#/definitions/APIError" } }, + "FileCommitList": { + "description": "FileCommitList", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Commit" + } + }, + "headers": { + "X-HasMore": { + "type": "boolean", + "description": "True if there is another page" + }, + "X-Page": { + "type": "integer", + "format": "int64", + "description": "The current page" + }, + "X-PageCount": { + "type": "integer", + "format": "int64", + "description": "Total number of pages" + }, + "X-PerPage": { + "type": "integer", + "format": "int64", + "description": "Commits per page" + }, + "X-Total": { + "type": "integer", + "format": "int64", + "description": "Total commit count" + } + } + }, "FileDeleteResponse": { "description": "FileDeleteResponse", "schema": {