Skip to content

Commit 5839388

Browse files
authored
Fix manifest artifacts reading (#45407)
1 parent 4504daa commit 5839388

File tree

1 file changed

+93
-72
lines changed

1 file changed

+93
-72
lines changed

src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.UnifiedBuild.Tasks/GetKnownArtifactsFromAssetManifests.cs

+93-72
Original file line numberDiff line numberDiff line change
@@ -4,89 +4,110 @@
44

55
#nullable enable
66

7+
using System;
78
using System.Collections.Generic;
89
using System.Linq;
10+
using System.Diagnostics.CodeAnalysis;
911
using System.Xml.Linq;
1012
using Microsoft.Build.Framework;
1113
using Microsoft.Build.Utilities;
1214

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
1421
{
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+
1552
/// <summary>
16-
/// Get a list of MSBuild Items that represent the packages described in the asset manifests.
53+
/// The list of known blobs.
1754
/// </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>
1995
{
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)
5799
{
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;
88109
}
89110

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));
91112
}
92-
}
113+
}

0 commit comments

Comments
 (0)