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.3 kB

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