4
4
5
5
#nullable enable
6
6
7
+ using System ;
7
8
using System . Collections . Generic ;
8
9
using System . Linq ;
10
+ using System . Diagnostics . CodeAnalysis ;
9
11
using System . Xml . Linq ;
10
12
using Microsoft . Build . Framework ;
11
13
using Microsoft . Build . Utilities ;
12
14
13
- namespace Microsoft . DotNet . UnifiedBuild . Tasks
15
+ namespace Microsoft . DotNet . UnifiedBuild . Tasks ;
16
+
17
+ /// <summary>
18
+ /// Get a list of MSBuild Items that represent the packages described in the asset manifests.
19
+ /// </summary>
20
+ public sealed class GetKnownArtifactsFromAssetManifests : Build . Utilities . Task
14
21
{
22
+ // Common metadata
23
+ private const string IdAttributeName = "Id" ;
24
+ private const string RepoOriginAttributeName = "RepoOrigin" ;
25
+ private const string NonShippingAttributeName = "NonShipping" ;
26
+ private const string DotNetReleaseShippingAttributeName = "DotNetReleaseShipping" ;
27
+
28
+ // Package metadata
29
+ private const string PackageElementName = "Package" ;
30
+ private const string PackageVersionAttributeName = "Version" ;
31
+
32
+ // Blob metadata
33
+ private const string BlobElementName = "Blob" ;
34
+
35
+ /// <summary>
36
+ /// A list of asset manifests to read.
37
+ /// </summary>
38
+ [ Required ]
39
+ public required ITaskItem [ ] AssetManifests { get ; set ; }
40
+
41
+ /// <summary>
42
+ /// If provided, only artifacts from that repository will be returned.
43
+ /// </summary>
44
+ public string ? RepoOrigin { get ; set ; }
45
+
46
+ /// <summary>
47
+ /// The list of known packages including their versions as metadata.
48
+ /// </summary>
49
+ [ Output ]
50
+ public ITaskItem [ ] ? KnownPackages { get ; set ; }
51
+
15
52
/// <summary>
16
- /// Get a list of MSBuild Items that represent the packages described in the asset manifests .
53
+ /// The list of known blobs .
17
54
/// </summary>
18
- public sealed class GetKnownArtifactsFromAssetManifests : Build . Utilities . Task
55
+ [ Output ]
56
+ public ITaskItem [ ] ? KnownBlobs { get ; set ; }
57
+
58
+ public override bool Execute ( )
59
+ {
60
+ XDocument [ ] xDocuments = AssetManifests
61
+ . Select ( manifest => XDocument . Load ( manifest . ItemSpec ) )
62
+ . ToArray ( ) ;
63
+
64
+ KnownPackages = xDocuments
65
+ . SelectMany ( doc => doc . Root ! . Descendants ( PackageElementName ) )
66
+ . Where ( ShouldIncludeElement )
67
+ . Select ( package => new TaskItem ( package . Attribute ( IdAttributeName ) ! . Value , new Dictionary < string , string >
68
+ {
69
+ { PackageVersionAttributeName , package . Attribute ( PackageVersionAttributeName ) ! . Value } ,
70
+ { RepoOriginAttributeName , package . Attribute ( RepoOriginAttributeName ) ? . Value ?? string . Empty } ,
71
+ { NonShippingAttributeName , package . Attribute ( NonShippingAttributeName ) ? . Value ?? string . Empty } ,
72
+ { DotNetReleaseShippingAttributeName , package . Attribute ( DotNetReleaseShippingAttributeName ) ? . Value ?? string . Empty }
73
+ } ) )
74
+ . Distinct ( TaskItemManifestEqualityComparer . Instance )
75
+ . ToArray ( ) ;
76
+
77
+ KnownBlobs = xDocuments
78
+ . SelectMany ( doc => doc . Root ! . Descendants ( BlobElementName ) )
79
+ . Where ( ShouldIncludeElement )
80
+ . Select ( blob => new TaskItem ( blob . Attribute ( IdAttributeName ) ! . Value , new Dictionary < string , string >
81
+ {
82
+ { RepoOriginAttributeName , blob . Attribute ( RepoOriginAttributeName ) ? . Value ?? string . Empty } ,
83
+ { NonShippingAttributeName , blob . Attribute ( NonShippingAttributeName ) ? . Value ?? string . Empty } ,
84
+ { DotNetReleaseShippingAttributeName , blob . Attribute ( DotNetReleaseShippingAttributeName ) ? . Value ?? string . Empty }
85
+ } ) )
86
+ . Distinct ( TaskItemManifestEqualityComparer . Instance )
87
+ . ToArray ( ) ;
88
+
89
+ return true ;
90
+ }
91
+
92
+ private bool ShouldIncludeElement ( XElement element ) => string . IsNullOrEmpty ( RepoOrigin ) || element . Attribute ( RepoOriginAttributeName ) ? . Value == RepoOrigin ;
93
+
94
+ sealed class TaskItemManifestEqualityComparer : IEqualityComparer < TaskItem >
19
95
{
20
- // Common metadata
21
- private const string IdAttributeName = "Id" ;
22
- private const string RepoOriginAttributeName = "RepoOrigin" ;
23
- private const string NonShippingAttributeName = "NonShipping" ;
24
- private const string DotNetReleaseShippingAttributeName = "DotNetReleaseShipping" ;
25
-
26
- // Package metadata
27
- private const string PackageElementName = "Package" ;
28
- private const string PackageVersionAttributeName = "Version" ;
29
-
30
- // Blob metadata
31
- private const string BlobElementName = "Blob" ;
32
-
33
- /// <summary>
34
- /// A list of asset manifests to read.
35
- /// </summary>
36
- [ Required ]
37
- public required ITaskItem [ ] AssetManifests { get ; set ; }
38
-
39
- /// <summary>
40
- /// If provided, only artifacts from that repository will be returned.
41
- /// </summary>
42
- public string ? RepoOrigin { get ; set ; }
43
-
44
- /// <summary>
45
- /// The list of known packages including their versions as metadata.
46
- /// </summary>
47
- [ Output ]
48
- public ITaskItem [ ] ? KnownPackages { get ; set ; }
49
-
50
- /// <summary>
51
- /// The list of known blobs.
52
- /// </summary>
53
- [ Output ]
54
- public ITaskItem [ ] ? KnownBlobs { get ; set ; }
55
-
56
- public override bool Execute ( )
96
+ public static TaskItemManifestEqualityComparer Instance { get ; } = new TaskItemManifestEqualityComparer ( ) ;
97
+
98
+ public bool Equals ( TaskItem ? x , TaskItem ? y )
57
99
{
58
- XDocument [ ] xDocuments = AssetManifests
59
- . Select ( manifest => XDocument . Load ( manifest . ItemSpec ) )
60
- . ToArray ( ) ;
61
-
62
- KnownPackages = xDocuments
63
- . SelectMany ( doc => doc . Root ! . Descendants ( PackageElementName ) )
64
- . Where ( ShouldIncludeElement )
65
- . Distinct ( )
66
- . Select ( package => new TaskItem ( package . Attribute ( IdAttributeName ) ! . Value , new Dictionary < string , string >
67
- {
68
- { PackageVersionAttributeName , package . Attribute ( PackageVersionAttributeName ) ! . Value } ,
69
- { RepoOriginAttributeName , package . Attribute ( RepoOriginAttributeName ) ? . Value ?? string . Empty } ,
70
- { NonShippingAttributeName , package . Attribute ( NonShippingAttributeName ) ? . Value ?? string . Empty } ,
71
- { DotNetReleaseShippingAttributeName , package . Attribute ( DotNetReleaseShippingAttributeName ) ? . Value ?? string . Empty }
72
- } ) )
73
- . ToArray ( ) ;
74
-
75
- KnownBlobs = xDocuments
76
- . SelectMany ( doc => doc . Root ! . Descendants ( BlobElementName ) )
77
- . Where ( ShouldIncludeElement )
78
- . Distinct ( )
79
- . Select ( blob => new TaskItem ( blob . Attribute ( IdAttributeName ) ! . Value , new Dictionary < string , string >
80
- {
81
- { RepoOriginAttributeName , blob . Attribute ( RepoOriginAttributeName ) ? . Value ?? string . Empty } ,
82
- { NonShippingAttributeName , blob . Attribute ( NonShippingAttributeName ) ? . Value ?? string . Empty } ,
83
- { DotNetReleaseShippingAttributeName , blob . Attribute ( DotNetReleaseShippingAttributeName ) ? . Value ?? string . Empty }
84
- } ) )
85
- . ToArray ( ) ;
86
-
87
- return true ;
100
+ if ( ReferenceEquals ( x , y ) ) return true ;
101
+
102
+ if ( x is null || y is null ) return false ;
103
+
104
+ // For blobs, there's no version metadata so these will be empty.
105
+ string xVersion = x . GetMetadata ( PackageVersionAttributeName ) ;
106
+ string yVersion = x . GetMetadata ( PackageVersionAttributeName ) ;
107
+
108
+ return x . ItemSpec == y . ItemSpec && xVersion == yVersion ;
88
109
}
89
110
90
- private bool ShouldIncludeElement ( XElement element ) => RepoOrigin == null || element . Attribute ( RepoOriginAttributeName ) ? . Value == RepoOrigin ;
111
+ public int GetHashCode ( [ DisallowNull ] TaskItem obj ) => HashCode . Combine ( obj . ItemSpec , obj . GetMetadata ( PackageVersionAttributeName ) ) ;
91
112
}
92
- }
113
+ }
0 commit comments