| File: parent\Common\ConflictResolution\ConflictItem.cs | Web Access |
| Project: Microsoft.NET.Build.Extensions.Tasks.csproj (Microsoft.NET.Build.Extensions.Tasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Build.Framework; #if EXTENSIONS using ConflictVersion = System.Version; #else using ConflictVersion = NuGet.Versioning.NuGetVersion; using NuGet.Versioning; #endif namespace Microsoft.NET.Build.Tasks.ConflictResolution { internal enum ConflictItemType { Reference, CopyLocal, Runtime, Platform, Analyzer } internal interface IConflictItem { Version? AssemblyVersion { get; } ConflictItemType ItemType { get; } bool Exists { get; } string? FileName { get; } Version? FileVersion { get; } string? PackageId { get; } string? DisplayName { get; } ConflictVersion? PackageVersion { get; } } // Wraps an ITask item and adds lazy evaluated properties used by Conflict resolution. internal class ConflictItem : IConflictItem { // Null when constructed from a caller that has not been migrated to a multi-threadable task // (e.g. ResolvePackageFileConflicts), or via the Platform-item constructor which does no file // access. When non-null, SourcePath is absolutized through it before any file I/O. private readonly TaskEnvironment? _taskEnvironment; public ConflictItem(ITaskItem originalItem, ConflictItemType itemType, TaskEnvironment? taskEnvironment) { OriginalItem = originalItem; ItemType = itemType; _taskEnvironment = taskEnvironment; } public ConflictItem(ITaskItem originalItem, ConflictItemType itemType) : this(originalItem, itemType, taskEnvironment: null) { } public ConflictItem(string fileName, string packageId, Version? assemblyVersion, Version? fileVersion) { OriginalItem = null; ItemType = ConflictItemType.Platform; FileName = fileName; SourcePath = fileName; PackageId = packageId; AssemblyVersion = assemblyVersion; FileVersion = fileVersion; } private bool _hasAssemblyVersion; private Version? _assemblyVersion; public Version? AssemblyVersion { get { if (!_hasAssemblyVersion) { _assemblyVersion = null; var assemblyVersionString = OriginalItem?.GetMetadata(nameof(AssemblyVersion)) ?? string.Empty; if (assemblyVersionString.Length != 0) { Version.TryParse(assemblyVersionString, out _assemblyVersion); } else { _assemblyVersion = FileUtilities.TryGetAssemblyVersion(SourcePathForFileAccess ?? string.Empty); } // assemblyVersion may be null but don't try to recalculate it _hasAssemblyVersion = true; } return _assemblyVersion; } private set { _assemblyVersion = value; _hasAssemblyVersion = true; } } public ConflictItemType ItemType { get; } private bool? _exists; public bool Exists { get { if (_exists == null) { _exists = ItemType == ConflictItemType.Platform || File.Exists(SourcePathForFileAccess); } return _exists.Value; } } private string? _fileName; public string? FileName { get { if (_fileName == null) { _fileName = OriginalItem == null ? string.Empty : Path.GetFileName(OriginalItem.ItemSpec); } return _fileName; } private set { _fileName = value; } } private bool _hasFileVersion; private Version? _fileVersion; public Version? FileVersion { get { if (!_hasFileVersion) { _fileVersion = null; var fileVersionString = OriginalItem?.GetMetadata(nameof(FileVersion)) ?? string.Empty; if (fileVersionString.Length != 0) { Version.TryParse(fileVersionString, out _fileVersion); } else { _fileVersion = FileUtilities.GetFileVersion(SourcePathForFileAccess); } // fileVersion may be null but don't try to recalculate it _hasFileVersion = true; } return _fileVersion; } private set { _fileVersion = value; _hasFileVersion = true; } } public ITaskItem? OriginalItem { get; } private string? _packageId; public string? PackageId { get { if (_packageId == null) { // We used to use a heuristic of walking up the folder tree until // we find a .nuspec in order to determine the package ID of a file. By now // We should be setting the package ID metadata on all the items coming from // NuGet packages, so we will rely on that. We still might have items from packages // that don't have the metadata set if the DLL is explicitly referenced, for example. _packageId = OriginalItem?.GetMetadata(MetadataNames.NuGetPackageId) ?? string.Empty; } return _packageId.Length == 0 ? null : _packageId; } private set { _packageId = value; } } private bool _hasPackageVersion; private ConflictVersion? _packageVersion; public ConflictVersion? PackageVersion { get { if (!_hasPackageVersion) { _packageVersion = null; var packageVersionString = OriginalItem?.GetMetadata(nameof(MetadataNames.NuGetPackageVersion)) ?? string.Empty; if (packageVersionString.Length != 0) { ConflictVersion.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 { get { if (_sourcePath == null) { _sourcePath = ItemUtilities.GetSourcePath(OriginalItem) ?? string.Empty; } return _sourcePath.Length == 0 ? null : _sourcePath; } private set { _sourcePath = value; } } private string? _sourcePathForFileAccess; private bool _hasSourcePathForFileAccess; private string? SourcePathForFileAccess { get { if (!_hasSourcePathForFileAccess) { var sourcePath = SourcePath; _sourcePathForFileAccess = !string.IsNullOrEmpty(sourcePath) && _taskEnvironment != null ? _taskEnvironment.GetAbsolutePath(sourcePath) : sourcePath; _hasSourcePathForFileAccess = true; } return _sourcePathForFileAccess; } } private string? _displayName; public string? DisplayName { get { if (_displayName == null) { var itemSpec = OriginalItem == null ? FileName : OriginalItem.ItemSpec; _displayName = $"{ItemType}:{itemSpec}"; } return _displayName; } } } }