commits.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package repo
  2. import (
  3. "net/http"
  4. "strings"
  5. "time"
  6. "github.com/gogs/git-module"
  7. api "github.com/gogs/go-gogs-client"
  8. "gogs.io/gogs/internal/conf"
  9. "gogs.io/gogs/internal/context"
  10. "gogs.io/gogs/internal/database"
  11. "gogs.io/gogs/internal/gitutil"
  12. )
  13. // GetAllCommits returns a slice of commits starting from HEAD.
  14. func GetAllCommits(c *context.APIContext) {
  15. // Get pagesize, set default if it is not specified.
  16. pageSize := c.QueryInt("pageSize")
  17. if pageSize == 0 {
  18. pageSize = 30
  19. }
  20. gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
  21. if err != nil {
  22. c.Error(err, "open repository")
  23. return
  24. }
  25. // The response object returned as JSON
  26. result := make([]*api.Commit, 0, pageSize)
  27. commits, err := gitRepo.Log("HEAD", git.LogOptions{MaxCount: pageSize})
  28. if err != nil {
  29. c.Error(err, "git log")
  30. }
  31. for _, commit := range commits {
  32. apiCommit, err := gitCommitToAPICommit(commit, c)
  33. if err != nil {
  34. c.Error(err, "convert git commit to api commit")
  35. return
  36. }
  37. result = append(result, apiCommit)
  38. }
  39. c.JSONSuccess(result)
  40. }
  41. // GetSingleCommit will return a single Commit object based on the specified SHA.
  42. func GetSingleCommit(c *context.APIContext) {
  43. if strings.Contains(c.Req.Request.Header.Get("Accept"), api.MediaApplicationSHA) {
  44. // Just call GetReferenceSHA directly - it will use c.Param("sha")
  45. GetReferenceSHA(c)
  46. return
  47. }
  48. gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
  49. if err != nil {
  50. c.Error(err, "open repository")
  51. return
  52. }
  53. commit, err := gitRepo.CatFileCommit(c.Param(":sha"))
  54. if err != nil {
  55. c.NotFoundOrError(gitutil.NewError(err), "get commit")
  56. return
  57. }
  58. apiCommit, err := gitCommitToAPICommit(commit, c)
  59. if err != nil {
  60. c.Error(err, "convert git commit to api commit")
  61. }
  62. c.JSONSuccess(apiCommit)
  63. }
  64. func GetReferenceSHA(c *context.APIContext) {
  65. gitRepo, err := git.Open(c.Repo.Repository.RepoPath())
  66. if err != nil {
  67. c.Error(err, "open repository")
  68. return
  69. }
  70. ref := c.Param("*")
  71. refType := 0 // 0-unknown, 1-branch, 2-tag
  72. if strings.HasPrefix(ref, git.RefsHeads) {
  73. ref = strings.TrimPrefix(ref, git.RefsHeads)
  74. refType = 1
  75. } else if strings.HasPrefix(ref, git.RefsTags) {
  76. ref = strings.TrimPrefix(ref, git.RefsTags)
  77. refType = 2
  78. } else {
  79. if gitRepo.HasBranch(ref) {
  80. refType = 1
  81. } else if gitRepo.HasTag(ref) {
  82. refType = 2
  83. } else {
  84. c.NotFound()
  85. return
  86. }
  87. }
  88. var sha string
  89. switch refType {
  90. case 1:
  91. sha, err = gitRepo.BranchCommitID(ref)
  92. case 2:
  93. sha, err = gitRepo.TagCommitID(ref)
  94. }
  95. if err != nil {
  96. c.NotFoundOrError(gitutil.NewError(err), "get reference commit ID")
  97. return
  98. }
  99. c.PlainText(http.StatusOK, sha)
  100. }
  101. // gitCommitToApiCommit is a helper function to convert git commit object to API commit.
  102. func gitCommitToAPICommit(commit *git.Commit, c *context.APIContext) (*api.Commit, error) {
  103. // Retrieve author and committer information
  104. var apiAuthor, apiCommitter *api.User
  105. author, err := database.Handle.Users().GetByEmail(c.Req.Context(), commit.Author.Email)
  106. if err != nil && !database.IsErrUserNotExist(err) {
  107. return nil, err
  108. } else if err == nil {
  109. apiAuthor = author.APIFormat()
  110. }
  111. // Save one query if the author is also the committer
  112. if commit.Committer.Email == commit.Author.Email {
  113. apiCommitter = apiAuthor
  114. } else {
  115. committer, err := database.Handle.Users().GetByEmail(c.Req.Context(), commit.Committer.Email)
  116. if err != nil && !database.IsErrUserNotExist(err) {
  117. return nil, err
  118. } else if err == nil {
  119. apiCommitter = committer.APIFormat()
  120. }
  121. }
  122. // Retrieve parent(s) of the commit
  123. apiParents := make([]*api.CommitMeta, commit.ParentsCount())
  124. for i := 0; i < commit.ParentsCount(); i++ {
  125. sha, _ := commit.ParentID(i)
  126. apiParents[i] = &api.CommitMeta{
  127. URL: c.BaseURL + "/repos/" + c.Repo.Repository.FullName() + "/commits/" + sha.String(),
  128. SHA: sha.String(),
  129. }
  130. }
  131. return &api.Commit{
  132. CommitMeta: &api.CommitMeta{
  133. URL: conf.Server.ExternalURL + c.Link[1:],
  134. SHA: commit.ID.String(),
  135. },
  136. HTMLURL: c.Repo.Repository.HTMLURL() + "/commits/" + commit.ID.String(),
  137. RepoCommit: &api.RepoCommit{
  138. URL: conf.Server.ExternalURL + c.Link[1:],
  139. Author: &api.CommitUser{
  140. Name: commit.Author.Name,
  141. Email: commit.Author.Email,
  142. Date: commit.Author.When.Format(time.RFC3339),
  143. },
  144. Committer: &api.CommitUser{
  145. Name: commit.Committer.Name,
  146. Email: commit.Committer.Email,
  147. Date: commit.Committer.When.Format(time.RFC3339),
  148. },
  149. Message: commit.Summary(),
  150. Tree: &api.CommitMeta{
  151. URL: c.BaseURL + "/repos/" + c.Repo.Repository.FullName() + "/tree/" + commit.ID.String(),
  152. SHA: commit.ID.String(),
  153. },
  154. },
  155. Author: apiAuthor,
  156. Committer: apiCommitter,
  157. Parents: apiParents,
  158. }, nil
  159. }