@@ -18,8 +18,8 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
18
18
public class WorkloadResolver : IWorkloadResolver
19
19
{
20
20
private readonly Dictionary < string , WorkloadManifest > _manifests = new Dictionary < string , WorkloadManifest > ( StringComparer . OrdinalIgnoreCase ) ;
21
- private readonly Dictionary < WorkloadId , WorkloadDefinition > _workloads = new Dictionary < WorkloadId , WorkloadDefinition > ( ) ;
22
- private readonly Dictionary < WorkloadPackId , WorkloadPack > _packs = new Dictionary < WorkloadPackId , WorkloadPack > ( ) ;
21
+ private readonly Dictionary < WorkloadId , ( WorkloadDefinition workload , WorkloadManifest manifest ) > _workloads = new Dictionary < WorkloadId , ( WorkloadDefinition , WorkloadManifest ) > ( ) ;
22
+ private readonly Dictionary < WorkloadPackId , ( WorkloadPack pack , WorkloadManifest manifest ) > _packs = new Dictionary < WorkloadPackId , ( WorkloadPack , WorkloadManifest ) > ( ) ;
23
23
private IWorkloadManifestProvider ? _manifestProvider ;
24
24
private string [ ] _currentRuntimeIdentifiers ;
25
25
private readonly string [ ] _dotnetRootPaths ;
@@ -97,15 +97,14 @@ private void LoadManifestsFromProvider(IWorkloadManifestProvider manifestProvide
97
97
using ( var manifestStream = openManifestStream ( ) )
98
98
{
99
99
var manifest = WorkloadManifestReader . ReadWorkloadManifest ( manifestId , manifestStream ) ;
100
- if ( _manifests . ContainsKey ( manifestId ) )
100
+ if ( ! string . Equals ( manifestId , manifest . Id , StringComparison . OrdinalIgnoreCase ) )
101
101
{
102
- throw new Exception ( $ "Duplicate workload manifest { manifestId } ") ;
102
+ throw new WorkloadManifestCompositionException ( $ "Manifest ' { manifestId } ' from provider { manifestProvider } does not match payload id ' { manifest . Id } ' ") ;
103
103
}
104
- if ( ! string . Equals ( manifestId , manifest . Id , StringComparison . OrdinalIgnoreCase ) )
104
+ if ( ! _manifests . TryAdd ( manifestId , manifest ) )
105
105
{
106
- throw new Exception ( $ "Manifest provider { manifestProvider } supplied manifest '{ manifestId } ' does not match payload id ' { manifest . Id } ' ") ;
106
+ throw new WorkloadManifestCompositionException ( $ "Duplicate manifest '{ manifestId } ' from provider { manifestProvider } ") ;
107
107
}
108
- _manifests . Add ( manifestId , manifest ) ;
109
108
}
110
109
}
111
110
}
@@ -125,12 +124,12 @@ private void ComposeWorkloadManifests()
125
124
{
126
125
if ( FXVersion . Compare ( dependency . Value , resolvedDependency . ParsedVersion ) > 0 )
127
126
{
128
- throw new Exception ( $ "Inconsistency in workload manifest '{ manifest . Id } ': requires '{ dependency . Key } ' version at least { dependency . Value } but found { resolvedDependency . Version } ") ;
127
+ throw new WorkloadManifestCompositionException ( $ "Inconsistency in workload manifest '{ manifest . Id } ': requires '{ dependency . Key } ' version at least { dependency . Value } but found { resolvedDependency . Version } ") ;
129
128
}
130
129
}
131
130
else
132
131
{
133
- throw new Exception ( $ "Inconsistency in workload manifest '{ manifest . Id } ': missing dependency '{ dependency . Key } '") ;
132
+ throw new WorkloadManifestCompositionException ( $ "Inconsistency in workload manifest '{ manifest . Id } ': missing dependency '{ dependency . Key } '") ;
134
133
}
135
134
}
136
135
}
@@ -140,11 +139,14 @@ private void ComposeWorkloadManifests()
140
139
{
141
140
if ( workload . Value is WorkloadRedirect redirect )
142
141
{
143
- ( redirects ?? ( redirects = new HashSet < WorkloadRedirect > ( ) ) ) . Add ( redirect ) ;
142
+ ( redirects ??= new HashSet < WorkloadRedirect > ( ) ) . Add ( redirect ) ;
144
143
}
145
144
else
146
145
{
147
- _workloads . Add ( workload . Key , ( WorkloadDefinition ) workload . Value ) ;
146
+ if ( ! _workloads . TryAdd ( workload . Key , ( ( WorkloadDefinition ) workload . Value , manifest ) ) )
147
+ {
148
+ throw new WorkloadManifestCompositionException ( $ "Workload '{ workload . Key } ' in manifest '{ manifest . Id } ' conflicts with manifest '{ _workloads [ workload . Key ] . manifest . Id } '") ;
149
+ }
148
150
}
149
151
}
150
152
@@ -156,7 +158,10 @@ private void ComposeWorkloadManifests()
156
158
while ( redirects . RemoveWhere ( redirect => {
157
159
if ( _workloads . TryGetValue ( redirect . ReplaceWith , out var replacement ) )
158
160
{
159
- _workloads . Add ( redirect . Id , replacement ) ;
161
+ if ( ! _workloads . TryAdd ( redirect . Id , replacement ) )
162
+ {
163
+ throw new WorkloadManifestCompositionException ( $ "Workload '{ redirect . Id } ' in manifest '{ manifest . Id } ' conflicts with manifest '{ _workloads [ redirect . Id ] . manifest . Id } '") ;
164
+ }
160
165
return true ;
161
166
}
162
167
return false ;
@@ -170,7 +175,10 @@ private void ComposeWorkloadManifests()
170
175
171
176
foreach ( var pack in manifest . Packs )
172
177
{
173
- _packs . Add ( pack . Key , pack . Value ) ;
178
+ if ( ! _packs . TryAdd ( pack . Key , ( pack . Value , manifest ) ) )
179
+ {
180
+ throw new WorkloadManifestCompositionException ( $ "Workload pack '{ pack . Key } ' in manifest '{ manifest . Id } ' conflicts with manifest '{ _packs [ pack . Key ] . manifest . Id } '") ;
181
+ }
174
182
}
175
183
}
176
184
}
@@ -184,7 +192,7 @@ private void ComposeWorkloadManifests()
184
192
/// </remarks>
185
193
public IEnumerable < PackInfo > GetInstalledWorkloadPacksOfKind ( WorkloadPackKind kind )
186
194
{
187
- foreach ( var pack in _packs . Values )
195
+ foreach ( ( var pack , _ ) in _packs . Values )
188
196
{
189
197
if ( pack . Kind != kind )
190
198
{
@@ -302,12 +310,12 @@ private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId,
302
310
private HashSet < WorkloadPackId > GetInstalledPacks ( )
303
311
{
304
312
var installedPacks = new HashSet < WorkloadPackId > ( ) ;
305
- foreach ( var pack in _packs )
313
+ foreach ( ( WorkloadPackId id , ( WorkloadPack pack , WorkloadManifest _ ) ) in _packs )
306
314
{
307
- ResolvePackPath ( pack . Value , out bool isInstalled ) ;
315
+ ResolvePackPath ( pack , out bool isInstalled ) ;
308
316
if ( isInstalled )
309
317
{
310
- installedPacks . Add ( pack . Key ) ;
318
+ installedPacks . Add ( id ) ;
311
319
}
312
320
}
313
321
return installedPacks ;
@@ -322,10 +330,11 @@ public IEnumerable<string> GetPacksInWorkload(string workloadId)
322
330
323
331
var id = new WorkloadId ( workloadId ) ;
324
332
325
- if ( ! _workloads . TryGetValue ( id , out var workload ) )
333
+ if ( ! _workloads . TryGetValue ( id , out var value ) )
326
334
{
327
335
throw new Exception ( $ "Workload not found: { id } . Known workloads: { string . Join ( " " , _workloads . Select ( workload => workload . Key . ToString ( ) ) ) } ") ;
328
336
}
337
+ var workload = value . workload ;
329
338
330
339
if ( workload . Extends ? . Count > 0 )
331
340
{
@@ -343,7 +352,7 @@ internal IEnumerable<WorkloadPackId> GetPacksInWorkload(WorkloadDefinition workl
343
352
344
353
IEnumerable < WorkloadPackId > ExpandPacks ( WorkloadId workloadId )
345
354
{
346
- if ( ! _workloads . TryGetValue ( workloadId , out var workloadInfo ) )
355
+ if ( ! ( _workloads . TryGetValue ( workloadId ) is ( WorkloadDefinition workloadInfo , _ ) ) )
347
356
{
348
357
// inconsistent manifest
349
358
throw new Exception ( "Workload not found" ) ;
@@ -388,11 +397,11 @@ IEnumerable<WorkloadPackId> ExpandPacks (WorkloadId workloadId)
388
397
throw new ArgumentException ( $ "'{ nameof ( packId ) } ' cannot be null or whitespace", nameof ( packId ) ) ;
389
398
}
390
399
391
- if ( _packs . TryGetValue ( new WorkloadPackId ( packId ) , out var pack ) )
400
+ if ( _packs . TryGetValue ( new WorkloadPackId ( packId ) ) is ( WorkloadPack pack , _ ) )
392
401
{
393
402
if ( ResolveId ( pack ) is WorkloadPackId resolvedPackageId )
394
403
{
395
- var aliasedPath = GetPackPath ( _dotnetRootPaths , resolvedPackageId , pack . Version , pack . Kind , out bool exists ) ;
404
+ var aliasedPath = GetPackPath ( _dotnetRootPaths , resolvedPackageId , pack . Version , pack . Kind , out _ ) ;
396
405
return CreatePackInfo ( pack , aliasedPath , resolvedPackageId ) ;
397
406
}
398
407
}
@@ -409,12 +418,12 @@ IEnumerable<WorkloadPackId> ExpandPacks (WorkloadId workloadId)
409
418
public ISet < WorkloadInfo > GetWorkloadSuggestionForMissingPacks ( IList < string > packIds )
410
419
{
411
420
var requestedPacks = new HashSet < WorkloadPackId > ( packIds . Select ( p => new WorkloadPackId ( p ) ) ) ;
412
- var expandedWorkloads = _workloads . Select ( w => ( w . Key , new HashSet < WorkloadPackId > ( GetPacksInWorkload ( w . Value ) ) ) ) ;
421
+ var expandedWorkloads = _workloads . Select ( w => ( w . Key , new HashSet < WorkloadPackId > ( GetPacksInWorkload ( w . Value . workload ) ) ) ) ;
413
422
var finder = new WorkloadSuggestionFinder ( GetInstalledPacks ( ) , requestedPacks , expandedWorkloads ) ;
414
423
415
424
return new HashSet < WorkloadInfo >
416
425
(
417
- finder . GetBestSuggestion ( ) . Workloads . Select ( s => new WorkloadInfo ( s . ToString ( ) , _workloads [ s ] . Description ) )
426
+ finder . GetBestSuggestion ( ) . Workloads . Select ( s => new WorkloadInfo ( s . ToString ( ) , _workloads [ s ] . workload . Description ) )
418
427
) ;
419
428
}
420
429
@@ -423,7 +432,10 @@ public ISet<WorkloadInfo> GetWorkloadSuggestionForMissingPacks(IList<string> pac
423
432
/// </summary>
424
433
public IEnumerable < WorkloadDefinition > GetAvailableWorkloads ( )
425
434
{
426
- return _workloads . Values ;
435
+ foreach ( ( WorkloadId _ , ( WorkloadDefinition workload , WorkloadManifest _ ) ) in _workloads )
436
+ {
437
+ yield return workload ;
438
+ }
427
439
}
428
440
429
441
/// <summary>
@@ -436,12 +448,12 @@ public IEnumerable<WorkloadId> GetUpdatedWorkloads(WorkloadResolver advertisingM
436
448
{
437
449
foreach ( var workloadId in installedWorkloads )
438
450
{
439
- var existingWorkload = _workloads [ workloadId ] ;
451
+ var existingWorkload = _workloads [ workloadId ] . workload ;
440
452
var existingPacks = GetPacksInWorkload ( existingWorkload ) . ToHashSet ( ) ;
441
- var updatedWorkload = advertisingManifestResolver . _workloads [ workloadId ] ;
453
+ var updatedWorkload = advertisingManifestResolver . _workloads [ workloadId ] . workload ;
442
454
var updatedPacks = advertisingManifestResolver . GetPacksInWorkload ( updatedWorkload ) ;
443
455
444
- if ( ! existingPacks . SetEquals ( updatedPacks ) || existingPacks . Any ( p=> PackHasChanged ( _packs [ p ] , advertisingManifestResolver . _packs [ p ] ) ) )
456
+ if ( ! existingPacks . SetEquals ( updatedPacks ) || existingPacks . Any ( p=> PackHasChanged ( _packs [ p ] . pack , advertisingManifestResolver . _packs [ p ] . pack ) ) )
445
457
{
446
458
yield return workloadId ;
447
459
}
@@ -539,12 +551,11 @@ public WorkloadInfo(string id, string? description)
539
551
540
552
public WorkloadInfo GetWorkloadInfo ( WorkloadId WorkloadId )
541
553
{
542
- if ( ! _workloads . TryGetValue ( WorkloadId , out var workload ) )
554
+ if ( _workloads . TryGetValue ( WorkloadId ) is ( WorkloadDefinition workload , _ ) )
543
555
{
544
- throw new Exception ( "Workload not found" ) ;
556
+ return new WorkloadInfo ( workload . Id . ToString ( ) , workload . Description ) ;
545
557
}
546
-
547
- return new WorkloadInfo ( workload . Id . ToString ( ) , workload . Description ) ;
558
+ throw new Exception ( "Workload not found" ) ;
548
559
}
549
560
550
561
public bool IsWorkloadPlatformCompatible ( WorkloadId workloadId )
@@ -562,10 +573,9 @@ public bool IsWorkloadPlatformCompatible(WorkloadId workloadId)
562
573
}
563
574
}
564
575
565
- #if ! NETCOREAPP
566
-
567
576
static class DictionaryExtensions
568
577
{
578
+ #if ! NETCOREAPP
569
579
public static bool TryAdd < TKey , TValue > ( this Dictionary < TKey , TValue > dictionary , TKey key , TValue value ) where TKey : notnull
570
580
{
571
581
if ( dictionary . ContainsKey ( key ) )
@@ -575,6 +585,23 @@ public static bool TryAdd<TKey,TValue>(this Dictionary<TKey, TValue> dictionary,
575
585
dictionary . Add ( key , value ) ;
576
586
return true ;
577
587
}
578
- }
588
+
589
+ public static void Deconstruct < TKey , TValue > ( this KeyValuePair < TKey , TValue > kvp , out TKey key , out TValue value )
590
+ {
591
+ key = kvp . Key ;
592
+ value = kvp . Value ;
593
+ }
579
594
#endif
595
+
596
+ public static TValue ? TryGetValue < TKey , TValue > ( this Dictionary < TKey , TValue > dictionary , TKey key )
597
+ where TKey : notnull
598
+ where TValue : struct
599
+ {
600
+ if ( dictionary . TryGetValue ( key , out TValue value ) )
601
+ {
602
+ return value ;
603
+ }
604
+ return default ( TValue ? ) ;
605
+ }
606
+ }
580
607
}
0 commit comments