tree_diff.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package hercules
  2. import (
  3. "io"
  4. "gopkg.in/src-d/go-git.v4"
  5. "gopkg.in/src-d/go-git.v4/plumbing/object"
  6. )
  7. // TreeDiff generates the list of changes for a commit. A change can be either one or two blobs
  8. // under the same path: "before" and "after". If "before" is nil, the change is an addition.
  9. // If "after" is nil, the change is a removal. Otherwise, it is a modification.
  10. // TreeDiff is a PipelineItem.
  11. type TreeDiff struct {
  12. previousTree *object.Tree
  13. }
  14. const (
  15. // DependencyTreeChanges is the name of the dependency provided by TreeDiff.
  16. DependencyTreeChanges = "changes"
  17. )
  18. func (treediff *TreeDiff) Name() string {
  19. return "TreeDiff"
  20. }
  21. func (treediff *TreeDiff) Provides() []string {
  22. arr := [...]string{DependencyTreeChanges}
  23. return arr[:]
  24. }
  25. func (treediff *TreeDiff) Requires() []string {
  26. return []string{}
  27. }
  28. func (treediff *TreeDiff) ListConfigurationOptions() []ConfigurationOption {
  29. return []ConfigurationOption{}
  30. }
  31. func (treediff *TreeDiff) Configure(facts map[string]interface{}) {}
  32. func (treediff *TreeDiff) Initialize(repository *git.Repository) {
  33. treediff.previousTree = nil
  34. }
  35. func (treediff *TreeDiff) Consume(deps map[string]interface{}) (map[string]interface{}, error) {
  36. commit := deps["commit"].(*object.Commit)
  37. tree, err := commit.Tree()
  38. if err != nil {
  39. return nil, err
  40. }
  41. var diff object.Changes
  42. if treediff.previousTree != nil {
  43. diff, err = object.DiffTree(treediff.previousTree, tree)
  44. if err != nil {
  45. return nil, err
  46. }
  47. } else {
  48. diff = []*object.Change{}
  49. err = func() error {
  50. fileIter := tree.Files()
  51. defer fileIter.Close()
  52. for {
  53. file, err := fileIter.Next()
  54. if err != nil {
  55. if err == io.EOF {
  56. break
  57. }
  58. return err
  59. }
  60. diff = append(diff, &object.Change{
  61. To: object.ChangeEntry{Name: file.Name, Tree: tree, TreeEntry: object.TreeEntry{
  62. Name: file.Name, Mode: file.Mode, Hash: file.Hash}}})
  63. }
  64. return nil
  65. }()
  66. if err != nil {
  67. return nil, err
  68. }
  69. }
  70. treediff.previousTree = tree
  71. return map[string]interface{}{DependencyTreeChanges: diff}, nil
  72. }
  73. func init() {
  74. Registry.Register(&TreeDiff{})
  75. }