list.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "io/ioutil"
  6. "path/filepath"
  7. "strings"
  8. shell "github.com/ipfs/go-ipfs-api"
  9. "github.com/pkg/errors"
  10. )
  11. func listInfoRefs(forPush bool) error {
  12. refsCat, err := ipfsShell.Cat(filepath.Join(ipfsRepoPath, "info", "refs"))
  13. if err != nil {
  14. return errors.Wrapf(err, "failed to cat info/refs from %s", ipfsRepoPath)
  15. }
  16. s := bufio.NewScanner(refsCat)
  17. for s.Scan() {
  18. hashRef := strings.Split(s.Text(), "\t")
  19. if len(hashRef) != 2 {
  20. return errors.Errorf("processing info/refs: what is this: %v", hashRef)
  21. }
  22. ref2hash[hashRef[1]] = hashRef[0]
  23. }
  24. if err := s.Err(); err != nil {
  25. return errors.Wrapf(err, "ipfs.Cat(info/refs) scanner error")
  26. }
  27. return nil
  28. }
  29. func listHeadRef() (string, error) {
  30. headCat, err := ipfsShell.Cat(filepath.Join(ipfsRepoPath, "HEAD"))
  31. if err != nil {
  32. return "", errors.Wrapf(err, "failed to cat HEAD from %s", ipfsRepoPath)
  33. }
  34. head, err := ioutil.ReadAll(headCat)
  35. if err != nil {
  36. return "", errors.Wrapf(err, "failed to readAll HEAD from %s", ipfsRepoPath)
  37. }
  38. if !bytes.HasPrefix(head, []byte("ref: ")) {
  39. return "", errors.Errorf("illegal HEAD file from %s: %q", ipfsRepoPath, head)
  40. }
  41. headRef := string(bytes.TrimSpace(head[5:]))
  42. headHash, ok := ref2hash[headRef]
  43. if !ok {
  44. // use first hash in map?..
  45. return "", errors.Errorf("unknown HEAD reference %q", headRef)
  46. }
  47. return headHash, headCat.Close()
  48. }
  49. func listIterateRefs(forPush bool) error {
  50. refsDir := filepath.Join(ipfsRepoPath, "refs")
  51. return Walk(refsDir, func(p string, info *shell.LsLink, err error) error {
  52. if err != nil {
  53. return errors.Wrapf(err, "walk(%s) failed", p)
  54. }
  55. log.Log("event", "debug", "name", info.Name, "msg", "iterateRefs: walked to", "p", p)
  56. if info.Type == 2 {
  57. rc, err := ipfsShell.Cat(p)
  58. if err != nil {
  59. return errors.Wrapf(err, "walk(%s) cat ref failed", p)
  60. }
  61. data, err := ioutil.ReadAll(rc)
  62. if err != nil {
  63. return errors.Wrapf(err, "walk(%s) readAll failed", p)
  64. }
  65. if err := rc.Close(); err != nil {
  66. return errors.Wrapf(err, "walk(%s) cat close failed", p)
  67. }
  68. sha1 := strings.TrimSpace(string(data))
  69. refName := strings.TrimPrefix(p, ipfsRepoPath+"/")
  70. ref2hash[refName] = sha1
  71. log.Log("event", "debug", "refMap", ref2hash, "msg", "ref2hash map updated")
  72. }
  73. return nil
  74. })
  75. }
  76. // semi-todo make shell implement http.FileSystem
  77. // then we can reuse filepath.Walk and make a lot of other stuff simpler
  78. var SkipDir = errors.Errorf("walk: skipping")
  79. type WalkFunc func(path string, info *shell.LsLink, err error) error
  80. func walk(path string, info *shell.LsLink, walkFn WalkFunc) error {
  81. err := walkFn(path, info, nil)
  82. if err != nil {
  83. if info.Type == 1 && err == SkipDir {
  84. return nil
  85. }
  86. return err
  87. }
  88. if info.Type != 1 {
  89. return nil
  90. }
  91. list, err := ipfsShell.List(path)
  92. if err != nil {
  93. log.Log("msg", "walk list failed", "err", err)
  94. return walkFn(path, info, err)
  95. }
  96. for _, lnk := range list {
  97. fname := filepath.Join(path, lnk.Name)
  98. err = walk(fname, lnk, walkFn)
  99. if err != nil {
  100. if lnk.Type != 1 || err != SkipDir {
  101. return err
  102. }
  103. }
  104. }
  105. return nil
  106. }
  107. func Walk(root string, walkFn WalkFunc) error {
  108. list, err := ipfsShell.List(root)
  109. if err != nil {
  110. log.Log("msg", "walk root failed", "err", err)
  111. return walkFn(root, nil, err)
  112. }
  113. for _, l := range list {
  114. fname := filepath.Join(root, l.Name)
  115. if err := walk(fname, l, walkFn); err != nil {
  116. return err
  117. }
  118. }
  119. return nil
  120. }