@@ -21,6 +21,9 @@ type Detector struct {
2121 PeopleDict map [string ]int
2222 // ReversedPeopleDict maps developer id -> description
2323 ReversedPeopleDict []string
24+ // ExactSignatures chooses the matching algorithm: opportunistic email || name
25+ // or exact email && name
26+ ExactSignatures bool
2427
2528 l core.Logger
2629}
@@ -43,6 +46,10 @@ const (
4346 // ConfigIdentityDetectorPeopleDictPath is the name of the configuration option
4447 // (Detector.Configure()) which allows to set the external PeopleDict mapping from a file.
4548 ConfigIdentityDetectorPeopleDictPath = "IdentityDetector.PeopleDictPath"
49+ // ConfigIdentityDetectorExactSignatures is the name of the configuration option
50+ // (Detector.Configure()) which changes the matching algorithm to exact signature (name + email)
51+ // correspondence.
52+ ConfigIdentityDetectorExactSignatures = "IdentityDetector.ExactSignatures"
4653 // FactIdentityDetectorPeopleCount is the name of the fact which is inserted in
4754 // Detector.Configure(). It is equal to the overall number of unique authors
4855 // (the length of ReversedPeopleDict).
@@ -78,7 +85,13 @@ func (detector *Detector) ListConfigurationOptions() []core.ConfigurationOption
7885 Description : "Path to the file with developer -> name|email associations." ,
7986 Flag : "people-dict" ,
8087 Type : core .PathConfigurationOption ,
81- Default : "" },
88+ Default : "" }, {
89+ Name : ConfigIdentityDetectorExactSignatures ,
90+ Description : "Disable separate name/email matching. This will lead to considerbly more " +
91+ "identities and should not be normally used." ,
92+ Flag : "exact-signatures" ,
93+ Type : core .BoolConfigurationOption ,
94+ Default : false },
8295 }
8396 return options [:]
8497}
@@ -96,6 +109,9 @@ func (detector *Detector) Configure(facts map[string]interface{}) error {
96109 if val , exists := facts [FactIdentityDetectorReversedPeopleDict ].([]string ); exists {
97110 detector .ReversedPeopleDict = val
98111 }
112+ if val , exists := facts [ConfigIdentityDetectorExactSignatures ].(bool ); exists {
113+ detector .ExactSignatures = val
114+ }
99115 if detector .PeopleDict == nil || detector .ReversedPeopleDict == nil {
100116 peopleDictPath , _ := facts [ConfigIdentityDetectorPeopleDictPath ].(string )
101117 if peopleDictPath != "" {
@@ -133,13 +149,19 @@ func (detector *Detector) Initialize(repository *git.Repository) error {
133149// in Provides(). If there was an error, nil is returned.
134150func (detector * Detector ) Consume (deps map [string ]interface {}) (map [string ]interface {}, error ) {
135151 commit := deps [core .DependencyCommit ].(* object.Commit )
152+ var authorID int
153+ var exists bool
136154 signature := commit .Author
137- authorID , exists := detector .PeopleDict [strings .ToLower (signature .Email )]
138- if ! exists {
139- authorID , exists = detector .PeopleDict [strings .ToLower (signature .Name )]
155+ if ! detector .ExactSignatures {
156+ authorID , exists = detector .PeopleDict [strings .ToLower (signature .Email )]
140157 if ! exists {
141- authorID = AuthorMissing
158+ authorID , exists = detector . PeopleDict [ strings . ToLower ( signature . Name )]
142159 }
160+ } else {
161+ authorID , exists = detector .PeopleDict [strings .ToLower (signature .String ())]
162+ }
163+ if ! exists {
164+ authorID = AuthorMissing
143165 }
144166 return map [string ]interface {}{DependencyAuthor : authorID }, nil
145167}
@@ -184,7 +206,8 @@ func (detector *Detector) GeneratePeopleDict(commits []*object.Commit) {
184206 size := 0
185207
186208 mailmapFile , err := commits [len (commits )- 1 ].File (".mailmap" )
187- if err == nil {
209+ // TODO(vmarkovtsev): properly handle .mailmap if ExactSignatures
210+ if ! detector .ExactSignatures && err == nil {
188211 mailMapContents , err := mailmapFile .Contents ()
189212 if err == nil {
190213 mailmap := ParseMailmap (mailMapContents )
@@ -239,34 +262,48 @@ func (detector *Detector) GeneratePeopleDict(commits []*object.Commit) {
239262 }
240263
241264 for _ , commit := range commits {
242- email := strings .ToLower (commit .Author .Email )
243- name := strings .ToLower (commit .Author .Name )
244- id , exists := dict [email ]
245- if exists {
246- _ , exists := dict [name ]
247- if ! exists {
248- dict [name ] = id
249- names [id ] = append (names [id ], name )
265+ if ! detector .ExactSignatures {
266+ email := strings .ToLower (commit .Author .Email )
267+ name := strings .ToLower (commit .Author .Name )
268+ id , exists := dict [email ]
269+ if exists {
270+ _ , exists := dict [name ]
271+ if ! exists {
272+ dict [name ] = id
273+ names [id ] = append (names [id ], name )
274+ }
275+ continue
276+ }
277+ id , exists = dict [name ]
278+ if exists {
279+ dict [email ] = id
280+ emails [id ] = append (emails [id ], email )
281+ continue
282+ }
283+ dict [email ] = size
284+ dict [name ] = size
285+ emails [size ] = append (emails [size ], email )
286+ names [size ] = append (names [size ], name )
287+ size ++
288+ } else { // !detector.ExactSignatures
289+ sig := strings .ToLower (commit .Author .String ())
290+ if _ , exists := dict [sig ]; ! exists {
291+ dict [sig ] = size
292+ size ++
250293 }
251- continue
252- }
253- id , exists = dict [name ]
254- if exists {
255- dict [email ] = id
256- emails [id ] = append (emails [id ], email )
257- continue
258294 }
259- dict [email ] = size
260- dict [name ] = size
261- emails [size ] = append (emails [size ], email )
262- names [size ] = append (names [size ], name )
263- size ++
264295 }
265296 reverseDict := make ([]string , size )
266- for _ , val := range dict {
267- sort .Strings (names [val ])
268- sort .Strings (emails [val ])
269- reverseDict [val ] = strings .Join (names [val ], "|" ) + "|" + strings .Join (emails [val ], "|" )
297+ if ! detector .ExactSignatures {
298+ for _ , val := range dict {
299+ sort .Strings (names [val ])
300+ sort .Strings (emails [val ])
301+ reverseDict [val ] = strings .Join (names [val ], "|" ) + "|" + strings .Join (emails [val ], "|" )
302+ }
303+ } else {
304+ for key , val := range dict {
305+ reverseDict [val ] = key
306+ }
270307 }
271308 detector .PeopleDict = dict
272309 detector .ReversedPeopleDict = reverseDict
0 commit comments