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