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

158 lines
3.8KB

  1. package object
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "strings"
  7. "gopkg.in/src-d/go-git.v4/utils/merkletrie"
  8. )
  9. // Change values represent a detected change between two git trees. For
  10. // modifications, From is the original status of the node and To is its
  11. // final status. For insertions, From is the zero value and for
  12. // deletions To is the zero value.
  13. type Change struct {
  14. From ChangeEntry
  15. To ChangeEntry
  16. }
  17. var empty = ChangeEntry{}
  18. // Action returns the kind of action represented by the change, an
  19. // insertion, a deletion or a modification.
  20. func (c *Change) Action() (merkletrie.Action, error) {
  21. if c.From == empty && c.To == empty {
  22. return merkletrie.Action(0),
  23. fmt.Errorf("malformed change: empty from and to")
  24. }
  25. if c.From == empty {
  26. return merkletrie.Insert, nil
  27. }
  28. if c.To == empty {
  29. return merkletrie.Delete, nil
  30. }
  31. return merkletrie.Modify, nil
  32. }
  33. // Files return the files before and after a change.
  34. // For insertions from will be nil. For deletions to will be nil.
  35. func (c *Change) Files() (from, to *File, err error) {
  36. action, err := c.Action()
  37. if err != nil {
  38. return
  39. }
  40. if action == merkletrie.Insert || action == merkletrie.Modify {
  41. to, err = c.To.Tree.TreeEntryFile(&c.To.TreeEntry)
  42. if !c.To.TreeEntry.Mode.IsFile() {
  43. return nil, nil, nil
  44. }
  45. if err != nil {
  46. return
  47. }
  48. }
  49. if action == merkletrie.Delete || action == merkletrie.Modify {
  50. from, err = c.From.Tree.TreeEntryFile(&c.From.TreeEntry)
  51. if !c.From.TreeEntry.Mode.IsFile() {
  52. return nil, nil, nil
  53. }
  54. if err != nil {
  55. return
  56. }
  57. }
  58. return
  59. }
  60. func (c *Change) String() string {
  61. action, err := c.Action()
  62. if err != nil {
  63. return fmt.Sprintf("malformed change")
  64. }
  65. return fmt.Sprintf("<Action: %s, Path: %s>", action, c.name())
  66. }
  67. // Patch returns a Patch with all the file changes in chunks. This
  68. // representation can be used to create several diff outputs.
  69. func (c *Change) Patch() (*Patch, error) {
  70. return c.PatchContext(context.Background())
  71. }
  72. // Patch returns a Patch with all the file changes in chunks. This
  73. // representation can be used to create several diff outputs.
  74. // If context expires, an non-nil error will be returned
  75. // Provided context must be non-nil
  76. func (c *Change) PatchContext(ctx context.Context) (*Patch, error) {
  77. return getPatchContext(ctx, "", c)
  78. }
  79. func (c *Change) name() string {
  80. if c.From != empty {
  81. return c.From.Name
  82. }
  83. return c.To.Name
  84. }
  85. // ChangeEntry values represent a node that has suffered a change.
  86. type ChangeEntry struct {
  87. // Full path of the node using "/" as separator.
  88. Name string
  89. // Parent tree of the node that has changed.
  90. Tree *Tree
  91. // The entry of the node.
  92. TreeEntry TreeEntry
  93. }
  94. // Changes represents a collection of changes between two git trees.
  95. // Implements sort.Interface lexicographically over the path of the
  96. // changed files.
  97. type Changes []*Change
  98. func (c Changes) Len() int {
  99. return len(c)
  100. }
  101. func (c Changes) Swap(i, j int) {
  102. c[i], c[j] = c[j], c[i]
  103. }
  104. func (c Changes) Less(i, j int) bool {
  105. return strings.Compare(c[i].name(), c[j].name()) < 0
  106. }
  107. func (c Changes) String() string {
  108. var buffer bytes.Buffer
  109. buffer.WriteString("[")
  110. comma := ""
  111. for _, v := range c {
  112. buffer.WriteString(comma)
  113. buffer.WriteString(v.String())
  114. comma = ", "
  115. }
  116. buffer.WriteString("]")
  117. return buffer.String()
  118. }
  119. // Patch returns a Patch with all the changes in chunks. This
  120. // representation can be used to create several diff outputs.
  121. func (c Changes) Patch() (*Patch, error) {
  122. return c.PatchContext(context.Background())
  123. }
  124. // Patch returns a Patch with all the changes in chunks. This
  125. // representation can be used to create several diff outputs.
  126. // If context expires, an non-nil error will be returned
  127. // Provided context must be non-nil
  128. func (c Changes) PatchContext(ctx context.Context) (*Patch, error) {
  129. return getPatchContext(ctx, "", c...)
  130. }
上海开阖软件有限公司 沪ICP备12045867号-1