• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moosetechnology / GitProjectHealth / 16429942649

21 Jul 2025 10:51PM UTC coverage: 72.954% (-1.9%) from 74.896%
16429942649

push

github

web-flow
Merge pull request #216 from moosetechnology/feature-issue

10 of 758 new or added lines in 11 files covered. (1.32%)

4 existing lines in 1 file now uncovered.

17584 of 24103 relevant lines covered (72.95%)

0.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

32.98
/src/GitLabHealth-Model-Analysis/GLHUserCatalogueV2.class.st
1
Class {
2
        #name : #GLHUserCatalogueV2,
3
        #superclass : #GLHUserCatalogue,
4
        #category : #'GitLabHealth-Model-Analysis'
5
}
6

7
{ #category : #import }
8
GLHUserCatalogueV2 class >> loadFromJson: aString [
1✔
9

1✔
10
        | catalogue dic |
1✔
11
        catalogue := self new.
1✔
12
        dic := (STONJSON fromString: aString) asDictionary.
1✔
13
        dic associationsDo: [ :assoc |
1✔
14
                | itsName itsUsername itsCommitNames itsId itsProjectIDs|
1✔
15
                itsName := assoc key.
1✔
16
                itsCommitNames := assoc value at: #foundNames.
1✔
17
                itsUsername := assoc value at: #username.
1✔
18
                itsId := assoc value at: #id.
1✔
19
                itsProjectIDs := assoc value at: #contributedProjects ifAbsent: [{}].
1✔
20

1✔
21
                catalogue
1✔
22
                        addUser: (GLHUser new
1✔
23
                                         id: itsId;
1✔
24
                                         username: itsUsername;
1✔
25
                                         name: itsName;
1✔
26
                                         yourself)
1✔
27
                        withNames: itsCommitNames
1✔
28
                        withProjects: itsProjectIDs ].
1✔
29

1✔
30
        ^ catalogue
1✔
31
]
1✔
32

33
{ #category : #'as yet unclassified' }
34
GLHUserCatalogueV2 class >> scrapeContributedProjectsForCommitAuthorsRelatedToUser: aGLHUser [
×
35
        "get all "
×
36

×
37
        | maxProjects itsProjects |
×
38
        self
×
39
                deprecated:
×
40
                'Use #scrapeWithImporter:ContributedProjectsForCommitAuthorsRelatedToUser: instead'
×
41
                on: '12 August 2024'
×
42
                in:
×
43
                'Pharo-11.0.0+build.726.sha.aece1b5473acf3830a0e082c1bc3a15d4ff3522b (64 Bit)'.
×
44

×
45
        aGLHUser id ifNil: [ ^ {  } asSet ].
×
46

×
47
        maxProjects := 10.
×
48

×
49
        GitlabModelImporter current withCommitDiffs: false.
×
50
        itsProjects := aGLHUser contributedProjects ifEmpty: [
×
51
                               GitlabModelImporter current
×
52
                                       importContributedProjectsOfUser: aGLHUser ].
×
53

×
54
        itsProjects
×
55
                collect: [ :project |
×
56
                        GitlabModelImporter current importAndLoadLatestsCommitsOfProject:
×
57
                                project ]
×
58
                from: 1
×
59
                to: (itsProjects size min: maxProjects).
×
60

×
61
        ^ (aGLHUser commits collect: [ :commit | commit author_name ]) asSet
×
62
]
×
63

64
{ #category : #'as yet unclassified' }
65
GLHUserCatalogueV2 class >> scrapeWithImporter: anImporter contributedProjectsForCommitAuthorsRelatedToUser: aGLHUser [
×
66
        "get all "
×
67

×
68
        | maxProjects itsProjects |
×
69
        aGLHUser id ifNil: [ ^ {  } asSet ].
×
70

×
71
        maxProjects := 10.
×
72

×
73
        anImporter withCommitDiffs: false.
×
74
        itsProjects := aGLHUser contributedProjects ifEmpty: [
×
75
                               anImporter
×
76
                                       importContributedProjectsOfUser: aGLHUser ].
×
77

×
78
        itsProjects
×
79
                collect: [ :project |
×
80
                        anImporter importAndLoadLatestsCommitsOfProject:
×
81
                                project ]
×
82
                from: 1
×
83
                to: (itsProjects size min: maxProjects).
×
84

×
85
        ^ (aGLHUser commits collect: [ :commit | commit author_name ]) asSet
×
86
]
×
87

88
{ #category : #'as yet unclassified' }
89
GLHUserCatalogueV2 >> RSHeatMapLevenshtein [
×
90
        
×
91
                | builder|
×
92
        builder := RSHeatmap new.
×
93
        builder objectsX: self keys.
×
94
        builder objectsY: self keys.
×
95

×
96
        builder dataMatrix: self levenshteinMatrix.
×
97

×
98
        builder build.
×
99
        builder gradientLegend remove.
×
100
        builder canvas open
×
101
]
×
102

103
{ #category : #'as yet unclassified' }
104
GLHUserCatalogueV2 >> RSHeatMapLevenshteinTrimedAt: aBlockCondition [
×
105
        
×
106
                | builder matrice|
×
107
        builder := RSHeatmap new.
×
108
        builder objectsX: self keys.
×
109
        builder objectsY: self keys.
×
110
        
×
111

×
112
        matrice := self levenshteinMatrix.
×
113
        1 to: matrice size do: [ :i |
×
114
                1 to: (matrice at: i) size do: [ :j |
×
115
                        |val|
×
116
                        val := ((matrice at: i) at: j).
×
117
                        (matrice at: i) at: j put: ( aBlockCondition value: val ).
×
118
                         ] ].
×
119
        
×
120
        
×
121
        builder dataMatrix: matrice.
×
122

×
123
        builder build.
×
124
        builder gradientLegend remove.
×
125
        builder canvas open
×
126
]
×
127

128
{ #category : #adding }
129
GLHUserCatalogueV2 >> addUser: aGLHUser [
1✔
130

1✔
131
        ^ self at: aGLHUser name ifAbsentPut: [
1✔
132
                self initACatalogueEntryForUser: aGLHUser ]
1✔
133
]
1✔
134

135
{ #category : #adding }
136
GLHUserCatalogueV2 >> addUser: aGLHUser withName: name [
1✔
137

1✔
138
        ^ self addUser: aGLHUser withNames: { name }
1✔
139
        
1✔
140
]
1✔
141

142
{ #category : #adding }
143
GLHUserCatalogueV2 >> addUser: aGLHUser withNames: aCollectionOfNames [
1✔
144
        | entry |
1✔
145
        entry := (self
1✔
146
                at: aGLHUser name
1✔
147
                ifAbsentPut: [ (self initACatalogueEntryForUser: aGLHUser ). ]).
1✔
148
        (entry  at: #names)  addAll: aCollectionOfNames. 
1✔
149
        ^ entry
1✔
150
]
1✔
151

152
{ #category : #adding }
153
GLHUserCatalogueV2 >> addUser: aGLHUser withNames: aCollectionOfNames withProject: aProjectID [
×
154

×
155
        ^ self addUser: aGLHUser withNames: aCollectionOfNames withProjects: { aProjectID }
×
156
]
×
157

158
{ #category : #adding }
159
GLHUserCatalogueV2 >> addUser: aGLHUser withNames: aCollectionOfNames withProjects: aCollectionOfProjectIDs [
1✔
160
        |entry|
1✔
161
        
1✔
162
        entry := self addUser: aGLHUser withNames: aCollectionOfNames.
1✔
163
        (entry at: #contributedProjects) addAll: aCollectionOfProjectIDs.
1✔
164
        ^ entry. 
1✔
165
        
1✔
166
]
1✔
167

168
{ #category : #adding }
169
GLHUserCatalogueV2 >> addUser: aGLHUser withProject: aProjectID [
1✔
170
        
1✔
171
        ^ self addUser: aGLHUser withProjects: {aProjectID}.
1✔
172
        
1✔
173
]
1✔
174

175
{ #category : #adding }
176
GLHUserCatalogueV2 >> addUser: aGLHUser withProjects: aCollectionOfProjectIDs [
1✔
177
        |entry|
1✔
178

1✔
179
        entry := self addUser: aGLHUser.
1✔
180
        (entry at: #contributedProjects) addAll: aCollectionOfProjectIDs.
1✔
181
        ^ entry.
1✔
182
        
1✔
183
]
1✔
184

185
{ #category : #accessing }
186
GLHUserCatalogueV2 >> anImporter: aGLHModelImporter [
1✔
187
        anImporter := aGLHModelImporter
1✔
188
        
1✔
189
]
1✔
190

191
{ #category : #accessing }
192
GLHUserCatalogueV2 >> atId: anId [ 
×
193
        ^ self detect: [ :entry |
×
194
                (entry at: #user) id =  anId ]
×
195
]
×
196

197
{ #category : #'as yet unclassified' }
198
GLHUserCatalogueV2 >> collectUsernames [
1✔
199

1✔
200
        | username2User |
1✔
201
        self ifEmpty: [ ^ OrderedDictionary new ].
1✔
202

1✔
203
        username2User := OrderedDictionary new.
1✔
204

1✔
205
        self associationsDo: [ :assoc |
1✔
206
                | user |
1✔
207
                user := assoc value at: #user.
1✔
208
                (assoc value at: #names) do: [ :username |
1✔
209
                        username2User at: username put: user ] ].
1✔
210

1✔
211
        ^ username2User
1✔
212
]
1✔
213

214
{ #category : #user }
NEW
215
GLHUserCatalogueV2 >> collectUsers [
×
NEW
216
        ^ self associations collect: [ :entry | entry value at: #user ]
×
NEW
217
]
×
218

219
{ #category : #completion }
220
GLHUserCatalogueV2 >> completeAuthorNameOfUser: aGLHUser with: authorName [
×
221

×
222
        self
×
223
                deprecated: 'Use #addUser:withName: instead'
×
224
                on: '12 August 2024'
×
225
                in:
×
226
                'Pharo-11.0.0+build.726.sha.aece1b5473acf3830a0e082c1bc3a15d4ff3522b (64 Bit)'.
×
227

×
228
        self addUser: aGLHUser withName: authorName
×
229
]
×
230

231
{ #category : #completion }
232
GLHUserCatalogueV2 >> completeAuthorNameOfUser: aGLHUser withAll: authorNames [
×
233

×
234
        self
×
235
                deprecated: 'Use #addUser:withNames: instead'
×
236
                on: '12 August 2024'
×
237
                in:
×
238
                'Pharo-11.0.0+build.726.sha.aece1b5473acf3830a0e082c1bc3a15d4ff3522b (64 Bit)'.
×
239

×
240

×
241
        self addUser: aGLHUser withNames: authorNames
×
242
]
×
243

244
{ #category : #export }
245
GLHUserCatalogueV2 >> exportToJson [
1✔
246

1✔
247
        | tempDic |
1✔
248
        "        tempDic := self associations collect: [ :assoc |
1✔
249
                                        Dictionary new at: (assoc key name) put: ({
1✔
250
                                   (#names -> assoc value asArray).
1✔
251
                                   (#id -> assoc key id) } asDictionary); yourself ]."
1✔
252
        tempDic := Dictionary new.
1✔
253
        self associationsDo: [ :assoc |
1✔
254
                |entry user names projectIDs|
1✔
255
                entry := assoc value.
1✔
256
                user := entry at: #user.
1✔
257
                names := entry at: #names.
1✔
258
                projectIDs := entry at: #contributedProjects.
1✔
259
                tempDic
1✔
260
                        at: assoc key put: {
1✔
261
                                        (#name -> user name).
1✔
262
                                        (#username -> user username).
1✔
263
                                        (#foundNames -> names asArray).
1✔
264
                                        (#contributedProjects -> projectIDs asArray).
1✔
265
                                        (#id -> user id) } asDictionary;
1✔
266
                        yourself ].
1✔
267

1✔
268
        ^ STONJSON toStringPretty: tempDic
1✔
269
]
1✔
270

271
{ #category : #fuse }
272
GLHUserCatalogueV2 >> fuse: mainUser with: subUser [ 
×
273
        self at: mainUser ifPresent: [ :entry |
×
274
                self at: subUser ifAbsent: [ ^ self ]. 
×
275
                (entry at: #names) addAll: (self at: subUser at: #names ).
×
276
                (entry at: #contributedProjects) addAll: (self at: subUser at: #contributedProjects ).
×
277
                self removeKey: subUser.
×
278
                 ].
×
279
]
×
280

281
{ #category : #'instance creation' }
282
GLHUserCatalogueV2 >> initACatalogueEntryForUser: aGLHUser [.
1✔
283

1✔
284
^ Dictionary new
1✔
285
                        at: #user put: aGLHUser;
1✔
286
                        at: #names put: (Set new
1✔
287
                                         add: aGLHUser username;
1✔
288
                                         add: aGLHUser name;
1✔
289
                                         yourself);
1✔
290
                        at: #contributedProjects put: (Set new 
1✔
291
                                        addAll: (aGLHUser contributedProjects collect: #id); 
1✔
292
                                        yourself );
1✔
293
                        yourself
1✔
294
]
1✔
295

296
{ #category : #initialization }
297
GLHUserCatalogueV2 >> initialize [
×
298

×
299
        anImporter := GitlabModelImporter new.
×
300
]
×
301

302
{ #category : #'as yet unclassified' }
303
GLHUserCatalogueV2 >> levenshteinMatrix [ 
×
304
        | matrix|
×
305

×
306
        matrix := Array new: self keys size .
×
307
        1 to: matrix size do: [ :i | matrix at: i put: (Array new: self keys size) ]. 
×
308
        
×
309
        1 to: self keys size do: [ :i |
×
310
                1 to: self keys size do: [ :j |
×
311
                        
×
312
                        (matrix at: i) at: j put: ( (self keys at: i) absLevenshteinDistanceWith: (self keys at: j) ). 
×
313
                          ].
×
314
                  ].
×
315

×
316
        ^ matrix.
×
317
]
×
318

319
{ #category : #'accessing - name' }
320
GLHUserCatalogueV2 >> names [
×
321
        ^ self collect: [ :entry | entry at: #names ]
×
322
]
×
323

324
{ #category : #'as yet unclassified' }
325
GLHUserCatalogueV2 >> namesAt: aGLHUser [
1✔
326
        ^ (self at: aGLHUser name) at: #names.
1✔
327
]
1✔
328

329
{ #category : #'as yet unclassified' }
330
GLHUserCatalogueV2 >> reImportAllUsers [
×
331
        "use it after a catalogue import from JSON"
×
332

×
333
        self associationsDo: [ :assoc |
×
334
                | user |
×
335
                user := assoc value at: #user.
×
336
                user := anImporter
×
337
                                ifNotNil: [
×
338
                                        user id
×
339
                                                ifNotNil: [ anImporter importUser: user id ]
×
340
                                                ifNil: [ anImporter importUserByUsername: user username ] ]
×
341
                                ifNil: [user].
×
342
                assoc value at: #user put: user ]
×
343
]
×
344

345
{ #category : #'as yet unclassified' }
346
GLHUserCatalogueV2 >> reImportUser: aGLHUser [
×
347
        "use it after a catalogue import from JSON"
×
348
        |user|
×
349
        user := anImporter
×
350
                                ifNotNil: [
×
351
                                        aGLHUser id
×
352
                                                ifNotNil: [ anImporter importUser: aGLHUser id ]
×
353
                                                ifNil: [ anImporter importUserByUsername: aGLHUser username ] ]
×
354
                                ifNil: [aGLHUser].
×
355
        
×
356
        
×
357
        self at: aGLHUser name at: #user put: (user).
×
358
        
×
359
]
×
360

361
{ #category : #scrape }
362
GLHUserCatalogueV2 >> scrapeAuthorNameForAllRealUsers [
×
363
        
×
364
        |listOfUsers|
×
365
        listOfUsers := self users select: [ :user | user id isNotNil ].
×
366
        listOfUsers do: [ :user | self scrapeAuthorNameForUser: user ].
×
367
]
×
368

369
{ #category : #'as yet unclassified' }
370
GLHUserCatalogueV2 >> scrapeAuthorNameForAllUsers [
×
371

×
372
        |listOfUsers|
×
373
        
×
374
        listOfUsers := self users. 
×
375
        listOfUsers do: [ :user | self scrapeAuthorNameForUser: user ]
×
376
]
×
377

378
{ #category : #'as yet unclassified' }
379
GLHUserCatalogueV2 >> scrapeAuthorNameForUser: aGLHUser [
×
380

×
381
        self addUser: aGLHUser withNames: (GLHUserCatalogue
×
382
                         scrapeWithImporter: anImporter
×
383
                         contributedProjectsForCommitAuthorsRelatedToUser: aGLHUser).
×
384
]
×
385

386
{ #category : #scrape }
387
GLHUserCatalogueV2 >> scrapeAuthorNamesForUsers: aUserCollection [ 
×
388
        
×
389
        aUserCollection do: [ :aGLHUser |
×
390
                self scrapeAuthorNameForUser: aGLHUser
×
391
                 ].
×
392
]
×
393

394
{ #category : #search }
395
GLHUserCatalogueV2 >> searchId: anId [ 
×
396
        ^ self select: [ :entry | (entry at: #user) id = anId ].
×
397
]
×
398

399
{ #category : #completion }
400
GLHUserCatalogueV2 >> searchModelForAuthorNamesOfUser: aGLHUser [
×
401

×
402
        self addUser: aGLHUser withNames: 
×
403
                (aGLHUser commits collect: [ :c | c author_name ])
×
404
]
×
405

406
{ #category : #search }
407
GLHUserCatalogueV2 >> searchName: aName [
×
408

×
409
        ^ self select: [ :entry |
×
410
                |collectionOfName|
×
411
                collectionOfName := entry at: #names.
×
412
                  (' ' join: collectionOfName) asLowercase includesSubstring:
×
413
                          aName asLowercase ]
×
414
]
×
415

416
{ #category : #search }
NEW
417
GLHUserCatalogueV2 >> searchNames: aCollection [
×
NEW
418
        |cat|
×
NEW
419
        cat := self class new.
×
NEW
420
        
×
NEW
421
        aCollection do: [ :name | 
×
NEW
422
                |res| 
×
NEW
423
                
×
NEW
424
                res := (self searchName: name). 
×
NEW
425
                res do: [:entry |
×
NEW
426
                                        cat addUser: (entry at: #user) withNames: (entry at: #names) withProjects: (entry at: #contributedProjects) ]
×
NEW
427
                         ].
×
NEW
428
                ^ cat
×
NEW
429

×
NEW
430
]
×
431

432
{ #category : #search }
433
GLHUserCatalogueV2 >> searchUserWithName: aName [
×
434

×
435
        ^ (self searchName: aName) users
×
436
]
×
437

438
{ #category : #accessing }
439
GLHUserCatalogueV2 >> userAt: aGLHUser [
×
440
        ^ (self at: aGLHUser name) at: #user.  
×
441
]
×
442

443
{ #category : #accessing }
444
GLHUserCatalogueV2 >> users [
×
445

×
446
        ^ self collect: [ :entry | entry at: #user ].
×
447
]
×
448

449
{ #category : #search }
450
GLHUserCatalogueV2 >> weirdUsers [
×
451
        "return user that have name containing weird caracter, making them suspicious"
×
452
        ^ self select: [ :entry |
×
453
                ((entry at:#user) name includesSubstring: '.') or: [ 
×
454
                        (entry at:#user) name includesSubstring: '@' ]
×
455
                 ].
×
456
]
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc