Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

145 строки
4.2 KiB

  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file or at
  5. // https://developers.google.com/open-source/licenses/bsd.
  6. package main
  7. import (
  8. "fmt"
  9. "log"
  10. "regexp"
  11. "strings"
  12. "time"
  13. "github.com/spf13/viper"
  14. "github.com/golang/gddo/doc"
  15. "github.com/golang/gddo/gosrc"
  16. )
  17. var testdataPat = regexp.MustCompile(`/testdata(?:/|$)`)
  18. // crawlDoc fetches the package documentation from the VCS and updates the database.
  19. func crawlDoc(source string, importPath string, pdoc *doc.Package, hasSubdirs bool, nextCrawl time.Time) (*doc.Package, error) {
  20. message := []interface{}{source}
  21. defer func() {
  22. message = append(message, importPath)
  23. log.Println(message...)
  24. }()
  25. if !nextCrawl.IsZero() {
  26. d := time.Since(nextCrawl) / time.Hour
  27. if d > 0 {
  28. message = append(message, "late:", int64(d))
  29. }
  30. }
  31. etag := ""
  32. if pdoc != nil {
  33. etag = pdoc.Etag
  34. message = append(message, "etag:", etag)
  35. }
  36. start := time.Now()
  37. var err error
  38. if strings.HasPrefix(importPath, "code.google.com/p/go.") {
  39. // Old import path for Go sub-repository.
  40. pdoc = nil
  41. err = gosrc.NotFoundError{Message: "old Go sub-repo", Redirect: "golang.org/x/" + importPath[len("code.google.com/p/go."):]}
  42. } else if blocked, e := db.IsBlocked(importPath); blocked && e == nil {
  43. pdoc = nil
  44. err = gosrc.NotFoundError{Message: "blocked."}
  45. } else if testdataPat.MatchString(importPath) {
  46. pdoc = nil
  47. err = gosrc.NotFoundError{Message: "testdata."}
  48. } else {
  49. var pdocNew *doc.Package
  50. pdocNew, err = doc.Get(httpClient, importPath, etag)
  51. message = append(message, "fetch:", int64(time.Since(start)/time.Millisecond))
  52. if err == nil && pdocNew.Name == "" && !hasSubdirs {
  53. for _, e := range pdocNew.Errors {
  54. message = append(message, "err:", e)
  55. }
  56. pdoc = nil
  57. err = gosrc.NotFoundError{Message: "no Go files or subdirs"}
  58. } else if _, ok := err.(gosrc.NotModifiedError); !ok {
  59. pdoc = pdocNew
  60. }
  61. }
  62. maxAge := viper.GetDuration(ConfigMaxAge)
  63. nextCrawl = start.Add(maxAge)
  64. switch {
  65. case strings.HasPrefix(importPath, "github.com/") || (pdoc != nil && len(pdoc.Errors) > 0):
  66. nextCrawl = start.Add(maxAge * 7)
  67. case strings.HasPrefix(importPath, "gist.github.com/"):
  68. // Don't spend time on gists. It's silly thing to do.
  69. nextCrawl = start.Add(maxAge * 30)
  70. }
  71. if err == nil {
  72. message = append(message, "put:", pdoc.Etag)
  73. if err := put(pdoc, nextCrawl); err != nil {
  74. log.Println(err)
  75. }
  76. return pdoc, nil
  77. } else if e, ok := err.(gosrc.NotModifiedError); ok {
  78. if pdoc.Status == gosrc.Active && !isActivePkg(importPath, e.Status) {
  79. if e.Status == gosrc.NoRecentCommits {
  80. e.Status = gosrc.Inactive
  81. }
  82. message = append(message, "archive", e)
  83. pdoc.Status = e.Status
  84. if err := db.Put(pdoc, nextCrawl, false); err != nil {
  85. log.Printf("ERROR db.Put(%q): %v", importPath, err)
  86. }
  87. } else {
  88. // Touch the package without updating and move on to next one.
  89. message = append(message, "touch")
  90. if err := db.SetNextCrawl(importPath, nextCrawl); err != nil {
  91. log.Printf("ERROR db.SetNextCrawl(%q): %v", importPath, err)
  92. }
  93. }
  94. return pdoc, nil
  95. } else if e, ok := err.(gosrc.NotFoundError); ok {
  96. message = append(message, "notfound:", e)
  97. if err := db.Delete(importPath); err != nil {
  98. log.Printf("ERROR db.Delete(%q): %v", importPath, err)
  99. }
  100. return nil, e
  101. } else {
  102. message = append(message, "ERROR:", err)
  103. return nil, err
  104. }
  105. }
  106. func put(pdoc *doc.Package, nextCrawl time.Time) error {
  107. if pdoc.Status == gosrc.NoRecentCommits &&
  108. isActivePkg(pdoc.ImportPath, gosrc.NoRecentCommits) {
  109. pdoc.Status = gosrc.Active
  110. }
  111. if err := db.Put(pdoc, nextCrawl, false); err != nil {
  112. return fmt.Errorf("ERROR db.Put(%q): %v", pdoc.ImportPath, err)
  113. }
  114. return nil
  115. }
  116. // isActivePkg reports whether a package is considered active,
  117. // either because its directory is active or because it is imported by another package.
  118. func isActivePkg(pkg string, status gosrc.DirectoryStatus) bool {
  119. switch status {
  120. case gosrc.Active:
  121. return true
  122. case gosrc.NoRecentCommits:
  123. // It should be inactive only if it has no imports as well.
  124. n, err := db.ImporterCount(pkg)
  125. if err != nil {
  126. log.Printf("ERROR db.ImporterCount(%q): %v", pkg, err)
  127. }
  128. return n > 0
  129. }
  130. return false
  131. }