@@ -219,6 +219,148 @@ func (p *Project) GetDirectDependencyNames(sm gps.SourceManager) (pkgtree.Packag
219
219
return ptree , directDeps , nil
220
220
}
221
221
222
+ type lockUnsatisfy uint8
223
+
224
+ const (
225
+ missingFromLock lockUnsatisfy = iota
226
+ inAdditionToLock
227
+ )
228
+
229
+ type constraintMismatch struct {
230
+ c gps.Constraint
231
+ v gps.Version
232
+ }
233
+
234
+ type constraintMismatches map [gps.ProjectRoot ]constraintMismatch
235
+
236
+ type LockSatisfaction struct {
237
+ nolock bool
238
+ missingPkgs , excessPkgs []string
239
+ pkgs map [string ]lockUnsatisfy
240
+ badovr , badconstraint constraintMismatches
241
+ }
242
+
243
+ // Passed is a shortcut method to check if any problems with the evaluted lock
244
+ // were identified.
245
+ func (ls LockSatisfaction ) Passed () bool {
246
+ if ls .nolock {
247
+ return false
248
+ }
249
+
250
+ if len (ls .pkgs ) > 0 {
251
+ return false
252
+ }
253
+
254
+ if len (ls .badovr ) > 0 {
255
+ return false
256
+ }
257
+
258
+ if len (ls .badconstraint ) > 0 {
259
+ return false
260
+ }
261
+
262
+ return true
263
+ }
264
+
265
+ func (ls LockSatisfaction ) MissingPackages () []string {
266
+ return ls .missingPkgs
267
+ }
268
+
269
+ func (ls LockSatisfaction ) ExcessPackages () []string {
270
+ return ls .excessPkgs
271
+ }
272
+
273
+ func (ls LockSatisfaction ) UnmatchedOverrides () map [gps.ProjectRoot ]constraintMismatch {
274
+ return ls .badovr
275
+ }
276
+
277
+ func (ls LockSatisfaction ) UnmatchedConstraints () map [gps.ProjectRoot ]constraintMismatch {
278
+ return ls .badconstraint
279
+ }
280
+
281
+ // LockSatisfiesInputs determines whether the Project's lock satisfies all the
282
+ // requirements indicated by the inputs (Manifest and RootPackageTree).
283
+ func (p * Project ) LockSatisfiesInputs (sm gps.SourceManager ) (LockSatisfaction , error ) {
284
+ if p .Lock == nil {
285
+ return LockSatisfaction {nolock : true }, nil
286
+ }
287
+
288
+ ptree , err := p .ParseRootPackageTree ()
289
+ if err != nil {
290
+ return LockSatisfaction {}, err
291
+ }
292
+
293
+ var ig * pkgtree.IgnoredRuleset
294
+ var req map [string ]bool
295
+ if p .Manifest != nil {
296
+ ig = p .Manifest .IgnoredPackages ()
297
+ req = p .Manifest .RequiredPackages ()
298
+ }
299
+
300
+ rm , _ := ptree .ToReachMap (true , true , false , ig )
301
+ reach := rm .FlattenFn (paths .IsStandardImportPath )
302
+
303
+ inlock := make (map [string ]bool , len (p .Lock .SolveMeta .InputImports ))
304
+ ininputs := make (map [string ]bool , len (reach )+ len (req ))
305
+
306
+ for _ , imp := range reach {
307
+ ininputs [imp ] = true
308
+ }
309
+
310
+ for imp := range req {
311
+ ininputs [imp ] = true
312
+ }
313
+
314
+ for _ , imp := range p .Lock .SolveMeta .InputImports {
315
+ inlock [imp ] = true
316
+ }
317
+
318
+ lsat := LockSatisfaction {
319
+ badovr : make (constraintMismatches ),
320
+ badconstraint : make (constraintMismatches ),
321
+ }
322
+
323
+ for ip := range ininputs {
324
+ if ! inlock [ip ] {
325
+ lsat .pkgs [ip ] = missingFromLock
326
+ } else {
327
+ // So we don't have to revisit it below
328
+ delete (inlock , ip )
329
+ }
330
+ }
331
+
332
+ for ip := range inlock {
333
+ if ! ininputs [ip ] {
334
+ lsat .pkgs [ip ] = inAdditionToLock
335
+ }
336
+ }
337
+
338
+ ineff := make (map [string ]bool )
339
+ for _ , pr := range p .FindIneffectualConstraints (sm ) {
340
+ ineff [string (pr )] = true
341
+ }
342
+
343
+ for _ , lp := range p .Lock .Projects () {
344
+ pr := lp .Ident ().ProjectRoot
345
+
346
+ if pp , has := p .Manifest .Ovr [pr ]; has && ! pp .Constraint .Matches (lp .Version ()) {
347
+ lsat .badovr [pr ] = constraintMismatch {
348
+ c : pp .Constraint ,
349
+ v : lp .Version (),
350
+ }
351
+ }
352
+
353
+ if pp , has := p .Manifest .Constraints [pr ]; has && ! ineff [string (pr )] && ! pp .Constraint .Matches (lp .Version ()) {
354
+ lsat .badconstraint [pr ] = constraintMismatch {
355
+ c : pp .Constraint ,
356
+ v : lp .Version (),
357
+ }
358
+ }
359
+ }
360
+
361
+ return lsat , nil
362
+ }
363
+
222
364
// FindIneffectualConstraints looks for constraint rules expressed in the
223
365
// manifest that will have no effect during solving, as they are specified for
224
366
// projects that are not direct dependencies of the Project.
0 commit comments