repo2.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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 models
  5. import (
  6. "fmt"
  7. "path"
  8. "strings"
  9. "time"
  10. "github.com/Unknwon/com"
  11. "github.com/gogits/git"
  12. )
  13. type Commit struct {
  14. Author string
  15. Email string
  16. Date time.Time
  17. SHA string
  18. Message string
  19. }
  20. var (
  21. ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded")
  22. )
  23. type RepoFile struct {
  24. *git.TreeEntry
  25. Path string
  26. Message string
  27. Created time.Time
  28. Size int64
  29. Repo *git.Repository
  30. LastCommit string
  31. }
  32. func (file *RepoFile) LookupBlob() (*git.Blob, error) {
  33. if file.Repo == nil {
  34. return nil, ErrRepoFileNotLoaded
  35. }
  36. return file.Repo.LookupBlob(file.Id)
  37. }
  38. func GetBranches(userName, reposName string) ([]string, error) {
  39. repo, err := git.OpenRepository(RepoPath(userName, reposName))
  40. if err != nil {
  41. return nil, err
  42. }
  43. refs, err := repo.AllReferences()
  44. if err != nil {
  45. return nil, err
  46. }
  47. brs := make([]string, len(refs))
  48. for i, ref := range refs {
  49. brs[i] = ref.Name
  50. }
  51. return brs, nil
  52. }
  53. func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, error) {
  54. repo, err := git.OpenRepository(RepoPath(userName, reposName))
  55. if err != nil {
  56. return nil, err
  57. }
  58. ref, err := repo.LookupReference("refs/heads/" + branchName)
  59. if err != nil {
  60. return nil, err
  61. }
  62. lastCommit, err := repo.LookupCommit(ref.Oid)
  63. if err != nil {
  64. return nil, err
  65. }
  66. var repodirs []*RepoFile
  67. var repofiles []*RepoFile
  68. lastCommit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int {
  69. if dirname == rpath {
  70. size, err := repo.ObjectSize(entry.Id)
  71. if err != nil {
  72. return 0
  73. }
  74. var cm = lastCommit
  75. for {
  76. if cm.ParentCount() == 0 {
  77. break
  78. } else if cm.ParentCount() == 1 {
  79. pt, _ := repo.SubTree(cm.Parent(0).Tree, dirname)
  80. if pt == nil {
  81. break
  82. }
  83. pEntry := pt.EntryByName(entry.Name)
  84. if pEntry == nil || !pEntry.Id.Equal(entry.Id) {
  85. break
  86. } else {
  87. cm = cm.Parent(0)
  88. }
  89. } else {
  90. var emptyCnt = 0
  91. var sameIdcnt = 0
  92. for i := 0; i < cm.ParentCount(); i++ {
  93. p := cm.Parent(i)
  94. pt, _ := repo.SubTree(p.Tree, dirname)
  95. var pEntry *git.TreeEntry
  96. if pt != nil {
  97. pEntry = pt.EntryByName(entry.Name)
  98. }
  99. if pEntry == nil {
  100. if emptyCnt == cm.ParentCount()-1 {
  101. goto loop
  102. } else {
  103. emptyCnt = emptyCnt + 1
  104. continue
  105. }
  106. } else {
  107. if !pEntry.Id.Equal(entry.Id) {
  108. goto loop
  109. } else {
  110. if sameIdcnt == cm.ParentCount()-1 {
  111. // TODO: now follow the first parent commit?
  112. cm = cm.Parent(0)
  113. break
  114. }
  115. sameIdcnt = sameIdcnt + 1
  116. }
  117. }
  118. }
  119. }
  120. }
  121. loop:
  122. rp := &RepoFile{
  123. entry,
  124. path.Join(dirname, entry.Name),
  125. cm.Message(),
  126. cm.Committer.When,
  127. size,
  128. repo,
  129. cm.Id().String(),
  130. }
  131. if entry.IsFile() {
  132. repofiles = append(repofiles, rp)
  133. } else if entry.IsDir() {
  134. repodirs = append(repodirs, rp)
  135. }
  136. }
  137. return 0
  138. })
  139. return append(repodirs, repofiles...), nil
  140. }
  141. func GetLastestCommit(userName, repoName string) (*Commit, error) {
  142. stdout, _, err := com.ExecCmd("git", "--git-dir="+RepoPath(userName, repoName), "log", "-1")
  143. if err != nil {
  144. return nil, err
  145. }
  146. commit := new(Commit)
  147. for _, line := range strings.Split(stdout, "\n") {
  148. if len(line) == 0 {
  149. continue
  150. }
  151. switch {
  152. case line[0] == 'c':
  153. commit.SHA = line[7:]
  154. case line[0] == 'A':
  155. infos := strings.SplitN(line, " ", 3)
  156. commit.Author = infos[1]
  157. commit.Email = infos[2][1 : len(infos[2])-1]
  158. case line[0] == 'D':
  159. commit.Date, err = time.Parse("Mon Jan 02 15:04:05 2006 -0700", line[8:])
  160. if err != nil {
  161. return nil, err
  162. }
  163. case line[:4] == " ":
  164. commit.Message = line[4:]
  165. }
  166. }
  167. return commit, nil
  168. }
  169. func GetCommits(userName, reposName, branchname string) ([]*git.Commit, error) {
  170. repo, err := git.OpenRepository(RepoPath(userName, reposName))
  171. if err != nil {
  172. return nil, err
  173. }
  174. r, err := repo.LookupReference(fmt.Sprintf("refs/heads/%s", branchname))
  175. if err != nil {
  176. return nil, err
  177. }
  178. return r.AllCommits()
  179. }