You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

commit.go 9.2 kB

11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "path"
  7. "strings"
  8. "code.gitea.io/git"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/base"
  11. "code.gitea.io/gitea/modules/context"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/setting"
  14. "github.com/Unknwon/paginater"
  15. )
  16. const (
  17. tplCommits base.TplName = "repo/commits"
  18. tplGraph base.TplName = "repo/graph"
  19. tplDiff base.TplName = "repo/diff/page"
  20. )
  21. // RefCommits render commits page
  22. func RefCommits(ctx *context.Context) {
  23. switch {
  24. case len(ctx.Repo.TreePath) == 0:
  25. Commits(ctx)
  26. case ctx.Repo.TreePath == "search":
  27. SearchCommits(ctx)
  28. default:
  29. FileHistory(ctx)
  30. }
  31. }
  32. // Commits render branch's commits
  33. func Commits(ctx *context.Context) {
  34. ctx.Data["PageIsCommits"] = true
  35. if ctx.Repo.Commit == nil {
  36. ctx.Handle(404, "Commit not found", nil)
  37. return
  38. }
  39. ctx.Data["PageIsViewCode"] = true
  40. commitsCount, err := ctx.Repo.GetCommitsCount()
  41. if err != nil {
  42. ctx.Handle(500, "GetCommitsCount", err)
  43. return
  44. }
  45. page := ctx.QueryInt("page")
  46. if page <= 1 {
  47. page = 1
  48. }
  49. ctx.Data["Page"] = paginater.New(int(commitsCount), git.CommitsRangeSize, page, 5)
  50. // Both `git log branchName` and `git log commitId` work.
  51. commits, err := ctx.Repo.Commit.CommitsByRange(page)
  52. if err != nil {
  53. ctx.Handle(500, "CommitsByRange", err)
  54. return
  55. }
  56. commits = models.ValidateCommitsWithEmails(commits)
  57. commits = models.ParseCommitsWithSignature(commits)
  58. commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
  59. ctx.Data["Commits"] = commits
  60. ctx.Data["Username"] = ctx.Repo.Owner.Name
  61. ctx.Data["Reponame"] = ctx.Repo.Repository.Name
  62. ctx.Data["CommitCount"] = commitsCount
  63. ctx.Data["Branch"] = ctx.Repo.BranchName
  64. ctx.HTML(200, tplCommits)
  65. }
  66. // Graph render commit graph - show commits from all branches.
  67. func Graph(ctx *context.Context) {
  68. ctx.Data["PageIsCommits"] = true
  69. ctx.Data["PageIsViewCode"] = true
  70. commitsCount, err := ctx.Repo.GetCommitsCount()
  71. if err != nil {
  72. ctx.Handle(500, "GetCommitsCount", err)
  73. return
  74. }
  75. graph, err := models.GetCommitGraph(ctx.Repo.GitRepo)
  76. if err != nil {
  77. ctx.Handle(500, "GetCommitGraph", err)
  78. return
  79. }
  80. ctx.Data["Graph"] = graph
  81. ctx.Data["Username"] = ctx.Repo.Owner.Name
  82. ctx.Data["Reponame"] = ctx.Repo.Repository.Name
  83. ctx.Data["CommitCount"] = commitsCount
  84. ctx.Data["Branch"] = ctx.Repo.BranchName
  85. ctx.Data["RequireGitGraph"] = true
  86. ctx.HTML(200, tplGraph)
  87. }
  88. // SearchCommits render commits filtered by keyword
  89. func SearchCommits(ctx *context.Context) {
  90. ctx.Data["PageIsCommits"] = true
  91. ctx.Data["PageIsViewCode"] = true
  92. keyword := strings.Trim(ctx.Query("q"), " ")
  93. if len(keyword) == 0 {
  94. ctx.Redirect(ctx.Repo.RepoLink + "/commits/" + ctx.Repo.BranchNameSubURL())
  95. return
  96. }
  97. all := ctx.QueryBool("all")
  98. commits, err := ctx.Repo.Commit.SearchCommits(keyword, all)
  99. if err != nil {
  100. ctx.Handle(500, "SearchCommits", err)
  101. return
  102. }
  103. commits = models.ValidateCommitsWithEmails(commits)
  104. commits = models.ParseCommitsWithSignature(commits)
  105. commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
  106. ctx.Data["Commits"] = commits
  107. ctx.Data["Keyword"] = keyword
  108. if all {
  109. ctx.Data["All"] = "checked"
  110. }
  111. ctx.Data["Username"] = ctx.Repo.Owner.Name
  112. ctx.Data["Reponame"] = ctx.Repo.Repository.Name
  113. ctx.Data["CommitCount"] = commits.Len()
  114. ctx.Data["Branch"] = ctx.Repo.BranchName
  115. ctx.HTML(200, tplCommits)
  116. }
  117. // FileHistory show a file's reversions
  118. func FileHistory(ctx *context.Context) {
  119. ctx.Data["IsRepoToolbarCommits"] = true
  120. fileName := ctx.Repo.TreePath
  121. if len(fileName) == 0 {
  122. Commits(ctx)
  123. return
  124. }
  125. branchName := ctx.Repo.BranchName
  126. commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(branchName, fileName)
  127. if err != nil {
  128. ctx.Handle(500, "FileCommitsCount", err)
  129. return
  130. } else if commitsCount == 0 {
  131. ctx.Handle(404, "FileCommitsCount", nil)
  132. return
  133. }
  134. page := ctx.QueryInt("page")
  135. if page <= 1 {
  136. page = 1
  137. }
  138. ctx.Data["Page"] = paginater.New(int(commitsCount), git.CommitsRangeSize, page, 5)
  139. commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(branchName, fileName, page)
  140. if err != nil {
  141. ctx.Handle(500, "CommitsByFileAndRange", err)
  142. return
  143. }
  144. commits = models.ValidateCommitsWithEmails(commits)
  145. commits = models.ParseCommitsWithSignature(commits)
  146. commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
  147. ctx.Data["Commits"] = commits
  148. ctx.Data["Username"] = ctx.Repo.Owner.Name
  149. ctx.Data["Reponame"] = ctx.Repo.Repository.Name
  150. ctx.Data["FileName"] = fileName
  151. ctx.Data["CommitCount"] = commitsCount
  152. ctx.Data["Branch"] = branchName
  153. ctx.HTML(200, tplCommits)
  154. }
  155. // Diff show different from current commit to previous commit
  156. func Diff(ctx *context.Context) {
  157. ctx.Data["PageIsDiff"] = true
  158. ctx.Data["RequireHighlightJS"] = true
  159. userName := ctx.Repo.Owner.Name
  160. repoName := ctx.Repo.Repository.Name
  161. commitID := ctx.Params(":sha")
  162. commit, err := ctx.Repo.GitRepo.GetCommit(commitID)
  163. if err != nil {
  164. if git.IsErrNotExist(err) {
  165. ctx.Handle(404, "Repo.GitRepo.GetCommit", err)
  166. } else {
  167. ctx.Handle(500, "Repo.GitRepo.GetCommit", err)
  168. }
  169. return
  170. }
  171. if len(commitID) != 40 {
  172. commitID = commit.ID.String()
  173. }
  174. statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository, ctx.Repo.Commit.ID.String(), 0)
  175. if err != nil {
  176. log.Error(3, "GetLatestCommitStatus: %v", err)
  177. }
  178. ctx.Data["CommitStatus"] = models.CalcCommitStatus(statuses)
  179. diff, err := models.GetDiffCommit(models.RepoPath(userName, repoName),
  180. commitID, setting.Git.MaxGitDiffLines,
  181. setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
  182. if err != nil {
  183. ctx.Handle(404, "GetDiffCommit", err)
  184. return
  185. }
  186. parents := make([]string, commit.ParentCount())
  187. for i := 0; i < commit.ParentCount(); i++ {
  188. sha, err := commit.ParentID(i)
  189. parents[i] = sha.String()
  190. if err != nil {
  191. ctx.Handle(404, "repo.Diff", err)
  192. return
  193. }
  194. }
  195. ctx.Data["CommitID"] = commitID
  196. ctx.Data["Username"] = userName
  197. ctx.Data["Reponame"] = repoName
  198. ctx.Data["IsImageFile"] = commit.IsImageFile
  199. ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
  200. ctx.Data["Commit"] = commit
  201. ctx.Data["Verification"] = models.ParseCommitWithSignature(commit)
  202. ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
  203. ctx.Data["Diff"] = diff
  204. ctx.Data["Parents"] = parents
  205. ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
  206. ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", commitID)
  207. if commit.ParentCount() > 0 {
  208. ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", parents[0])
  209. }
  210. ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", commitID)
  211. ctx.HTML(200, tplDiff)
  212. }
  213. // RawDiff dumps diff results of repository in given commit ID to io.Writer
  214. func RawDiff(ctx *context.Context) {
  215. if err := models.GetRawDiff(
  216. models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name),
  217. ctx.Params(":sha"),
  218. models.RawDiffType(ctx.Params(":ext")),
  219. ctx.Resp,
  220. ); err != nil {
  221. ctx.Handle(500, "GetRawDiff", err)
  222. return
  223. }
  224. }
  225. // CompareDiff show different from one commit to another commit
  226. func CompareDiff(ctx *context.Context) {
  227. ctx.Data["IsRepoToolbarCommits"] = true
  228. ctx.Data["IsDiffCompare"] = true
  229. userName := ctx.Repo.Owner.Name
  230. repoName := ctx.Repo.Repository.Name
  231. beforeCommitID := ctx.Params(":before")
  232. afterCommitID := ctx.Params(":after")
  233. commit, err := ctx.Repo.GitRepo.GetCommit(afterCommitID)
  234. if err != nil {
  235. ctx.Handle(404, "GetCommit", err)
  236. return
  237. }
  238. diff, err := models.GetDiffRange(models.RepoPath(userName, repoName), beforeCommitID,
  239. afterCommitID, setting.Git.MaxGitDiffLines,
  240. setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
  241. if err != nil {
  242. ctx.Handle(404, "GetDiffRange", err)
  243. return
  244. }
  245. commits, err := commit.CommitsBeforeUntil(beforeCommitID)
  246. if err != nil {
  247. ctx.Handle(500, "CommitsBeforeUntil", err)
  248. return
  249. }
  250. commits = models.ValidateCommitsWithEmails(commits)
  251. commits = models.ParseCommitsWithSignature(commits)
  252. commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
  253. ctx.Data["CommitRepoLink"] = ctx.Repo.RepoLink
  254. ctx.Data["Commits"] = commits
  255. ctx.Data["CommitCount"] = commits.Len()
  256. ctx.Data["BeforeCommitID"] = beforeCommitID
  257. ctx.Data["AfterCommitID"] = afterCommitID
  258. ctx.Data["Username"] = userName
  259. ctx.Data["Reponame"] = repoName
  260. ctx.Data["IsImageFile"] = commit.IsImageFile
  261. ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID) + " · " + userName + "/" + repoName
  262. ctx.Data["Commit"] = commit
  263. ctx.Data["Diff"] = diff
  264. ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
  265. ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", afterCommitID)
  266. ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", beforeCommitID)
  267. ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", afterCommitID)
  268. ctx.Data["RequireHighlightJS"] = true
  269. ctx.HTML(200, tplDiff)
  270. }