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

moosetechnology / GitProjectHealth / 17854662497

19 Sep 2025 09:40AM UTC coverage: 73.962% (+0.6%) from 73.342%
17854662497

Pull #232

github

web-flow
Merge b59e3bc46 into dd8ffa1f6
Pull Request #232: add constructor in class since of GitModelImporter for quality of life setup

49 of 167 new or added lines in 8 files covered. (29.34%)

45 existing lines in 3 files now uncovered.

18909 of 25566 relevant lines covered (73.96%)

0.74 hits per line

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

59.25
/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st
1
"
2
I am a superclass for Model importer.
3
I am a try of normalization for the different importer.
4

5
I also define some contract so it is easier to switch from one importer to another
6
"
7
Class {
8
        #name : #GitModelImporter,
9
        #superclass : #Object,
10
        #instVars : [
11
                'withCommitsSince',
12
                'withFiles',
13
                'glhModel',
14
                'userCatalogue',
15
                'repoApi',
16
                'withCommitDiffs'
17
        ],
18
        #classVars : [
19
                'currentImporter'
20
        ],
21
        #category : #'GitProjectHealth-Model-Importer'
22
}
23

24
{ #category : #bitbucket }
NEW
25
GitModelImporter class >> forBitbucketHostOn: anHostURL withToken: anApiToken [
×
NEW
26
        
×
NEW
27
        ^ self forBitbucketHostOn: anHostURL withToken: anApiToken andModel: GLHModel new. 
×
NEW
28
]
×
29

30
{ #category : #bitbucket }
NEW
31
GitModelImporter class >> forBitbucketHostOn: anHostURL withToken: anApiToken andModel: aGitModel [
×
NEW
32
        
×
NEW
33
        | bitbucketApi bitBucketImporter |
×
NEW
34
        bitbucketApi := BitbucketApi new
×
NEW
35
                host: anHostURL;
×
NEW
36
                bearerToken: anApiToken.
×
NEW
37

×
NEW
38
        bitBucketImporter := BitBucketModelImporter new
×
NEW
39
                     repoApi: bitbucketApi;
×
NEW
40
                     glhModel: aGitModel;
×
NEW
41
                     withFiles: false;
×
NEW
42
                     withCommitsSince: 3 day;
×
NEW
43
                     withCommitDiffs: false.
×
NEW
44
        ^bitBucketImporter 
×
NEW
45
]
×
46

47
{ #category : #github }
NEW
48
GitModelImporter class >> forGithubWithToken: anApiToken [
×
NEW
49
        ^ self forGithubWithToken: anApiToken andModel: GLHModel new
×
NEW
50
]
×
51

52
{ #category : #github }
NEW
53
GitModelImporter class >> forGithubWithToken: anApiToken andModel: aGitModel [
×
NEW
54

×
NEW
55
        | githubImport |
×
NEW
56
        githubImport := GithubModelImporter new
×
NEW
57
                                glhModel: aGitModel;
×
NEW
58
                                privateToken: anApiToken;
×
NEW
59
                                withCommitsSince: 3 day;
×
NEW
60
                                yourself.
×
NEW
61
        ^ githubImport
×
NEW
62
]
×
63

64
{ #category : #gitlab }
NEW
65
GitModelImporter class >> forGitlabHostOn: anHostURL withToken: anApiToken [ 
×
NEW
66
        ^ self forGitlabHostOn: anHostURL withToken: anApiToken andModel: GLHModel new. 
×
NEW
67
]
×
68

69
{ #category : #gitlab }
NEW
70
GitModelImporter class >> forGitlabHostOn: anHostURL withToken: anApiToken andModel: aGitModel [
×
NEW
71
        "use it when accessing onpremise or custom gitlab platform"
×
NEW
72
        | glphApi gitlabImporter |
×
NEW
73
        
×
NEW
74
        glphApi := GitlabApi new
×
NEW
75
    privateToken: anApiToken;
×
NEW
76
    hostUrl: anHostURL;
×
NEW
77
         output: 'json';
×
NEW
78
    yourself.
×
NEW
79

×
NEW
80
        gitlabImporter := GitlabModelImporter new
×
NEW
81
    repoApi: glphApi;
×
NEW
82
    glhModel: aGitModel;
×
NEW
83
         withFiles: false;
×
NEW
84
         withCommitsSince: 3 day;
×
NEW
85
         withCommitDiffs: false.
×
NEW
86
                
×
NEW
87
        ^ gitlabImporter 
×
NEW
88
]
×
89

90
{ #category : #gitlab }
NEW
91
GitModelImporter class >> forGitlabWithToken: anApiToken [
×
NEW
92
        ^ self forGitlabHostOn: 'https://gitlab.com/api/v4' withToken: anApiToken andModel: GLHModel new. 
×
NEW
93
]
×
94

95
{ #category : #gitlab }
NEW
96
GitModelImporter class >> forGitlabWithToken: anApiToken andModel: aGitModel [
×
NEW
97
        ^ self forGitlabHostOn: 'https://gitlab.com/api/v4' withToken: anApiToken andModel: aGitModel
×
NEW
98
]
×
99

100
{ #category : #'accessing - global variables' }
101
GitModelImporter class >> importers [
×
102
        ^ currentImporter 
×
103
]
×
104

105
{ #category : #initialization }
106
GitModelImporter class >> reset [
×
107
        currentImporter := OrderedDictionary new.
×
108
]
×
109

110
{ #category : #accessing }
111
GitModelImporter >> beWithFiles [
×
112

×
113
        withFiles := true
×
114
]
×
115

116
{ #category : #accessing }
117
GitModelImporter >> beWithoutFiles [
×
118

×
119
        withFiles := false
×
120
]
×
121

122
{ #category : #'as yet unclassified' }
123
GitModelImporter >> blockEqualityOn: aSymbol [
1✔
124
        ^ [ :existing :new |
1✔
125
          (existing perform: aSymbol) = (new perform: aSymbol) ]
1✔
126
]
1✔
127

128
{ #category : #'as yet unclassified' }
129
GitModelImporter >> blockEqualityOn: aSymbol andOn: aSecondSymbol [
×
130
        ^ (self blockEqualityOn: aSymbol) and: [ self blockEqualityOn: aSecondSymbol ]
×
131
]
×
132

133
{ #category : #equality }
134
GitModelImporter >> blockForBranchEquality [
1✔
135
        ^ [ :existing :new |
1✔
136
          (existing name = new name) and: [ existing repository project id = new repository project id ] ]
1✔
137
        
1✔
138
]
1✔
139

140
{ #category : #equality }
141
GitModelImporter >> blockForDiffEquality [
1✔
142
        ^ [ :existing :new |
1✔
143
                        existing diffString size = new diffString size and: [
1✔
144
                                existing diffString = new diffString ] ]
1✔
145
]
1✔
146

147
{ #category : #'as yet unclassified' }
148
GitModelImporter >> blockForDiffRangeEquality [
1✔
149

1✔
150
        ^ [ :existing :new |
1✔
151
          existing diff mooseID = new diff mooseID and: [
1✔
152
                  existing originalLineRange = new originalLineRange and: [
1✔
153
                          existing newLineRange = new newLineRange ] ] ]
1✔
154
]
1✔
155

156
{ #category : #equality }
157
GitModelImporter >> blockOnIdEquality [
1✔
158

1✔
159
        ^ [ :existing :new |
1✔
160
          existing id = new id ]
1✔
161
]
1✔
162

163
{ #category : #equality }
164
GitModelImporter >> blockOnNameEquality [
1✔
165

1✔
166
        ^ self blockEqualityOn: #name
1✔
167
]
1✔
168

169
{ #category : #commit }
170
GitModelImporter >> chainsCommitsFrom: commitsCollection [
1✔
171

1✔
172
        | dic |
1✔
173
        ('Chains ' , commitsCollection size printString , ' commits')
1✔
174
                recordInfo.
1✔
175

1✔
176
        dic := ((self glhModel allWithType: GLHCommit) collect: [ :commit |
1✔
177
                        commit id -> commit ]) asSet asDictionary.
1✔
178

1✔
179
        commitsCollection do: [ :commit |
1✔
180
                commit parent_ids do: [ :parentId |
1✔
181
                        dic
1✔
182
                                at: parentId
1✔
183
                                ifPresent: [ :parentCommit |
1✔
184
                                        parentCommit childCommits
1✔
185
                                                add: commit
1✔
186
                                                unless: [ :existing :new | existing id = new id ] ]
1✔
187
                                ifAbsent: [  ] ] ].
1✔
188
        ^ commitsCollection
1✔
189
]
1✔
190

191
{ #category : #commit }
192
GitModelImporter >> completeImportedCommit: aGLHCommit [ 
×
193
        
×
194
        
×
195
        ('completing commit: ' , aGLHCommit short_id printString) recordInfo.
×
196
        self importCreatorOfCommit: aGLHCommit.
×
197

×
198
        self withCommitDiffs ifTrue: [
×
199
                | diffs |
×
200
                aGLHCommit diffs ifEmpty: [
×
201
                        diffs := self importDiffOfCommit: aGLHCommit.
×
202
                        self glhModel addAll: diffs unless: self blockForDiffEquality ] ].
×
203

×
204
        ^ aGLHCommit
×
205
]
×
206

207
{ #category : #'as yet unclassified' }
208
GitModelImporter >> filterCommitChanges: aCollection [
1✔
209

1✔
210
        ^ aCollection reject: [ :line |
1✔
211
                  | trimmedLine |
1✔
212
                  trimmedLine := line trimLeft.
1✔
213
                  (trimmedLine beginsWith: '---') or: [
1✔
214
                          (trimmedLine beginsWith: '+++') or: [
1✔
215
                                  trimmedLine beginsWith: '\ No newline at end of file' ] ] ]
1✔
216
]
1✔
217

218
{ #category : #accessing }
219
GitModelImporter >> glhModel [
1✔
220

1✔
221
        ^ glhModel
1✔
222
]
1✔
223

224
{ #category : #accessing }
225
GitModelImporter >> glhModel: anObject [
1✔
226

1✔
227
        glhModel := anObject
1✔
228
]
1✔
229

230
{ #category : #'import - repositories' }
231
GitModelImporter >> importBranchesOf: aGLHProject [
232

233
        ^ self subclassResponsibility
234
]
235

236
{ #category : #import }
237
GitModelImporter >> importDiffRangesForDiff: aGLHDiff [
1✔
238

1✔
239
        | diffRanges |
1✔
240
        aGLHDiff diffRanges ifNotEmpty: [
1✔
241
                ('Diffs already imported for ' , aGLHDiff printString) recordInfo.
1✔
242
                ^ aGLHDiff diffRanges ].
1✔
243

1✔
244
        ('Import changes of diff ' , aGLHDiff printString) recordInfo.
1✔
245
        "the import of 'diffRanges' entites is technically done inside the parseDiffString"
1✔
246

1✔
247
        diffRanges := self glhModel
1✔
248
                              addAll: (self parseDiffString: aGLHDiff)
1✔
249
                              unless: self blockForDiffRangeEquality.
1✔
250
        ^ aGLHDiff diffRanges
1✔
251
                  addAll: diffRanges
1✔
252
                  unless: self blockForDiffRangeEquality
1✔
253
]
1✔
254

255
{ #category : #'import - groups' }
256
GitModelImporter >> importGroup: aGroupID [
257

258
        self subclassResponsibility
259
]
260

261
{ #category : #pipelines }
262
GitModelImporter >> importLatestPipelinesOfProject: aGLHProject [ 
×
263
        (self pipelinesOf: aGLHProject id withLimit:30) do: [ :pipeline |
×
264
                self glhModel add: pipeline unless: self blockOnIdEquality .
×
265
                aGLHProject pipelines add: pipeline unless: self blockOnIdEquality]
×
266
]
×
267

268
{ #category : #'import - notes' }
269
GitModelImporter >> importNotesfromMergeRequest: mergeRequest [
270

271
        self subclassResponsibility
272
]
273

274
{ #category : #'import - projects' }
275
GitModelImporter >> importProject: id [
276
        "id can be a string or an integer depending on the APi implementation"
277

278
        "return the project created or retrieved"
279

280
        ^ self subclassResponsibility
281
]
282

283
{ #category : #'import - projects' }
284
GitModelImporter >> importProjects: aCollectionOfProjectID [
×
285

×
286

×
287
        ^ aCollectionOfProjectID collect: [ :id | self importProject: id ]
×
288
]
×
289

290
{ #category : #initialization }
291
GitModelImporter >> initialize [
1✔
292

1✔
293
        super initialize.
1✔
294
        self withCommitsSince: (Date today - 1 week) asDateAndTime.
1✔
295
        userCatalogue := GLHUserCatalogueV2 new
1✔
296
                                 anImporter: self;
1✔
297
                                 yourself.
1✔
298
]
1✔
299

300
{ #category : #'as yet unclassified' }
301
GitModelImporter >> makeGlobal [
×
302
        ^ self makeGlobal: DateAndTime now printString.
×
303
]
×
304

305
{ #category : #'as yet unclassified' }
306
GitModelImporter >> makeGlobal: aLabel [ 
×
307

×
308
        currentImporter := GithubModelImporter importers ifNil: [ OrderedDictionary new ].
×
309
        currentImporter at: aLabel put: self. 
×
310
        ^ currentImporter 
×
311
]
×
312

313
{ #category : #parsing }
314
GitModelImporter >> parseDiffString: aDiff [
1✔
315
        "parse diff string to create entities for each lines"
1✔
316

1✔
317
        | lines range index firstChangeRange |
1✔
318
        lines := aDiff diffString lines.
1✔
319
        index := 0.
1✔
320
        range := nil.
1✔
321

1✔
322
        lines ifEmpty: [ ^ aDiff diffRanges ].
1✔
323
        lines := self filterCommitChanges: lines.
1✔
324
        lines ifEmpty: [ ^ aDiff diffRanges ].
1✔
325
        (lines first beginsWith: '@@') ifFalse: [ ^ aDiff diffRanges ].
1✔
326

1✔
327
        lines do: [ :line |
1✔
328
                | aChange |
1✔
329
                firstChangeRange := false.
1✔
330
                (line trim beginsWith: #'@@') ifTrue: [
1✔
331
                        range := GLHDiffRange newFrom: line.
1✔
332
                        firstChangeRange := true.
1✔
333
                        range := aDiff diffRanges add: range unless: [ :existing :new |
1✔
334
                                         existing originalLineRange = new originalLineRange and: [
1✔
335
                                                 existing newLineRange = new newLineRange ] ] ].
1✔
336

1✔
337
                self withCommitDiffs ifTrue: [
1✔
338
                        firstChangeRange ifFalse: [
1✔
339
                                aChange := GLHChange newFrom: line.
1✔
340
                                aChange relativeIndex: index.
1✔
341
                                aChange := range changes add: aChange unless: [ :existing :new |
1✔
342
                                                   existing sourceCode = new sourceCode and: [
1✔
343
                                                           existing index = new index ] ].
1✔
344
                                index := index + 1 ] ] ].
1✔
345

1✔
346
        "add changes to the diff range"
1✔
347
        aDiff diffRanges do: [ :diffRange |
1✔
348
                self glhModel addAll: diffRange changes unless: [ :existing :new |
1✔
349
                        existing diffRange mooseID = new diffRange mooseID and: [
1✔
350
                                existing sourceCode = new sourceCode and: [
1✔
351
                                        existing index = new index ] ] ] ].
1✔
352

1✔
353
        ^ aDiff diffRanges
1✔
354
]
1✔
355

356
{ #category : #accessing }
357
GitModelImporter >> repoApi [
1✔
358

1✔
359
        ^ repoApi
1✔
360
]
1✔
361

362
{ #category : #accessing }
363
GitModelImporter >> repoApi: anObject [
1✔
364

1✔
365
        repoApi := anObject
1✔
366
]
1✔
367

368
{ #category : #accessing }
369
GitModelImporter >> userCatalogue [
1✔
370
        ^ userCatalogue 
1✔
371
]
1✔
372

373
{ #category : #accessing }
374
GitModelImporter >> userCatalogue: aGLHUserCatalogue [
×
375

×
376
        userCatalogue := aGLHUserCatalogue.
×
377
        aGLHUserCatalogue anImporter: self. 
×
378
]
×
379

380
{ #category : #accessing }
381
GitModelImporter >> withCommitDiffs [
1✔
382

1✔
383
        ^ withCommitDiffs
1✔
384
]
1✔
385

386
{ #category : #accessing }
387
GitModelImporter >> withCommitDiffs: anObject [
1✔
388

1✔
389
        withCommitDiffs := anObject
1✔
390
]
1✔
391

392
{ #category : #accessing }
393
GitModelImporter >> withCommitsSince [
×
394

×
395
        ^ withCommitsSince
×
396
]
×
397

398
{ #category : #accessing }
399
GitModelImporter >> withCommitsSince: someDays [
1✔
400
        "substract the current date with a given number of days. Use to retrieve the commits submit in the last giving days"
1✔
401

1✔
402
        "(GitlabModelImporter new withCommitsSince: 1 week ) >>> (Date today - 1 week) asDateAndTime"
1✔
403

1✔
404
        "(GitlabModelImporter new withCommitsSince: 30 day ) >>> (Date today - 30 day) asDateAndTime"
1✔
405

1✔
406
        (someDays isKindOf: DateAndTime)
1✔
407
                ifTrue: [ withCommitsSince := someDays ]
1✔
408
                ifFalse: [
1✔
409
                withCommitsSince := (DateAndTime today - someDays) ].
1✔
410
        ^ withCommitsSince
1✔
411
]
1✔
412

413
{ #category : #accessing }
414
GitModelImporter >> withFiles [
1✔
415

1✔
416
        ^ withFiles
1✔
417
]
1✔
418

419
{ #category : #accessing }
420
GitModelImporter >> withFiles: anObject [
1✔
421

1✔
422
        withFiles := anObject
1✔
423
]
1✔
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