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

moosetechnology / GitProjectHealth / 9746494520

01 Jul 2024 02:55PM UTC coverage: 29.879% (+0.02%) from 29.855%
9746494520

push

github

HLAD Nicolas
Merge f7e69aebf

44 of 163 new or added lines in 8 files covered. (26.99%)

546 existing lines in 10 files now uncovered.

2266 of 7584 relevant lines covered (29.88%)

0.3 hits per line

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

0.0
/src/GitLabHealth-Model-Analysis/GitMetric4User.class.st
1
Class {
2
        #name : #GitMetric4User,
3
        #superclass : #Object,
4
        #instVars : [
5
                'user',
6
                'itsProjects',
7
                'itsGroups',
8
                'itsCommits',
9
                'gitAnalyzer',
10
                'glhModel',
11
                'glhImporter',
12
                'itsMergeRequests'
13
        ],
14
        #category : #'GitLabHealth-Model-Analysis'
15
}
16

17
{ #category : #churn }
18
GitMetric4User >> codeChurnSince: since until: until onACommitWindowOf: commitLimit overA: aDateWeekMonthOrYear [
×
19

×
20
        | commits res groupedByDate totalContributions userCommits |
×
21
        "for each commit, we get its churn result (a dictionnary)""debug halt""percentage := (((totalChurn * 100) / totalContribution) asFloat)""                (
×
22
                #churn -> ((groupedByDate sum: [ :frac | frac numerator ]) ->
×
23
                     (groupedByDate sum: [ :frac | frac denominator ]))
×
24
                )."
×
25
        'GitMetric4User: code churn' recordInfo.
×
26
        totalContributions := OrderedCollection new.
×
27
        groupedByDate := self
×
28
                                 setupGroupedDateFrom: since
×
29
                                 to: until
×
30
                                 over: aDateWeekMonthOrYear.
×
31
        gitAnalyzer := GitAnalyzer new
×
32
                               glhImporter: glhImporter;
×
33
                               onModel: glhModel;
×
34
                               maxChildCommit: commitLimit.
×
35
        glhImporter withCommitDiffs: false.
×
36
        commits := self
×
37
                           loadCommitOfProjects: itsProjects keys
×
38
                           since: since
×
39
                           until: until.
×
40
        glhImporter withCommitDiffs: true.
×
41
        userCommits := commits reject: [ :commit |
×
42
                               commit commitCreator ~= user ].
×
43
        commits := self
×
44
                           foundSuccessorOf: userCommits
×
45
                           andCompleteImportForMax: commitLimit.
×
46

×
47

×
48
        res := commits collect: [ :commit |
×
49
                       commit -> (gitAnalyzer
×
50
                                fromCommit: commit;
×
51
                                analyseChurn) ].
×
52
        res do: [ :commits4Churns |
×
53
                | commit allChurnsInCommit sumChurnInCommit overDate contribution churnOnCommit |
×
54
                commit := commits4Churns key.
×
55
                allChurnsInCommit := commits4Churns value.
×
56
                sumChurnInCommit := (allChurnsInCommit at: #churns) sum: [ :churn |
×
57
                                            | numerator |
×
58
                                            numerator := churn value at: #churnLoC.
×
59
                                            numerator ].
×
60
                contribution := allChurnsInCommit at: #totalContribution.
×
61
                totalContributions add: contribution.
×
62
                churnOnCommit := {
×
63
                                         (#churnOnCommit -> sumChurnInCommit).
×
64
                                         (#LoCOnCommit -> contribution) } asDictionary.
×
65
                overDate := self
×
66
                                    transformDate: commit created_at
×
67
                                    to: aDateWeekMonthOrYear.
×
68
                groupedByDate
×
69
                        at: overDate printString
×
70
                        ifPresent: [ :array | array add: churnOnCommit ]
×
71
                        ifAbsentPut: [
×
72
                                OrderedCollection new
×
73
                                        add: churnOnCommit;
×
74
                                        yourself ] ].
×
75
        groupedByDate := groupedByDate collect: [ :churnsAtDate |
×
76
                                 | totalChurn totalContribution percentage |
×
77
                                 totalChurn := churnsAtDate sum: [ :churn |
×
78
                                                       churn at: #churnOnCommit ].
×
79
                                 totalContribution := churnsAtDate sum: [ :churn |
×
80
                                                              churn at: #LoCOnCommit ].
×
81
                                 totalContribution = 0
×
82
                                         ifTrue: [ percentage := 0 asFloat ]
×
83
                                         ifFalse: [
×
84
                                         percentage := (totalChurn * 100
×
85
                                                        / totalContribution) asFloat ].
×
86
                                 {
×
87
                                         (#churn -> totalChurn).
×
88
                                         (#contribution -> totalContribution).
×
89
                                         (#percentage -> percentage) } asDictionary ].
×
90
        ^ {
×
91
                  (#details -> groupedByDate).
×
92
                  (#totalContribution -> (totalContributions
×
93
                            ifEmpty: [ 0 ]
×
94
                            ifNotEmpty: [ totalContributions sum ])).
×
95
                  (#totalChurn -> (groupedByDate sum: [ :date | date at: #churn ])).
×
96
                  (#churn
×
97
                   ->
×
98
                   (groupedByDate collect: [ :date | date at: #percentage ]) average).
×
99
                  (#overEach -> aDateWeekMonthOrYear name).
×
100
                  (#forOver -> (groupedByDate keys size printString
×
101
                    , aDateWeekMonthOrYear printString)).
×
102
                  (#userCommits -> commits size).
×
103
                  (#churnWindow -> commitLimit) } asDictionary
×
104
]
×
105

106
{ #category : #metrics }
107
GitMetric4User >> codeContributionsSince: since until: until overA: aDateWeekMonthOrYear [
×
108

×
109
        | commits contributions groupedByDate |
×
110
        'GitMetric4User: code contribution' recordInfo.
×
111

×
112

×
113

×
114
        groupedByDate := self
×
115
                                 setupGroupedDateFrom: since
×
116
                                 to: until
×
117
                                 over: aDateWeekMonthOrYear.
×
118

×
119
        gitAnalyzer := GitAnalyzer new
×
120
                               onModel: glhModel;
×
121
                               glhImporter: glhImporter.
×
122

×
123
        glhImporter withCommitDiffs: false.
×
124
        commits := self
×
125
                           loadCommitOfProjects: itsProjects keys
×
126
                           since: since
×
127
                           until: until.
×
128
        glhImporter withCommitDiffs: true.
×
129
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
130

×
131
        contributions := commits collect: [ :commit |
×
132
                                 commit -> (gitAnalyzer
×
133
                                          fromCommit: commit;
×
134
                                          analyseCommitContribution) ].
×
135

×
136
        contributions do: [ :assoc |
×
137
                | dateOver |
×
138
                dateOver := self
×
139
                                    transformDate: assoc key created_at
×
140
                                    to: aDateWeekMonthOrYear.
×
141
                groupedByDate
×
142
                        at: dateOver printString
×
143
                        ifPresent: [ :v | v add: assoc value ]
×
144
                        ifAbsentPut: [
×
145
                                OrderedCollection new
×
146
                                        add: assoc value;
×
147
                                        yourself ] ].
×
148

×
149
        groupedByDate := groupedByDate collect: [ :contribs |
×
150
                                 | totalAdd totalDele |
×
151
                                 totalAdd := contribs sum: [ :v | v at: #addition ].
×
152
                                 totalDele := contribs sum: [ :v | v at: #deletion ].
×
153
                                 {
×
154
                                         (#addition -> totalAdd).
×
155
                                         (#deletion -> totalDele) } asDictionary ].
×
156

×
157

×
158
        ^ {
×
159
                  (#overEach -> aDateWeekMonthOrYear name).
×
160
                  (#forOver -> (groupedByDate keys size printString
×
161
                    , aDateWeekMonthOrYear printString)).
×
162
                  (#avgAddition
×
163
                   ->
×
164
                   (groupedByDate collect: [ :d | d at: #addition ]) average asFloat).
×
165
                  (#avgDeletion
×
166
                   ->
×
167
                   (groupedByDate collect: [ :d | d at: #deletion ]) average asFloat).
×
168
                  (#details -> groupedByDate).
×
169
                  (#userCommits -> commits size) } asDictionary
×
170
]
×
171

172
{ #category : #metrics }
173
GitMetric4User >> commentsContributionsSince: since until: until overA: aDateWeekMonthOrYear [
×
174

×
175
        | commits contributions groupedByDate |
×
176
        'GitMetric4User: comment contribution' recordInfo.
×
177

×
178
        groupedByDate := self
×
179
                                 setupGroupedDateFrom: since
×
180
                                 to: until
×
181
                                 over: aDateWeekMonthOrYear.
×
182

×
183
        gitAnalyzer := GitAnalyzer new
×
184
                               onModel: glhModel;
×
185
                               glhImporter: glhImporter.
×
186

×
187
        glhImporter withCommitDiffs: false.
×
188
        commits := self
×
189
                           loadCommitOfProjects: itsProjects keys
×
190
                           since: since
×
191
                           until: until.
×
192
        glhImporter withCommitDiffs: true.
×
193
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
194
        commits do: [ :commit | glhImporter completeImportedCommit: commit ].
×
195

×
196

×
197
        contributions := commits collect: [ :commit |
×
198
                                 commit -> (gitAnalyzer
×
199
                                          fromCommit: commit;
×
200
                                          analyseCommentContributions) ].
×
201

×
202

×
203
        contributions do: [ :assoc |
×
204
                | dateOver |
×
205
                dateOver := self
×
206
                                    transformDate: assoc key created_at
×
207
                                    to: aDateWeekMonthOrYear.
×
208
                groupedByDate
×
209
                        at: dateOver printString
×
210
                        ifPresent: [ :v | v add: assoc value ]
×
211
                        ifAbsentPut: [
×
212
                                OrderedCollection new
×
213
                                        add: assoc value;
×
214
                                        yourself ] ].
×
215

×
216
        groupedByDate := groupedByDate collect: [ :contribs |
×
217
                                 contribs
×
218
                                         ifNotEmpty: [ contribs sum ]
×
219
                                         ifEmpty: [ 0 ] ].
×
220

×
221

×
222
        ^ {
×
223
                  (#details -> groupedByDate).
×
224
                  (#totalComments -> groupedByDate values sum).
×
225
                  (#avgComments -> groupedByDate values average asFloat).
×
226
                  (#overEach -> aDateWeekMonthOrYear name).
×
227
                  (#forOver -> (groupedByDate keys size printString
×
228
                    , aDateWeekMonthOrYear printString)).
×
229
                  (#userCommits -> commits size) } asDictionary
×
230
]
×
231

232
{ #category : #metrics }
233
GitMetric4User >> commitFrequencySince: since until: until overA: aDateWeekMonthOrYear [
×
234

×
235
        | periods total groupedByDate userCommits |
×
236
        'GitMetric4User: commit frequency' recordInfo.
×
237

×
238

×
239
        groupedByDate := self
×
240
                                 setupGroupedDateFrom: since
×
241
                                 to: until
×
242
                                 over: aDateWeekMonthOrYear.
×
243

×
244
        glhImporter withCommitDiffs: false.
×
245
        userCommits := self
×
246
                               loadCommitOfProjects: itsProjects keys
×
247
                               since: since
×
248
                               until: until.
×
249
        glhImporter withCommitDiffs: true.
×
250
        userCommits := userCommits reject: [ :c | c commitCreator ~= user ].
×
251

×
252
        userCommits do: [ :c |
×
253
                | dateOver |
×
254
                dateOver := self
×
255
                                    transformDate: c created_at
×
256
                                    to: aDateWeekMonthOrYear.
×
257
                groupedByDate at: dateOver printString ifPresent: [ :v | v add: c ] ].
×
258

×
259
        periods := groupedByDate keys size.
×
260
        total := groupedByDate values sum: [ :commits | commits size ].
×
261

×
262

×
263
        ^ {
×
264
                  (#averageFrac -> (total / periods)).
×
265
                  (#averageFloat -> (total / periods) asFloat).
×
266
                  (#userCommit -> total).
×
267
                  (#forOver -> (groupedByDate keys size printString
×
268
                    , aDateWeekMonthOrYear printString)).
×
269
                  (#periode -> aDateWeekMonthOrYear name).
×
270
                  (#details -> groupedByDate) } asOrderedDictionary
×
271
]
×
272

273
{ #category : #'as yet unclassified' }
274
GitMetric4User >> commitsProducedOnProject: projectId since: sinceDate until: untilDate [
×
275

×
276
        | frequencies |
×
277
        
×
278
        
×
279
        gitAnalyzer := GitAnalyzer new 
×
280
        glhImporter: glhImporter; 
×
281
        onModel: glhModel.
×
282
         
×
283
        frequencies := gitAnalyzer
×
284
                               onProject: (itsProjects at: projectId);
×
285
                               analyseCommitFrequencySince: sinceDate
×
286
                               until: untilDate. 
×
287
        
×
288
        "complete each commit "
×
289
        frequencies values flattened do: [ :commit |
×
290
                glhImporter completeImportedCommit: commit.
×
291
                 ].
×
292
        
×
293
        "Filter the associations in the 'frequencies' collection, removing any commits not created by the specified 'user'. "
×
294
        frequencies associations do: [ :assoc |
×
295
                |commits| 
×
296
                commits := assoc value.
×
297
                assoc value: (commits reject: [ :commit | commit commitCreator ~= user ]). 
×
298
        ].
×
299
        
×
300
        ^ frequencies 
×
301
]
×
302

303
{ #category : #metrics }
304
GitMetric4User >> commitsProducedOnProject: aProjectId since: since until: until overA: aWeekOrMonthOrYear [
×
305
        "'aWeekOrMonthOrYear' should be the class of Week, Month or Year"
×
306

×
307
        "self commitFrequencyOnProject: 6462 since: (Date today - 60 day) until: (Date today) overA: Week. "
×
308

×
309
        | frequency aggregatedFrequencies |
×
310
        aggregatedFrequencies := self setupGroupedDateFrom: since to: until  over: aWeekOrMonthOrYear.
×
311
        
×
312
        frequency := self
×
313
                             commitsProducedOnProject: aProjectId
×
314
                             since: since
×
315
                             until: until.
×
316

×
317

×
318
        frequency associations do: [ :assoc |
×
319
                | date commits overDate |
×
320
                date := assoc key.
×
321
                commits := assoc value.
×
322

×
323
                commits ifNotEmpty: [ " convert the date as its week date. For some english reason, the week start in sunday so we should add a + 1 day "
×
324
                        overDate := self transformDate: date to: aWeekOrMonthOrYear.
×
325
                        aggregatedFrequencies
×
326
                                at: overDate printString
×
327
                                ifPresent: [ :collection | collection addAll: commits ]
×
328
                                ifAbsentPut: [ commits ] ] ].
×
329

×
330
        ^ aggregatedFrequencies
×
331
]
×
332

333
{ #category : #churn }
334
GitMetric4User >> delayUntilFirstChurnSince: since until: until onACommitWindowOf: maxCommitWindow overA: aDateWeekMonthOrYear [
×
335

×
336
        | commits groupedByDate res avg userCommits|
×
337
        'GitMetric4User: delay until first churn' recordInfo.
×
338

×
339
        groupedByDate := self
×
340
                                 setupGroupedDateFrom: since
×
341
                                 to: until
×
342
                                 over: aDateWeekMonthOrYear.
×
343

×
344
        glhImporter withCommitDiffs: false.
×
345
        commits := self
×
346
                           loadCommitOfProjects: itsProjects keys
×
347
                           since: since
×
348
                           until: until.
×
349
        glhImporter withCommitDiffs: true.
×
350

×
351
        userCommits := commits reject: [ :commit |
×
352
                               commit commitCreator ~= user ].
×
353
        commits := self
×
354
                           foundSuccessorOf: userCommits
×
355
                           andCompleteImportForMax: maxCommitWindow.
×
356
        
×
357

×
358
        "class commit by dates, filter none user commits"
×
359
        commits do: [ :commit |
×
360
                commit commitCreator = user ifTrue: [
×
361
                        | overDate |
×
362
                        overDate := self
×
363
                                            transformDate: commit created_at
×
364
                                            to: aDateWeekMonthOrYear.
×
365

×
366
                        groupedByDate
×
367
                                at: overDate printString
×
368
                                ifPresent: [ :arrayOfCommits | arrayOfCommits add: commit ]
×
369
                                ifAbsentPut: [
×
370
                                        OrderedCollection new
×
371
                                                add: commit;
×
372
                                                yourself ] ] ].
×
373

×
374

×
375

×
376
        res := groupedByDate collect: [ :commits4Date |
×
377
                       | durationFromA2B |
×
378
                       commits4Date collect: [ :commitA |
×
379
                               | commitB |
×
380
                               commitB := GitAnalyzer new
×
381
                                                  glhImporter: glhImporter;
×
382
                                                  onModel: glhModel;
×
383
                                                  fromCommit: commitA;
×
384
                                                  maxChildCommit: maxCommitWindow;
×
385
                                                  analyseAmandment.
×
386

×
387
                               durationFromA2B := commitB
×
388
                                                          ifNil: [ 0 ]
×
389
                                                          ifNotNil: [
×
390
                                                          commitB created_at - commitA created_at ].
×
391
                               durationFromA2B ] ].
×
392

×
393

×
394

×
395
        res := res collect: [ :durationsByDate |
×
396
                       | filtered |
×
397
                       filtered := durationsByDate reject: [ :value | value = 0 ].
×
398
                       filtered isEmpty
×
399
                               ifTrue: [ nil ]
×
400
                               ifFalse: [
×
401
                               (filtered sum: [ :v | v asDuration ]) / filtered size ] ].
×
402

×
403
        res := res reject: #isNil.
×
404

×
405
        res
×
406
                ifEmpty: [ avg := nil ]
×
407
                ifNotEmpty: [ avg := res values sum / res keys size ].
×
408

×
409

×
410
        ^ {
×
411
                  (#avgDelay -> avg).
×
412
                  (#overEach -> aDateWeekMonthOrYear name).
×
413
                  (#forOver -> (groupedByDate keys size printString
×
414
                    , aDateWeekMonthOrYear printString)).
×
415
                  (#details -> groupedByDate) } asDictionary
×
416
]
×
417

418
{ #category : #churn }
419
GitMetric4User >> delayUntilFirstChurnSince: since until: until overA: aDateWeekMonthOrYear [
×
420

×
421
        | commits groupedByDate res avg |
×
422
        self
×
423
                deprecated:
×
424
                'Use #delayUntilFirstChurnSince:until:onACommitWindowOf:overA: instead'
×
425
                on: '1 July 2024'
×
426
                in:
×
427
                'Pharo-11.0.0+build.726.sha.aece1b5473acf3830a0e082c1bc3a15d4ff3522b (64 Bit)'.
×
428

×
429
        'GitMetric4User: delay until first churn' recordInfo.
×
430

×
431
        groupedByDate := self
×
432
                                 setupGroupedDateFrom: since
×
433
                                 to: until
×
434
                                 over: aDateWeekMonthOrYear.
×
435

×
436
        commits := self
×
437
                           loadCommitOfProjects: itsProjects keys
×
438
                           since: since
×
439
                           until: until.
×
440

×
441
        "class commit by dates, filter none user commits"
×
442
        commits do: [ :commit |
×
443
                commit commitCreator = user ifTrue: [
×
444
                        | overDate |
×
445
                        overDate := self
×
446
                                            transformDate: commit created_at
×
447
                                            to: aDateWeekMonthOrYear.
×
448

×
449
                        groupedByDate
×
450
                                at: overDate printString
×
451
                                ifPresent: [ :arrayOfCommits | arrayOfCommits add: commit ]
×
452
                                ifAbsentPut: [
×
453
                                        OrderedCollection new
×
454
                                                add: commit;
×
455
                                                yourself ] ] ].
×
456

×
457

×
458

×
459
        res := groupedByDate collect: [ :commits4Date |
×
460
                       | durationFromA2B |
×
461
                       commits4Date collect: [ :commitA |
×
462
                               | commitB |
×
463
                               commitB := GitAnalyzer new
×
464
                                                  glhImporter: glhImporter;
×
465
                                                  onModel: glhModel;
×
466
                                                  fromCommit: commitA;
×
467
                                                  maxChildCommit: 5;
×
468
                                                  analyseAmandment.
×
469

×
470
                               durationFromA2B := commitB
×
471
                                                          ifNil: [ 0 ]
×
472
                                                          ifNotNil: [
×
473
                                                          commitB created_at - commitA created_at ].
×
474
                               durationFromA2B ] ].
×
475

×
476

×
477

×
478
        res := res collect: [ :durationsByDate |
×
479
                       | filtered |
×
480
                       filtered := durationsByDate reject: [ :value | value = 0 ].
×
481
                       filtered isEmpty
×
482
                               ifTrue: [ nil ]
×
483
                               ifFalse: [
×
484
                               (filtered sum: [ :v | v asDuration ]) / filtered size ] ].
×
485

×
486
        res := res reject: #isNil.
×
487

×
488
        res
×
489
                ifEmpty: [ avg := nil ]
×
490
                ifNotEmpty: [ avg := res values sum / res keys size ].
×
491

×
492

×
493
        ^ {
×
494
                  (#avgDelay -> avg).
×
495
                  (#overEach -> aDateWeekMonthOrYear name).
×
496
                  (#forOver -> (groupedByDate keys size printString
×
497
                    , aDateWeekMonthOrYear printString)).
×
498
                  (#details -> groupedByDate) } asDictionary
×
499
]
×
500

501
{ #category : #'as yet unclassified' }
502
GitMetric4User >> findUserNamed: aUsername [
×
503

×
504
        user := glhImporter importUserByUsername: aUsername.
×
505
        ^ user
×
506
]
×
507

508
{ #category : #churn }
509
GitMetric4User >> foundSuccessorOf: userCommits andCompleteImportForMax: commitLimit [
×
510

×
511
        | analyzingCommits i|
×
512
        analyzingCommits := Set new.
×
513
        glhImporter withCommitDiffs: true.
×
514

×
515
        userCommits do: [ :c |
×
516
                gitAnalyzer
×
517
                        visitChildCommits: c childCommits
×
518
                        toStoreThemIn: analyzingCommits
×
519
                        upto: commitLimit ].
×
520
        i := 1. 
×
521
        analyzingCommits do: [ :c | 
×
522
                (' ' join: { 'import commit creators: ' .(i) . '/' . analyzingCommits size }) recordInfo.
×
523
                i := i + 1. 
×
524
                glhImporter completeImportedCommit: c ].
×
525
        ^ analyzingCommits
×
526
]
×
527

528
{ #category : #accessing }
529
GitMetric4User >> glhImporter: aGLPHModelImporter [ 
×
530
        glhImporter := aGLPHModelImporter
×
531
]
×
532

533
{ #category : #initialization }
534
GitMetric4User >> initialize [
×
535

×
536
        user := GLHUser new.
×
537
        itsProjects := Dictionary new.
×
538
        itsCommits := Dictionary new.
×
539
        itsGroups := Dictionary new.
×
540
        itsMergeRequests := Dictionary new
×
541
]
×
542

543
{ #category : #accessing }
544
GitMetric4User >> itsProjects: projects [
×
545
        itsProjects := projects .
×
546
]
×
547

548
{ #category : #churn }
549
GitMetric4User >> loadCommitOfProjects: aCollection since: aTimespan [
×
550
        |commits|
×
551
        
×
552
        commits := (aCollection collect: [ :id |
×
553
                 glhImporter
×
554
                        importCommitsOProject: (itsProjects at: id)
×
555
                        since: aTimespan
×
556
                        until: nil ]) flattened.
×
557

×
558
        commits do: [ :commit |
×
559
                glhImporter completeImportedCommit: commit. 
×
560
                 ].
×
561

×
562
        ^ self userCommits.
×
563
]
×
564

565
{ #category : #churn }
566
GitMetric4User >> loadCommitOfProjects: aCollection since: since until: until [
×
567

×
568
        | allCommits period i|
×
569
        period := ('commits since ' , since printString , ' to '
×
570
                   , until printString) asSymbol.
×
571

×
572
        "download commits unless project cache is not empty"
×
573
        allCommits := aCollection collect: [ :idProject |
×
574
                              | project |
×
575
                              project := itsProjects at: idProject.
×
576
                              project repository cacheAt: period ifAbsentPut: [
×
577
                                      | foundCommits |
×
578
                                      foundCommits := glhImporter
×
579
                                                              importCommitsOProject: project
×
580
                                                              since: since
×
581
                                                              until: until.
×
582
                                      foundCommits ] ].
×
583

×
584
        allCommits := allCommits flatten.
×
585

×
586
        i := 1. 
×
587
        allCommits do: [ :commit |
×
588
                (' ' join: { 'import creators ' .(i) . '/' . allCommits size }) recordInfo.
×
589
                glhImporter importCreatorOfCommit: commit.
×
590
                i := i + 1. 
×
591
         ].
×
592

×
593
        glhImporter chainsCommitsFrom: allCommits.
×
594

×
595
        ^ allCommits
×
596
]
×
597

598
{ #category : #churn }
599
GitMetric4User >> loadMergeRequestsOfProjects: aCollection since: since until: until [
×
600

×
601
        | allMr period|
×
602
        "itsMergeRequests ifNil: [ itsMergeRequests := Dictionary new ]."
×
603
        
×
604
        period := ('mr since ' , since printString , ' to '
×
605
                   , until printString) asSymbol.
×
606

×
607
        allMr := aCollection collect: [ :idProject |
×
608
                              | project mr|
×
609
                              project := itsProjects at: idProject.
×
610
                              project cacheAt: period ifAbsentPut: [ 
×
611
                                                        mr :=        glhImporter
×
612
                                                        importMergeRequests: project
×
613
                                                        since: since
×
614
                                                        until: until.
×
615
                                                        mr.         
×
616
                         ].        
×
617
                ].
×
618
        
×
619
        ^  allMr flattened.
×
620

×
621
]
×
622

623
{ #category : #loading }
624
GitMetric4User >> loadProjects: projectIds [
×
625

×
626
        projectIds do: [ :id |
×
627
                
×
628
                itsProjects at: id ifAbsentPut: [ glhImporter importProject: id ] ].
×
629

×
630
        ^ itsProjects
×
631
]
×
632

633
{ #category : #metrics }
634
GitMetric4User >> mergeRequestDurationSince: since until: until overA: aDateWeekMonthOrYear [
×
635

×
636
        | mergeRequest res groupedByDate filterGroups avg |
×
637
        groupedByDate := self
×
638
                                 setupGroupedDateFrom: since
×
639
                                 to: until
×
640
                                 over: aDateWeekMonthOrYear.
×
641

×
642
        gitAnalyzer := GitAnalyzer new
×
643
                               glhImporter: glhImporter;
×
644
                               onModel: glhModel.
×
645

×
646
        glhImporter withCommitDiffs: false.
×
647
        mergeRequest := self
×
648
                                loadMergeRequestsOfProjects: itsProjects keys
×
649
                                since: since
×
650
                                until: until.
×
651
        glhImporter withCommitDiffs: true.
×
652

×
653
        mergeRequest ifEmpty: [
×
654
                ^ {
×
655
                          (#avgDuration -> nil).
×
656
                          (#overEach -> aDateWeekMonthOrYear name).
×
657
                          (#forOver -> (groupedByDate keys size printString
×
658
                            , aDateWeekMonthOrYear printString)).
×
659
                          (#totalMergeRequest -> 0).
×
660
                          (#details -> nil) } asDictionary ].
×
661

×
662
        res := mergeRequest collect: [ :mr |
×
663
                       gitAnalyzer analyseMergeResquestValidation: mr ].
×
664

×
665

×
666
        res do: [ :dic |
×
667
                | overDate |
×
668
                overDate := self
×
669
                                    transformDate: (dic at: #created_at)
×
670
                                    to: aDateWeekMonthOrYear.
×
671

×
672
                groupedByDate
×
673
                        at: overDate printString
×
674
                        ifPresent: [ :durations | durations add: (dic at: #duration) ]
×
675
                        ifAbsentPut: [
×
676
                                OrderedCollection new
×
677
                                        add: (dic at: #duration);
×
678
                                        yourself ] ].
×
679

×
680

×
681
        filterGroups := groupedByDate reject: [ :array | array isEmpty ].
×
682

×
683
        filterGroups associations do: [ :assoc |
×
684
                | sum denominator |
×
685
                denominator := assoc value size.
×
686

×
687
                sum := assoc value sum: [ :v |
×
688
                               v ifNil: [
×
689
                                       denominator := denominator - 1.
×
690
                                       0 asDuration ] ].
×
691
                denominator = 0 ifTrue: [ denominator := 1 ].
×
692

×
693
                filterGroups at: assoc key put: sum / denominator ].
×
694

×
695

×
696
        filterGroups keys
×
697
                ifEmpty: [ avg := 0 ]
×
698
                ifNotEmpty: [
×
699
                avg := filterGroups values sum / filterGroups keys size ].
×
700

×
701

×
702
        ^ {
×
703
                  (#avgDuration -> avg).
×
704
                  (#overEach -> aDateWeekMonthOrYear name).
×
705
                  (#forOver -> (groupedByDate keys size printString
×
706
                    , aDateWeekMonthOrYear printString)).
×
707
                  (#totalMergeRequest -> mergeRequest size).
×
708
                  (#details -> groupedByDate) } asDictionary
×
709
]
×
710

711
{ #category : #setup }
712
GitMetric4User >> setupGroupedDateFrom: since to: until over: aDateWeekMonthOrYear [
×
713

×
714
        | groupedByDate start end over increment|
×
715
        groupedByDate := OrderedDictionary new.
×
716

×
717
        increment := 1.
×
718
        start := self transformDate: since to: aDateWeekMonthOrYear.
×
719
        end := self transformDate: until to: aDateWeekMonthOrYear.
×
720

×
721
        groupedByDate
×
722
                at: start printString
×
723
                ifAbsentPut: [ OrderedCollection new ].
×
724
        
×
725
        over := aDateWeekMonthOrYear name asLowercase asSymbol.
×
726
                over = #date ifTrue: [ over := #day ].
×
727
                over = #month ifTrue: [ increment := 32. over := #day ].
×
728
                 
×
729

×
730
        [ groupedByDate keys last asDateAndTime < end ] whileTrue: [
×
731
                | index  |
×
732
                index := groupedByDate keys last asDateAndTime + (increment perform: over).
×
733
                index := self transformDate: index to: aDateWeekMonthOrYear.
×
734
                groupedByDate
×
735
                        at: index printString
×
736
                        ifAbsentPut: [ OrderedCollection new ] ].
×
737
        
×
738
        
×
UNCOV
739
        over = #day ifTrue: [ 
×
UNCOV
740
                groupedByDate keys do: [ :date |
×
UNCOV
741
                        |aWeekday|
×
UNCOV
742
                         aWeekday := date asDate weekday. 
×
UNCOV
743
                        ((aWeekday =  #Sunday) or: [ aWeekday = #Saturday ] )ifTrue: [ 
×
UNCOV
744
                                groupedByDate removeKey: date. 
×
UNCOV
745
                                 ] 
×
UNCOV
746
                         ].
×
UNCOV
747
                 ].
×
UNCOV
748
        
×
UNCOV
749

×
UNCOV
750
        groupedByDate
×
UNCOV
751
                at: end printString
×
UNCOV
752
                ifAbsentPut: [ OrderedCollection new ].
×
UNCOV
753

×
UNCOV
754
        ^ groupedByDate
×
UNCOV
755
]
×
756

757
{ #category : #'as yet unclassified' }
UNCOV
758
GitMetric4User >> transformDate: date to: aWeekOrMonthOrYear [
×
UNCOV
759

×
UNCOV
760
        aWeekOrMonthOrYear = Month ifTrue: [ ^ date asDate month asDate ].
×
UNCOV
761

×
UNCOV
762
        ^ (date asDate perform: ('as' , aWeekOrMonthOrYear name) asSymbol)
×
UNCOV
763
                  asDate
×
UNCOV
764
]
×
765

766
{ #category : #accessing }
UNCOV
767
GitMetric4User >> user [
×
UNCOV
768
        ^ user
×
UNCOV
769
]
×
770

771
{ #category : #accessing }
UNCOV
772
GitMetric4User >> user: anUser [
×
UNCOV
773
        user := anUser. 
×
UNCOV
774
]
×
775

776
{ #category : #accessing }
UNCOV
777
GitMetric4User >> userCommits [
×
UNCOV
778
        ^ user commits
×
UNCOV
779
]
×
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