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