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

325 lines
8.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  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. "github.com/Unknwon/com"
  9. "github.com/gogits/gogs/models"
  10. "github.com/gogits/gogs/modules/base"
  11. "github.com/gogits/gogs/modules/git"
  12. "github.com/gogits/gogs/modules/middleware"
  13. "github.com/gogits/gogs/modules/setting"
  14. )
  15. const (
  16. COMMITS base.TplName = "repo/commits"
  17. DIFF base.TplName = "repo/diff"
  18. )
  19. func RefCommits(ctx *middleware.Context) {
  20. switch {
  21. case len(ctx.Repo.TreeName) == 0:
  22. Commits(ctx)
  23. case ctx.Repo.TreeName == "search":
  24. SearchCommits(ctx)
  25. default:
  26. FileHistory(ctx)
  27. }
  28. }
  29. func RenderIssueLinks(oldCommits *list.List, repoLink string) *list.List {
  30. newCommits := list.New()
  31. for e := oldCommits.Front(); e != nil; e = e.Next() {
  32. c := e.Value.(*git.Commit)
  33. c.CommitMessage = c.CommitMessage
  34. newCommits.PushBack(c)
  35. }
  36. return newCommits
  37. }
  38. func Commits(ctx *middleware.Context) {
  39. ctx.Data["IsRepoToolbarCommits"] = true
  40. userName := ctx.Repo.Owner.Name
  41. repoName := ctx.Repo.Repository.Name
  42. brs, err := ctx.Repo.GitRepo.GetBranches()
  43. if err != nil {
  44. ctx.Handle(500, "GetBranches", err)
  45. return
  46. } else if len(brs) == 0 {
  47. ctx.Handle(404, "GetBranches", nil)
  48. return
  49. }
  50. commitsCount, err := ctx.Repo.Commit.CommitsCount()
  51. if err != nil {
  52. ctx.Handle(500, "GetCommitsCount", err)
  53. return
  54. }
  55. // Calculate and validate page number.
  56. page, _ := com.StrTo(ctx.Query("p")).Int()
  57. if page < 1 {
  58. page = 1
  59. }
  60. lastPage := page - 1
  61. if lastPage < 0 {
  62. lastPage = 0
  63. }
  64. nextPage := page + 1
  65. if page*50 > commitsCount {
  66. nextPage = 0
  67. }
  68. // Both `git log branchName` and `git log commitId` work.
  69. commits, err := ctx.Repo.Commit.CommitsByRange(page)
  70. if err != nil {
  71. ctx.Handle(500, "CommitsByRange", err)
  72. return
  73. }
  74. commits = RenderIssueLinks(commits, ctx.Repo.RepoLink)
  75. commits = models.ValidateCommitsWithEmails(commits)
  76. ctx.Data["Commits"] = commits
  77. ctx.Data["Username"] = userName
  78. ctx.Data["Reponame"] = repoName
  79. ctx.Data["CommitCount"] = commitsCount
  80. ctx.Data["LastPageNum"] = lastPage
  81. ctx.Data["NextPageNum"] = nextPage
  82. ctx.HTML(200, COMMITS)
  83. }
  84. func SearchCommits(ctx *middleware.Context) {
  85. ctx.Data["IsSearchPage"] = true
  86. ctx.Data["IsRepoToolbarCommits"] = true
  87. keyword := ctx.Query("q")
  88. if len(keyword) == 0 {
  89. ctx.Redirect(ctx.Repo.RepoLink + "/commits/" + ctx.Repo.BranchName)
  90. return
  91. }
  92. userName := ctx.Params(":username")
  93. repoName := ctx.Params(":reponame")
  94. brs, err := ctx.Repo.GitRepo.GetBranches()
  95. if err != nil {
  96. ctx.Handle(500, "GetBranches", err)
  97. return
  98. } else if len(brs) == 0 {
  99. ctx.Handle(404, "GetBranches", nil)
  100. return
  101. }
  102. commits, err := ctx.Repo.Commit.SearchCommits(keyword)
  103. if err != nil {
  104. ctx.Handle(500, "SearchCommits", err)
  105. return
  106. }
  107. commits = RenderIssueLinks(commits, ctx.Repo.RepoLink)
  108. commits = models.ValidateCommitsWithEmails(commits)
  109. ctx.Data["Keyword"] = keyword
  110. ctx.Data["Username"] = userName
  111. ctx.Data["Reponame"] = repoName
  112. ctx.Data["CommitCount"] = commits.Len()
  113. ctx.Data["Commits"] = commits
  114. ctx.HTML(200, COMMITS)
  115. }
  116. func FileHistory(ctx *middleware.Context) {
  117. ctx.Data["IsRepoToolbarCommits"] = true
  118. fileName := ctx.Repo.TreeName
  119. if len(fileName) == 0 {
  120. Commits(ctx)
  121. return
  122. }
  123. userName := ctx.Repo.Owner.Name
  124. repoName := ctx.Repo.Repository.Name
  125. branchName := ctx.Repo.BranchName
  126. brs, err := ctx.Repo.GitRepo.GetBranches()
  127. if err != nil {
  128. ctx.Handle(500, "GetBranches", err)
  129. return
  130. } else if len(brs) == 0 {
  131. ctx.Handle(404, "GetBranches", nil)
  132. return
  133. }
  134. commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(branchName, fileName)
  135. if err != nil {
  136. ctx.Handle(500, "repo.FileHistory(GetCommitsCount)", err)
  137. return
  138. } else if commitsCount == 0 {
  139. ctx.Handle(404, "repo.FileHistory", nil)
  140. return
  141. }
  142. // Calculate and validate page number.
  143. page := com.StrTo(ctx.Query("p")).MustInt()
  144. if page < 1 {
  145. page = 1
  146. }
  147. lastPage := page - 1
  148. if lastPage < 0 {
  149. lastPage = 0
  150. }
  151. nextPage := page + 1
  152. if nextPage*50 > commitsCount {
  153. nextPage = 0
  154. }
  155. commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(
  156. branchName, fileName, page)
  157. if err != nil {
  158. ctx.Handle(500, "repo.FileHistory(CommitsByRange)", err)
  159. return
  160. }
  161. commits = RenderIssueLinks(commits, ctx.Repo.RepoLink)
  162. commits = models.ValidateCommitsWithEmails(commits)
  163. ctx.Data["Commits"] = commits
  164. ctx.Data["Username"] = userName
  165. ctx.Data["Reponame"] = repoName
  166. ctx.Data["FileName"] = fileName
  167. ctx.Data["CommitCount"] = commitsCount
  168. ctx.Data["LastPageNum"] = lastPage
  169. ctx.Data["NextPageNum"] = nextPage
  170. ctx.HTML(200, COMMITS)
  171. }
  172. func Diff(ctx *middleware.Context) {
  173. ctx.Data["IsRepoToolbarCommits"] = true
  174. userName := ctx.Repo.Owner.Name
  175. repoName := ctx.Repo.Repository.Name
  176. commitId := ctx.Repo.CommitId
  177. commit := ctx.Repo.Commit
  178. commit.CommitMessage = commit.CommitMessage
  179. diff, err := models.GetDiffCommit(models.RepoPath(userName, repoName),
  180. commitId, setting.Git.MaxGitDiffLines)
  181. if err != nil {
  182. ctx.Handle(404, "GetDiffCommit", err)
  183. return
  184. }
  185. isImageFile := func(name string) bool {
  186. blob, err := ctx.Repo.Commit.GetBlobByPath(name)
  187. if err != nil {
  188. return false
  189. }
  190. dataRc, err := blob.Data()
  191. if err != nil {
  192. return false
  193. }
  194. buf := make([]byte, 1024)
  195. n, _ := dataRc.Read(buf)
  196. if n > 0 {
  197. buf = buf[:n]
  198. }
  199. _, isImage := base.IsImageFile(buf)
  200. return isImage
  201. }
  202. parents := make([]string, commit.ParentCount())
  203. for i := 0; i < commit.ParentCount(); i++ {
  204. sha, err := commit.ParentId(i)
  205. parents[i] = sha.String()
  206. if err != nil {
  207. ctx.Handle(404, "repo.Diff", err)
  208. return
  209. }
  210. }
  211. ctx.Data["Username"] = userName
  212. ctx.Data["Reponame"] = repoName
  213. ctx.Data["IsImageFile"] = isImageFile
  214. ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitId)
  215. ctx.Data["Commit"] = commit
  216. ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
  217. ctx.Data["Diff"] = diff
  218. ctx.Data["Parents"] = parents
  219. ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
  220. ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", commitId)
  221. if (commit.ParentCount() > 0) {
  222. ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", parents[0])
  223. }
  224. ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", commitId)
  225. ctx.HTML(200, DIFF)
  226. }
  227. func CompareDiff(ctx *middleware.Context) {
  228. ctx.Data["IsRepoToolbarCommits"] = true
  229. ctx.Data["IsDiffCompare"] = true
  230. userName := ctx.Repo.Owner.Name
  231. repoName := ctx.Repo.Repository.Name
  232. beforeCommitId := ctx.Params(":before")
  233. afterCommitId := ctx.Params(":after")
  234. commit, err := ctx.Repo.GitRepo.GetCommit(afterCommitId)
  235. if err != nil {
  236. ctx.Handle(404, "GetCommit", err)
  237. return
  238. }
  239. diff, err := models.GetDiffRange(models.RepoPath(userName, repoName), beforeCommitId,
  240. afterCommitId, setting.Git.MaxGitDiffLines)
  241. if err != nil {
  242. ctx.Handle(404, "GetDiffRange", err)
  243. return
  244. }
  245. isImageFile := func(name string) bool {
  246. blob, err := commit.GetBlobByPath(name)
  247. if err != nil {
  248. return false
  249. }
  250. dataRc, err := blob.Data()
  251. if err != nil {
  252. return false
  253. }
  254. buf := make([]byte, 1024)
  255. n, _ := dataRc.Read(buf)
  256. if n > 0 {
  257. buf = buf[:n]
  258. }
  259. _, isImage := base.IsImageFile(buf)
  260. return isImage
  261. }
  262. commits, err := commit.CommitsBeforeUntil(beforeCommitId)
  263. if err != nil {
  264. ctx.Handle(500, "CommitsBeforeUntil", err)
  265. return
  266. }
  267. commits = models.ValidateCommitsWithEmails(commits)
  268. ctx.Data["Commits"] = commits
  269. ctx.Data["CommitCount"] = commits.Len()
  270. ctx.Data["BeforeCommitId"] = beforeCommitId
  271. ctx.Data["AfterCommitId"] = afterCommitId
  272. ctx.Data["Username"] = userName
  273. ctx.Data["Reponame"] = repoName
  274. ctx.Data["IsImageFile"] = isImageFile
  275. ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitId) + "..." + base.ShortSha(afterCommitId) + " · " + userName + "/" + repoName
  276. ctx.Data["Commit"] = commit
  277. ctx.Data["Diff"] = diff
  278. ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
  279. ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", afterCommitId)
  280. ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", beforeCommitId)
  281. ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", afterCommitId)
  282. ctx.HTML(200, DIFF)
  283. }