本站源代码
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.

138 lines
3.1KB

  1. package object
  2. import (
  3. "bytes"
  4. "io"
  5. "strings"
  6. "gopkg.in/src-d/go-git.v4/plumbing/filemode"
  7. "gopkg.in/src-d/go-git.v4/plumbing/storer"
  8. "gopkg.in/src-d/go-git.v4/utils/binary"
  9. "gopkg.in/src-d/go-git.v4/utils/ioutil"
  10. )
  11. // File represents git file objects.
  12. type File struct {
  13. // Name is the path of the file. It might be relative to a tree,
  14. // depending of the function that generates it.
  15. Name string
  16. // Mode is the file mode.
  17. Mode filemode.FileMode
  18. // Blob with the contents of the file.
  19. Blob
  20. }
  21. // NewFile returns a File based on the given blob object
  22. func NewFile(name string, m filemode.FileMode, b *Blob) *File {
  23. return &File{Name: name, Mode: m, Blob: *b}
  24. }
  25. // Contents returns the contents of a file as a string.
  26. func (f *File) Contents() (content string, err error) {
  27. reader, err := f.Reader()
  28. if err != nil {
  29. return "", err
  30. }
  31. defer ioutil.CheckClose(reader, &err)
  32. buf := new(bytes.Buffer)
  33. if _, err := buf.ReadFrom(reader); err != nil {
  34. return "", err
  35. }
  36. return buf.String(), nil
  37. }
  38. // IsBinary returns if the file is binary or not
  39. func (f *File) IsBinary() (bin bool, err error) {
  40. reader, err := f.Reader()
  41. if err != nil {
  42. return false, err
  43. }
  44. defer ioutil.CheckClose(reader, &err)
  45. return binary.IsBinary(reader)
  46. }
  47. // Lines returns a slice of lines from the contents of a file, stripping
  48. // all end of line characters. If the last line is empty (does not end
  49. // in an end of line), it is also stripped.
  50. func (f *File) Lines() ([]string, error) {
  51. content, err := f.Contents()
  52. if err != nil {
  53. return nil, err
  54. }
  55. splits := strings.Split(content, "\n")
  56. // remove the last line if it is empty
  57. if splits[len(splits)-1] == "" {
  58. return splits[:len(splits)-1], nil
  59. }
  60. return splits, nil
  61. }
  62. // FileIter provides an iterator for the files in a tree.
  63. type FileIter struct {
  64. s storer.EncodedObjectStorer
  65. w TreeWalker
  66. }
  67. // NewFileIter takes a storer.EncodedObjectStorer and a Tree and returns a
  68. // *FileIter that iterates over all files contained in the tree, recursively.
  69. func NewFileIter(s storer.EncodedObjectStorer, t *Tree) *FileIter {
  70. return &FileIter{s: s, w: *NewTreeWalker(t, true, nil)}
  71. }
  72. // Next moves the iterator to the next file and returns a pointer to it. If
  73. // there are no more files, it returns io.EOF.
  74. func (iter *FileIter) Next() (*File, error) {
  75. for {
  76. name, entry, err := iter.w.Next()
  77. if err != nil {
  78. return nil, err
  79. }
  80. if entry.Mode == filemode.Dir || entry.Mode == filemode.Submodule {
  81. continue
  82. }
  83. blob, err := GetBlob(iter.s, entry.Hash)
  84. if err != nil {
  85. return nil, err
  86. }
  87. return NewFile(name, entry.Mode, blob), nil
  88. }
  89. }
  90. // ForEach call the cb function for each file contained in this iter until
  91. // an error happens or the end of the iter is reached. If plumbing.ErrStop is sent
  92. // the iteration is stop but no error is returned. The iterator is closed.
  93. func (iter *FileIter) ForEach(cb func(*File) error) error {
  94. defer iter.Close()
  95. for {
  96. f, err := iter.Next()
  97. if err != nil {
  98. if err == io.EOF {
  99. return nil
  100. }
  101. return err
  102. }
  103. if err := cb(f); err != nil {
  104. if err == storer.ErrStop {
  105. return nil
  106. }
  107. return err
  108. }
  109. }
  110. }
  111. func (iter *FileIter) Close() {
  112. iter.w.Close()
  113. }
上海开阖软件有限公司 沪ICP备12045867号-1