Skip to content

Commit

Permalink
Speed up ResolvePackageFileConflicts by avoiding reading files for As…
Browse files Browse the repository at this point in the history
…semblyVersion.

Allow for packages to override other packages by default.
  • Loading branch information
eerhardt committed Dec 8, 2017
1 parent cb20a5f commit dd07581
Show file tree
Hide file tree
Showing 12 changed files with 684 additions and 16 deletions.
33 changes: 31 additions & 2 deletions src/Tasks/Common/ConflictResolution/ConflictItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ internal interface IConflictItem
Version FileVersion { get; }
string PackageId { get; }
string DisplayName { get; }

// NOTE: Technically this should be NuGetVersion because System.Version doesn't work with symver.
// However, the only scenarios we need to support this property for in conflict resolution is stable versions
// of System packages. PackageVersion will be null if System.Version can't parse the version (i.e. if is pre-release)
Version PackageVersion { get; }
}

// Wraps an ITask item and adds lazy evaluated properties used by Conflict resolution.
Expand Down Expand Up @@ -103,7 +108,7 @@ public string FileName
{
if (_fileName == null)
{
_fileName = OriginalItem == null ? String.Empty : OriginalItem.GetMetadata(MetadataNames.FileName) + OriginalItem.GetMetadata(MetadataNames.Extension);
_fileName = OriginalItem == null ? String.Empty : Path.GetFileName(OriginalItem.ItemSpec);
}
return _fileName;
}
Expand Down Expand Up @@ -165,7 +170,31 @@ public string PackageId
}
private set { _packageId = value; }
}


private bool _hasPackageVersion;
private Version _packageVersion;
public Version PackageVersion
{
get
{
if (!_hasPackageVersion)
{
_packageVersion = null;

var packageVersionString = OriginalItem?.GetMetadata(nameof(MetadataNames.NuGetPackageVersion)) ?? String.Empty;

if (packageVersionString.Length != 0)
{
Version.TryParse(packageVersionString, out _packageVersion);
}

// PackageVersion may be null but don't try to recalculate it
_hasPackageVersion = true;
}

return _packageVersion;
}
}

private string _sourcePath;
public string SourcePath
Expand Down
10 changes: 9 additions & 1 deletion src/Tasks/Common/ConflictResolution/ConflictResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ internal class ConflictResolver<TConflictItem> where TConflictItem : class, ICon
private Dictionary<string, TConflictItem> winningItemsByKey = new Dictionary<string, TConflictItem>();
private ILog log;
private PackageRank packageRank;
private PackageOverrideResolver<TConflictItem> packageOverrideResolver;

public ConflictResolver(PackageRank packageRank, ILog log)
public ConflictResolver(PackageRank packageRank, PackageOverrideResolver<TConflictItem> packageOverrideResolver, ILog log)
{
this.log = log;
this.packageRank = packageRank;
this.packageOverrideResolver = packageOverrideResolver;
}

public void ResolveConflicts(IEnumerable<TConflictItem> conflictItems, Func<TConflictItem, string> getItemKey,
Expand Down Expand Up @@ -87,6 +89,12 @@ public void ResolveConflicts(IEnumerable<TConflictItem> conflictItems, Func<TCon

private TConflictItem ResolveConflict(TConflictItem item1, TConflictItem item2)
{
var winner = packageOverrideResolver.Resolve(item1, item2);
if (winner != null)
{
return winner;
}

string conflictMessage = string.Format(CultureInfo.CurrentCulture, Strings.EncounteredConflict,
item1.DisplayName,
item2.DisplayName);
Expand Down
1 change: 1 addition & 0 deletions src/Tasks/Common/ConflictResolution/MetadataNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ static class MetadataNames
public const string FileName = "FileName";
public const string HintPath = "HintPath";
public const string NuGetPackageId = "NuGetPackageId";
public const string NuGetPackageVersion = "NuGetPackageVersion";
public const string Path = "Path";
public const string Private = "Private";
public const string TargetPath = "TargetPath";
Expand Down
18 changes: 15 additions & 3 deletions src/Tasks/Common/ConflictResolution/ResolvePackageFileConflicts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ public class ResolvePackageFileConflicts : TaskBase
/// </summary>
public string[] PreferredPackages { get; set; }

/// <summary>
/// A collection of items that contain information of which packages get overriden
/// by which packages before doing any other conflict resolution.
/// </summary>
/// <remarks>
/// This is an optimizaiton so AssemblyVersions, FileVersions, etc. don't need to be read
/// in the default cases where platform packages (Microsoft.NETCore.App) should override specific packages
/// (System.Console v4.3.0).
/// </remarks>
public ITaskItem[] PackageOverrides { get; set; }

[Output]
public ITaskItem[] ReferencesWithoutConflicts { get; set; }

Expand All @@ -44,6 +55,7 @@ protected override void ExecuteCore()
{
var log = new MSBuildLog(Log);
var packageRanks = new PackageRank(PreferredPackages);
var packageOverrides = new PackageOverrideResolver<ConflictItem>(PackageOverrides);

// Treat assemblies from FrameworkList.xml as platform assemblies that also get considered at compile time
IEnumerable<ConflictItem> compilePlatformItems = null;
Expand All @@ -60,7 +72,7 @@ protected override void ExecuteCore()
// resolve conflicts at compile time
var referenceItems = GetConflictTaskItems(References, ConflictItemType.Reference).ToArray();

var compileConflictScope = new ConflictResolver<ConflictItem>(packageRanks, log);
var compileConflictScope = new ConflictResolver<ConflictItem>(packageRanks, packageOverrides, log);

compileConflictScope.ResolveConflicts(referenceItems,
ci => ItemUtilities.GetReferenceFileName(ci.OriginalItem),
Expand All @@ -74,7 +86,7 @@ protected override void ExecuteCore()
}

// resolve conflicts that class in output
var runtimeConflictScope = new ConflictResolver<ConflictItem>(packageRanks, log);
var runtimeConflictScope = new ConflictResolver<ConflictItem>(packageRanks, packageOverrides, log);

runtimeConflictScope.ResolveConflicts(referenceItems,
ci => ItemUtilities.GetReferenceTargetPath(ci.OriginalItem),
Expand All @@ -95,7 +107,7 @@ protected override void ExecuteCore()

// resolve conflicts with platform (eg: shared framework) items
// we only commit the platform items since its not a conflict if other items share the same filename.
var platformConflictScope = new ConflictResolver<ConflictItem>(packageRanks, log);
var platformConflictScope = new ConflictResolver<ConflictItem>(packageRanks, packageOverrides, log);
var platformItems = PlatformManifests?.SelectMany(pm => PlatformManifestReader.LoadConflictItems(pm.ItemSpec, log)) ?? Enumerable.Empty<ConflictItem>();

if (compilePlatformItems != null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
<!--
***********************************************************************************************
Microsoft.NET.DefaultPackageConflictOverrides.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>

<ItemGroup Condition="'$(DisableDefaultPackageConflictOverrides)' != 'true'">
<PackageConflictOverrides Include="Microsoft.NETCore.App">
<OverridenPackages>
Microsoft.CSharp|4.4.0;
Microsoft.Win32.Primitives|4.3.0;
Microsoft.Win32.Registry|4.4.0;
runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple|4.3.0;
runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
System.AppContext|4.3.0;
System.Collections|4.3.0;
System.Collections.Concurrent|4.3.0;
System.Collections.Immutable|1.4.0;
System.Collections.NonGeneric|4.3.0;
System.Collections.Specialized|4.3.0;
System.ComponentModel|4.3.0;
System.ComponentModel.EventBasedAsync|4.3.0;
System.ComponentModel.Primitives|4.3.0;
System.ComponentModel.TypeConverter|4.3.0;
System.Console|4.3.0;
System.Data.Common|4.3.0;
System.Diagnostics.Contracts|4.3.0;
System.Diagnostics.Debug|4.3.0;
System.Diagnostics.FileVersionInfo|4.3.0;
System.Diagnostics.Process|4.3.0;
System.Diagnostics.StackTrace|4.3.0;
System.Diagnostics.TextWriterTraceListener|4.3.0;
System.Diagnostics.Tools|4.3.0;
System.Diagnostics.TraceSource|4.3.0;
System.Diagnostics.Tracing|4.3.0;
System.Dynamic.Runtime|4.3.0;
System.Globalization|4.3.0;
System.Globalization.Extensions|4.3.0;
System.IO|4.3.0;
System.IO.Compression|4.3.0;
System.IO.Compression.ZipFile|4.3.0;
System.IO.FileSystem|4.3.0;
System.IO.FileSystem.AccessControl|4.4.0;
System.IO.FileSystem.DriveInfo|4.3.0;
System.IO.FileSystem.Primitives|4.3.0;
System.IO.FileSystem.Watcher|4.3.0;
System.IO.IsolatedStorage|4.3.0;
System.IO.MemoryMappedFiles|4.3.0;
System.IO.Pipes|4.3.0;
System.IO.UnmanagedMemoryStream|4.3.0;
System.Linq|4.3.0;
System.Linq.Expressions|4.3.0;
System.Linq.Queryable|4.3.0;
System.Net.Http|4.3.0;
System.Net.NameResolution|4.3.0;
System.Net.Primitives|4.3.0;
System.Net.Requests|4.3.0;
System.Net.Security|4.3.0;
System.Net.Sockets|4.3.0;
System.Net.WebHeaderCollection|4.3.0;
System.ObjectModel|4.3.0;
System.Private.DataContractSerialization|4.3.0;
System.Reflection|4.3.0;
System.Reflection.Emit|4.3.0;
System.Reflection.Emit.ILGeneration|4.3.0;
System.Reflection.Emit.Lightweight|4.3.0;
System.Reflection.Extensions|4.3.0;
System.Reflection.Metadata|1.5.0;
System.Reflection.Primitives|4.3.0;
System.Reflection.TypeExtensions|4.3.0;
System.Resources.ResourceManager|4.3.0;
System.Runtime|4.3.0;
System.Runtime.Extensions|4.3.0;
System.Runtime.Handles|4.3.0;
System.Runtime.InteropServices|4.3.0;
System.Runtime.InteropServices.RuntimeInformation|4.3.0;
System.Runtime.Loader|4.3.0;
System.Runtime.Numerics|4.3.0;
System.Runtime.Serialization.Formatters|4.3.0;
System.Runtime.Serialization.Json|4.3.0;
System.Runtime.Serialization.Primitives|4.3.0;
System.Security.AccessControl|4.4.0;
System.Security.Claims|4.3.0;
System.Security.Cryptography.Algorithms|4.3.0;
System.Security.Cryptography.Cng|4.4.0;
System.Security.Cryptography.Csp|4.3.0;
System.Security.Cryptography.Encoding|4.3.0;
System.Security.Cryptography.OpenSsl|4.4.0;
System.Security.Cryptography.Primitives|4.3.0;
System.Security.Cryptography.X509Certificates|4.3.0;
System.Security.Cryptography.Xml|4.4.0;
System.Security.Principal|4.3.0;
System.Security.Principal.Windows|4.4.0;
System.Text.Encoding|4.3.0;
System.Text.Encoding.Extensions|4.3.0;
System.Text.RegularExpressions|4.3.0;
System.Threading|4.3.0;
System.Threading.Overlapped|4.3.0;
System.Threading.Tasks|4.3.0;
System.Threading.Tasks.Extensions|4.3.0;
System.Threading.Tasks.Parallel|4.3.0;
System.Threading.Thread|4.3.0;
System.Threading.ThreadPool|4.3.0;
System.Threading.Timer|4.3.0;
System.ValueTuple|4.3.0;
System.Xml.ReaderWriter|4.3.0;
System.Xml.XDocument|4.3.0;
System.Xml.XmlDocument|4.3.0;
System.Xml.XmlSerializer|4.3.0;
System.Xml.XPath|4.3.0;
System.Xml.XPath.XDocument|4.3.0;
</OverridenPackages>
</PackageConflictOverrides>
<PackageConflictOverrides Include="NETStandard.Library">
<OverridenPackages>
Microsoft.Win32.Primitives|4.3.0;
System.AppContext|4.3.0;
System.Collections|4.3.0;
System.Collections.Concurrent|4.3.0;
System.Collections.Immutable|1.4.0;
System.Collections.NonGeneric|4.3.0;
System.Collections.Specialized|4.3.0;
System.ComponentModel|4.3.0;
System.ComponentModel.EventBasedAsync|4.3.0;
System.ComponentModel.Primitives|4.3.0;
System.ComponentModel.TypeConverter|4.3.0;
System.Console|4.3.0;
System.Data.Common|4.3.0;
System.Diagnostics.Contracts|4.3.0;
System.Diagnostics.Debug|4.3.0;
System.Diagnostics.FileVersionInfo|4.3.0;
System.Diagnostics.Process|4.3.0;
System.Diagnostics.StackTrace|4.3.0;
System.Diagnostics.TextWriterTraceListener|4.3.0;
System.Diagnostics.Tools|4.3.0;
System.Diagnostics.TraceSource|4.3.0;
System.Diagnostics.Tracing|4.3.0;
System.Dynamic.Runtime|4.3.0;
System.Globalization|4.3.0;
System.Globalization.Extensions|4.3.0;
System.IO|4.3.0;
System.IO.Compression|4.3.0;
System.IO.Compression.ZipFile|4.3.0;
System.IO.FileSystem|4.3.0;
System.IO.FileSystem.DriveInfo|4.3.0;
System.IO.FileSystem.Primitives|4.3.0;
System.IO.FileSystem.Watcher|4.3.0;
System.IO.IsolatedStorage|4.3.0;
System.IO.MemoryMappedFiles|4.3.0;
System.IO.Pipes|4.3.0;
System.IO.UnmanagedMemoryStream|4.3.0;
System.Linq|4.3.0;
System.Linq.Expressions|4.3.0;
System.Linq.Queryable|4.3.0;
System.Net.Http|4.3.0;
System.Net.NameResolution|4.3.0;
System.Net.Primitives|4.3.0;
System.Net.Requests|4.3.0;
System.Net.Security|4.3.0;
System.Net.Sockets|4.3.0;
System.Net.WebHeaderCollection|4.3.0;
System.ObjectModel|4.3.0;
System.Private.DataContractSerialization|4.3.0;
System.Reflection|4.3.0;
System.Reflection.Emit|4.3.0;
System.Reflection.Emit.ILGeneration|4.3.0;
System.Reflection.Emit.Lightweight|4.3.0;
System.Reflection.Extensions|4.3.0;
System.Reflection.Primitives|4.3.0;
System.Reflection.TypeExtensions|4.3.0;
System.Resources.ResourceManager|4.3.0;
System.Runtime|4.3.0;
System.Runtime.Extensions|4.3.0;
System.Runtime.Handles|4.3.0;
System.Runtime.InteropServices|4.3.0;
System.Runtime.InteropServices.RuntimeInformation|4.3.0;
System.Runtime.Loader|4.3.0;
System.Runtime.Numerics|4.3.0;
System.Runtime.Serialization.Formatters|4.3.0;
System.Runtime.Serialization.Json|4.3.0;
System.Runtime.Serialization.Primitives|4.3.0;
System.Security.AccessControl|4.4.0;
System.Security.Claims|4.3.0;
System.Security.Cryptography.Algorithms|4.3.0;
System.Security.Cryptography.Csp|4.3.0;
System.Security.Cryptography.Encoding|4.3.0;
System.Security.Cryptography.Primitives|4.3.0;
System.Security.Cryptography.X509Certificates|4.3.0;
System.Security.Cryptography.Xml|4.4.0;
System.Security.Principal|4.3.0;
System.Security.Principal.Windows|4.4.0;
System.Text.Encoding|4.3.0;
System.Text.Encoding.Extensions|4.3.0;
System.Text.RegularExpressions|4.3.0;
System.Threading|4.3.0;
System.Threading.Overlapped|4.3.0;
System.Threading.Tasks|4.3.0;
System.Threading.Tasks.Extensions|4.3.0;
System.Threading.Tasks.Parallel|4.3.0;
System.Threading.Thread|4.3.0;
System.Threading.ThreadPool|4.3.0;
System.Threading.Timer|4.3.0;
System.ValueTuple|4.3.0;
System.Xml.ReaderWriter|4.3.0;
System.Xml.XDocument|4.3.0;
System.Xml.XmlDocument|4.3.0;
System.Xml.XmlSerializer|4.3.0;
System.Xml.XPath|4.3.0;
System.Xml.XPath.XDocument|4.3.0;
</OverridenPackages>
</PackageConflictOverrides>
</ItemGroup>
</Project>
Loading

0 comments on commit dd07581

Please sign in to comment.