context_gin.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package context
  2. import (
  3. "os"
  4. "path"
  5. "strings"
  6. "github.com/G-Node/git-module"
  7. "github.com/G-Node/gogs/internal/db"
  8. "github.com/G-Node/gogs/internal/setting"
  9. "github.com/G-Node/gogs/internal/tool"
  10. "github.com/G-Node/libgin/libgin"
  11. "github.com/unknwon/com"
  12. log "gopkg.in/clog.v1"
  13. )
  14. // readNotice checks if a notice file exists and loads the message to display
  15. // on all pages.
  16. func readNotice(c *Context) {
  17. fileloc := path.Join(setting.CustomPath, "notice")
  18. var maxlen int64 = 1024
  19. if !com.IsExist(fileloc) {
  20. return
  21. }
  22. log.Trace("Found notice file")
  23. fp, err := os.Open(fileloc)
  24. if err != nil {
  25. log.Error(2, "Failed to open notice file %s: %v", fileloc, err)
  26. return
  27. }
  28. defer fp.Close()
  29. finfo, err := fp.Stat()
  30. if err != nil {
  31. log.Error(2, "Failed to stat notice file %s: %v", fileloc, err)
  32. return
  33. }
  34. if finfo.Size() > maxlen { // Refuse to print very long messages
  35. log.Error(2, "Notice file %s size too large [%d > %d]: refusing to render", fileloc, finfo.Size(), maxlen)
  36. return
  37. }
  38. buf := make([]byte, maxlen)
  39. n, err := fp.Read(buf)
  40. if err != nil {
  41. log.Error(2, "Failed to read notice file: %v", err)
  42. return
  43. }
  44. buf = buf[:n]
  45. if !tool.IsTextFile(buf) {
  46. log.Error(2, "Notice file %s does not appear to be a text file: aborting", fileloc)
  47. return
  48. }
  49. noticetext := strings.SplitN(string(buf), "\n", 2)
  50. c.Data["HasNotice"] = true
  51. c.Data["NoticeTitle"] = noticetext[0]
  52. c.Data["NoticeMessage"] = noticetext[1]
  53. }
  54. // getRepoDOI returns the DOI for the repository based on the following rules:
  55. // - if the repository belongs to the DOI user and has a tag that matches the
  56. // DOI prefix, returns the tag.
  57. // - if the repo is forked by the DOI user, check the DOI fork for the tag as above.
  58. // - if the repo is forked by the DOI user and the fork doesn't have a tag,
  59. // returns the (old-style) calculated DOI, based on the hash of the repository
  60. // path.
  61. // - An empty string is returned if it is not not forked by the DOI user.
  62. // If an error occurs at any point, returns an empty string (the error is logged).
  63. // Tag retrieval is allowed to fail and falls back on the hashed DOI method.
  64. func getRepoDOI(c *Context) string {
  65. repo := c.Repo.Repository
  66. var doiFork *db.Repository
  67. if repo.Owner.Name == "doi" {
  68. doiFork = repo
  69. } else {
  70. if forks, err := repo.GetForks(); err == nil {
  71. for _, fork := range forks {
  72. if fork.MustOwner().Name == "doi" {
  73. doiFork = fork
  74. break
  75. }
  76. }
  77. } else {
  78. log.Error(2, "failed to get forks for repository %q (%d): %v", repo.FullName(), repo.ID, err)
  79. return ""
  80. }
  81. }
  82. if doiFork == nil {
  83. // not owned or forked by DOI, so not registered
  84. return ""
  85. }
  86. // check the DOI fork for a tag that matches our DOI prefix
  87. // if multiple exit, get the latest one
  88. doiBase := setting.DOI.Base
  89. doiForkGit, err := git.OpenRepository(doiFork.RepoPath())
  90. if err != nil {
  91. log.Error(2, "failed to open git repository at %q (%d): %v", doiFork.RepoPath(), doiFork.ID, err)
  92. return ""
  93. }
  94. if tags, err := doiForkGit.GetTags(); err == nil {
  95. var latestTime int64
  96. latestTag := ""
  97. for _, tagName := range tags {
  98. if strings.Contains(tagName, doiBase) {
  99. tag, err := doiForkGit.GetTag(tagName)
  100. if err != nil {
  101. // log the error and continue to the next tag
  102. log.Error(2, "failed to get information for tag %q for repository at %q: %v", tagName, doiForkGit.Path, err)
  103. continue
  104. }
  105. commit, err := tag.Commit()
  106. if err != nil {
  107. // log the error and continue to the next tag
  108. log.Error(2, "failed to get commit for tag %q for repository at %q: %v", tagName, doiForkGit.Path, err)
  109. continue
  110. }
  111. commitTime := commit.Committer.When.Unix()
  112. if commitTime > latestTime {
  113. latestTag = tagName
  114. latestTime = commitTime
  115. }
  116. return latestTag
  117. }
  118. }
  119. } else {
  120. // this shouldn't happen even if there are no tags
  121. // log the error, but fall back to the old method anyway
  122. log.Error(2, "failed to get tags for repository at %q: %v", doiForkGit.Path, err)
  123. }
  124. // Has DOI fork but isn't tagged: return old style has-based DOI
  125. repoPath := repo.FullName()
  126. // get base repo name if it's a DOI fork
  127. if c.Repo.Repository.IsFork && c.Repo.Owner.Name == "doi" {
  128. repoPath = c.Repo.Repository.BaseRepo.FullName()
  129. }
  130. uuid := libgin.RepoPathToUUID(repoPath)
  131. return doiBase + uuid[:6]
  132. }