identity.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package hercules
  2. import (
  3. "bufio"
  4. "os"
  5. "strings"
  6. "gopkg.in/src-d/go-git.v4"
  7. "gopkg.in/src-d/go-git.v4/plumbing/object"
  8. )
  9. type IdentityDetector struct {
  10. // Maps email || name -> developer id.
  11. PeopleDict map[string]int
  12. // Maps developer id -> description
  13. ReversePeopleDict map[int]string
  14. }
  15. const MISSING_AUTHOR = (1 << 18) - 1
  16. const SELF_AUTHOR = (1 << 18) - 2
  17. func (id *IdentityDetector) Name() string {
  18. return "IdentityDetector"
  19. }
  20. func (id *IdentityDetector) Provides() []string {
  21. arr := [...]string{"author"}
  22. return arr[:]
  23. }
  24. func (id *IdentityDetector) Requires() []string {
  25. return []string{}
  26. }
  27. func (id *IdentityDetector) Initialize(repository *git.Repository) {
  28. }
  29. func (self *IdentityDetector) Consume(deps map[string]interface{}) (map[string]interface{}, error) {
  30. commit := deps["commit"].(*object.Commit)
  31. signature := commit.Author
  32. id, exists := self.PeopleDict[strings.ToLower(signature.Email)]
  33. if !exists {
  34. id, exists = self.PeopleDict[strings.ToLower(signature.Name)]
  35. if !exists {
  36. id = MISSING_AUTHOR
  37. }
  38. }
  39. return map[string]interface{}{"author": id}, nil
  40. }
  41. func (id *IdentityDetector) Finalize() interface{} {
  42. return nil
  43. }
  44. func (id *IdentityDetector) LoadPeopleDict(path string) error {
  45. file, err := os.Open(path)
  46. if err != nil {
  47. return err
  48. }
  49. defer file.Close()
  50. scanner := bufio.NewScanner(file)
  51. dict := make(map[string]int)
  52. reverse_dict := make(map[int]string)
  53. size := 0
  54. for scanner.Scan() {
  55. for _, id := range strings.Split(strings.ToLower(scanner.Text()), "|") {
  56. dict[id] = size
  57. }
  58. reverse_dict[size] = scanner.Text()
  59. size += 1
  60. }
  61. id.PeopleDict = dict
  62. id.ReversePeopleDict = reverse_dict
  63. return nil
  64. }
  65. func (id *IdentityDetector) GeneratePeopleDict(commits []*object.Commit) {
  66. dict := make(map[string]int)
  67. emails := make(map[int][]string)
  68. names := make(map[int][]string)
  69. size := 0
  70. for _, commit := range commits {
  71. email := strings.ToLower(commit.Author.Email)
  72. name := strings.ToLower(commit.Author.Name)
  73. id, exists := dict[email]
  74. if exists {
  75. _, exists := dict[name]
  76. if !exists {
  77. dict[name] = id
  78. names[id] = append(names[id], name)
  79. }
  80. continue
  81. }
  82. id, exists = dict[name]
  83. if exists {
  84. dict[email] = id
  85. emails[id] = append(emails[id], email)
  86. continue
  87. }
  88. dict[email] = size
  89. dict[name] = size
  90. emails[size] = append(emails[size], email)
  91. names[size] = append(names[size], name)
  92. size += 1
  93. }
  94. reverse_dict := make(map[int]string)
  95. for _, val := range dict {
  96. reverse_dict[val] = strings.Join(names[val], "|") + "|" + strings.Join(emails[val], "|")
  97. }
  98. id.PeopleDict = dict
  99. id.ReversePeopleDict = reverse_dict
  100. }