From d7c7c0e04ef5b91945d759edeb9e8d637316d34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Wed, 14 Oct 2020 05:51:50 +0300 Subject: [PATCH 001/129] Fix broken link to Windows 10 SDK (#3697) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af446dff442..b23751da251 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ - .NET desktop development - Visual Studio extension development. - Desktop development with C++ -- [Windows 10 SDK](https://dev.windows.com/en-US/downloads/windows-10-sdk) +- [Windows 10 SDK](https://developer.microsoft.com/windows/downloads/windows-10-sdk/) - [.NET 5.0 SDK](https://dotnet.microsoft.com/download/dotnet/5.0) - Please note the preview.5 has an issue that's a blocker for our repository [11862](https://github.com/dotnet/sdk/issues/11862). Avoid .NET 5 preview.5 - Git From 36253329cdc2377cdddeb68cec490b2c9222cbee Mon Sep 17 00:00:00 2001 From: Rob Relyea Date: Thu, 15 Oct 2020 07:19:19 -0700 Subject: [PATCH 002/129] Make package icon loading in PM UI async to prepare for codespaces improvements needed. (#3702) When connected to a codespaces sesssion, we are going to need to call the server instance to get embedded license files and embedded icons (for packages not accessed via search to http feeds). In order to make that work well, we need to change our Icon fetching to be more async. This change doesn't add the codespaces side of things yet...is just trying to make our current icon loading as good, and better than it is now. The ViewModel.IconUrl property now has a matching IconBitmap property...and IconBitmapStatus Since 2016, we've used a ValueConverter (runs on UI thread only) to convert the Url to a BitmapImage that an Image element could show. This approach causes a UI delay when network retrieval of images is slow. We believe this work should fix that. In order to move off the UI thread...we moved the download into background work that IconBitmap getter kicks off. We rely on INotifyPropertyChanged to notify databinding later, that the IconBitmap value has changed on the background thread. Binding can update UI properties on UI Thread that were modified on a viewmodel in a background thread(s). ErrorFloodGate.cs - made this thread safe. Testing/Validation Tests Added: Yes Validation: testing with instrumented version of UI to see where each image came from (memorycache, download, default, defaultduetonetworkproblem, etc...). tested with clumsy to slow network, drop packets, etc... --- .../Common/ErrorFloodGate.cs | 42 +- .../IconUrlToImageCacheConverter.cs | 260 ---------- .../IconUrlToVisibilityConverter.cs | 32 -- .../GlobalSuppressions.cs | 2 - .../Models/DetailControlModel.cs | 4 + .../Models/IconBitmapStatus.cs | 24 + .../Models/PackageItemListViewModel.cs | 341 ++++++++++++- .../NuGet.PackageManagement.UI.csproj | 4 +- .../Resources/Images.cs | 44 +- .../Resources/Resources.xaml | 112 ++--- .../Resources/Resources.xaml.cs | 12 - .../Utility/IconBitmapStatusUtility.cs | 36 ++ .../IconUrlToImageCacheConverterTests.cs | 441 ----------------- .../Models/PackageItemListViewModelTests.cs | 446 +++++++++++++++++- .../NuGet.PackageManagement.UI.Test.csproj | 11 +- .../Resources/packageicon.png | Bin 13750 -> 0 bytes 16 files changed, 955 insertions(+), 856 deletions(-) delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToImageCacheConverter.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToVisibilityConverter.cs create mode 100644 src/NuGet.Clients/NuGet.PackageManagement.UI/Models/IconBitmapStatus.cs create mode 100644 src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/IconBitmapStatusUtility.cs delete mode 100644 test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Converters/IconUrlToImageCacheConverterTests.cs delete mode 100644 test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Resources/packageicon.png diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Common/ErrorFloodGate.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Common/ErrorFloodGate.cs index 5d46e015cc0..558b4fcf2bc 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Common/ErrorFloodGate.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Common/ErrorFloodGate.cs @@ -1,12 +1,11 @@ using System; -using System.Collections.Generic; +using System.Collections.Concurrent; namespace NuGet.PackageManagement.UI { /// - /// Sliding in time error threshold evaluator. + /// Sliding in time error threshold evaluator. /// Verifies the number of fatal errors within last hour not bigger than reasonable threshold. - /// Not thread-safe as all value converter calls happen in main UI thread. /// internal class ErrorFloodGate { @@ -17,13 +16,13 @@ internal class ErrorFloodGate private const int MinFailuresCount = 5; private const int SecondsInOneTick = 5; private readonly DateTimeOffset _origin = DateTimeOffset.Now; - private readonly Queue _attempts = new Queue(); - private readonly Queue _failures = new Queue(); + private readonly ConcurrentQueue _attempts = new ConcurrentQueue(); + private readonly ConcurrentQueue _failures = new ConcurrentQueue(); private DateTimeOffset _lastEvaluate = DateTimeOffset.Now; - private bool _isOpen = false; + private bool _hasTooManyNetworkErrors = false; - public bool IsOpen + public bool HasTooManyNetworkErrors { get { @@ -36,18 +35,35 @@ public bool IsOpen var attemptsCount = _attempts.Count; var failuresCount = _failures.Count; - _isOpen = attemptsCount > 0 && failuresCount > MinFailuresCount && ((double)failuresCount / attemptsCount) > StopLoadingThreshold; + _hasTooManyNetworkErrors = attemptsCount > 0 && failuresCount > MinFailuresCount && ((double)failuresCount / attemptsCount) > StopLoadingThreshold; _lastEvaluate = DateTimeOffset.Now; } - return _isOpen; + return _hasTooManyNetworkErrors; } } - private static void ExpireOlderValues(Queue q, int expirationOffsetInTicks) + private static void ExpireOlderValues(ConcurrentQueue q, int expirationOffsetInTicks) { - while (q.Count > 0 && q.Peek() < expirationOffsetInTicks) + lock (q) //locking for TryPeek and TryDequeue { - q.Dequeue(); + while (q.Count > 0) + { + int result; + bool peekSucceeded = q.TryPeek(out result); + if (!peekSucceeded) + { + continue; + } + + if (result < expirationOffsetInTicks) + { + q.TryDequeue(out result); + } + else + { + return; + } + } } } @@ -57,7 +73,7 @@ public void ReportAttempt() _attempts.Enqueue(ticks); } - public void ReportError() + public void ReportBadNetworkError() { int ticks = GetTicks(_origin); _failures.Enqueue(ticks); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToImageCacheConverter.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToImageCacheConverter.cs deleted file mode 100644 index db8e3382292..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToImageCacheConverter.cs +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Cache; -using System.Runtime.Caching; -using System.Windows.Data; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using NuGet.Common; -using NuGet.Packaging; - -namespace NuGet.PackageManagement.UI -{ - internal class IconUrlToImageCacheConverter : IMultiValueConverter - { - private const int DecodePixelWidth = 32; - - // same URIs can reuse the bitmapImage that we've already used. - private static readonly ObjectCache BitmapImageCache = MemoryCache.Default; - - private static readonly WebExceptionStatus[] FatalErrors = new[] - { - WebExceptionStatus.ConnectFailure, - WebExceptionStatus.RequestCanceled, - WebExceptionStatus.ConnectionClosed, - WebExceptionStatus.Timeout, - WebExceptionStatus.UnknownError - }; - - private static readonly RequestCachePolicy RequestCacheIfAvailable = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable); - - private static readonly ErrorFloodGate ErrorFloodGate = new ErrorFloodGate(); - - /// - /// Converts IconUrl from PackageItemListViewModel to an image represented by a BitmapSource - /// - /// An array of two elements containing the IconUri and a generator function of PackageReaderBase objects - /// unused - /// A BitmapImage that will be used as the default package icon - /// unused - /// A BitmapSource with the image - /// - /// We bind to a BitmapImage instead of a Uri so that we can control the decode size, since we are displaying 32x32 images, while many of the images are 128x128 or larger. - /// This leads to a memory savings. - /// - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) - { - if (values == null || values.Length == 0) - { - return null; - } - - var iconUrl = values[0] as Uri; - var defaultPackageIcon = parameter as BitmapSource; - if (iconUrl == null) - { - return null; - } - - string cacheKey = GenerateKeyFromIconUri(iconUrl); - var cachedBitmapImage = BitmapImageCache.Get(cacheKey) as BitmapSource; - if (cachedBitmapImage != null) - { - return cachedBitmapImage; - } - - // Some people run on networks with internal NuGet feeds, but no access to the package images on the internet. - // This is meant to detect that kind of case, and stop spamming the network, so the app remains responsive. - if (ErrorFloodGate.IsOpen) - { - return defaultPackageIcon; - } - - var iconBitmapImage = new BitmapImage(); - iconBitmapImage.BeginInit(); - - BitmapSource imageResult; - - if (IsEmbeddedIconUri(iconUrl)) - { - // Check if we have enough info to read the icon from the package - if (values.Length == 2 && values[1] is Func lazyReader) - { - try - { - PackageReaderBase reader = lazyReader(); // Always returns a new reader. That avoids using an already disposed one - if (reader is PackageArchiveReader par) // This reader is closed in BitmapImage events - { - var iconEntryNormalized = PathUtility.StripLeadingDirectorySeparators( - Uri.UnescapeDataString(iconUrl.Fragment) - .Substring(1)); // Substring skips the '#' in the URI fragment - iconBitmapImage.StreamSource = par.GetEntry(iconEntryNormalized).Open(); - - void EmbeddedIcon_DownloadOrDecodeFailed(object sender, ExceptionEventArgs args) - { - reader.Dispose(); - CheckForFailedCacheEntry(cacheKey, args); - } - - void EmbeddedIcon_DownloadCompleted(object sender, EventArgs args) - { - reader.Dispose(); - IconBitmapImage_DownloadCompleted(sender, args); - } - - iconBitmapImage.DecodeFailed += EmbeddedIcon_DownloadOrDecodeFailed; - iconBitmapImage.DownloadFailed += EmbeddedIcon_DownloadOrDecodeFailed; - iconBitmapImage.DownloadCompleted += EmbeddedIcon_DownloadCompleted; - - imageResult = FinishImageProcessing(iconBitmapImage, iconUrl, defaultPackageIcon); - } - else // we cannot use the reader object - { - reader?.Dispose(); - AddToCache(cacheKey, defaultPackageIcon); - imageResult = defaultPackageIcon; - } - } - catch (Exception) - { - AddToCache(cacheKey, defaultPackageIcon); - imageResult = defaultPackageIcon; - } - } - else // Identified an embedded icon URI, but we are unable to process it - { - AddToCache(cacheKey, defaultPackageIcon); - imageResult = defaultPackageIcon; - } - } - else - { - iconBitmapImage.UriSource = iconUrl; - - iconBitmapImage.DecodeFailed += IconBitmapImage_DownloadOrDecodeFailed; - iconBitmapImage.DownloadFailed += IconBitmapImage_DownloadOrDecodeFailed; - iconBitmapImage.DownloadCompleted += IconBitmapImage_DownloadCompleted; - - imageResult = FinishImageProcessing(iconBitmapImage, iconUrl, defaultPackageIcon); - } - - return imageResult; - } - - public BitmapSource FinishImageProcessing(BitmapImage iconBitmapImage, Uri iconUrl, BitmapSource defaultPackageIcon) - { - // Default cache policy: Per MSDN, satisfies a request for a resource either by using the cached copy of the resource or by sending a request - // for the resource to the server. The action taken is determined by the current cache policy and the age of the content in the cache. - // This is the cache level that should be used by most applications. - iconBitmapImage.UriCachePolicy = RequestCacheIfAvailable; - - // Instead of scaling larger images and keeping larger image in memory, this makes it so we scale it down, and throw away the bigger image. - // Only need to set this on one dimension, to preserve aspect ratio - iconBitmapImage.DecodePixelWidth = DecodePixelWidth; - - // Workaround for https://github.com/dotnet/wpf/issues/3503 - iconBitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; - - BitmapSource image = null; - try - { - iconBitmapImage.EndInit(); - } - // if the URL is a file: URI (which actually happened!), we'll get an exception. - // if the URL is a file: URI which is in an existing directory, but the file doesn't exist, we'll fail silently. - catch (Exception) - { - iconBitmapImage = null; - } - finally - { - // store this bitmapImage in the bitmap image cache, so that other occurances can reuse the BitmapImage - var cachedBitmapImage = iconBitmapImage ?? defaultPackageIcon; - string cacheKey = GenerateKeyFromIconUri(iconUrl); - AddToCache(cacheKey, cachedBitmapImage); - ErrorFloodGate.ReportAttempt(); - - image = cachedBitmapImage; - } - - return image; - } - - private static void AddToCache(string cacheKey, BitmapSource iconBitmapImage) - { - var policy = new CacheItemPolicy - { - SlidingExpiration = TimeSpan.FromMinutes(10), - RemovedCallback = CacheEntryRemoved - }; - BitmapImageCache.Set(cacheKey, iconBitmapImage, policy); - } - - private static string GenerateKeyFromIconUri(Uri iconUrl) - { - return iconUrl == null ? string.Empty : iconUrl.ToString(); - } - - private static void CacheEntryRemoved(CacheEntryRemovedArguments arguments) - { - - } - - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) - { - throw new NotSupportedException(); - } - - private void IconBitmapImage_DownloadCompleted(object sender, EventArgs e) - { - var bitmapImage = sender as BitmapImage; - if (bitmapImage != null && bitmapImage.CanFreeze && !bitmapImage.IsFrozen) - { - bitmapImage.Freeze(); - } - } - - private void IconBitmapImage_DownloadOrDecodeFailed(object sender, ExceptionEventArgs e) - { - var bitmapImage = sender as BitmapImage; - - string cacheKey = GenerateKeyFromIconUri(bitmapImage?.UriSource); - CheckForFailedCacheEntry(cacheKey, e); - } - - private void CheckForFailedCacheEntry(string cacheKey, ExceptionEventArgs e) - { - // Fix the bitmap image cache to have default package icon, if some other failure didn't already do that. - var cachedBitmapImage = BitmapImageCache.Get(cacheKey) as BitmapSource; - if (cachedBitmapImage != Images.DefaultPackageIcon) - { - AddToCache(cacheKey, Images.DefaultPackageIcon); - - var webex = e.ErrorException as WebException; - if (webex != null && FatalErrors.Any(c => webex.Status == c)) - { - ErrorFloodGate.ReportError(); - } - } - } - - /// - /// NuGet Embedded Icon Uri verification - /// - /// An URI to test - /// true if iconUrl is an URI to an embedded icon in a NuGet package - public static bool IsEmbeddedIconUri(Uri iconUrl) - { - return iconUrl != null - && iconUrl.IsAbsoluteUri - && iconUrl.IsFile - && !string.IsNullOrEmpty(iconUrl.Fragment) - && iconUrl.Fragment.Length > 1; - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToVisibilityConverter.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToVisibilityConverter.cs deleted file mode 100644 index 463e2d2aef7..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Converters/IconUrlToVisibilityConverter.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Windows; -using System.Windows.Data; - -namespace NuGet.PackageManagement.UI -{ - public class IconUrlToVisibilityConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var uri = value as Uri; - if (uri == null) - { - return Visibility.Collapsed; - } - - return Visibility.Visible; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - // no op - Debug.Fail("Not Implemented"); - return null; - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs index 11a83d0c45f..379638d8fa1 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs @@ -42,8 +42,6 @@ [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task DetailControlModel.SetCurrentPackage(PackageItemListViewModel searchResultPackage, ItemFilter filter, Func getPackageItemListViewModel)', validate parameter 'getPackageItemListViewModel' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.DetailControlModel.SetCurrentPackage(NuGet.PackageManagement.UI.PackageItemListViewModel,NuGet.PackageManagement.UI.ItemFilter,System.Func{NuGet.PackageManagement.UI.PackageItemListViewModel})~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'DetailedPackageMetadata.DetailedPackageMetadata(IPackageSearchMetadata serverData, PackageDeprecationMetadata deprecationMetadata, long? downloadCount)', validate parameter 'serverData' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.DetailedPackageMetadata.#ctor(NuGet.Protocol.Core.Types.IPackageSearchMetadata,NuGet.Protocol.PackageDeprecationMetadata,System.Nullable{System.Int64})")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'DisplayVersion.DisplayVersion(VersionRange range, string additionalInfo, bool isValidVersion = true, bool isCurrentInstalled = false, bool autoReferenced = false, bool isDeprecated = false, string versionFormat = \"N\")', validate parameter 'range' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.DisplayVersion.#ctor(NuGet.Versioning.VersionRange,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean,System.String)")] -[assembly: SuppressMessage("Build", "CA1031:Modify 'Convert' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.IconUrlToImageCacheConverter.Convert(System.Object[],System.Type,System.Object,System.Globalization.CultureInfo)~System.Object")] -[assembly: SuppressMessage("Build", "CA1031:Modify 'FinishImageProcessing' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.IconUrlToImageCacheConverter.FinishImageProcessing(System.Windows.Media.Imaging.BitmapImage,System.Uri,System.Windows.Media.Imaging.BitmapSource)~System.Windows.Media.Imaging.BitmapSource")] [assembly: SuppressMessage("Build", "CA1822:Member WaitForInitialResultsAsync does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.InfiniteScrollList.WaitForInitialResultsAsync(NuGet.PackageManagement.UI.IItemLoader{NuGet.PackageManagement.UI.PackageItemListViewModel},System.IProgress{NuGet.PackageManagement.UI.IItemLoaderState},System.Threading.CancellationToken)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1801:Parameter parameter of method Convert is never used. Remove the parameter or use it in the method body.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.MessageLevelToBrushConverter.Convert(System.Object[],System.Type,System.Object,System.Globalization.CultureInfo)~System.Object")] [assembly: SuppressMessage("Build", "CA1303:Method 'object NotEqualConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)' passes a literal string as parameter 'message' of a call to 'ArgumentException.ArgumentException(string message)'. Retrieve the following string(s) from a resource table instead: \"Parameter should not be null and should inherit from IComparable\".", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.UI.NotEqualConverter.Convert(System.Object,System.Type,System.Object,System.Globalization.CultureInfo)~System.Object")] diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs index e126b214690..5bbe6aa77af 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Windows.Media.Imaging; using NuGet.PackageManagement.VisualStudio; using NuGet.Packaging; using NuGet.Packaging.Core; @@ -102,6 +103,7 @@ public async virtual Task SetCurrentPackage( OnPropertyChanged(nameof(Id)); OnPropertyChanged(nameof(PackageReader)); OnPropertyChanged(nameof(IconUrl)); + OnPropertyChanged(nameof(IconBitmap)); OnPropertyChanged(nameof(PrefixReserved)); var getVersionsTask = searchResultPackage.GetVersionsAsync(); @@ -312,6 +314,8 @@ protected void OnPropertyChanged(string propertyName) public Uri IconUrl => _searchResultPackage?.IconUrl; + public BitmapSource IconBitmap => _searchResultPackage?.IconBitmap; + public bool PrefixReserved => _searchResultPackage?.PrefixReserved ?? false; public bool IsPackageDeprecated => _packageMetadata?.DeprecationMetadata != null; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/IconBitmapStatus.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/IconBitmapStatus.cs new file mode 100644 index 00000000000..678658fd7c0 --- /dev/null +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/IconBitmapStatus.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace NuGet.PackageManagement.UI +{ + // IconBitmapStatusUtility has some helper methods that will need to be modified if we add new enum values. + public enum IconBitmapStatus + { + None = 0, + NeedToFetch, + Fetching, + MemoryCachedIcon, + DownloadedIcon, + EmbeddedIcon, + DefaultIcon, + DefaultIconDueToDecodingError, + DefaultIconDueToNullStream, + DefaultIconDueToNoPackageReader, + DefaultIconDueToNetworkFailures, + DefaultIconDueToWebExceptionBadNetwork, + DefaultIconDueToWebExceptionOther, + DefaultIconDueToRelativeUri + } +} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageItemListViewModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageItemListViewModel.cs index 53c071bef70..cc3eb4942f7 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageItemListViewModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageItemListViewModel.cs @@ -5,8 +5,15 @@ using System.Collections.Generic; using System.ComponentModel; using System.Globalization; +using System.IO; using System.Linq; +using System.Net; +using System.Net.Cache; +using System.Runtime.Caching; +using System.Runtime.InteropServices; using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Microsoft.VisualStudio.Threading; using NuGet.Common; using NuGet.PackageManagement.VisualStudio; using NuGet.Packaging; @@ -22,11 +29,29 @@ namespace NuGet.PackageManagement.UI // Some of its properties, such as Latest Version, Status, are fetched on-demand in the background. public class PackageItemListViewModel : INotifyPropertyChanged { - private static readonly AsyncLazy> LazyEmptyVersionInfo = - AsyncLazy.New(Enumerable.Empty()); + private static readonly Common.AsyncLazy> LazyEmptyVersionInfo = + Common.AsyncLazy.New(Enumerable.Empty()); - private static readonly AsyncLazy LazyNullDeprecationMetadata = - AsyncLazy.New((PackageDeprecationMetadata)null); + private static readonly Common.AsyncLazy LazyNullDeprecationMetadata = + Common.AsyncLazy.New((PackageDeprecationMetadata)null); + + internal const int DecodePixelWidth = 32; + + // same URIs can reuse the bitmapImage that we've already used. + private static readonly ObjectCache BitmapImageCache = MemoryCache.Default; + + private static readonly WebExceptionStatus[] BadNetworkErrors = new[] + { + WebExceptionStatus.ConnectFailure, + WebExceptionStatus.RequestCanceled, + WebExceptionStatus.ConnectionClosed, + WebExceptionStatus.Timeout, + WebExceptionStatus.UnknownError + }; + + private static readonly RequestCachePolicy RequestCacheIfAvailable = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable); + + private static readonly ErrorFloodGate ErrorFloodGate = new ErrorFloodGate(); public event PropertyChangedEventHandler PropertyChanged; @@ -369,7 +394,66 @@ public bool IsPackageDeprecated } } - public Uri IconUrl { get; set; } + private Uri _iconUrl; + public Uri IconUrl + { + get { return _iconUrl; } + set + { + _iconUrl = value; + OnPropertyChanged(nameof(IconUrl)); + } + } + + private IconBitmapStatus _bitmapStatus; + + public IconBitmapStatus BitmapStatus + { + get { return _bitmapStatus; } + set + { + if (_bitmapStatus != value) + { + _bitmapStatus = value; + OnPropertyChanged(nameof(BitmapStatus)); + } + } + } + + private BitmapSource _iconBitmap; + public BitmapSource IconBitmap + { + get + { + if (_iconBitmap == null) + { + if (BitmapStatus == IconBitmapStatus.None) + { + (BitmapSource iconBitmap, IconBitmapStatus nextStatus) = GetInitialIconBitmapAndStatus(); + + BitmapStatus = nextStatus; + _iconBitmap = iconBitmap; + if (BitmapStatus == IconBitmapStatus.NeedToFetch) + { + BitmapStatus = IconBitmapStatus.Fetching; + NuGetUIThreadHelper.JoinableTaskFactory + .RunAsync(FetchThenSetIconBitmapAsync) + .PostOnFailure(nameof(PackageItemListViewModel), nameof(IconBitmap)); + } + } + } + + return _iconBitmap; + } + set + { + if (_iconBitmap != value) + { + _iconBitmap = value; + OnPropertyChanged(nameof(IconBitmap)); + } + } + } public Lazy>> Versions { private get; set; } public Task> GetVersionsAsync() => (Versions ?? LazyEmptyVersionInfo).Value; @@ -382,6 +466,253 @@ public bool IsPackageDeprecated private Lazy> _backgroundLatestVersionLoader; private Lazy> _backgroundDeprecationMetadataLoader; + private (BitmapSource, IconBitmapStatus) GetInitialIconBitmapAndStatus() + { + BitmapSource imageBitmap = null; + IconBitmapStatus status; + + if (IconUrl == null) + { + imageBitmap = Images.DefaultPackageIcon; + status = IconBitmapStatus.DefaultIcon; + } + else if (!IconUrl.IsAbsoluteUri) + { + imageBitmap = Images.DefaultPackageIcon; + status = IconBitmapStatus.DefaultIconDueToRelativeUri; + } + else + { + string cacheKey = GenerateKeyFromIconUri(IconUrl); + var cachedBitmapImage = BitmapImageCache.Get(cacheKey) as BitmapSource; + if (cachedBitmapImage != null) + { + imageBitmap = cachedBitmapImage; + status = IconBitmapStatus.MemoryCachedIcon; + } + else + { + // Some people run on networks with internal NuGet feeds, but no access to the package images on the internet. + // This is meant to detect that kind of case, and stop spamming the network, so the app remains responsive. + if (ErrorFloodGate.HasTooManyNetworkErrors) + { + imageBitmap = Images.DefaultPackageIcon; + status = IconBitmapStatus.DefaultIconDueToNetworkFailures; + } + else + { + imageBitmap = Images.DefaultPackageIcon; + status = IconBitmapStatus.NeedToFetch; + } + } + } + + return (imageBitmap, status); + } + + private async Task FetchThenSetIconBitmapAsync() + { + await TaskScheduler.Default; + + if (IsEmbeddedIconUri(IconUrl)) + { + if (PackageReader is Func lazyReader) + { + FetchEmbeddedImage(lazyReader, IconUrl); + } + else // Identified an embedded icon URI, but we are unable to process it + { + IconBitmap = Images.DefaultPackageIcon; + BitmapStatus = IconBitmapStatus.DefaultIconDueToNoPackageReader; + } + } + else + { + // download http or file image + await FetchImageAsync(IconUrl); + } + + if (IconBitmap != null) + { + string cacheKey = GenerateKeyFromIconUri(IconUrl); + AddToCache(cacheKey, IconBitmap); + } + } + + private void FetchEmbeddedImage(Func lazyReader, Uri iconUrl) + { + var iconBitmapImage = new BitmapImage(); + iconBitmapImage.BeginInit(); + try + { + using (PackageReaderBase reader = lazyReader()) // Always returns a new reader. That avoids using an already disposed one + { + if (reader is PackageArchiveReader par) // This reader is closed in BitmapImage events + { + string iconEntryNormalized = PathUtility.StripLeadingDirectorySeparators( + Uri.UnescapeDataString(iconUrl.Fragment) + .Substring(1)); // Substring skips the '#' in the URI fragment + + // need to use a memorystream, or the bitmapimage won't be freezable. + using (Stream parStream = par.GetEntry(iconEntryNormalized).Open()) + using (var memoryStream = new MemoryStream()) + { + parStream.CopyTo(memoryStream); + iconBitmapImage.StreamSource = memoryStream; + FinalizeBitmapImage(iconBitmapImage); + } + + iconBitmapImage.Freeze(); + + IconBitmap = iconBitmapImage; + BitmapStatus = IconBitmapStatus.EmbeddedIcon; + } + else // we cannot use the reader object + { + IconBitmap = Images.DefaultPackageIcon; + BitmapStatus = IconBitmapStatus.DefaultIconDueToNoPackageReader; + } + } + } + catch (Exception ex) when (IsHandleableBitmapEncodingException(ex)) + { + IconBitmap = Images.DefaultPackageIcon; + BitmapStatus = IconBitmapStatus.DefaultIconDueToDecodingError; + } + } + + private static bool IsHandleableBitmapEncodingException(Exception ex) + { + return ex is ArgumentException || + ex is COMException || + ex is FileFormatException || + ex is InvalidOperationException || + ex is NotSupportedException || + ex is OutOfMemoryException || + ex is IOException || + ex is UnauthorizedAccessException; + } + + private async Task FetchImageAsync(Uri iconUrl) + { + if (iconUrl is null) + { + return; + } + + using (Stream stream = await GetStream(iconUrl)) + { + if (stream != null) + { + var iconBitmapImage = new BitmapImage(); + iconBitmapImage.BeginInit(); + iconBitmapImage.StreamSource = stream; + + try + { + FinalizeBitmapImage(iconBitmapImage); + iconBitmapImage.Freeze(); + IconBitmap = iconBitmapImage; + BitmapStatus = IconBitmapStatus.DownloadedIcon; + } + catch (Exception ex) when (IsHandleableBitmapEncodingException(ex)) + { + IconBitmap = Images.DefaultPackageIcon; + BitmapStatus = IconBitmapStatus.DefaultIconDueToDecodingError; + } + } + else + { + if (BitmapStatus == IconBitmapStatus.Fetching) + { + BitmapStatus = IconBitmapStatus.DefaultIconDueToNullStream; + } + } + + ErrorFloodGate.ReportAttempt(); + } + } + + private static void FinalizeBitmapImage(BitmapImage iconBitmapImage) + { + // Default cache policy: Per MSDN, satisfies a request for a resource either by using the cached copy of the resource or by sending a request + // for the resource to the server. The action taken is determined by the current cache policy and the age of the content in the cache. + // This is the cache level that should be used by most applications. + iconBitmapImage.UriCachePolicy = RequestCacheIfAvailable; + + // Instead of scaling larger images and keeping larger image in memory, this makes it so we scale it down, and throw away the bigger image. + // Only need to set this on one dimension, to preserve aspect ratio + iconBitmapImage.DecodePixelWidth = DecodePixelWidth; + + // Workaround for https://github.com/dotnet/wpf/issues/3503 + iconBitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; + + iconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; + + iconBitmapImage.EndInit(); + } + + /// + /// NuGet Embedded Icon Uri verification + /// + /// An URI to test + /// true if iconUrl is an URI to an embedded icon in a NuGet package + public static bool IsEmbeddedIconUri(Uri iconUrl) + { + return iconUrl != null + && iconUrl.IsAbsoluteUri + && iconUrl.IsFile + && !string.IsNullOrEmpty(iconUrl.Fragment) + && iconUrl.Fragment.Length > 1; + } + + private static string GenerateKeyFromIconUri(Uri iconUrl) + { + return iconUrl == null ? string.Empty : iconUrl.ToString(); + } + + private static void AddToCache(string cacheKey, BitmapSource iconBitmapImage) + { + var policy = new CacheItemPolicy + { + SlidingExpiration = TimeSpan.FromMinutes(10), + }; + BitmapImageCache.Set(cacheKey, iconBitmapImage, policy); + } + + private async Task GetStream(Uri imageUri) + { + // BitmapImage can download on its own from URIs, but in order + // to support downloading on a worker thread, we need to download the image + // data and put into a memorystream. Then have the BitmapImage decode the + // image from the memorystream. + byte[] imageData = null; + MemoryStream ms = null; + + using (var wc = new System.Net.WebClient()) + { + try + { + imageData = await wc.DownloadDataTaskAsync(imageUri); + ms = new MemoryStream(imageData, writable: false); + } + catch (WebException webex) + { + if (BadNetworkErrors.Any(c => webex.Status == c)) + { + ErrorFloodGate.ReportBadNetworkError(); + BitmapStatus = IconBitmapStatus.DefaultIconDueToWebExceptionBadNetwork; + } + else + { + BitmapStatus = IconBitmapStatus.DefaultIconDueToWebExceptionOther; + } + } + } + + return ms; + } + private void TriggerStatusLoader() { if (!_backgroundLatestVersionLoader.IsValueCreated) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj b/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj index fbc0aaa3ab7..3b5c887ace0 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj @@ -73,6 +73,7 @@ + @@ -130,6 +131,7 @@ + @@ -169,7 +171,6 @@ - @@ -181,7 +182,6 @@ - diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs index 3969448ee7e..0b6f44ea317 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs @@ -1,26 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; +using System.Windows; +using System.Windows.Media; using System.Windows.Media.Imaging; namespace NuGet.PackageManagement.UI { internal static class Images { - public static readonly BitmapImage DefaultPackageIcon; + public static readonly BitmapSource DefaultPackageIcon; static Images() { - DefaultPackageIcon = new BitmapImage(); - DefaultPackageIcon.BeginInit(); + // in VS, look up the icon via pack://application url + if (Application.Current != null) + { + var image = new BitmapImage(); + image.BeginInit(); - // If the DLL name changes, this URI would need to change to match. - DefaultPackageIcon.UriSource = new Uri("pack://application:,,,/NuGet.PackageManagement.UI;component/Resources/packageicon.png"); + // If the DLL name changes, this URI would need to change to match. + image.UriSource = new Uri("pack://application:,,,/NuGet.PackageManagement.UI;component/Resources/packageicon.png"); - // Instead of scaling larger images and keeping larger image in memory, this makes it so we scale it down, and throw away the bigger image. - // Only need to set this on one dimension, to preserve aspect ratio - DefaultPackageIcon.DecodePixelWidth = 32; + // Instead of scaling larger images and keeping larger image in memory, this makes it so we scale it down, and throw away the bigger image. + // Only need to set this on one dimension, to preserve aspect ratio + image.DecodePixelWidth = PackageItemListViewModel.DecodePixelWidth; - DefaultPackageIcon.EndInit(); - DefaultPackageIcon.Freeze(); + image.EndInit(); + image.Freeze(); + DefaultPackageIcon = image; + } + else // for tests, don't actually load the icon, just use a 1x1 image. + { + BitmapSource image = BitmapSource.Create( + pixelWidth: 1, + pixelHeight: 1, + dpiX: 96.0, + dpiY: 96.0, + PixelFormats.Bgr32, + palette: null, + pixels: new byte[] { 0, 0, 255, 0 }, + stride: 32); + image.Freeze(); + DefaultPackageIcon = image; + } } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml index 86676492316..a520f4253fb 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml @@ -8,8 +8,6 @@ - - @@ -182,13 +178,13 @@ @@ -252,21 +248,21 @@ - - @@ -313,21 +309,21 @@ - - @@ -374,21 +370,21 @@ - - @@ -425,21 +421,21 @@ - - @@ -477,15 +473,15 @@ - - @@ -603,7 +599,7 @@ - - - - - - - - - - + diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml.cs index d4eafcc2d59..65af164175a 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml.cs @@ -14,17 +14,5 @@ public SharedResources() { InitializeComponent(); } - - private void PackageIconImage_ImageFailed(object sender, ExceptionRoutedEventArgs e) - { - var image = sender as Image; - - e.Handled = true; // don't repropagate the event - MultiBindingExpression binding = BindingOperations.GetMultiBindingExpression(image, Image.SourceProperty); - if (binding != null && binding.BindingExpressions.All((x) => x.Status != BindingStatus.Detached)) - { - binding.UpdateTarget(); - } - } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/IconBitmapStatusUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/IconBitmapStatusUtility.cs new file mode 100644 index 00000000000..f964b4d5a16 --- /dev/null +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/IconBitmapStatusUtility.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace NuGet.PackageManagement.UI +{ + internal static class IconBitmapStatusUtility + { + internal static bool GetIsDefaultIcon(IconBitmapStatus bitmapStatus) + { + return bitmapStatus == IconBitmapStatus.DefaultIcon || + bitmapStatus == IconBitmapStatus.DefaultIconDueToDecodingError || + bitmapStatus == IconBitmapStatus.DefaultIconDueToNullStream || + bitmapStatus == IconBitmapStatus.DefaultIconDueToNoPackageReader || + bitmapStatus == IconBitmapStatus.DefaultIconDueToNetworkFailures || + bitmapStatus == IconBitmapStatus.DefaultIconDueToWebExceptionBadNetwork || + bitmapStatus == IconBitmapStatus.DefaultIconDueToWebExceptionOther || + bitmapStatus == IconBitmapStatus.DefaultIconDueToRelativeUri; + } + + internal static bool GetIsCompleted(IconBitmapStatus bitmapStatus) + { + switch (bitmapStatus) + { + case IconBitmapStatus.None: + case IconBitmapStatus.NeedToFetch: + case IconBitmapStatus.Fetching: + return false; + + default: + return true; + } + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Converters/IconUrlToImageCacheConverterTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Converters/IconUrlToImageCacheConverterTests.cs deleted file mode 100644 index 6a4edb23b22..00000000000 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Converters/IconUrlToImageCacheConverterTests.cs +++ /dev/null @@ -1,441 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using NuGet.Packaging; -using NuGet.Test.Utility; -using Xunit; -using Xunit.Abstractions; - -namespace NuGet.PackageManagement.UI.Test -{ - public class IconUrlToImageCacheConverterTests - { - private static readonly ImageSource DefaultPackageIcon; - private readonly ITestOutputHelper output; - - static IconUrlToImageCacheConverterTests() - { - // Mimic the default image - var width = 32; - var height = 32; - var format = PixelFormats.Bgr24; - var stride = width * format.BitsPerPixel; - var data = new byte[width * height * format.BitsPerPixel]; - - DefaultPackageIcon = BitmapSource.Create(width, height, 96, 96, format, null, data, stride); - DefaultPackageIcon.Freeze(); - } - - public IconUrlToImageCacheConverterTests(ITestOutputHelper output) - { - this.output = output; - } - - [Fact] - public void Convert_WithMalformedUrlScheme_ReturnsDefault() - { - var iconUrl = new Uri("ttp://fake.com/image.png"); - - var converter = new IconUrlToImageCacheConverter(); - - var image = converter.Convert( - values: new object[] { iconUrl, DependencyProperty.UnsetValue }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null); - - VerifyImageResult(image); - Assert.Same(DefaultPackageIcon, image); - } - - [Fact] - public void Convert_WhenFileNotFound_ReturnsDefault() - { - var iconUrl = new Uri(@"C:\path\to\image.png"); - - var converter = new IconUrlToImageCacheConverter(); - - var image = converter.Convert( - values: new object[] { iconUrl, DependencyProperty.UnsetValue }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null); - - VerifyImageResult(image); - Assert.Same(DefaultPackageIcon, image); - } - - [Fact] - public void Convert_WithLocalPath_LoadsImage() - { - var iconUrl = new Uri(@"resources/packageicon.png", UriKind.Relative); - - var converter = new IconUrlToImageCacheConverter(); - - var image = converter.Convert( - values: new object[] { iconUrl, DependencyProperty.UnsetValue }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null) as BitmapImage; - - VerifyImageResult(image); - Assert.NotSame(DefaultPackageIcon, image); - Assert.Equal(iconUrl, image.UriSource); - } - - [Fact] - public void Convert_WithLocalPathAndColorProfile_LoadsImage() - { - var iconUrl = new Uri(@"resources/grayicc.png", UriKind.Relative); - - var converter = new IconUrlToImageCacheConverter(); - - var image = converter.Convert( - values: new object[] { iconUrl, DependencyProperty.UnsetValue }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null) as BitmapImage; - - VerifyImageResult(image); - Assert.NotSame(DefaultPackageIcon, image); - Assert.Equal(iconUrl, image.UriSource); - } - - [Fact(Skip = "Fails on CI. Tracking issue: https://github.com/NuGet/Home/issues/2474")] - public void Convert_WithValidImageUrl_DownloadsImage_DefaultImage() - { - var iconUrl = new Uri("http://fake.com/image.png"); - - var converter = new IconUrlToImageCacheConverter(); - - var image = converter.Convert( - values: new object[] { iconUrl, DependencyProperty.UnsetValue }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null) as BitmapImage; - - VerifyImageResult(image); - Assert.NotSame(DefaultPackageIcon, image); - Assert.Equal(iconUrl, image.UriSource); - } - - [LocalOnlyTheory] - [InlineData("icon.png", "icon.png", "icon.png", "")] - [InlineData("folder/icon.png", "folder\\icon.png", "folder/icon.png", "folder")] - [InlineData("folder\\icon.png", "folder\\icon.png", "folder\\icon.png", "folder")] - public void Convert_EmbeddedIcon_HappyPath_LoadsImage( - string iconElement, - string iconFileLocation, - string fileSourceElement, - string fileTargetElement) - { - using (var testDir = TestDirectory.Create()) - { - // Create decoy nuget package - var zipPath = Path.Combine(testDir.Path, "file.nupkg"); - CreateDummyPackage( - zipPath: zipPath, - iconName: iconElement, - iconFile: iconFileLocation, - iconFileSourceElement: fileSourceElement, - iconFileTargetElement: fileTargetElement, - isRealImage: true); - - // prepare test - var converter = new IconUrlToImageCacheConverter(); - - UriBuilder builder = new UriBuilder(new Uri(zipPath, UriKind.Absolute)) - { - Fragment = iconElement - }; - - output.WriteLine($"ZipPath {zipPath}"); - output.WriteLine($"File Exists {File.Exists(zipPath)}"); - output.WriteLine($"Url {builder.Uri}"); - - // Act - var result = converter.Convert( - values: new object[] - { - builder.Uri, - new Func(() => new PackageArchiveReader(zipPath)) - }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null); - - // Assert - output.WriteLine($"result {result}"); - VerifyImageResult(result); - Assert.NotSame(DefaultPackageIcon, result); - } - } - - [CIOnlyTheory] - [InlineData("icon.jpg", "icon.jpg", "icon.jpg", "")] - [InlineData("icon2.jpg", "icon2.jpg", "icon2.jpg", "")] - public void Convert_EmbeddedIcon_NotAnIcon_ReturnsDefault( - string iconElement, - string iconFileLocation, - string fileSourceElement, - string fileTargetElement) - { - using (var testDir = TestDirectory.Create()) - { - // Create decoy nuget package - var zipPath = Path.Combine(testDir.Path, "file.nupkg"); - CreateDummyPackage( - zipPath: zipPath, - iconName: iconElement, - iconFile: iconFileLocation, - iconFileSourceElement: fileSourceElement, - iconFileTargetElement: fileTargetElement, - isRealImage: false); - - // prepare test - var converter = new IconUrlToImageCacheConverter(); - - UriBuilder builder = new UriBuilder(new Uri(zipPath, UriKind.Absolute)) - { - Fragment = iconElement - }; - - output.WriteLine($"ZipPath {zipPath}"); - output.WriteLine($"File Exists {File.Exists(zipPath)}"); - output.WriteLine($"Url {builder.Uri}"); - - // Act - var result = converter.Convert( - values: new object[] - { - builder.Uri, - new Func(() => new PackageArchiveReader(zipPath)) - }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null); - - VerifyImageResult(result); - var image = result as BitmapSource; - - output.WriteLine($"result {result}"); - output.WriteLine($"Pixel format: {image.Format}"); - - // Assert - Assert.Same(DefaultPackageIcon, result); - } - } - - [Fact] - public void Convert_FileUri_LoadsImage() - { - // Prepare - var converter = new IconUrlToImageCacheConverter(); - - using (var testDir = TestDirectory.Create()) - { - var imagePath = Path.Combine(testDir, "image.png"); - CreateNoisePngImage(path: imagePath); - - var uri = new Uri(imagePath, UriKind.Absolute); - - // Act - var result = converter.Convert( - values: new object[] { uri, DependencyProperty.UnsetValue }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null); - - var image = result as BitmapImage; - - // Assert - VerifyImageResult(result); - Assert.NotSame(DefaultPackageIcon, result); - } - } - - [Theory] - [InlineData(@"/")] - [InlineData(@"\")] - public void Convert_EmbeddedIcon_RelativeParentPath_ReturnsDefault(string separator) - { - using (var testDir = TestDirectory.Create()) - { - // Create decoy nuget package - var zipPath = Path.Combine(testDir.Path, "file.nupkg"); - CreateDummyPackage(zipPath); - - // prepare test - var converter = new IconUrlToImageCacheConverter(); - UriBuilder builder = new UriBuilder(new Uri(zipPath, UriKind.Absolute)) - { - Fragment = $@"..{separator}icon.png" - }; - - // Act - var result = converter.Convert( - values: new object[] { builder.Uri, new Func(() => new PackageArchiveReader(zipPath)) }, - targetType: null, - parameter: DefaultPackageIcon, - culture: null); - - // Assert - VerifyImageResult(result); - Assert.Same(DefaultPackageIcon, result); - } - } - - [Theory] - [MemberData(nameof(TestData))] - public void IsEmbeddedIconUri_Tests(Uri testUri, bool expectedResult) - { - var result = IconUrlToImageCacheConverter.IsEmbeddedIconUri(testUri); - Assert.Equal(expectedResult, result); - } - - public static IEnumerable TestData() - { - Uri baseUri = new Uri(@"C:\path\to\package"); - UriBuilder builder1 = new UriBuilder(baseUri) - { - Fragment = " " // UriBuilder trims the string - }; - UriBuilder builder2 = new UriBuilder(baseUri) - { - Fragment = "icon.png" - }; - UriBuilder builder3 = new UriBuilder(baseUri) - { - Fragment = @"..\icon.png" - }; - UriBuilder builder4 = new UriBuilder(baseUri) - { - Fragment = string.Empty // implies that there's a Tag, but no value - }; - UriBuilder builder5 = new UriBuilder(baseUri) - { - Query = "aParam" - }; - - return new List - { - new object[]{ builder1.Uri, false }, - new object[]{ builder2.Uri, true }, - new object[]{ builder3.Uri, true }, - new object[]{ builder4.Uri, false }, - new object[]{ builder5.Uri, false }, - new object[]{ new Uri("https://sample.uri/"), false }, - new object[]{ baseUri, false }, - new object[]{ new Uri("https://another.uri/#"), false }, - new object[]{ new Uri("https://complimentary.uri/#anchor"), false }, - new object[]{ new Uri("https://complimentary.uri/?param"), false }, - new object[]{ new Uri("relative/path", UriKind.Relative), false }, - }; - } - - - /// - /// Creates a NuGet package with .nupkg extension and with a PNG image named "icon.png" - /// - /// Path to NuGet package - /// Icon filename with .png extension - private static void CreateDummyPackage( - string zipPath, - string iconName = "icon.png", - string iconFile = "icon.png", - string iconFileSourceElement = "icon.png", - string iconFileTargetElement = "", - bool isRealImage = true) - { - var dir = Path.GetDirectoryName(zipPath); - var holdDir = "pkg"; - var folderPath = Path.Combine(dir, holdDir); - - // base dir - Directory.CreateDirectory(folderPath); - - // create nuspec - var nuspec = NuspecBuilder.Create() - .WithIcon(iconName) - .WithFile(iconFileSourceElement, iconFileTargetElement); - - // create png image - var iconPath = Path.Combine(folderPath, iconFile); - var iconDir = Path.GetDirectoryName(iconPath); - Directory.CreateDirectory(iconDir); - - if (isRealImage) - { - CreateNoisePngImage(iconPath); - } - else - { - File.WriteAllText(iconPath, "I am an image"); - } - - // Create nuget package - using (var nuspecStream = new MemoryStream()) - using (FileStream nupkgStream = File.Create(zipPath)) - { - var writer = new StreamWriter(nuspecStream); - nuspec.Write(writer); - writer.Flush(); - nuspecStream.Position = 0; - var pkgBuilder = new PackageBuilder(stream: nuspecStream, basePath: folderPath); - pkgBuilder.Save(nupkgStream); - } - } - - /// - /// Creates a PNG image with random pixels - /// - /// Filename in which the image is created - /// Image width in pixels - /// Image height in pixels - /// Horizontal Dots (pixels) Per Inch in the image - /// Vertical Dots (pixels) Per Inch in the image - private static void CreateNoisePngImage(string path, int w = 128, int h = 128, int dpiX = 96, int dpiY = 96) - { - // Create PNG image with noise - var fmt = PixelFormats.Bgr32; - - // a row of pixels - int stride = (w * fmt.BitsPerPixel); - var data = new byte[stride * h]; - - // Random pixels - Random rnd = new Random(); - rnd.NextBytes(data); - - BitmapSource bitmap = BitmapSource.Create(w, h, - dpiX, dpiY, - fmt, - null, data, stride); - - BitmapEncoder encoder = new PngBitmapEncoder(); - - encoder.Frames.Add(BitmapFrame.Create(bitmap)); - - using (var fs = File.OpenWrite(path)) - { - encoder.Save(fs); - } - } - - private static void VerifyImageResult(object result) - { - Assert.NotNull(result); - Assert.True(result is BitmapImage || result is CachedBitmap); - var image = result as BitmapSource; - Assert.NotNull(image); - Assert.Equal(32, image.PixelWidth); - Assert.Equal(32, image.PixelHeight); - } - } -} diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs index 6456dd91d48..c708b3ba300 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs @@ -3,28 +3,44 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.IO; +using System.Reflection; using System.Threading.Tasks; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Microsoft; +using Microsoft.VisualStudio.Threading; +using NuGet.PackageManagement.VisualStudio.Test; using NuGet.Packaging; -using NuGet.Protocol; using NuGet.Test.Utility; +using NuGet.VisualStudio; +using Test.Utility.Threading; using Xunit; +using Xunit.Abstractions; namespace NuGet.PackageManagement.UI.Test { - public class PackageItemListViewModelTests : IClassFixture + [Collection(DispatcherThreadCollection.CollectionName)] + public class PackageItemListViewModelTests : IClassFixture, IClassFixture { private readonly LocalPackageSearchMetadataFixture _testData; private readonly PackageItemListViewModel _testInstance; + private readonly ITestOutputHelper _output; + private readonly JoinableTaskFactory _jtf; - public PackageItemListViewModelTests(LocalPackageSearchMetadataFixture testData) + public PackageItemListViewModelTests(DispatcherThreadFixture fixture, ITestOutputHelper output, LocalPackageSearchMetadataFixture testData) { _testData = testData; _testInstance = new PackageItemListViewModel() { PackageReader = _testData.TestData.PackageReader, }; + _output = output; + + Assumes.Present(fixture); + + _jtf = fixture.JoinableTaskFactory; + NuGetUIThreadHelper.SetCustomJoinableTaskFactory(_jtf); } [Fact] @@ -37,5 +53,425 @@ public void LocalSources_PackageReader_NotNull() PackageReaderBase reader = func(); Assert.IsType(typeof(PackageArchiveReader), reader); } + + [Fact] + public async Task IconUrl_WithMalformedUrlScheme_ReturnsDefaultInitallyAndFinally() + { + var iconUrl = new Uri("httphttphttp://fake.test/image.png"); + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = iconUrl + }; + + // initial result should be fetching and defaultpackageicon + BitmapSource initialResult = packageItemListViewModel.IconBitmap; + Assert.Equal(IconBitmapStatus.Fetching, packageItemListViewModel.BitmapStatus); + Assert.Same(initialResult, Images.DefaultPackageIcon); + + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DefaultIconDueToWebExceptionBadNetwork, packageItemListViewModel.BitmapStatus); + } + + [Fact] + public async Task IconUrl_WhenFileNotFound_ReturnsDefault() + { + var iconUrl = new Uri(@"C:\path\to\image.png"); + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = iconUrl + }; + + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DefaultIconDueToWebExceptionBadNetwork, packageItemListViewModel.BitmapStatus); + } + + [Fact] + public async Task IconUrl_RelativeUri_ReturnsDefault() + { + // relative URIs are not supported in viewmodel. + var iconUrl = new Uri("resources/testpackageicon.png", UriKind.Relative); + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = iconUrl + }; + + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DefaultIconDueToRelativeUri, packageItemListViewModel.BitmapStatus); + } + + [Fact] + public async Task IconUrl_WithLocalPathAndColorProfile_LoadsImage() + { + // Prepare + using (var testDir = TestDirectory.Create()) + { + byte[] bytes; + Assembly testAssembly = typeof(PackageItemListViewModelTests).Assembly; + + using (Stream sourceStream = testAssembly.GetManifestResourceStream("NuGet.PackageManagement.UI.Test.Resources.grayicc.png")) + using (var memoryStream = new MemoryStream()) + { + sourceStream.CopyTo(memoryStream); + bytes = memoryStream.ToArray(); + } + + string grayiccImagePath = Path.Combine(testDir, "grayicc.png"); + File.WriteAllBytes(grayiccImagePath, bytes); + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = new Uri(grayiccImagePath, UriKind.Absolute) + }; + + // Act + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + // Assert + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DownloadedIcon, packageItemListViewModel.BitmapStatus); + } + } + + [Fact] + public async Task IconUrl_WithValidImageUrl_FailsDownloadsImage_ReturnsDefault() + { + var iconUrl = new Uri("http://fake.test/image.png"); + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = iconUrl + }; + + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DefaultIconDueToWebExceptionOther, packageItemListViewModel.BitmapStatus); + } + + [LocalOnlyTheory] + [InlineData("icon.png", "icon.png", "icon.png", "")] + [InlineData("folder/icon.png", "folder\\icon.png", "folder/icon.png", "folder")] + [InlineData("folder\\icon.png", "folder\\icon.png", "folder\\icon.png", "folder")] + public async Task IconUrl_EmbeddedIcon_HappyPath_LoadsImage( + string iconElement, + string iconFileLocation, + string fileSourceElement, + string fileTargetElement) + { + using (var testDir = TestDirectory.Create()) + { + // Create decoy nuget package + var zipPath = Path.Combine(testDir.Path, "file.nupkg"); + CreateDummyPackage( + zipPath: zipPath, + iconName: iconElement, + iconFile: iconFileLocation, + iconFileSourceElement: fileSourceElement, + iconFileTargetElement: fileTargetElement, + isRealImage: true); + + // prepare test + var builder = new UriBuilder(new Uri(zipPath, UriKind.Absolute)) + { + Fragment = iconElement + }; + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = builder.Uri, + PackageReader = new Func(() => new PackageArchiveReader(zipPath)) + }; + + _output.WriteLine($"ZipPath {zipPath}"); + _output.WriteLine($"File Exists {File.Exists(zipPath)}"); + _output.WriteLine($"Url {builder.Uri}"); + + // Act + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + // Assert + _output.WriteLine($"result {result}"); + Assert.Equal(IconBitmapStatus.EmbeddedIcon, packageItemListViewModel.BitmapStatus); + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + } + } + + [Fact] + public async Task IconUrl_FileUri_LoadsImage() + { + // Prepare + using (var testDir = TestDirectory.Create()) + { + var imagePath = Path.Combine(testDir, "image.png"); + CreateNoisePngImage(path: imagePath); + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = new Uri(imagePath, UriKind.Absolute) + }; + + // Act + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + // Assert + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DownloadedIcon, packageItemListViewModel.BitmapStatus); + } + } + + [Theory] + [InlineData("/")] + [InlineData(@"\")] + public async Task IconUrl_EmbeddedIcon_RelativeParentPath_ReturnsDefault(string separator) + { + using (var testDir = TestDirectory.Create()) + { + // Create decoy nuget package + var zipPath = Path.Combine(testDir.Path, "file.nupkg"); + CreateDummyPackage(zipPath); + + // prepare test + var builder = new UriBuilder(new Uri(zipPath, UriKind.Absolute)) + { + Fragment = $"..{separator}icon.png" + }; + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = builder.Uri, + PackageReader = new Func(() => new PackageArchiveReader(zipPath)) + }; + + // Act + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + // Assert + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + Assert.Equal(IconBitmapStatus.DefaultIconDueToDecodingError, packageItemListViewModel.BitmapStatus); + } + } + + [Theory] + [MemberData(nameof(EmbeddedTestData))] + public void IsEmbeddedIconUri_Tests(Uri testUri, bool expectedResult) + { + var result = PackageItemListViewModel.IsEmbeddedIconUri(testUri); + Assert.Equal(expectedResult, result); + } + + public static IEnumerable EmbeddedTestData() + { + Uri baseUri = new Uri(@"C:\path\to\package"); + var builder1 = new UriBuilder(baseUri) + { + Fragment = " " // UriBuilder trims the string + }; + var builder2 = new UriBuilder(baseUri) + { + Fragment = "icon.png" + }; + var builder3 = new UriBuilder(baseUri) + { + Fragment = @"..\icon.png" + }; + var builder4 = new UriBuilder(baseUri) + { + Fragment = string.Empty // implies that there's a Tag, but no value + }; + var builder5 = new UriBuilder(baseUri) + { + Query = "aParam" + }; + return new List + { + new object[]{ builder1.Uri, false }, + new object[]{ builder2.Uri, true }, + new object[]{ builder3.Uri, true }, + new object[]{ builder4.Uri, false }, + new object[]{ builder5.Uri, false }, + new object[]{ new Uri("https://sample.test/"), false }, + new object[]{ baseUri, false }, + new object[]{ new Uri("https://another.test/#"), false }, + new object[]{ new Uri("https://complimentary.test/#anchor"), false }, + new object[]{ new Uri("https://complimentary.test/?param"), false }, + new object[]{ new Uri("relative/path", UriKind.Relative), false }, + }; + } + + /// + /// Tests the final bitmap returned by the view model, by waiting for the BitmapStatus to be "complete". + /// + private static async Task GetFinalIconBitmapAsync(PackageItemListViewModel packageItemListViewModel) + { + BitmapSource result = packageItemListViewModel.IconBitmap; + int millisecondsToWait = 3000; + while (!IconBitmapStatusUtility.GetIsCompleted(packageItemListViewModel.BitmapStatus) && millisecondsToWait >= 0) + { + await Task.Delay(250); + millisecondsToWait -= 250; + } + + result = packageItemListViewModel.IconBitmap; + return result; + } + + [Theory] + [InlineData("icon.jpg", "icon.jpg", "icon.jpg", "")] + [InlineData("icon2.jpg", "icon2.jpg", "icon2.jpg", "")] + public async Task IconUrl_EmbeddedIcon_NotAnIcon_ReturnsDefault( + string iconElement, + string iconFileLocation, + string fileSourceElement, + string fileTargetElement) + { + using (var testDir = TestDirectory.Create()) + { + // Create decoy nuget package + var zipPath = Path.Combine(testDir.Path, "file.nupkg"); + CreateDummyPackage( + zipPath: zipPath, + iconName: iconElement, + iconFile: iconFileLocation, + iconFileSourceElement: fileSourceElement, + iconFileTargetElement: fileTargetElement, + isRealImage: false); + + // prepare test + UriBuilder builder = new UriBuilder(new Uri(zipPath, UriKind.Absolute)) + { + Fragment = iconElement + }; + + var packageItemListViewModel = new PackageItemListViewModel() + { + IconUrl = builder.Uri, + PackageReader = new Func(() => new PackageArchiveReader(zipPath)) + }; + + _output.WriteLine($"ZipPath {zipPath}"); + _output.WriteLine($"File Exists {File.Exists(zipPath)}"); + _output.WriteLine($"Url {builder.Uri}"); + + // Act + BitmapSource result = await GetFinalIconBitmapAsync(packageItemListViewModel); + + VerifyImageResult(result, packageItemListViewModel.BitmapStatus); + + _output.WriteLine($"result {result}"); + string resultFormat = result != null ? result.Format.ToString() : ""; + _output.WriteLine($"Pixel format: {resultFormat}"); + + // Assert + Assert.Equal(IconBitmapStatus.DefaultIconDueToDecodingError, packageItemListViewModel.BitmapStatus); + } + } + + private static void VerifyImageResult(object result, IconBitmapStatus bitmapStatus) + { + Assert.NotNull(result); + Assert.True(result is BitmapImage || result is CachedBitmap); + var image = result as BitmapSource; + Assert.NotNull(image); + int expectedSize = IconBitmapStatusUtility.GetIsDefaultIcon(bitmapStatus) + ? 1 + : PackageItemListViewModel.DecodePixelWidth; + Assert.Equal(expectedSize, image.PixelWidth); + Assert.Equal(expectedSize, image.PixelHeight); + } + + /// + /// Creates a NuGet package with .nupkg extension and with a PNG image named "icon.png" + /// + /// Path to NuGet package + /// Icon filename with .png extension + private static void CreateDummyPackage( + string zipPath, + string iconName = "icon.png", + string iconFile = "icon.png", + string iconFileSourceElement = "icon.png", + string iconFileTargetElement = "", + bool isRealImage = true) + { + var dir = Path.GetDirectoryName(zipPath); + var holdDir = "pkg"; + var folderPath = Path.Combine(dir, holdDir); + + // base dir + Directory.CreateDirectory(folderPath); + + // create nuspec + var nuspec = NuspecBuilder.Create() + .WithIcon(iconName) + .WithFile(iconFileSourceElement, iconFileTargetElement); + + // create png image + var iconPath = Path.Combine(folderPath, iconFile); + var iconDir = Path.GetDirectoryName(iconPath); + Directory.CreateDirectory(iconDir); + + if (isRealImage) + { + CreateNoisePngImage(iconPath); + } + else + { + File.WriteAllText(iconPath, "I am an image"); + } + + // Create nuget package + using (var nuspecStream = new MemoryStream()) + using (FileStream nupkgStream = File.Create(zipPath)) + using (var writer = new StreamWriter(nuspecStream)) + { + nuspec.Write(writer); + writer.Flush(); + nuspecStream.Position = 0; + var pkgBuilder = new PackageBuilder(stream: nuspecStream, basePath: folderPath); + pkgBuilder.Save(nupkgStream); + } + } + + /// + /// Creates a PNG image with random pixels + /// + /// Filename in which the image is created + /// Image width in pixels + /// Image height in pixels + /// Horizontal Dots (pixels) Per Inch in the image + /// Vertical Dots (pixels) Per Inch in the image + private static void CreateNoisePngImage(string path, int w = 128, int h = 128, int dpiX = 96, int dpiY = 96) + { + // Create PNG image with noise + var fmt = PixelFormats.Bgr32; + + // a row of pixels + int stride = (w * fmt.BitsPerPixel); + var data = new byte[stride * h]; + + // Random pixels + Random rnd = new Random(); + rnd.NextBytes(data); + + BitmapSource bitmap = BitmapSource.Create(w, h, + dpiX, dpiY, + fmt, + null, data, stride); + + BitmapEncoder encoder = new PngBitmapEncoder(); + + encoder.Frames.Add(BitmapFrame.Create(bitmap)); + + using (var fs = File.OpenWrite(path)) + { + encoder.Save(fs); + } + } } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/NuGet.PackageManagement.UI.Test.csproj b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/NuGet.PackageManagement.UI.Test.csproj index c2049e335ea..7d097042db6 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/NuGet.PackageManagement.UI.Test.csproj +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/NuGet.PackageManagement.UI.Test.csproj @@ -32,7 +32,6 @@ - @@ -68,6 +67,7 @@ + @@ -79,12 +79,7 @@ - - PreserveNewest - - - PreserveNewest - + @@ -100,4 +95,4 @@ - \ No newline at end of file + diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Resources/packageicon.png b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Resources/packageicon.png deleted file mode 100644 index 0f7717cf585287b7076153919481e13c5f1b1d63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13750 zcmV;nHA%{eP)agRh9R-Z>g%@JL&8R z350zOpr|oOqOyoG;5aHSe4^q8sNjg`pn~9hexD;FZu7Y?3ND|>C$b5nsGtaf29kgR z35h`VgzhBWUEN*ld-s0luJ68Aud2J#U7a|l^1FGjUM>CVo^$?Zx#yfq7-MkY@%Q^6 z2N>W0100xz0}OEB@psDrhaYj&fm!%Fet4t3;r2hRJQy+Jjf}GM@VJ6%z(C}n6n;k; zy9*e(^JR0pHy)VIseepVfa@Xv622R0d_%zKyQ@g)5Gl_n0F|^?|KS%90xl4sA^pAs z&gHK>X!^hbviyxRz@2}3Y(t~P&mAe!SU@3 zj=|vqk{@6YLiUf#7tj3d0n+@9GQgcHAAfg1=}n~|gcn9A{9rSK=Y|1FA%kj&2*9N9 zJIDnYe18_HzPJtG{CNx(v=H!!13|g+=1b0f&Fvf3uRCC2?&l2P_Vmm!PwrUx*og@B zw;=Iz5BG)e)eRK33{%LLDU9GKAO{pH6v|-;)hdHBGD!s)qrXJq=|Kh^Xi?0}AR4&t zS<7F4?gOhIynp+i-MbD@sfiDpetYw9>?f468<4o&>jp!(>A3*<3jySd0Sw_7DF;w0 zg;1^pP{w1iRD}Y6tx$zLzHdi9gj=2uU;`e}PUvdy>i#l*rH>p+4v=a8eHaF~{f{fT zvA1Hd62iCESE0Wc3gVBH0;u4%5T&1@#Iq{Jf#)~^yk5cAM~YR!2m{CnKiwF@a6rNF z{bm35qubufQRcuj{|zue$k=(+5dFIC0rZUoDBV>kl_lX>5C9_2R9QApupb%1E6vD#sL3&pm6coj;8BKH=(18QLZe27pm_v<;aH~|^Dcr>(#t)qT? zQ1NaRK~VH$cqHn1D5HgpI^td8Qc!gj0+8s#2Oj$s18@WY&*w{nz@flFX(oaRSVVji z{?!C$iV5VA;B!J8a2SsYG7%n@d?6TxsBz%2KQaIsa09N#U{0$8J`2G^G1g4Ls6~7& z^~92TO>fNA4+pEKE7<;^ zW$NDoUnqM*z5K*WW^@ni7Yx8}xinJxG0A2xUN%1mt2Py&fWM-GD8LbbazZnW;Kb7A z@|uI^zT-d+M+?Hh@q0wi`fCo+!Z$b%>1pI?DEB>~DP7%~<@ zOn`=C`0OakPN-TuKHfVZ7y{+zLHv7nzI0~y6Z?z-Hg8z}jYEz-{^CQreK>J;1|Hp5 zfxwkBAr^szt_P#@^)w;!gYO~X5dzv#>R&oH2ZvA3fQ#?B@3vcijBl#)v0?o>IswAJ z8|RGYBfL=%9KW0Lp~$qgLWD!oS0zxQjVa0M5W88pVe>*4&UUAZD2a15)8i{@(2eHu z3VgZ(nc|w2FA9dZ6YZ(*pE7IO@1}wQ?A5^R^*_1$3oTvK{&}ESg&SAyhG%|+;h5PiaOo?1peyUai<>un=TjHH;~V(a-FzSel*cRW zNc79`^fDxNwvd*G>^MJVFA zTn?5@plm+yTnDl!{cRZ+PMF^c?>%KYbYwgTE9Ld?f8A@|hHo3e(TigU86X_X4Xxfi z(2XK42p>9*Ap9UYDSs&tcnZI*Kj6~NK-;ENd8$IkDC!%!E4S6+gE2Ay87Uc(!`Vl7!OIr4Lk3|XD3;fM`Kl{E z@XVT3d>wcXA7hn%B>v?{q-!|g8M>64QNmXZ5m;X&e650q8N{GE289!3oD{01pBb+e zSc06amb8kV9EpF9D6M4`vqNG-#g$T zL+swM@WaGMi?F#{M{3O{KGBZ`oiZQ$IBHC`O4)Pt_S^}{_HhE5YGMZ<>%pd+!VS_cYzXk zG*961AtDGJ(1`FHjY64-Do}{3{6wmVtfihZE$J5YTb5q4Yypxyw?ZVuLIuqXj+sBj z3`8OV7bZs`0T(KMY(+#^-c8}yHpv7e2>x8HR^Id4L+7ts=zoEgr3%i9*e zZ25|pwRd&T)4o5y`TRitj@!O_B>A{||$0M9wl z24LI^pqAms)H&z?5lacsu*r7;(^P;hDaHs?L3e4K!CapVJ+opo#NzU(Gcc7pi#?TLsl zC0|N9cQ*sY2-*gq3IQT7fC+=tNI%H@14b=k+iJiPZ#E9=j*USR)N}QcUV-iY5oP#A zsHouHK6fl85H^9d3p~XPr}tP)P#F2Z$NurGaWlb$OT&=xbzjr4ZxR0nAns)${+eIy zCh#PhidDvgOq%#S)}Y{CF@a1wpvn-GMjut~Tip65F%*v@I;jKyBz}#JPuH`A!B@io z3Bym@0Ws;fhJ;&U2reaGooj|rOyMiL;I+sEN28MFOfWLA=d4e@{oG%VhY6a-0H3<* zYGN-QzTx7JUWml!*1jQrh00ok0I@w#A!n}tH8Tk4*KVND`SRRId8AdVNwKSA8aO^W@jx&FER;G56BUUQ5C6WRHUBs6tj?@3v`gr`H^4agQ}w# zJX{?rVHv8SjZA$#`FiYqVC)e}Yp?0|(lGHli|&J}ScZOo#PDF^9f1yd zh4K5XhSCm_s*;+dtpb|izv$x&VL0EJ%yD16c*_;A&(#7mA7DBk!--Nb17S&`8euXQ)4>luHv;fn zJHQcb1ZK@$a6P__XJnTf*#q9>N`KrS_Iyt)>})OotR7TQr-?7%Ih2wfMu?y#mmiIU z7Dm7;7GQBJgGKEQ%x?8y!J-z(mn*Pg_aN*kGk9(=gzZiXgdN>#_K9Hz=@TkOP`Wdn z=#!VWXrhmGa%jOa06BrRe;o+Jj;R-{2ojAjn@|$7F*xf7+(^Xh51~DU)QqD6Sk92d?!az1pnX2lXTkC$s{Voak-2&*>lhM%tQg})TDP-*W{Z*UYMSoWTd z2oaV*0XAVKAa$M?MqpNEouaX$_>!tnu=I48u<*H*vrt~w#vgH5^kI&1T;&Q?05DJ{ zuqF?%Y`O!T-P1mWmu^;Jde&41(Acl1)ARhR1N>#13Jf+Dw2`CqJ+&--VazG14`d?> zuCrli5YFnMaQ+GNp}Q>ySgh!w2g)cv~3wn7J zyS2^2T?-8&GK^!Te|&)>lRLpR1(T}+)bY&sT-1$xc^+rGM+dZZYen}$ zZMlcaV%OHYG>W=PL-5YSd{}`5ZSg&kci_9O41TyoEuTjIHw9@~2WV8~&@OoG(evQA z`31Q0w>#jO5uC)fHa%@}`t3lro#WV~#C4Wr2Cx#X8I!Ici?mdXKQ-YUNo39~+|ZMG zg>u!@p|W2?$fOHdz>BN%1YU(G(9zxf4*c}@lp3f(0e7PH<-Gp?YJ`7V`j0vFRUf3p zId5l$z=OM0bT8nwgEWHsAUYc2BN{j;`5!&H4VE1~8``oyw4mg-_%7spb;Rd91ucu1 zm{G$QMdCd%(Xu$EFrhfUVwkpENov;@tcW5&gcNqP zRSU;33ff8C4zy&v1+(VPy?xcgzwfgwiRQV1>Xt5~cy~|bwGT}V>+X^d2Qx% z1rVrl!poOl0(I&$oyq2CZv5f>F5z?gbY9(%GW4is0#58u2WJ%Vkr@upRp4zeIS2_U ziQmSFt0bQjo#!74$;azF6FC|Z5%`dZ;R#0J-*fD|>2TJ}0NkMgFf(lDjIlJTObryo z)-06aCs#9>iCYN!#tKw1E4UPz_=dG$X2m%EI>gllftI%RrD`?Topc7^)_;r-9Crl| zXL8rCp!|Mml?E6RwDs3xez*%$e4u!R?ehmmJK5k z?EGx@=nFsg@gve~K4(%S-wL!K4VH7)Z%a`HZbW2E5u7TxXI6wPl##rd=;PiqPT)KbD(&f^pu0jQF6Y2Aa7b{goLl{d;R`}Zs3{keP1_HY7xK5Ed`y#sW?=} z;VHA?@>2StT!!NgY8Cq1S48I$%we63gZRl+IL-k4Z*#S?Tp!&>Y7FZcwv?&OX$>o-C z@3gP1?JbqTqb<}hf-l46c-^g5V0v3dNv$KIeVzjn z>mWg$0aJqv%v$4)c?RY+HFsbq$5>fXMqS9y4^-uQTiV)Au^6B^2!J;oqE1LI`mF`RB(x0G#X-`3Z-A zrlj2HC2in@EV6nP0x;CmrAiPLNH~)dk|VK#3u60QQMVI2tE6V^Lu63+&eXleK+DXh zHLtN4f^8o#L}YoRSA6kH%O;fpY7l_&buAM4v^2`yiipn4YZ|WH)^=F`V&3G%83>=G zB}%b;Di)!rl_qQv7aFO830nAL!Tfq&fu1XKPSv?G6g3mX-fPXVdS23syp;EuyRvgtPDm>GkLu} zI0*ge`97#-TjOdVRxf5pWSSHa9Pih%#L5wk;seaChN?jfD{Y?V65_;rQD!7*76LH) zM>4HfLw%zp9_=!7F7M^fJ4>Pry(7mI!%Tc}R;P~h29`fwy%Q>#PUS;cMjuI;?ERsi znVJHf!(wiWO6eDN0slu-Ed+m$8^sVbANv7?Oh}+!ir|D0;MQAjW$6sd3{+8dC$XBn zn7Wk=GJpo^cOTv$`x5c6rp4(K5jM_D+xrXf$DKi}vq`LCG#LkGDc2fVYU3JXvUgbWrT5^e2-`=2ks_B|seOE#cv zuYi~t>1R;D3HZXVo`u~kYrVnF&agzRq4l0-tnH13-{5;1p+OC=uo$1lz7FTkg^trm_qF^S*V^Uo1mK6pKVFTWq}04QY!b- z=4Uj--)lENqzSVAobosY!#c%NrxS3lK%OnORKQmR=3e~9`)II!- zwF7?mR33&Ze}-%S;dq$d+5%aeDNpuOF@=>R1@iTgZ*K9Mb=%-0zt|4Doc6|0MG_E9 zni=h5^)HcnHZ?I7M+_3Vt9At}o_qMad6!mEGp6k@#!}LdCJ_OyyYAXVZImLcnN%x3 zzvgHsHaoynjH24o0Y6(;gm>P&3RZ1;5e7?DR0*nxL?w}M^`M8YmMJ3l_YD={;#*h2 zd+yi76_j))-gm31N^#9ouB0!o) zsGBy`7(0wWqDarm+b4(wU9ftf0&n{MI#@c_g^QLgf@O!zmN9+DiRJWi&tct;e)#UA zo8b2^jKKDa2Vq;674#wr_bwJ~kJN+C*=81=v3kfSLC>LA* zG@cNO`ku%{i1bkQ)H8rwuwZsPKvnO=)3H@#l29e7G?G|O3_lAcF9W~bL*Wm%Z-NfG z9u{`_FssuO$sYW%Yb1bP9NWtt6x;@dX(5Ww>a`-WqfcIohZA}gUL{e{~0fBg1d`K8JjMYJbQN+HH zv;)MgWRl2J*C6F++lKn$6ASv3Im`KS_}AT+CI%&|JePhpf~TM=qqV+n*HBqq_M zf{-tW?^sNo65AR>5M^>z03j)^K)u#XMBBI!^&e*O0z(rEWwpikKx$DSSye$u+R92w zs}B~3EtViOV-1jijcxiqwE3IGDDoZ(IAP}O?jmqX(Vw=Uq7cwf7~*iLrAgS z^?Ou;gS}mjorariAYd8+BwL(XM^?vENY*i+Z%>9wyse7K4~W{N)bUuxV4^g~2qcNP zy0z|JtDzHXRJL9==d8YuZlv9|3li6Wr38Ukx<16utW~G`m9?jKqe@{{B{DJ zEe#BwkNXRXN0SuKx*j{j;?6*LeX^Eqhec!Q?V#1?Z2>U@)Kv+X;g#^s9 zXU6CYHirQi)Gn#TBp%{+K+H9B;szNcKi9~uA^>RxRkpjSnTtZoB2Yrl$Et?np*Ocu zfNrM@OJ@7<@~}Hb;0?@c=8>wA8 zPEGh=={8Dwe6^PFg*?p51@MOBJK>Bai=e9|3t7)IjhuA*SJNTOT88Ds=|m z_0h%7xrFfHj8ff=MrdOVAC zYS#j4er+J6doK!;#%2cB)kBZ9YkDPuayzS*9aNTXsz^WY~ z(3Y;aTg$V#92O3>{sl^~bYF9jAU#Wmtyq%8jF3}X*p^*+_DN^5PPnab1r@}ss z73aC7Jgivc!4+p84(&M(_e2z@W=*{!k#!8JsdLl`yv}MR=$bxc1Y{sxE}s<@&Ykd; z3r~Wt{`_gUYi%CNnGVGOj;sU`zt>4tlqMvf!I%wzW*UL4CLT>{*Whac7HKFj&ILA- zrg~B!Cr12~ylWhp@-UotOcvg^;!tSMW}=!!KPp!B74$o%b}{lsNKKrG84#k5T;dM+ zCL1mVKa{0xzMF%OpLYVxnYJFj{ct~&`BJvM^`Z`&yE5D!KHEPNo8QUTYtCNwyMu|`B@3yNenU&329EKH#WZ=VR9xjM4dlbmt16kFR zz*7aNHsME`cDv?**?~^JNd#vmDmUKLYUF~`j)b*a*TDUM9R$|erD6a&-`=T>QP@Uq zT3&cFBY~spTn4cO1yb(=6ROQmOP+(Y#==%K&o0ZAEj|zKWbolL4mHGY^&QiuhBE-) z8;QfeGfK(&Xv|=LURE+Y0$p@l9PVO%{_Q8iF+E78plTSE7L88=V4KT(MEtZ~WVSjIE5#Q4HI$WEp48z6CXTi+Q7Sm+HK))-Aq+LB{ z5~`PyjNt1|C%nrE{_XD8EL?fsVbDfP@mg?}2pOyG=FA$}7?-LYn4(8K5X&0qd@{JTFr(!O{gTymaww*{DLnz9v2=4w)pvH(~@{#F{}S%c&knC*%FR z?&zFQO=*EDV)sgCb=C)_k^$lsBK2-8(ZHQ)?q!gY2{DFIXDK(fqXdgrPDGWfV&uXC zy!X|ML`RXF?nuTV-;=Ihvxp!2wKfy*O*!%J^Ik`nzV0aK@vAsLw8mX!*1Qrm*M=bo zYk0p?U;|j8{S+6~c4Y{gNXwRlvz>&=WYJv8zH>_#W#OQn4ylXP$hb1d<20H0NhTnw z?~(6GyI{_=Hh9IMEx^jR;j@~VdNSCwK_u=BRj)Y85s0~xwb(S@5bvzM& zY8e1(Z^(|yl9+Ukf%pw;C+Z*rO}Kw{Go5JPIhd0T;3bP^%HWQP@Tuq?OnnWp-R4HD zH{gE@XLi6L)7==F5oX%}S_QCClc}1o0-$~{h5$=h32b2fk6Koj5^rFvcE?DX=(l2x zBj)5pn_0~OVsVE=ol5q_BiZJL+X9Eq&YAKXViIkl-)xeF#Ev8^v0KsPh}a7L2}{@nW0v?v@qm;9k7RmRA`L4O7U7VY?P|Y1 zX?#UHdhRRo$5FslcEL%9pqdIQv4D`COYK2PwGdagQ^o)+VFae#MBV-OY_DLi+ia!y z{xrFIrX@cFsFZ=^cM1KkyOgHQiTpwT)Bn}W4~w8> z!!XXhj6!V>pYgIDgZc>`L4ZWB0#vK=NCOf6&2h-r7Qb#yw;vF{CP?JScm$6SREWArq_EM3zhfo7*|sZ`L^gZQhRTHsqr?z3aRTz#6A`(Zp*IZQN|{c($+ge?5I|>v%`csVS{huQ3+eTVP5U zKyGovz(a@ z;~@h$e8Q3P4&U-DWTp`^Q>$8fI~6u2HIP!rm%3J-zBW;=RQI|U(NsTp7EuWWiDX!< zN>!>tpqPyk4Y*)(+r+8K@5(wUR;=j*Vx6Z9R>vk7mkTn=YYAi2$+W@~&-F&lm-aKF z+xIh2C=0|C>E{sNeA=<+mq=HZXOGQjm#OLbfq{He8K7J)Kgf@rIZ{Jdhec@Mu-ZZ{ zV+SDy}T!GQ2*lbEkJUuQ6FT8C#1SMy-e*$J_~8V-%BYSf|UKXCzSy% zIrp43e4hF8WiF!$9;pDy2rLd;G5As_KrBnv*bsXg5>87#VKs*0U$+j4N}bT|xwjvw z0DeEEN(j$x8;Q@Gqa{C*cu|+gpCbp%>U7227YidB6!F8RF@SK)g5Y6Jv<2Osxk1;l zxK%kO4vCn;Y`h?+h79m${uk#@cMV4x*MvlHpDgIs zszTZb%z7=#ZznJoX=h_=@{~Y;0QKt4_dX5fYN$40f(dmhom}{5P)7CimAn27ft!{3 zUd@-Q@&;T>4MZhs0Ef=@h4}RC+`bOgKvf|?b8LVO>({YTsq}k(e#lHe234+Q2e_t> zKe1l3m>{MSNKKS$TqsaCHjwa%91k8_pNHpn_Ny)K1-LFT5lueF-E9sU?c~uGShuYNpZne;kT0ly#gs<7olTL;CtKcD;Zrw10&BOH!O!MYW)SLl zq_SWJSLH8gCQ!Sl^6Mup$_lg`*uCq)ryhU2AL&s9xq~<~8v*zu7~He_i(F5?^w1VT zTu=F?+Eo!1wfv}bzNeOAjcQQu)yuOQ9fX%aQlf}VH=DKc;A)V7jks0gJMaF{55KLTzm$akW->td#G`+>gEE@$#G6@iaEnEFVi_(FLxzY+q%ELT zg{y1=H|9YoCNRf{9pY}K-FdD)^d|z>5cq9y>ub>n}h^0;-f42 zwR_gUx9;5xkZq6lMRp@;7kZx$FX~a?D`W7?CGA4`_w@DMbKlQy+k$gbO!ENv!|myr zF`*mZvwK(SwXGZ0mrgzF4MQz$9cRz#a$)V3vRKtM{eu&3nd%uDYxYGL#1@XgEF{Il z#iWMNkxDS`qkV3#Qr5Jsjs_(jta*ATJh#0MPCIDem`+?y?ST06irWhJKDq-gxb7G5Lf-%sP&#?%@<8p{8BPEVm_>ZvE@sQ_ zJiP1r`{C9HcgBd%hpQysS4`lkT1C%M2;dQD%eipo2~zrdcWk@m*LU2$8GrAHf`6KJ z4^2S;b)DgNvn5NHZRzfrc|H$H>>diBe>jZUX*Ed;BwjV7lOc#D_eA#qRO<>gD3FF4 zq~7v$Y|Dz8*QM^s!1lfo`1$Yu3L`-Yj$b@e24Jkt-jSWzIHANqJw%<(M^MGw`p~m* z<#$%X`W+SUT00cHdx`-Z!3@6dN$KbHisIZ6QqQk(ra0}GHh}<)(V?$=`qNkR?c6b- zq`xrb3?NnoduGswe)01yr=9c0IoVvxN%MPrcz$OEDgm?XF$Mjsw#P-R+plVcX0I8T z$beQ0rdfkpb4WCAa8h#;qWD78qAyyYFe{X<4~4*kKmB<--1G1T7!JyC)WYdeKS~x? zZ*_~C6!A-lBn7ncZ+&PTeCDP~!4MhI zuEvEU=jUL>v2EhsS3msFr_uO(8qf2{Z22_n-|*| zvq$v~R^gtNgUIzEx>!s|fC#wo)G*#Pi-%wX6^ad|53Y|?HCHklB{OS}VtXGwy&svq zw~iGZWQhzR#;En0y??v4cEaMhhE8<^=Av!0l2ZyjV0N?ErxQ_@22v z8F=d}yC9cwpm+PWTP}a=TfT&Ub_hSWt5T`t>q-AqF#w;1?D>~`Y{{~-&-*p{upJv; zEW>@P@`?cz;R8u%?sIeBTXfM1L0prIGb|#$j??R z8%BZEIKnUtRfQMKFc{JOgitMHNC1l$cEa?IEOd8e1Ti&m@p~;4tI)Tn1e8_fM0J%;=g5CH_Ynx1@W)H@)I9?X3gr| z_;>m1;4j2T@%bm9-#+*gV8u4Rll%C9%N zTtRA0`nFDjNUSj0M;TZmvFKy;+)=?M$CPCAYi6;9NWwTO{_d#f;yp+}$8pRM&qb6@ zN9t76PC&YZbAHYt-F3A!uZFKJeBT&#^5_Yj@9Xw->U}*O9=z!lNc?HO$o9GKwx3?{ zz|ZgIK7Ss+zrR!}jY|9}V*r~89=i9gwI?n;wZD7%jMHa!yRdjp7G8K!#t7_mF_X<| zCyqFFB8gSRA*3lx;i&bST{~seeNjOb|kU2VdtrH zoA8DKJPGkq$9qD@3k1k`BETbg|IydK_My9e_=D$hUPtin z^mlZ03?uRfW2MQI*Z^rpA&#zheeBAm%g%iLe|Q;x9yh}tTQ>qLpB+&fMk=FF8-bzR zB90dW>D4(=0jBhQloZTj8!1NFz1D`*R;zfO%FdEC1d-(k3~H|ts}Fjz#En?n71%ZY z#Gs8*DXvQ15KN*%y`0fRnYuy=aa|gFXPw*$ht1E5l<$$@q19jc^i>~!dey1{P5fLg zH#9UfTp7>m^^`L}f(bfKKJ~PP@Ba9wzSPmx{c3*KefcUp^p|1S+FOoXLFFn+V^Fz% z)H438OkQR&0FA8)S&gb=ff-iYU(aF!R&!m4t(n#JBr0Yw0Vq2*p^5KUj9{#PdqGDd z3NgVS&Jf3;)Gt52L%4bTyS8n7;l@wC>w@p#@2=qUVf>DP*4EbH!NI}mcvBbl2?JP6 z;N#$1dv<^RyFd8g{DT)?j1$noCwJ|p60Af-=pPAC(wRX7?GkEtkS1aQwJ`xJ4q&YY zvPAci`0MfRBCMv#G)qn0jICo3E4buD<>s0RTvsJ^D5-aJX}YJ8z=4IcvatMw4q@f< z@2&>H_D6nw-*q?s@Bj5U{^l}%-w>k5V0(M}$eulWg1yOG*=G!3F#&g&+i-L)dBxIs z7k%QYtGat;oU6lYf8Ab&C!Z?_Z^1Bt6%UZ5gH&~WOU451^nesX$I!rDpi18uD!vPA z117ME4^is2VFaDGr-v6Y09OmgE^3974r@iid$O%8qeDA3Z~h5N{f+pWIiX9++Rt}) zbroOi?G5&p2K$r&EJol=kmD+WBfS1E!6x#R!mKfLdvfU5qhATvsrt*^XJouxqxbFiQj){w)tjr@y(jhvA@Z&%vSd z_{gGxC%1!RR1*H?8~**4wNI?cbI4ago;>>b!!u^|R5owk5>909_X`F{sDu{92yJJ- z^=*f|{`_}b(mkVRh2yv#+8nD?7;M>9fnCT5TM!vaWeUB6K`rzHYuImsK?5d8t4d{c z`tY+_;zM%X!HEpQgJxv}k!N*hV8JXO4w{)Y%p$UBg6fXmZCmfT`GzmwvUbgyJibsx zcdv-(G2*!Ha7#-|Y2m_yg4=&~8=WZq_8SIBL=Cfw5x8n-<vz7jUdEm!;qg5M)b%62@0WUdrdLm0wv1k@w(0wC#{d=@a7M@|)zGRKfqg*Pi4})-c z&#t~zy<4|!_{(D}*WZ8lUEAflkj^#b0KYXZGtDN|hk8Cy@wzs#@uC6Yoi4Jun{_mCn zQkWrxlr-nbdR%?=HKP*xsi&S6@9FI7B#jJ!e15RT&OGk8V_7|0 Date: Thu, 15 Oct 2020 10:40:53 -0700 Subject: [PATCH 003/129] Save RTM build symbols for publishing (#3714) --- build/symbols.proj | 3 ++- build/templates/Build_and_UnitTest.yml | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/build/symbols.proj b/build/symbols.proj index e8bdf956b37..c4cf713ff42 100644 --- a/build/symbols.proj +++ b/build/symbols.proj @@ -15,7 +15,8 @@ + Targets="GetSymbolsToIndex" + Properties="NoBuild=true;"> Date: Thu, 15 Oct 2020 15:03:12 -0700 Subject: [PATCH 004/129] PM UI: propagate remote exceptions (#3711) Fix https://github.com/NuGet/Home/issues/10034. --- build/packages.targets | 6 +- .../UserInterfaceService/NuGetUI.cs | 80 ++-- .../Services/NuGetProjectManagerService.cs | 373 ++++++++++-------- .../Formatters/ILogMessageFormatter.cs | 371 +++++++++++++++++ .../Formatters/RemoteErrorFormatter.cs | 140 +++++++ .../NuGetJsonRpc.cs | 30 ++ .../NuGetServiceMessagePackRpcDescriptor.cs | 10 +- .../RemoteErrorCode.cs | 16 + .../Utility/RemoteError.cs | 42 ++ .../Utility/RemoteErrorUtility.cs | 67 ++++ .../UserInterfaceService/NuGetUITests.cs | 77 +++- .../NuGetProjectManagerServiceTests.cs | 30 +- .../Formatters/ILogMessageFormatterTests.cs | 96 +++++ .../Formatters/RemoteErrorFormatterTests.cs | 49 +++ .../NuGetJsonRpcTests.cs | 89 +++++ .../TestUtility.cs | 95 +++++ .../Utility/RemoteErrorTests.cs | 87 ++++ .../Utility/RemoteErrorUtilityTests.cs | 20 + 18 files changed, 1472 insertions(+), 206 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/ILogMessageFormatter.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/RemoteErrorFormatter.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/RemoteErrorCode.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/ILogMessageFormatterTests.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/RemoteErrorFormatterTests.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetJsonRpcTests.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/TestUtility.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorTests.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorUtilityTests.cs diff --git a/build/packages.targets b/build/packages.targets index 53021570cd6..873850ccb71 100644 --- a/build/packages.targets +++ b/build/packages.targets @@ -6,7 +6,7 @@ 16.6.255 16.6.30107.105 16.153.0 - 16.7.54 + 16.7.56 5.0.0-preview.3.20214.6 @@ -27,7 +27,7 @@ - + @@ -62,7 +62,7 @@ - + diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs index 24c3dc89f52..8091ddeb647 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -23,6 +22,7 @@ using NuGet.Resolver; using NuGet.VisualStudio; using NuGet.VisualStudio.Internal.Contracts; +using StreamJsonRpc; using Task = System.Threading.Tasks.Task; namespace NuGet.PackageManagement.UI @@ -357,36 +357,45 @@ private void InvokeOnUIThread(Action action) public void ShowError(Exception ex) { - var signException = ex as SignatureException; + if (ex is RemoteInvocationException remoteException + && remoteException.DeserializedErrorData is RemoteError remoteError) + { + ShowError(remoteError); + } + else + { + ProjectContext.Log(MessageLevel.Error, ex.ToString()); + + UILogger.ReportError(new LogMessage(LogLevel.Error, ExceptionUtilities.DisplayMessage(ex, indent: false))); + } + } - if (signException != null) + private void ShowError(RemoteError error) + { + if (error.TypeName == typeof(SignatureException).FullName) { - ProcessSignatureIssues(signException); + ProcessSignatureIssues(error); } else { - if (ex is NuGetResolverConstraintException || - ex is PackageAlreadyInstalledException || - ex is MinClientVersionException || - ex is FrameworkException || - ex is NuGetProtocolException || - ex is PackagingException || - ex is InvalidOperationException || - ex is PackageReferenceRollbackException) + if (error.TypeName == typeof(NuGetResolverConstraintException).FullName + || error.TypeName == typeof(PackageAlreadyInstalledException).FullName + || error.TypeName == typeof(MinClientVersionException).FullName + || error.TypeName == typeof(FrameworkException).FullName + || error.TypeName == typeof(NuGetProtocolException).FullName + || error.TypeName == typeof(PackagingException).FullName + || error.TypeName == typeof(InvalidOperationException).FullName + || error.TypeName == typeof(PackageReferenceRollbackException).FullName) { - // for exceptions that are known to be normal error cases, just - // display the message. - ProjectContext.Log(MessageLevel.Info, ExceptionUtilities.DisplayMessage(ex, indent: true)); + ProjectContext.Log(MessageLevel.Info, error.ProjectContextLogMessage); - // write to activity log - var activityLogMessage = string.Format(CultureInfo.CurrentCulture, ex.ToString()); - ActivityLog.LogError(LogEntrySource, activityLogMessage); + ActivityLog.LogError(LogEntrySource, error.ActivityLogMessage); // Log additional messages to the error list to provide context on why the rollback failed - var rollbackException = ex as PackageReferenceRollbackException; - if (rollbackException != null) + if (error.LogMessages != null + && error.TypeName == typeof(PackageReferenceRollbackException).FullName) { - foreach (var message in rollbackException.LogMessages) + foreach (ILogMessage message in error.LogMessages) { if (message.Level == LogLevel.Error || message.Level == LogLevel.Warning) { @@ -397,10 +406,10 @@ ex is InvalidOperationException || } else { - ProjectContext.Log(MessageLevel.Error, ex.ToString()); + ProjectContext.Log(MessageLevel.Error, error.ProjectContextLogMessage); } - UILogger.ReportError(new LogMessage(LogLevel.Error, ExceptionUtilities.DisplayMessage(ex, indent: false))); + UILogger.ReportError(error.LogMessage); } } @@ -411,30 +420,27 @@ public void Dispose() GC.SuppressFinalize(this); } - private void ProcessSignatureIssues(SignatureException ex) + private void ProcessSignatureIssues(RemoteError error) { - if (!string.IsNullOrEmpty(ex.Message)) + if (!string.IsNullOrEmpty(error.LogMessage.Message)) { - UILogger.ReportError(ex.AsLogMessage()); - ProjectContext.Log(ex.AsLogMessage()); + UILogger.ReportError(error.LogMessage); + ProjectContext.Log(error.LogMessage); } - if (ex.Results is null) + if (error.LogMessages is null) { return; } - foreach (var result in ex.Results) - { - var errorList = result.GetErrorIssues().ToList(); - var warningList = result.GetWarningIssues().ToList(); + var errorList = error.LogMessages.Where(message => message.Level == LogLevel.Error).ToList(); + var warningList = error.LogMessages.Where(message => message.Level == LogLevel.Warning).ToList(); - errorList.ForEach(p => UILogger.ReportError(p)); - warningList.ForEach(p => UILogger.ReportError(p)); + errorList.ForEach(p => UILogger.ReportError(p)); + warningList.ForEach(p => UILogger.ReportError(p)); - errorList.ForEach(p => ProjectContext.Log(p)); - warningList.ForEach(p => ProjectContext.Log(p)); - } + errorList.ForEach(p => ProjectContext.Log(p)); + warningList.ForEach(p => ProjectContext.Log(p)); } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs index ce243930d23..29634544ca5 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs @@ -15,11 +15,13 @@ using Microsoft.VisualStudio.Threading; using NuGet.Packaging; using NuGet.Packaging.Core; +using NuGet.Packaging.Signing; using NuGet.ProjectManagement; using NuGet.Protocol.Core.Types; using NuGet.Resolver; using NuGet.VisualStudio; using NuGet.VisualStudio.Internal.Contracts; +using StreamJsonRpc; namespace NuGet.PackageManagement.VisualStudio { @@ -218,38 +220,51 @@ public async ValueTask ExecuteActionsAsync(IReadOnlyList actions, cancellationToken.ThrowIfCancellationRequested(); - INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); + await CatchAndRethrowExceptionAsync(async () => + { + INuGetProjectContext? projectContext = null; - Assumes.NotNull(projectContext); + try + { + projectContext = await ServiceLocator.GetInstanceAsync(); - if (IsDirectInstall(actions)) - { - NuGetPackageManager.SetDirectInstall(_state.PackageIdentity, projectContext); - } + Assumes.NotNull(projectContext); - var nugetProjectActions = new List(); + if (IsDirectInstall(actions)) + { + NuGetPackageManager.SetDirectInstall(_state.PackageIdentity, projectContext); + } - foreach (ProjectAction action in actions) - { - if (_state.ResolvedActions.TryGetValue(action.Id, out ResolvedAction resolvedAction)) - { - nugetProjectActions.Add(resolvedAction.Action); - } - } + var nugetProjectActions = new List(); - Assumes.NotNullOrEmpty(nugetProjectActions); + foreach (ProjectAction action in actions) + { + if (_state.ResolvedActions.TryGetValue(action.Id, out ResolvedAction resolvedAction)) + { + nugetProjectActions.Add(resolvedAction.Action); + } + } - NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); - IEnumerable projects = nugetProjectActions.Select(action => action.Project); + Assumes.NotNullOrEmpty(nugetProjectActions); - await packageManager.ExecuteNuGetProjectActionsAsync( - projects, - nugetProjectActions, - projectContext, - _state.SourceCacheContext, - cancellationToken); + NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); + IEnumerable projects = nugetProjectActions.Select(action => action.Project); - NuGetPackageManager.ClearDirectInstall(projectContext); + await packageManager.ExecuteNuGetProjectActionsAsync( + projects, + nugetProjectActions, + projectContext, + _state.SourceCacheContext, + cancellationToken); + } + finally + { + if (projectContext != null) + { + NuGetPackageManager.ClearDirectInstall(projectContext); + } + } + }); } public async ValueTask> GetInstallActionsAsync( @@ -270,69 +285,72 @@ public async ValueTask> GetInstallActionsAsync( cancellationToken.ThrowIfCancellationRequested(); - _state.PackageIdentity = packageIdentity; + return await CatchAndRethrowExceptionAsync(async () => + { + _state.PackageIdentity = packageIdentity; - IReadOnlyList sourceRepositories = await GetSourceRepositoriesAsync( - packageSourceNames, - cancellationToken); + IReadOnlyList sourceRepositories = await GetSourceRepositoriesAsync( + packageSourceNames, + cancellationToken); - Assumes.NotNullOrEmpty(sourceRepositories); + Assumes.NotNullOrEmpty(sourceRepositories); - INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); - IReadOnlyList projects = await GetProjectsAsync(projectIds, cancellationToken); + INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); + IReadOnlyList projects = await GetProjectsAsync(projectIds, cancellationToken); - var resolutionContext = new ResolutionContext( - dependencyBehavior, - includePrelease, - includeUnlisted: false, - versionConstraints, - new GatherCache(), - _state.SourceCacheContext); - - NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); - IEnumerable resolvedActions = await packageManager.PreviewProjectsInstallPackageAsync( - projects, - _state.PackageIdentity, - resolutionContext, - projectContext, - sourceRepositories, - cancellationToken); + var resolutionContext = new ResolutionContext( + dependencyBehavior, + includePrelease, + includeUnlisted: false, + versionConstraints, + new GatherCache(), + _state.SourceCacheContext); - var projectActions = new List(); + NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); + IEnumerable resolvedActions = await packageManager.PreviewProjectsInstallPackageAsync( + projects, + _state.PackageIdentity, + resolutionContext, + projectContext, + sourceRepositories, + cancellationToken); - foreach (ResolvedAction resolvedAction in resolvedActions) - { - List? implicitActions = null; + var projectActions = new List(); - if (resolvedAction.Action is BuildIntegratedProjectAction buildIntegratedAction) + foreach (ResolvedAction resolvedAction in resolvedActions) { - implicitActions = new List(); + List? implicitActions = null; - foreach (NuGetProjectAction? buildAction in buildIntegratedAction.GetProjectActions()) + if (resolvedAction.Action is BuildIntegratedProjectAction buildIntegratedAction) { - var implicitAction = new ImplicitProjectAction( - CreateProjectActionId(), - buildAction.PackageIdentity, - buildAction.NuGetProjectActionType); + implicitActions = new List(); - implicitActions.Add(implicitAction); + foreach (NuGetProjectAction? buildAction in buildIntegratedAction.GetProjectActions()) + { + var implicitAction = new ImplicitProjectAction( + CreateProjectActionId(), + buildAction.PackageIdentity, + buildAction.NuGetProjectActionType); + + implicitActions.Add(implicitAction); + } } - } - string projectId = resolvedAction.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); - var projectAction = new ProjectAction( - CreateProjectActionId(), - projectId, - resolvedAction.Action.PackageIdentity, - resolvedAction.Action.NuGetProjectActionType, - implicitActions); + string projectId = resolvedAction.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); + var projectAction = new ProjectAction( + CreateProjectActionId(), + projectId, + resolvedAction.Action.PackageIdentity, + resolvedAction.Action.NuGetProjectActionType, + implicitActions); - _state.ResolvedActions[projectAction.Id] = resolvedAction; + _state.ResolvedActions[projectAction.Id] = resolvedAction; - projectActions.Add(projectAction); - } + projectActions.Add(projectAction); + } - return projectActions; + return projectActions; + }); } public async ValueTask> GetUninstallActionsAsync( @@ -351,39 +369,43 @@ public async ValueTask> GetUninstallActionsAsync( cancellationToken.ThrowIfCancellationRequested(); - INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); - (bool success, NuGetProject? project) = await TryGetNuGetProjectMatchingProjectIdAsync(projectId); + return await CatchAndRethrowExceptionAsync(async () => + { - Assumes.True(success); - Assumes.NotNull(project); + INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); + (bool success, NuGetProject? project) = await TryGetNuGetProjectMatchingProjectIdAsync(projectId); - var projectActions = new List(); - var uninstallationContext = new UninstallationContext(removeDependencies, forceRemove); + Assumes.True(success); + Assumes.NotNull(project); - NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); - IEnumerable actions = await packageManager.PreviewUninstallPackageAsync( - project, - packageIdentity.Id, - uninstallationContext, - projectContext, - cancellationToken); + var projectActions = new List(); + var uninstallationContext = new UninstallationContext(removeDependencies, forceRemove); - foreach (NuGetProjectAction action in actions) - { - var resolvedAction = new ResolvedAction(project, action); - var projectAction = new ProjectAction( - CreateProjectActionId(), - projectId, - action.PackageIdentity, - action.NuGetProjectActionType, - implicitActions: null); + NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); + IEnumerable actions = await packageManager.PreviewUninstallPackageAsync( + project, + packageIdentity.Id, + uninstallationContext, + projectContext, + cancellationToken); - _state.ResolvedActions[projectAction.Id] = resolvedAction; + foreach (NuGetProjectAction action in actions) + { + var resolvedAction = new ResolvedAction(project, action); + var projectAction = new ProjectAction( + CreateProjectActionId(), + projectId, + action.PackageIdentity, + action.NuGetProjectActionType, + implicitActions: null); - projectActions.Add(projectAction); - } + _state.ResolvedActions[projectAction.Id] = resolvedAction; - return projectActions; + projectActions.Add(projectAction); + } + + return projectActions; + }); } public async ValueTask> GetUpdateActionsAsync( @@ -402,76 +424,79 @@ public async ValueTask> GetUpdateActionsAsync( Assumes.NotNull(_state.ResolvedActions); Assumes.Null(_state.PackageIdentity); - var primarySources = new List(); - var secondarySources = new List(); + return await CatchAndRethrowExceptionAsync(async () => + { + var primarySources = new List(); + var secondarySources = new List(); - ISourceRepositoryProvider sourceRepositoryProvider = await _sharedState.SourceRepositoryProvider.GetValueAsync(cancellationToken); - IEnumerable sourceRepositories = sourceRepositoryProvider.GetRepositories(); - var packageSourceNamesSet = new HashSet(packageSourceNames, StringComparer.OrdinalIgnoreCase); + ISourceRepositoryProvider sourceRepositoryProvider = await _sharedState.SourceRepositoryProvider.GetValueAsync(cancellationToken); + IEnumerable sourceRepositories = sourceRepositoryProvider.GetRepositories(); + var packageSourceNamesSet = new HashSet(packageSourceNames, StringComparer.OrdinalIgnoreCase); - foreach (SourceRepository sourceRepository in sourceRepositories) - { - if (packageSourceNamesSet.Contains(sourceRepository.PackageSource.Name)) + foreach (SourceRepository sourceRepository in sourceRepositories) { - primarySources.Add(sourceRepository); - } + if (packageSourceNamesSet.Contains(sourceRepository.PackageSource.Name)) + { + primarySources.Add(sourceRepository); + } - if (sourceRepository.PackageSource.IsEnabled) - { - secondarySources.Add(sourceRepository); + if (sourceRepository.PackageSource.IsEnabled) + { + secondarySources.Add(sourceRepository); + } } - } - INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); - var projects = new List(); + INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); + var projects = new List(); - foreach (string projectId in projectIds) - { - (bool success, NuGetProject? project) = await TryGetNuGetProjectMatchingProjectIdAsync(projectId); + foreach (string projectId in projectIds) + { + (bool success, NuGetProject? project) = await TryGetNuGetProjectMatchingProjectIdAsync(projectId); - Assumes.True(success); - Assumes.NotNull(project); + Assumes.True(success); + Assumes.NotNull(project); - projects.Add(project); - } + projects.Add(project); + } - var resolutionContext = new ResolutionContext( - dependencyBehavior, - includePrelease, - includeUnlisted: true, - versionConstraints, - new GatherCache(), - _state.SourceCacheContext); - - NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); - IEnumerable actions = await packageManager.PreviewUpdatePackagesAsync( - packageIdentities.ToList(), - projects, - resolutionContext, - projectContext, - primarySources, - secondarySources, - cancellationToken); - - var projectActions = new List(); - - foreach (NuGetProjectAction action in actions) - { - string projectId = action.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); - var resolvedAction = new ResolvedAction(action.Project, action); - var projectAction = new ProjectAction( - CreateProjectActionId(), - projectId, - action.PackageIdentity, - action.NuGetProjectActionType, - implicitActions: null); - - _state.ResolvedActions[projectAction.Id] = resolvedAction; - - projectActions.Add(projectAction); - } + var resolutionContext = new ResolutionContext( + dependencyBehavior, + includePrelease, + includeUnlisted: true, + versionConstraints, + new GatherCache(), + _state.SourceCacheContext); + + NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); + IEnumerable actions = await packageManager.PreviewUpdatePackagesAsync( + packageIdentities.ToList(), + projects, + resolutionContext, + projectContext, + primarySources, + secondarySources, + cancellationToken); + + var projectActions = new List(); + + foreach (NuGetProjectAction action in actions) + { + string projectId = action.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); + var resolvedAction = new ResolvedAction(action.Project, action); + var projectAction = new ProjectAction( + CreateProjectActionId(), + projectId, + action.PackageIdentity, + action.NuGetProjectActionType, + implicitActions: null); + + _state.ResolvedActions[projectAction.Id] = resolvedAction; + + projectActions.Add(projectAction); + } - return projectActions; + return projectActions; + }); } public async ValueTask> GetProjectsWithDeprecatedDotnetFrameworkAsync(CancellationToken cancellationToken) @@ -557,5 +582,41 @@ private bool IsDirectInstall(IReadOnlyList projectActions) return (project != null, project); } + + private async ValueTask CatchAndRethrowExceptionAsync(Func taskFunc) + { + try + { + await taskFunc(); + } + catch (Exception ex) + { + var exception = new LocalRpcException(ex.Message, ex) + { + ErrorCode = (int)RemoteErrorCode.RemoteError, + ErrorData = RemoteErrorUtility.ToRemoteError(ex) + }; + + throw exception; + } + } + + private async ValueTask CatchAndRethrowExceptionAsync(Func> taskFunc) + { + try + { + return await taskFunc(); + } + catch (Exception ex) + { + var exception = new LocalRpcException(ex.Message, ex) + { + ErrorCode = (int)RemoteErrorCode.RemoteError, + ErrorData = RemoteErrorUtility.ToRemoteError(ex) + }; + + throw exception; + } + } } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/ILogMessageFormatter.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/ILogMessageFormatter.cs new file mode 100644 index 00000000000..523e330d558 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/ILogMessageFormatter.cs @@ -0,0 +1,371 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System; +using System.Collections.Generic; +using MessagePack; +using MessagePack.Formatters; +using Microsoft; +using NuGet.Common; +using NuGet.Packaging.Signing; + +namespace NuGet.VisualStudio.Internal.Contracts +{ + internal sealed class ILogMessageFormatter : IMessagePackFormatter + { + private const string CodePropertyName = "code"; + private const string EndColumnNumberPropertyName = "endcolumnnumber"; + private const string EndLineNumberPropertyName = "endlinenumber"; + private const string FilePathPropertyName = "filepath"; + private const string LevelPropertyName = "level"; + private const string LibraryIdPropertyName = "libraryid"; + private const string MessagePropertyName = "message"; + private const string ProjectPathPropertyName = "projectpath"; + private const string ShouldDisplayPropertyName = "shoulddisplay"; + private const string StartColumnNumberPropertyName = "startcolumnnumber"; + private const string StartLineNumberPropertyName = "startlinenumber"; + private const string TargetGraphsPropertyName = "targetgraphs"; + private const string TimePropertyName = "time"; + private const string TypeNamePropertyName = "typename"; + private const string WarningLevelPropertyName = "warninglevel"; + + private static readonly string LogMessageTypeName = typeof(LogMessage).Name; + private static readonly string PackagingLogMessageTypeName = typeof(PackagingLogMessage).Name; + private static readonly string RestoreLogMessageTypeName = typeof(RestoreLogMessage).Name; + private static readonly string SignatureLogTypeName = typeof(SignatureLog).Name; + + internal static readonly IMessagePackFormatter Instance = new ILogMessageFormatter(); + + private ILogMessageFormatter() + { + } + + public ILogMessage? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) + { + if (reader.TryReadNil()) + { + return null; + } + + // stack overflow mitigation - see https://github.com/neuecc/MessagePack-CSharp/security/advisories/GHSA-7q36-4xx7-xcxf + options.Security.DepthStep(ref reader); + + try + { + NuGetLogCode? code = null; + int? endColumnNumber = null; + int? endLineNumber = null; + string? filePath = null; + string? libraryId = null; + LogLevel? logLevel = null; + string? message = null; + string? projectPath = null; + bool? shouldDisplay = null; + int? startColumnNumber = null; + int? startLineNumber = null; + List? targetGraphs = null; + DateTimeOffset? time = null; + string? typeName = null; + WarningLevel? warningLevel = null; + + int propertyCount = reader.ReadMapHeader(); + + for (var propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) + { + switch (reader.ReadString()) + { + case CodePropertyName: + code = options.Resolver.GetFormatter().Deserialize(ref reader, options); + break; + + case EndColumnNumberPropertyName: + endColumnNumber = reader.ReadInt32(); + break; + + case EndLineNumberPropertyName: + endLineNumber = reader.ReadInt32(); + break; + + case FilePathPropertyName: + filePath = reader.ReadString(); + break; + + case LevelPropertyName: + logLevel = options.Resolver.GetFormatter().Deserialize(ref reader, options); + break; + + case LibraryIdPropertyName: + libraryId = reader.ReadString(); + break; + + case MessagePropertyName: + message = reader.ReadString(); + break; + + case ProjectPathPropertyName: + projectPath = reader.ReadString(); + break; + + case ShouldDisplayPropertyName: + shouldDisplay = reader.ReadBoolean(); + break; + + case StartColumnNumberPropertyName: + startColumnNumber = reader.ReadInt32(); + break; + + case StartLineNumberPropertyName: + startLineNumber = reader.ReadInt32(); + break; + + case TargetGraphsPropertyName: + if (!reader.TryReadNil()) + { + targetGraphs = new List(); + + int targetGraphsCount = reader.ReadArrayHeader(); + + for (var i = 0; i < targetGraphsCount; ++i) + { + string targetGraph = reader.ReadString(); + + targetGraphs.Add(targetGraph); + } + } + break; + + case TimePropertyName: + time = options.Resolver.GetFormatter().Deserialize(ref reader, options); + break; + + case TypeNamePropertyName: + typeName = reader.ReadString(); + break; + + case WarningLevelPropertyName: + warningLevel = options.Resolver.GetFormatter().Deserialize(ref reader, options); + break; + + default: + reader.Skip(); + break; + } + } + + Assumes.NotNullOrEmpty(typeName); + Assumes.True(code.HasValue); + Assumes.True(logLevel.HasValue); + Assumes.NotNull(message); + Assumes.True(time.HasValue); + Assumes.True(warningLevel.HasValue); + + ILogMessage? logMessage = null; + + if (typeName == LogMessageTypeName) + { + logMessage = new LogMessage(logLevel.Value, message) + { + Code = code.Value, + ProjectPath = projectPath, + Time = time.Value, + WarningLevel = warningLevel.Value + }; + } + else if (typeName == PackagingLogMessageTypeName) + { + Assumes.True(endColumnNumber.HasValue); + Assumes.True(endLineNumber.HasValue); + Assumes.True(startColumnNumber.HasValue); + Assumes.True(startLineNumber.HasValue); + + PackagingLogMessage packagingLogMessage = PackagingLogMessage.CreateError(message, code.Value); + + packagingLogMessage.Code = code.Value; + packagingLogMessage.EndColumnNumber = endColumnNumber.Value; + packagingLogMessage.EndLineNumber = endLineNumber.Value; + packagingLogMessage.FilePath = filePath; + packagingLogMessage.Level = logLevel.Value; + packagingLogMessage.ProjectPath = projectPath; + packagingLogMessage.StartColumnNumber = startColumnNumber.Value; + packagingLogMessage.StartLineNumber = startLineNumber.Value; + packagingLogMessage.Time = time.Value; + packagingLogMessage.WarningLevel = warningLevel.Value; + + logMessage = packagingLogMessage; + } + else if (typeName == RestoreLogMessageTypeName) + { + Assumes.True(endColumnNumber.HasValue); + Assumes.True(endLineNumber.HasValue); + Assumes.True(shouldDisplay.HasValue); + Assumes.True(startColumnNumber.HasValue); + Assumes.True(startLineNumber.HasValue); + + logMessage = new RestoreLogMessage(logLevel.Value, message) + { + Code = code.Value, + EndColumnNumber = endColumnNumber.Value, + EndLineNumber = endLineNumber.Value, + FilePath = filePath, + Level = logLevel.Value, + LibraryId = libraryId, + Message = message, + ProjectPath = projectPath, + ShouldDisplay = shouldDisplay.Value, + StartColumnNumber = startColumnNumber.Value, + StartLineNumber = startLineNumber.Value, + TargetGraphs = targetGraphs, + Time = time.Value, + WarningLevel = warningLevel.Value + }; + } + else if (typeName == SignatureLogTypeName) + { + SignatureLog signatureLog = SignatureLog.Error(code.Value, message); + + signatureLog.Code = code.Value; + signatureLog.Level = logLevel.Value; + signatureLog.LibraryId = libraryId; + signatureLog.ProjectPath = projectPath; + signatureLog.Time = time.Value; + signatureLog.WarningLevel = warningLevel.Value; + + logMessage = signatureLog; + } + else + { + throw new InvalidOperationException(); + } + + return logMessage; + } + finally + { + // stack overflow mitigation - see https://github.com/neuecc/MessagePack-CSharp/security/advisories/GHSA-7q36-4xx7-xcxf + reader.Depth--; + } + } + + public void Serialize(ref MessagePackWriter writer, ILogMessage? value, MessagePackSerializerOptions options) + { + if (value == null) + { + writer.WriteNil(); + return; + } + + if (value is LogMessage logMessage) + { + Serialize(ref writer, logMessage, options); + } + else if (value is RestoreLogMessage restoreLogMessage) + { + Serialize(ref writer, restoreLogMessage, options); + } + else if (value is SignatureLog signatureLogMessage) + { + Serialize(ref writer, signatureLogMessage, options); + } + else if (value is PackagingLogMessage packagingLogMessage) + { + Serialize(ref writer, packagingLogMessage, options); + } + else + { + throw new InvalidOperationException(); + } + } + + private void SerializeCommonProperties(ref MessagePackWriter writer, ILogMessage value, MessagePackSerializerOptions options) + { + writer.Write(TypeNamePropertyName); + writer.Write(value.GetType().Name); + writer.Write(CodePropertyName); + options.Resolver.GetFormatter().Serialize(ref writer, value.Code, options); + writer.Write(LevelPropertyName); + options.Resolver.GetFormatter().Serialize(ref writer, value.Level, options); + writer.Write(MessagePropertyName); + writer.Write(value.Message); + writer.Write(ProjectPathPropertyName); + writer.Write(value.ProjectPath); + writer.Write(TimePropertyName); + options.Resolver.GetFormatter().Serialize(ref writer, value.Time, options); + writer.Write(WarningLevelPropertyName); + options.Resolver.GetFormatter().Serialize(ref writer, value.WarningLevel, options); + } + + private void Serialize(ref MessagePackWriter writer, LogMessage logMessage, MessagePackSerializerOptions options) + { + writer.WriteMapHeader(count: 7); + + SerializeCommonProperties(ref writer, logMessage, options); + } + + private void Serialize(ref MessagePackWriter writer, PackagingLogMessage logMessage, MessagePackSerializerOptions options) + { + writer.WriteMapHeader(count: 12); + + SerializeCommonProperties(ref writer, logMessage, options); + + writer.Write(EndColumnNumberPropertyName); + writer.Write(logMessage.EndColumnNumber); + writer.Write(EndLineNumberPropertyName); + writer.Write(logMessage.EndLineNumber); + writer.Write(FilePathPropertyName); + writer.Write(logMessage.FilePath); + writer.Write(StartColumnNumberPropertyName); + writer.Write(logMessage.StartColumnNumber); + writer.Write(StartLineNumberPropertyName); + writer.Write(logMessage.StartLineNumber); + } + + private void Serialize(ref MessagePackWriter writer, RestoreLogMessage logMessage, MessagePackSerializerOptions options) + { + writer.WriteMapHeader(count: 15); + + SerializeCommonProperties(ref writer, logMessage, options); + + writer.Write(EndColumnNumberPropertyName); + writer.Write(logMessage.EndColumnNumber); + writer.Write(EndLineNumberPropertyName); + writer.Write(logMessage.EndLineNumber); + writer.Write(FilePathPropertyName); + writer.Write(logMessage.FilePath); + writer.Write(LibraryIdPropertyName); + writer.Write(logMessage.LibraryId); + writer.Write(ShouldDisplayPropertyName); + writer.Write(logMessage.ShouldDisplay); + writer.Write(StartColumnNumberPropertyName); + writer.Write(logMessage.StartColumnNumber); + writer.Write(StartLineNumberPropertyName); + writer.Write(logMessage.StartLineNumber); + writer.Write(TargetGraphsPropertyName); + + if (logMessage.TargetGraphs is null) + { + writer.WriteNil(); + } + else + { + writer.WriteArrayHeader(logMessage.TargetGraphs.Count); + + foreach (string targetGraph in logMessage.TargetGraphs) + { + writer.Write(targetGraph); + } + } + } + + private void Serialize(ref MessagePackWriter writer, SignatureLog logMessage, MessagePackSerializerOptions options) + { + writer.WriteMapHeader(count: 8); + + SerializeCommonProperties(ref writer, logMessage, options); + + writer.Write(LibraryIdPropertyName); + writer.Write(logMessage.LibraryId); + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/RemoteErrorFormatter.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/RemoteErrorFormatter.cs new file mode 100644 index 00000000000..fb6aec84841 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/RemoteErrorFormatter.cs @@ -0,0 +1,140 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System.Collections.Generic; +using MessagePack; +using MessagePack.Formatters; +using Microsoft; +using NuGet.Common; + +namespace NuGet.VisualStudio.Internal.Contracts +{ + internal sealed class RemoteErrorFormatter : IMessagePackFormatter + { + private const string ActivityLogMessagePropertyName = "activitylog"; + private const string LogMessagePropertyName = "logmessage"; + private const string LogMessagesPropertyName = "logmessages"; + private const string ProjectContextLogMessagePropertyName = "projectcontextlogmessage"; + private const string TypeNamePropertyName = "typename"; + + internal static readonly IMessagePackFormatter Instance = new RemoteErrorFormatter(); + + private RemoteErrorFormatter() + { + } + + public RemoteError? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) + { + if (reader.TryReadNil()) + { + return null; + } + + // stack overflow mitigation - see https://github.com/neuecc/MessagePack-CSharp/security/advisories/GHSA-7q36-4xx7-xcxf + options.Security.DepthStep(ref reader); + + try + { + string? activityLogMessage = null; + ILogMessage? logMessage = null; + List? logMessages = null; + string? projectContextLogMessage = null; + string? typeName = null; + + int propertyCount = reader.ReadMapHeader(); + + for (var propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) + { + switch (reader.ReadString()) + { + case ActivityLogMessagePropertyName: + activityLogMessage = reader.ReadString(); + break; + + case LogMessagePropertyName: + logMessage = ILogMessageFormatter.Instance.Deserialize(ref reader, options); + break; + + case LogMessagesPropertyName: + if (!reader.TryReadNil()) + { + logMessages = new List(); + + int logMessagesCount = reader.ReadArrayHeader(); + + for (var i = 0; i < logMessagesCount; ++i) + { + ILogMessage? lm = ILogMessageFormatter.Instance.Deserialize(ref reader, options); + + Assumes.NotNull(lm); + + logMessages.Add(lm); + } + } + break; + + case ProjectContextLogMessagePropertyName: + projectContextLogMessage = reader.ReadString(); + break; + + case TypeNamePropertyName: + typeName = reader.ReadString(); + break; + + default: + reader.Skip(); + break; + } + } + + Assumes.NotNullOrEmpty(typeName); + Assumes.NotNull(logMessage); + + return new RemoteError(typeName, logMessage, logMessages, projectContextLogMessage, activityLogMessage); + } + finally + { + // stack overflow mitigation - see https://github.com/neuecc/MessagePack-CSharp/security/advisories/GHSA-7q36-4xx7-xcxf + reader.Depth--; + } + } + + public void Serialize(ref MessagePackWriter writer, RemoteError? value, MessagePackSerializerOptions options) + { + if (value == null) + { + writer.WriteNil(); + return; + } + + writer.WriteMapHeader(count: 5); + writer.Write(ActivityLogMessagePropertyName); + writer.Write(value.ActivityLogMessage); + writer.Write(LogMessagePropertyName); + ILogMessageFormatter.Instance.Serialize(ref writer, value.LogMessage, options); + + writer.Write(LogMessagesPropertyName); + + if (value.LogMessages is null) + { + writer.WriteNil(); + } + else + { + writer.WriteArrayHeader(value.LogMessages.Count); + + foreach (ILogMessage logMessage in value.LogMessages) + { + ILogMessageFormatter.Instance.Serialize(ref writer, logMessage, options); + } + } + + writer.Write(ProjectContextLogMessagePropertyName); + writer.Write(value.ProjectContextLogMessage); + writer.Write(TypeNamePropertyName); + writer.Write(value.TypeName); + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs new file mode 100644 index 00000000000..384dc05454c --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using StreamJsonRpc; +using StreamJsonRpc.Protocol; + +namespace NuGet.VisualStudio.Internal.Contracts +{ + // Unsealed only to facilitate testing. + internal class NuGetJsonRpc : JsonRpc + { + internal NuGetJsonRpc(IJsonRpcMessageHandler messageHandler) + : base(messageHandler) + { + } + + protected override Type GetErrorDetailsDataType(JsonRpcError error) + { + if (error is object + && error.Error is object + && (int)error.Error.Code == (int)RemoteErrorCode.RemoteError) + { + return typeof(RemoteError); + } + + return base.GetErrorDetailsDataType(error); + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs index bc38c7eb13d..f5c8dae57ea 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs @@ -34,11 +34,14 @@ static NuGetServiceMessagePackRpcDescriptor() PackageSourceFormatter.Instance, PackageSourceUpdateOptionsFormatter.Instance, ProjectActionFormatter.Instance, + RemoteErrorFormatter.Instance, VersionRangeFormatter.Instance }; var resolvers = new IFormatterResolver[] { MessagePackSerializerOptions.Standard.Resolver }; - MessagePackSerializerOptions = MessagePackSerializerOptions.Standard.WithSecurity(MessagePackSecurity.UntrustedData).WithResolver(CompositeResolver.Create(formatters, resolvers)); + MessagePackSerializerOptions = MessagePackSerializerOptions.Standard + .WithSecurity(MessagePackSecurity.UntrustedData) + .WithResolver(CompositeResolver.Create(formatters, resolvers)); } internal NuGetServiceMessagePackRpcDescriptor(ServiceMoniker serviceMoniker) @@ -66,5 +69,10 @@ protected override IJsonRpcMessageFormatter CreateFormatter() formatter.SetMessagePackSerializerOptions(MessagePackSerializerOptions); return formatter; } + + protected override JsonRpc CreateJsonRpc(IJsonRpcMessageHandler handler) + { + return new NuGetJsonRpc(handler); + } } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/RemoteErrorCode.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/RemoteErrorCode.cs new file mode 100644 index 00000000000..ac353db9eb6 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/RemoteErrorCode.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace NuGet.VisualStudio.Internal.Contracts +{ + // Values -32768 to -32000 are reserved by the JSON-RPC protocol. Do not use them! + // See https://www.jsonrpc.org/specification#error_object for details. + public enum RemoteErrorCode : int + { + /// + /// This code serves as a hint to clients on how to deserialize the error data. + /// It does not represent a unique error condition. + /// + RemoteError = -31999 + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs new file mode 100644 index 00000000000..7f046aa72f8 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using NuGet.Common; + +namespace NuGet.VisualStudio.Internal.Contracts +{ + public sealed class RemoteError + { + public ILogMessage LogMessage { get; } + public IReadOnlyList LogMessages { get; } + public string ProjectContextLogMessage { get; } + public string ActivityLogMessage { get; } + public string TypeName { get; } + + public RemoteError(string typeName, ILogMessage logMessage, IReadOnlyList logMessages) + { + if (string.IsNullOrEmpty(typeName)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(typeName)); + } + + TypeName = typeName; + LogMessage = logMessage ?? throw new ArgumentNullException(nameof(logMessage)); + LogMessages = logMessages; + } + + public RemoteError( + string typeName, + ILogMessage logMessage, + IReadOnlyList logMessages, + string projectContextLogMessage, + string activityLogMessage) + : this(typeName, logMessage, logMessages) + { + ProjectContextLogMessage = projectContextLogMessage; + ActivityLogMessage = activityLogMessage; + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs new file mode 100644 index 00000000000..50c97c7f5af --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs @@ -0,0 +1,67 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using NuGet.Common; +using NuGet.Frameworks; +using NuGet.PackageManagement; +using NuGet.Packaging; +using NuGet.Packaging.Core; +using NuGet.Packaging.Signing; +using NuGet.Protocol.Core.Types; +using NuGet.Resolver; + +namespace NuGet.VisualStudio.Internal.Contracts +{ + public static class RemoteErrorUtility + { + public static RemoteError ToRemoteError(Exception exception) + { + if (exception is null) + { + throw new ArgumentNullException(nameof(exception)); + } + + ILogMessage logMessage; + IReadOnlyList logMessages = null; + string typeName = exception.GetType().FullName; + + if (exception is SignatureException signatureException) + { + logMessage = signatureException.AsLogMessage(); + IReadOnlyList results = signatureException.Results ?? Array.Empty(); + logMessages = results.SelectMany(result => result.Issues).ToArray(); + + return new RemoteError(typeName, logMessage, logMessages); + } + + logMessage = new LogMessage(LogLevel.Error, ExceptionUtilities.DisplayMessage(exception, indent: false)); + string projectContextLogMessage = null; + string activityLogMessage = null; + + if (exception is NuGetResolverConstraintException + || exception is PackageAlreadyInstalledException + || exception is MinClientVersionException + || exception is FrameworkException + || exception is NuGetProtocolException + || exception is PackagingException + || exception is InvalidOperationException + || exception is PackageReferenceRollbackException) + { + projectContextLogMessage = ExceptionUtilities.DisplayMessage(exception, indent: true); + activityLogMessage = exception.ToString(); + + if (exception is PackageReferenceRollbackException rollbackException) + { + logMessages = rollbackException.LogMessages + .Where(message => message.Level == LogLevel.Error || message.Level == LogLevel.Warning) + .ToArray(); + } + } + + return new RemoteError(typeName, logMessage, logMessages, projectContextLogMessage, activityLogMessage); + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/UserInterfaceService/NuGetUITests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/UserInterfaceService/NuGetUITests.cs index 6f1a49e4378..7e4d5083a1a 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/UserInterfaceService/NuGetUITests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/UserInterfaceService/NuGetUITests.cs @@ -7,6 +7,7 @@ using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Threading; using Moq; +using NuGet.Common; using NuGet.Configuration; using NuGet.PackageManagement.VisualStudio; using NuGet.Packaging.Signing; @@ -14,6 +15,8 @@ using NuGet.Protocol.Core.Types; using NuGet.Test.Utility; using NuGet.VisualStudio; +using NuGet.VisualStudio.Internal.Contracts; +using StreamJsonRpc; using Xunit; namespace NuGet.PackageManagement.UI.Test @@ -54,7 +57,77 @@ public void ShowError_WhenArgumentIsSignatureExceptionWithNullResults_DoesNotThr } } + [Fact] + public void ShowError_WhenArgumentIsRemoteInvocationExceptionForSignatureException_ShowsError() + { + var remoteError = new RemoteError( + typeName: typeof(SignatureException).FullName, + new LogMessage(LogLevel.Error, message: "a", NuGetLogCode.NU3018), + new[] + { + new LogMessage(LogLevel.Error, message: "b", NuGetLogCode.NU3019), + new LogMessage(LogLevel.Warning, message: "c", NuGetLogCode.NU3027) + }, + projectContextLogMessage: "d", + activityLogMessage: "e"); + var exception = new RemoteInvocationException( + message: "f", + errorCode: 0, + errorData: null, + deserializedErrorData: remoteError); + var defaultLogger = new Mock(); + var projectLogger = new Mock(); + + defaultLogger.Setup(x => x.ReportError(It.Is(logMessage => ReferenceEquals(logMessage, remoteError.LogMessage)))); + defaultLogger.Setup(x => x.ReportError(It.Is(logMessage => ReferenceEquals(logMessage, remoteError.LogMessages[0])))); + defaultLogger.Setup(x => x.ReportError(It.Is(logMessage => ReferenceEquals(logMessage, remoteError.LogMessages[1])))); + projectLogger.Setup(x => x.Log(It.Is(logMessage => ReferenceEquals(logMessage, remoteError.LogMessage)))); + projectLogger.Setup(x => x.Log(It.Is(logMessage => ReferenceEquals(logMessage, remoteError.LogMessages[0])))); + projectLogger.Setup(x => x.Log(It.Is(logMessage => ReferenceEquals(logMessage, remoteError.LogMessages[1])))); + + using (NuGetUI ui = CreateNuGetUI(defaultLogger.Object, projectLogger.Object)) + { + ui.ShowError(exception); + + defaultLogger.VerifyAll(); + projectLogger.VerifyAll(); + } + } + + [Fact] + public void ShowError_WhenArgumentIsNotRemoteInvocationException_ShowsError() + { + var exception = new DivideByZeroException(); + var defaultLogger = new Mock(); + var projectLogger = new Mock(); + const bool indent = false; + + defaultLogger.Setup( + x => x.ReportError( + It.Is( + logMessage => logMessage.Level == LogLevel.Error + && logMessage.Message == ExceptionUtilities.DisplayMessage(exception, indent)))); + projectLogger.Setup( + x => x.Log( + It.Is( + logMessage => logMessage.Level == LogLevel.Error + && logMessage.Message == exception.ToString()))); + + using (NuGetUI ui = CreateNuGetUI(defaultLogger.Object, projectLogger.Object)) + { + ui.ShowError(exception); + + defaultLogger.VerifyAll(); + projectLogger.VerifyAll(); + } + } + private NuGetUI CreateNuGetUI() + { + return CreateNuGetUI(Mock.Of(), Mock.Of()); + } + + private NuGetUI CreateNuGetUI(INuGetUILogger defaultLogger, INuGetUILogger projectLogger) { var uiContext = CreateNuGetUIContext(); @@ -62,9 +135,9 @@ private NuGetUI CreateNuGetUI() Mock.Of(), new NuGetUIProjectContext( Mock.Of(), - Mock.Of(), + projectLogger, Mock.Of()), - Mock.Of(), + defaultLogger, uiContext); } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs index b6df1b5f864..be99e569811 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs @@ -16,6 +16,7 @@ using Microsoft.VisualStudio.Threading; using Moq; using NuGet.Commands.Test; +using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; using NuGet.Packaging; @@ -28,6 +29,7 @@ using NuGet.Versioning; using NuGet.VisualStudio; using NuGet.VisualStudio.Internal.Contracts; +using StreamJsonRpc; using Test.Utility; using Test.Utility.Threading; using Xunit; @@ -81,7 +83,7 @@ await PerformOperationAsync(async (projectManager) => var packageIdentity = new PackageIdentity(id: "b", NuGetVersion.Parse("1.0.0")); string[] packageSourceNames = new[] { TestSourceRepositoryUtility.V3PackageSource.Name }; - ArgumentException exception = await Assert.ThrowsAsync( + LocalRpcException exception = await Assert.ThrowsAsync( () => projectManager.GetInstallActionsAsync( projectIds, packageIdentity, @@ -91,8 +93,23 @@ await PerformOperationAsync(async (projectManager) => packageSourceNames, CancellationToken.None).AsTask()); - Assert.StartsWith($"A project with ID '{projectIds.Single()}' was not found.", exception.Message); - Assert.Equal("projectIds", exception.ParamName); + string expectedMessage = $"A project with ID '{projectIds.Single()}' was not found.\r\nParameter name: projectIds"; + Assert.StartsWith(expectedMessage, exception.Message); + Assert.Equal((int)RemoteErrorCode.RemoteError, exception.ErrorCode); + Assert.IsType(exception.ErrorData); + + var remoteError = (RemoteError)exception.ErrorData; + + Assert.Null(remoteError.ActivityLogMessage); + Assert.Equal(NuGetLogCode.Undefined, remoteError.LogMessage.Code); + Assert.Equal(LogLevel.Error, remoteError.LogMessage.Level); + Assert.Equal(expectedMessage, remoteError.LogMessage.Message); + Assert.Null(remoteError.LogMessage.ProjectPath); + Assert.InRange(remoteError.LogMessage.Time, DateTimeOffset.UtcNow.AddSeconds(-10), DateTimeOffset.UtcNow.AddSeconds(1)); + Assert.Equal(WarningLevel.Severe, remoteError.LogMessage.WarningLevel); + Assert.Null(remoteError.LogMessages); + Assert.Null(remoteError.ProjectContextLogMessage); + Assert.Equal(typeof(ArgumentException).FullName, remoteError.TypeName); }); } @@ -348,11 +365,11 @@ private void Initialize(IReadOnlyList packageSources = null) deleteOnRestartManager); _state = new NuGetProjectManagerServiceState(); _sharedState = new TestSharedServiceState( - new AsyncLazy( + new Microsoft.VisualStudio.Threading.AsyncLazy( () => Task.FromResult(_packageManager)), - new AsyncLazy( + new Microsoft.VisualStudio.Threading.AsyncLazy( () => Task.FromResult(_solutionManager)), - new AsyncLazy( + new Microsoft.VisualStudio.Threading.AsyncLazy( () => Task.FromResult(sourceRepositoryProvider))); _projectManager = new NuGetProjectManagerService( default(ServiceActivationOptions), @@ -434,7 +451,6 @@ public TestMSBuildNuGetProject( packagesConfigFolderPath) { InternalMetadata[NuGetProjectMetadataKeys.ProjectId] = projectId; - //ProjectClosure = new List(); } } diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/ILogMessageFormatterTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/ILogMessageFormatterTests.cs new file mode 100644 index 00000000000..fea29010d53 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/ILogMessageFormatterTests.cs @@ -0,0 +1,96 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using NuGet.Common; +using NuGet.Packaging.Signing; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + public sealed class ILogMessageFormatterTests : FormatterTests + { + private const string Message = "a"; + + [Theory] + [MemberData(nameof(ILogMessages))] + public void SerializeThenDeserialize_WithValidArguments_RoundTrips(ILogMessage expectedResult) + { + ILogMessage actualResult = SerializeThenDeserialize(ILogMessageFormatter.Instance, expectedResult); + + TestUtility.AssertEqual(expectedResult, actualResult); + } + + public static TheoryData ILogMessages => new TheoryData + { + { new LogMessage(LogLevel.Error, Message, NuGetLogCode.NU3000) }, + { + new LogMessage(LogLevel.Warning, Message, NuGetLogCode.NU3027) + { + ProjectPath = "b", + WarningLevel = WarningLevel.Important + } + }, + { PackagingLogMessage.CreateError(Message, NuGetLogCode.NU1103) }, + { PackagingLogMessage.CreateMessage(Message, LogLevel.Verbose) }, + { PackagingLogMessage.CreateWarning(Message, NuGetLogCode.NU1103) }, + { CreatePackagingLogMessage() }, + { SignatureLog.DebugLog(Message) }, + { SignatureLog.DetailedLog(Message) }, + { SignatureLog.Error(NuGetLogCode.NU3014, Message) }, + { SignatureLog.InformationLog(Message) }, + { SignatureLog.Issue(fatal: true, NuGetLogCode.NU3030, Message) }, + { CreateSignatureLog() }, + { + new RestoreLogMessage(LogLevel.Error, errorString: "a") + { + Code = NuGetLogCode.NU1605, + EndColumnNumber = 1, + EndLineNumber = 2, + FilePath = "b", + Level = LogLevel.Minimal, + LibraryId = "c", + ProjectPath = "d", + ShouldDisplay = true, + StartColumnNumber = 3, + StartLineNumber = 4, + TargetGraphs = new string[] { "e", "f" }, + Time = DateTimeOffset.UtcNow, + WarningLevel = WarningLevel.Important + } + } + }; + + private static PackagingLogMessage CreatePackagingLogMessage() + { + PackagingLogMessage packagingLogMessage = PackagingLogMessage.CreateError(Message, NuGetLogCode.NU3031); + + packagingLogMessage.Code = NuGetLogCode.NU1103; + packagingLogMessage.EndColumnNumber = 1; + packagingLogMessage.EndLineNumber = 2; + packagingLogMessage.FilePath = "b"; + packagingLogMessage.Level = LogLevel.Minimal; + packagingLogMessage.ProjectPath = "c"; + packagingLogMessage.StartColumnNumber = 3; + packagingLogMessage.StartLineNumber = 4; + packagingLogMessage.Time = DateTimeOffset.UtcNow; + packagingLogMessage.WarningLevel = WarningLevel.Minimal; + + return packagingLogMessage; + } + + private static SignatureLog CreateSignatureLog() + { + SignatureLog signatureLog = SignatureLog.Error(NuGetLogCode.NU3031, Message); + + signatureLog.Code = NuGetLogCode.NU3017; + signatureLog.Level = LogLevel.Verbose; + signatureLog.LibraryId = "b"; + signatureLog.ProjectPath = "c"; + signatureLog.Time = DateTimeOffset.UtcNow; + signatureLog.WarningLevel = WarningLevel.Important; + + return signatureLog; + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/RemoteErrorFormatterTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/RemoteErrorFormatterTests.cs new file mode 100644 index 00000000000..16acf768348 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Formatters/RemoteErrorFormatterTests.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using NuGet.Common; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + public sealed class RemoteErrorFormatterTests : FormatterTests + { + private static readonly LogMessage LogMessage = new LogMessage(LogLevel.Error, message: "a"); + private static readonly IReadOnlyList LogMessages = new[] { new LogMessage(LogLevel.Warning, message: "b") }; + private const string TypeName = "c"; + + [Theory] + [MemberData(nameof(RemoteErrors))] + public void SerializeThenDeserialize_WithValidArguments_RoundTrips(RemoteError expectedResult) + { + RemoteError actualResult = SerializeThenDeserialize(RemoteErrorFormatter.Instance, expectedResult); + + Assert.Equal(expectedResult.ActivityLogMessage, actualResult.ActivityLogMessage); + TestUtility.AssertEqual(expectedResult.LogMessage, actualResult.LogMessage); + TestUtility.AssertEqual(expectedResult.LogMessages, actualResult.LogMessages); + Assert.Equal(expectedResult.ProjectContextLogMessage, actualResult.ProjectContextLogMessage); + Assert.Equal(expectedResult.TypeName, actualResult.TypeName); + } + + public static TheoryData RemoteErrors => new TheoryData + { + { + new RemoteError( + TypeName, + LogMessage, + logMessages: null, + projectContextLogMessage: null, + activityLogMessage: null) + }, + { + new RemoteError( + TypeName, + LogMessage, + LogMessages, + projectContextLogMessage: "d", + activityLogMessage: "e") + }, + }; + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetJsonRpcTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetJsonRpcTests.cs new file mode 100644 index 00000000000..94830e7fa86 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetJsonRpcTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Moq; +using StreamJsonRpc; +using StreamJsonRpc.Protocol; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + public class NuGetJsonRpcTests + { + [Fact] + public void GetErrorDetailsDataType_WhenErrorIsNull_CallsBase() + { + using (var rpc = new TestJsonRpc()) + { + Type type = rpc.GetErrorDetailsDataTypeHelper(error: null); + + Assert.Equal(typeof(CommonErrorData), type); + } + } + + [Fact] + public void GetErrorDetailsDataType_WhenErrorPropertyIsNull_CallsBase() + { + using (var rpc = new TestJsonRpc()) + { + Type type = rpc.GetErrorDetailsDataTypeHelper( + new JsonRpcError() + { + Error = null + }); + + Assert.Equal(typeof(CommonErrorData), type); + } + } + + [Fact] + public void GetErrorDetailsDataType_WhenErrorCodePropertyIsNotAMatch_CallsBase() + { + using (var rpc = new TestJsonRpc()) + { + Type type = rpc.GetErrorDetailsDataTypeHelper( + new JsonRpcError() + { + Error = new JsonRpcError.ErrorDetail() + { + Code = (JsonRpcErrorCode)int.MinValue + } + }); + + Assert.Equal(typeof(CommonErrorData), type); + } + } + + [Fact] + public void GetErrorDetailsDataType_WhenErrorCodePropertyIsAMatch_ReturnsRemoteErrorType() + { + using (var rpc = new TestJsonRpc()) + { + Type type = rpc.GetErrorDetailsDataTypeHelper( + new JsonRpcError() + { + Error = new JsonRpcError.ErrorDetail() + { + Code = (JsonRpcErrorCode)(int)RemoteErrorCode.RemoteError + } + }); + + Assert.Equal(typeof(RemoteError), type); + } + } + + private sealed class TestJsonRpc : NuGetJsonRpc + { + internal TestJsonRpc() + : base(Mock.Of()) + { + } + + internal Type GetErrorDetailsDataTypeHelper(JsonRpcError error) + { + return GetErrorDetailsDataType(error); + } + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/TestUtility.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/TestUtility.cs new file mode 100644 index 00000000000..91091f84d05 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/TestUtility.cs @@ -0,0 +1,95 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using NuGet.Common; +using NuGet.Packaging.Signing; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + internal static class TestUtility + { + internal static void AssertEqual(ILogMessage expectedResult, ILogMessage actualResult) + { + if (expectedResult is null) + { + Assert.Null(actualResult); + + return; + } + else + { + Assert.NotNull(actualResult); + } + + Assert.Equal(expectedResult.Code, actualResult.Code); + Assert.Equal(expectedResult.Level, actualResult.Level); + Assert.Equal(expectedResult.Message, actualResult.Message); + Assert.Equal(expectedResult.ProjectPath, actualResult.ProjectPath); + Assert.Equal(expectedResult.Time, actualResult.Time); + Assert.Equal(expectedResult.WarningLevel, actualResult.WarningLevel); + + if (expectedResult is PackagingLogMessage expectedPackagingResult) + { + Assert.IsType(actualResult); + + var actualPackagingResult = (PackagingLogMessage)actualResult; + + Assert.Equal(expectedPackagingResult.EndColumnNumber, actualPackagingResult.EndColumnNumber); + Assert.Equal(expectedPackagingResult.EndLineNumber, actualPackagingResult.EndLineNumber); + Assert.Equal(expectedPackagingResult.FilePath, actualPackagingResult.FilePath); + Assert.Equal(expectedPackagingResult.StartColumnNumber, actualPackagingResult.StartColumnNumber); + Assert.Equal(expectedPackagingResult.StartLineNumber, actualPackagingResult.StartLineNumber); + } + else if (expectedResult is RestoreLogMessage expectedRestoreResult) + { + Assert.IsType(actualResult); + + var actualRestoreResult = (RestoreLogMessage)actualResult; + + Assert.Equal(expectedRestoreResult.EndColumnNumber, actualRestoreResult.EndColumnNumber); + Assert.Equal(expectedRestoreResult.EndLineNumber, actualRestoreResult.EndLineNumber); + Assert.Equal(expectedRestoreResult.FilePath, actualRestoreResult.FilePath); + Assert.Equal(expectedRestoreResult.LibraryId, actualRestoreResult.LibraryId); + Assert.Equal(expectedRestoreResult.ShouldDisplay, actualRestoreResult.ShouldDisplay); + Assert.Equal(expectedRestoreResult.StartColumnNumber, actualRestoreResult.StartColumnNumber); + Assert.Equal(expectedRestoreResult.StartLineNumber, actualRestoreResult.StartLineNumber); + Assert.Equal(expectedRestoreResult.TargetGraphs, actualRestoreResult.TargetGraphs); + } + else if (expectedResult is SignatureLog expectedSignatureResult) + { + Assert.IsType(actualResult); + + var actualSignatureResult = (SignatureLog)actualResult; + + Assert.Equal(expectedSignatureResult.LibraryId, actualSignatureResult.LibraryId); + } + else + { + Assert.IsType(expectedResult); + Assert.IsType(actualResult); + } + } + + internal static void AssertEqual( + IReadOnlyList expectedResults, + IReadOnlyList actualResults) + { + if (expectedResults is null) + { + Assert.Null(actualResults); + } + else + { + Assert.NotNull(actualResults); + Assert.Equal(expectedResults.Count, actualResults.Count); + + for (var i = 0; i < expectedResults.Count; ++i) + { + TestUtility.AssertEqual(expectedResults[i], actualResults[i]); + } + } + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorTests.cs new file mode 100644 index 00000000000..48c8ae9c046 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorTests.cs @@ -0,0 +1,87 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using NuGet.Common; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + public class RemoteErrorTests + { + private const string ActivityLogMessage = "a"; + private static readonly LogMessage LogMessage = new LogMessage(LogLevel.Error, message: "b"); + private static readonly IReadOnlyList LogMessages = new[] + { + new LogMessage(LogLevel.Warning, message: "c") + }; + private const string ProjectContextLogMessage = "d"; + private const string TypeName = "e"; + + [Theory] + [InlineData(null)] + [InlineData("")] + public void Constructor_WhenTypeNameIsNullOrEmpty_Throws(string typeName) + { + ArgumentException exception = Assert.Throws( + () => new RemoteError( + typeName, + LogMessage, + LogMessages, + ProjectContextLogMessage, + ActivityLogMessage)); + + Assert.StartsWith("The argument cannot be null or empty.", exception.Message); + Assert.Equal("typeName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenLogMessageIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new RemoteError( + TypeName, + logMessage: null, + LogMessages, + ProjectContextLogMessage, + ActivityLogMessage)); + + Assert.Equal("logMessage", exception.ParamName); + } + + [Fact] + public void Constructor_WhenArgumentsAreValid_InitializesProperties() + { + var error = new RemoteError( + TypeName, + LogMessage, + LogMessages, + ProjectContextLogMessage, + ActivityLogMessage); + + Assert.Equal(ActivityLogMessage, error.ActivityLogMessage); + TestUtility.AssertEqual(LogMessage, error.LogMessage); + TestUtility.AssertEqual(LogMessages, error.LogMessages); + Assert.Equal(ProjectContextLogMessage, error.ProjectContextLogMessage); + Assert.Equal(TypeName, error.TypeName); + } + + [Fact] + public void Constructor_WhenNullableArgumentsAreNull_InitializesProperties() + { + var error = new RemoteError( + TypeName, + LogMessage, + logMessages: null, + projectContextLogMessage: null, + activityLogMessage: null); + + Assert.Null(error.ActivityLogMessage); + TestUtility.AssertEqual(LogMessage, error.LogMessage); + Assert.Null(error.LogMessages); + Assert.Null(error.ProjectContextLogMessage); + Assert.Equal(TypeName, error.TypeName); + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorUtilityTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorUtilityTests.cs new file mode 100644 index 00000000000..07e838314ef --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/Utility/RemoteErrorUtilityTests.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + public class RemoteErrorUtilityTests + { + [Fact] + public void ToRemoteError_WhenExceptionIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => RemoteErrorUtility.ToRemoteError(exception: null)); + + Assert.Equal("exception", exception.ParamName); + } + } +} From 4b8e34c959b87474434e62b7d88f5135b278e58a Mon Sep 17 00:00:00 2001 From: cmanu Date: Fri, 16 Oct 2020 09:52:56 -0700 Subject: [PATCH 005/129] Disable cpvm transitive pinning. (#3719) Disable cpvm transitive pinning. --- .../PackageSpecReferenceDependencyProvider.cs | 3 +- .../RestoreNETCoreTest.cs | 76 ++++++++++++++++++- .../PackCommandTests.cs | 2 +- .../RestoreCommandTests.cs | 3 +- .../NuGet.Commands.Test/RestoreRunnerTests.cs | 2 +- ...ageSpecReferenceDependencyProviderTests.cs | 2 +- 6 files changed, 82 insertions(+), 6 deletions(-) diff --git a/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs b/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs index 3b392123b7c..f0d56e0540b 100644 --- a/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs +++ b/src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs @@ -326,6 +326,7 @@ internal static List GetSpecDependencies( var targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework); dependencies.AddRange(targetFrameworkInfo.Dependencies); +#if enableCPVMTransitivePinning if (packageSpec.RestoreMetadata?.CentralPackageVersionsEnabled == true) { var dependencyNamesSet = new HashSet(targetFrameworkInfo.Dependencies.Select(d => d.Name), StringComparer.OrdinalIgnoreCase); @@ -338,7 +339,7 @@ internal static List GetSpecDependencies( ReferenceType = LibraryDependencyReferenceType.None, })); } - +#endif // Remove all framework assemblies dependencies.RemoveAll(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference); diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs index c409a25b117..6d4268dcf0a 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs @@ -9795,7 +9795,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( /// P will be accepted (because its parent B is Accepted) /// S will be accepted (because its parent O 300 is Accepted) /// - [Fact] + [Fact(Skip = "https://github.com/NuGet/Home/issues/10133")] public async Task RestoreNetCore_CPVMProject_MultipleLinkedCentralTransitiveDepenencies() { // Arrange @@ -10060,6 +10060,80 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( } } + [Fact] + public async Task RestoreNetCore_CPVMProject_TransitiveDependenciesAreNotPinned() + { + // Arrange + using (var pathContext = new SimpleTestPathContext()) + { + // Set up solution, project, and packages + var solution = new SimpleTestSolutionContext(pathContext.SolutionRoot); + var packagesForSource = new List(); + var packagesForProject = new List(); + var framework = FrameworkConstants.CommonFrameworks.NetCoreApp20; + + SimpleTestPackageContext createTestPackage(string name, string version, List source) + { + var result = new SimpleTestPackageContext() + { + Id = name, + Version = version + }; + result.Files.Clear(); + source.Add(result); + return result; + }; + + var projectA = SimpleTestProjectContext.CreateNETCore( + "projectA", + pathContext.SolutionRoot, + framework); + projectA.Properties.Add("ManagePackageVersionsCentrally", "true"); + + // the package references defined in the project should not have version + var packageBNoVersion = createTestPackage("B", null, packagesForProject); + var packageB100 = createTestPackage("B", "1.0.0", packagesForSource); + var packageC100 = createTestPackage("C", "1.0.0", packagesForSource); + var packageC200 = createTestPackage("C", "2.0.0", packagesForSource); + + packageB100.Dependencies.Add(packageC100); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + packagesForSource.ToArray()); + + projectA.AddPackageToAllFrameworks(packagesForProject.ToArray()); + + var cpvmFile = CentralPackageVersionsManagementFile.Create(pathContext.SolutionRoot) + .AddPackageVersion("B", "1.0.0") + .AddPackageVersion("C", "2.0.0"); + + solution.Projects.Add(projectA); + solution.CentralPackageVersionsManagementFile = cpvmFile; + solution.Create(pathContext.SolutionRoot); + + // Act + var r = Util.RestoreSolution(pathContext); + + // Assert + r.Success.Should().BeTrue(); + Assert.True(File.Exists(projectA.AssetsFileOutputPath)); + + var assetFileReader = new LockFileFormat(); + var assetsFile = assetFileReader.Read(projectA.AssetsFileOutputPath); + + var expectedLibraries = new List() { "B.1.0.0", "C.1.0.0" }; + var libraries = assetsFile.Libraries.Select(l => $"{l.Name}.{l.Version}").OrderBy(n => n).ToList(); + Assert.Equal(expectedLibraries, libraries); + + var centralfileDependencyGroups = assetsFile + .CentralTransitiveDependencyGroups + .SelectMany(g => g.TransitiveDependencies.Select(t => $"{g.FrameworkName}_{t.LibraryRange.Name}.{t.LibraryRange.VersionRange.OriginalString}")).ToList(); + + Assert.Equal(0, centralfileDependencyGroups.Count); + } + } + private static byte[] GetTestUtilityResource(string name) { return ResourceTestUtility.GetResourceBytes( diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs index 40390238ca2..54181f944c5 100644 --- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs @@ -4425,7 +4425,7 @@ public void PackCommand_WhenUsingSemver2Version_NU5105_IsNotRaised() } } - [PlatformFact(Platform.Windows)] + [PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Home/issues/10133")] public void PackCommand_PackProjectWithCentralTransitiveDependencies() { using (var testDirectory = msbuildFixture.CreateTestDirectory()) diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs index bfd237bf11f..69e0d76d18a 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs @@ -1569,7 +1569,7 @@ public async Task RestoreCommand_LogDowngradeWarningsOrErrorsAsync_ErrorWhenCpvm Assert.Equal(NuGetLogCode.NU1109, logMessage.Code); } - [Fact] + [Fact(Skip = "https://github.com/NuGet/Home/issues/10133")] public async Task RestoreCommand_DowngradeIsErrorWhen_DowngradedByCentralTransitiveDependency() { // Arrange @@ -1983,6 +1983,7 @@ public async Task RestoreCommand_CentralVersion_AssetsFile_VerifyProjectsReferen Assert.True(targetLib.Dependencies.Where(d => d.Id == packageName).Any()); } } + private static TargetFrameworkInformation CreateTargetFrameworkInformation(List dependencies, List centralVersionsDependencies, NuGetFramework framework = null) { NuGetFramework nugetFramework = framework ?? new NuGetFramework("net40"); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreRunnerTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreRunnerTests.cs index 7d8a4f72b2e..e64664e19a4 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreRunnerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreRunnerTests.cs @@ -1896,7 +1896,7 @@ public async Task RestoreRunner_FrameworkReferenceIsProjectToProjectTransitive() } } - [Fact] + [Fact(Skip = "https://github.com/NuGet/Home/issues/10133")] public async Task RestoreRunner_ExecuteAndCommit_ProjectAssetsIsNotCommitedIfNotChanged() { var assetsFileName = "project.assets.json"; diff --git a/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/PackageSpecReferenceDependencyProviderTests.cs b/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/PackageSpecReferenceDependencyProviderTests.cs index d960867e5dc..ff31b925783 100644 --- a/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/PackageSpecReferenceDependencyProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/PackageSpecReferenceDependencyProviderTests.cs @@ -13,7 +13,7 @@ namespace NuGet.ProjectModel.Test { public class PackageSpecReferenceDependencyProviderTests { - [Theory] + [Theory(Skip = "https://github.com/NuGet/Home/issues/10133")] [InlineData(true)] [InlineData(false)] public void GetSpecDependencies_AddsCentralPackageVersionsIfDefined(bool cpvmEnabled) From 30d80e2668bca6752fc85ac6f1e75b9a1ae17497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Fri, 16 Oct 2020 13:33:05 -0700 Subject: [PATCH 006/129] correctly suppress aliased dependencies according to request (#3717) Fixes: https://github.com/nuget/home/issues/10097 --- .../NuGet.Build.Tasks.Pack/PackTaskLogic.cs | 19 +++++++++- .../PackCommandTests.cs | 36 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs b/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs index 5398346fc39..e7174729f32 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs @@ -219,13 +219,30 @@ public PackageBuilder GetPackageBuilder(IPackTaskRequest request) .ToDictionary(msbuildItem => msbuildItem.Identity, msbuildItem => msbuildItem.GetProperty("ProjectVersion"), PathUtility.GetStringComparerBasedOnOS()); } + + var aliases = new Dictionary(); + foreach (var tfm in assetsFile.PackageSpec.TargetFrameworks) + { + aliases[tfm.TargetAlias] = tfm.FrameworkName.GetShortFolderName(); + } + var nuGetFrameworkComparer = new NuGetFrameworkFullComparer(); var frameworksWithSuppressedDependencies = new HashSet(nuGetFrameworkComparer); if (request.FrameworksWithSuppressedDependencies != null && request.FrameworksWithSuppressedDependencies.Any()) { frameworksWithSuppressedDependencies = new HashSet(request.FrameworksWithSuppressedDependencies - .Select(t => NuGetFramework.Parse(t.Identity)).ToList(), nuGetFrameworkComparer); + .Select(t => + { + if (aliases.TryGetValue(t.Identity, out string translated)) + { + return NuGetFramework.Parse(translated); + } + else + { + return NuGetFramework.Parse(t.Identity); + } + }).ToList(), nuGetFrameworkComparer); } PopulateProjectAndPackageReferences(builder, diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs index 54181f944c5..68c1e46e49d 100644 --- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs @@ -73,6 +73,42 @@ public void PackCommand_PackNewDefaultProject_NupkgExists() } } + [PlatformFact(Platform.Windows)] + public void PackCommand_PackToolUsingAlias_DoesNotWarnAboutNoExactMatchInDependencyGroupAndLibRefDirectories() + { + // Ref: https://github.com/NuGet/Home/issues/10097 + using (var testDirectory = msbuildFixture.CreateTestDirectory()) + { + // Arrange + var projectName = "ConsoleApp1"; + var workingDirectory = Path.Combine(testDirectory, projectName); + msbuildFixture.CreateDotnetNewProject(testDirectory.Path, projectName, " console"); + var projectFile = Path.Combine(workingDirectory, $"{projectName}.csproj"); + using (var stream = new FileStream(projectFile, FileMode.Open, FileAccess.ReadWrite)) + { + var xml = XDocument.Load(stream); + + ProjectFileUtils.AddProperty(xml, "PackAsTool", "true"); + ProjectFileUtils.ChangeProperty(xml, "TargetFramework", "myalias"); + + var tfmProps = new Dictionary(); + tfmProps["TargetFrameworkIdentifier"] = ".NETCoreApp"; + tfmProps["TargetFrameworkVersion"] = "v3.1"; + tfmProps["TargetFrameworkMoniker"] = ".NETCoreApp,Version=v3.1"; + ProjectFileUtils.AddProperties(xml, tfmProps, " '$(TargetFramework)' == 'myalias' "); + + ProjectFileUtils.WriteXmlToFile(xml, stream); + } + + // Act + msbuildFixture.RestoreProject(workingDirectory, projectName, string.Empty); + var result = msbuildFixture.PackProject(workingDirectory, projectName, $"-o {workingDirectory}"); + + // Assert + result.AllOutput.Should().NotContain("NU5128"); + } + } + [PlatformFact(Platform.Windows)] public void PackCommand_PackNewDefaultProject_IncludeSymbolsWithSnupkg() { From 9fb8c4b96a8807938b1b30fef964e70985d15fa3 Mon Sep 17 00:00:00 2001 From: Nirmal Guru Date: Mon, 19 Oct 2020 22:49:38 +0530 Subject: [PATCH 007/129] Fix output path issues with customized builds (#3270) * Move output paths default initialization out of the target This fixes a host of path related issues when doing a customized build with Pack targets. It also obsoletes the 'PackageOutputPath' in the SDK's 'DefaultOutputPaths' targets. It also ensures non-sdk style projects doesn't have to specify some default paths. * Remove default value to PackageOutputPath The Default is now implied and points to the same directory. It is now redundant, and by removing it, the tests should not fail. * Added new Tests to check default output paths - Checks the default output paths from Project/Solution builds. - Check both the default and custom paths from continuous Project/Solution builds. * Remove duplicate logic inside the target The duplicate logic is not needed. (edited anyway but will push if anyone approves) --- .../NuGet.Build.Tasks.Pack.targets | 61 +++--- .../NuGetPackCommandTest.cs | 1 - .../PackCommandTests.cs | 189 +++++++++++++++++- 3 files changed, 225 insertions(+), 26 deletions(-) diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.targets b/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.targets index 018be43c8af..7843482da0f 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.targets +++ b/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.targets @@ -43,7 +43,6 @@ Copyright (c) .NET Foundation. All rights reserved. true symbols.nupkg DeterminePortableBuildCapabilities - $(BaseIntermediateOutputPath)$(Configuration)\ false false .dll; .exe; .winmd; .json; .pri; .xml; $(AllowedOutputExtensionsInPackageBuildOutputFolder) @@ -70,8 +69,22 @@ Copyright (c) .NET Foundation. All rights reserved. - + + $(MSBuildProjectExtensionsPath) + $(BaseOutputPath)$(Configuration)\ + $(BaseIntermediateOutputPath)$(Configuration)\ + + + + + + + @@ -80,6 +93,19 @@ Copyright (c) .NET Foundation. All rights reserved. + + + + + + false - - $(OutputPath) - $(MSBuildProjectExtensionsPath) - - - - - - - - - - - - - - @@ -203,6 +212,11 @@ Copyright (c) .NET Foundation. All rights reserved. Condition="$(IsPackable) == 'true'" Inputs="@(NuGetPackInput)" Outputs="@(NuGetPackOutput)" DependsOnTargets="$(GenerateNuspecDependsOn);_CalculateInputsOutputsForPack;_GetProjectReferenceVersions;_InitializeNuspecRepositoryInformationProperties"> + + + + + - - - + DependsOnTargets="_GetAbsoluteOutputPathsForPack;$(GetPackageVersionDependsOn)"> + + diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs index 086042d86cd..a19efe1430a 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs @@ -6070,7 +6070,6 @@ public void PackCommand_ProjectFile_PackageIconUrl_WithNuspec_WithPackTask_Warns out v4.0 https://test/icon.jpg - bin\Debug\ Alice diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs index 68c1e46e49d..2bc96eb23e7 100644 --- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs @@ -28,6 +28,194 @@ public PackCommandTests(MsbuildIntegrationTestFixture fixture) msbuildFixture = fixture; } + [PlatformFact(Platform.Windows)] + public void PackCommand_NewProject_OutputsInDefaultPaths() + { + // Arrange + using (var testDirectory = TestDirectory.Create()) + { + var projectName = "ClassLibrary1"; + var workingDirectory = Path.Combine(testDirectory, projectName); + var nupkgPath = Path.Combine(workingDirectory, @"bin\Debug", $"{projectName}.1.0.0.nupkg"); + var nuspecPath = Path.Combine(workingDirectory, @"obj\Debug", $"{projectName}.1.0.0.nuspec"); + + // Act + msbuildFixture.CreateDotnetNewProject(testDirectory.Path, projectName, "classlib"); + msbuildFixture.PackProject(workingDirectory, projectName, string.Empty, null); + + // Assert + Assert.True(File.Exists(nupkgPath), "The output .nupkg is not in the default place"); + Assert.True(File.Exists(nuspecPath), "The intermediate nuspec file is not in the default place"); + } + } + + [PlatformFact(Platform.Windows)] + public void PackCommand_NewProject_ContinuousOutputInBothDefaultAndCustomPaths() + { + // Arrange + using (var testDirectory = TestDirectory.Create()) + { + var projectName = "ClassLibrary1"; + var workingDirectory = Path.Combine(testDirectory, projectName); + + msbuildFixture.CreateDotnetNewProject(testDirectory.Path, projectName, "classlib"); + msbuildFixture.RestoreProject(workingDirectory, projectName, string.Empty); + msbuildFixture.BuildProject(workingDirectory, projectName, string.Empty); + + // With default output path + var nupkgPath = Path.Combine(workingDirectory, @"bin\Debug", $"{projectName}.1.0.0.nupkg"); + var nuspecPath = Path.Combine(workingDirectory, @"obj\Debug", $"{projectName}.1.0.0.nuspec"); + + // Act + msbuildFixture.PackProject(workingDirectory, projectName, "--no-build", null); + + // Assert + Assert.True(File.Exists(nupkgPath), "The output .nupkg is not in the default place"); + Assert.True(File.Exists(nuspecPath), "The intermediate nuspec file is not in the default place"); + + // With custom output path + var publishDir = Path.Combine(workingDirectory, "publish"); + nupkgPath = Path.Combine(publishDir, $"{projectName}.1.0.0.nupkg"); + nuspecPath = Path.Combine(publishDir, $"{projectName}.1.0.0.nuspec"); + + // Act + msbuildFixture.PackProject(workingDirectory, projectName, $"--no-build -o {publishDir}", publishDir); + + // Assert + Assert.True(File.Exists(nupkgPath), "The output .nupkg is not in the expected place"); + Assert.True(File.Exists(nuspecPath), "The intermediate nuspec file is not in the expected place"); + } + } + + [PlatformFact(Platform.Windows)] + public void PackCommand_NewSolution_OutputInDefaultPaths() + { + // Arrange + using (var testDirectory = TestDirectory.Create()) + { + var solutionName = "Solution1"; + var projectName = "ClassLibrary1"; + var referencedProject1 = "ClassLibrary2"; + var referencedProject2 = "ClassLibrary3"; + + var projectAndReference1Folder = "Src"; + var reference2Folder = "src"; + + var projectFolder = Path.Combine(testDirectory.Path, projectAndReference1Folder, projectName); + + var projectFileRelativ = Path.Combine(projectAndReference1Folder, projectName, $"{projectName}.csproj"); + var referencedProject1RelativDir = Path.Combine(projectAndReference1Folder, referencedProject1, $"{referencedProject1}.csproj"); + var referencedProject2RelativDir = Path.Combine(reference2Folder, referencedProject2, $"{referencedProject2}.csproj"); + + msbuildFixture.CreateDotnetNewProject(Path.Combine(testDirectory.Path, projectAndReference1Folder), projectName, "classlib"); + msbuildFixture.CreateDotnetNewProject(Path.Combine(testDirectory.Path, projectAndReference1Folder), referencedProject1, "classlib"); + msbuildFixture.CreateDotnetNewProject(Path.Combine(testDirectory.Path, reference2Folder), referencedProject2, "classlib"); + + msbuildFixture.RunDotnet(testDirectory.Path, $"new solution -n {solutionName}"); + msbuildFixture.RunDotnet(testDirectory.Path, $"sln {solutionName}.sln add {projectFileRelativ}"); + msbuildFixture.RunDotnet(testDirectory.Path, $"sln {solutionName}.sln add {referencedProject1RelativDir}"); + msbuildFixture.RunDotnet(testDirectory.Path, $"sln {solutionName}.sln add {referencedProject2RelativDir}"); + + var projectFile = Path.Combine(testDirectory.Path, projectFileRelativ); + using (var stream = new FileStream(projectFile, FileMode.Open, FileAccess.ReadWrite)) + { + var xml = XDocument.Load(stream); + var attributes = new Dictionary(); + var properties = new Dictionary(); + + ProjectFileUtils.AddItem(xml, "ProjectReference", @"..\ClassLibrary2\ClassLibrary2.csproj", string.Empty, properties, attributes); + ProjectFileUtils.AddItem(xml, "ProjectReference", @"..\ClassLibrary3\ClassLibrary3.csproj", string.Empty, properties, attributes); + + ProjectFileUtils.WriteXmlToFile(xml, stream); + } + + msbuildFixture.RestoreSolution(testDirectory, solutionName, string.Empty); + + var nupkgPath = Path.Combine(projectFolder, @"bin\Debug", $"{projectName}.1.0.0.nupkg"); + var nuspecPath = Path.Combine(projectFolder, @"obj\Debug", $"{projectName}.1.0.0.nuspec"); + + // Act + msbuildFixture.PackSolution(testDirectory, solutionName, string.Empty, null); + + // Assert + Assert.True(File.Exists(nupkgPath), "The output .nupkg is not in the default place"); + Assert.True(File.Exists(nuspecPath), "The intermediate nuspec file is not in the default place"); + } + } + + [PlatformFact(Platform.Windows)] + public void PackCommand_NewSolution_ContinuousOutputInBothDefaultAndCustomPaths() + { + // Arrange + using (var testDirectory = TestDirectory.Create()) + { + var solutionName = "Solution1"; + var projectName = "ClassLibrary1"; + var referencedProject1 = "ClassLibrary2"; + var referencedProject2 = "ClassLibrary3"; + + var projectAndReference1Folder = "Src"; + var reference2Folder = "src"; + + var projectFolder = Path.Combine(testDirectory.Path, projectAndReference1Folder, projectName); + + var projectFileRelativ = Path.Combine(projectAndReference1Folder, projectName, $"{projectName}.csproj"); + var referencedProject1RelativDir = Path.Combine(projectAndReference1Folder, referencedProject1, $"{referencedProject1}.csproj"); + var referencedProject2RelativDir = Path.Combine(reference2Folder, referencedProject2, $"{referencedProject2}.csproj"); + + msbuildFixture.CreateDotnetNewProject(Path.Combine(testDirectory.Path, projectAndReference1Folder), projectName, "classlib"); + msbuildFixture.CreateDotnetNewProject(Path.Combine(testDirectory.Path, projectAndReference1Folder), referencedProject1, "classlib"); + msbuildFixture.CreateDotnetNewProject(Path.Combine(testDirectory.Path, reference2Folder), referencedProject2, "classlib"); + + msbuildFixture.RunDotnet(testDirectory.Path, $"new solution -n {solutionName}"); + msbuildFixture.RunDotnet(testDirectory.Path, $"sln {solutionName}.sln add {projectFileRelativ}"); + msbuildFixture.RunDotnet(testDirectory.Path, $"sln {solutionName}.sln add {referencedProject1RelativDir}"); + msbuildFixture.RunDotnet(testDirectory.Path, $"sln {solutionName}.sln add {referencedProject2RelativDir}"); + + var projectFile = Path.Combine(testDirectory.Path, projectFileRelativ); + using (var stream = new FileStream(projectFile, FileMode.Open, FileAccess.ReadWrite)) + { + var xml = XDocument.Load(stream); + var attributes = new Dictionary(); + var properties = new Dictionary(); + + ProjectFileUtils.AddItem(xml, "ProjectReference", @"..\ClassLibrary2\ClassLibrary2.csproj", string.Empty, properties, attributes); + ProjectFileUtils.AddItem(xml, "ProjectReference", @"..\ClassLibrary3\ClassLibrary3.csproj", string.Empty, properties, attributes); + + ProjectFileUtils.WriteXmlToFile(xml, stream); + } + + msbuildFixture.RestoreSolution(testDirectory, solutionName, string.Empty); + msbuildFixture.BuildSolution(testDirectory, solutionName, string.Empty); + + // With default output path within project folder + + // Arrange + var nupkgPath = Path.Combine(projectFolder, @"bin\Debug", $"{projectName}.1.0.0.nupkg"); + var nuspecPath = Path.Combine(projectFolder, @"obj\Debug", $"{projectName}.1.0.0.nuspec"); + + // Act + msbuildFixture.PackSolution(testDirectory, solutionName, "--no-build", null); + + // Assert + Assert.True(File.Exists(nupkgPath), "The output .nupkg is not in the default place"); + Assert.True(File.Exists(nuspecPath), "The intermediate nuspec file is not in the default place"); + + // With common publish path within solution folder + + // Arrange + var publishDir = Path.Combine(testDirectory.Path, "publish"); + nupkgPath = Path.Combine(publishDir, $"{projectName}.1.0.0.nupkg"); + nuspecPath = Path.Combine(publishDir, $"{projectName}.1.0.0.nuspec"); + + msbuildFixture.PackSolution(testDirectory, solutionName, $"--no-build -o {publishDir}", publishDir); + + // Assert + Assert.True(File.Exists(nupkgPath), "The output .nupkg is not in the expected place"); + Assert.True(File.Exists(nuspecPath), "The intermediate nuspec file is not in the expected place"); + } + } + [PlatformFact(Platform.Windows)] public void PackCommand_PackNewDefaultProject_NupkgExists() { @@ -4410,7 +4598,6 @@ public void PackCommand_PackIcon_WithNuspec_IconUrl_Warns_Succeeds() projectBuilder .WithProjectName("test") .WithProperty("Authors", "Alice") - .WithProperty("PackageOutputPath", "bin\\Debug\\") .WithProperty("NuspecFile", "test.nuspec") .WithPackageIconUrl("https://test/icon.jpg"); From 13867d1bcbcae888b0bcf862eee7a2070e743af7 Mon Sep 17 00:00:00 2001 From: Fernando Aguilar Date: Mon, 19 Oct 2020 10:35:19 -0700 Subject: [PATCH 008/129] Adds telemetry to count projects based on ProjectType (#3705) Fixes https://github.com/NuGet/Client.Engineering/issues/431 --- .../SolutionRestoreJob.cs | 12 +++- .../Telemetry/RestoreTelemetryEvent.cs | 28 ++++++++++ ....cs => CpsPackageReferenceProjectTests.cs} | 56 +++++++++---------- ...PackageManagement.VisualStudio.Test.csproj | 2 +- .../Telemetry/RestoreTelemetryServiceTests.cs | 34 +++++++++-- 5 files changed, 98 insertions(+), 34 deletions(-) rename test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/{NetCorePackageReferenceProjectTests.cs => CpsPackageReferenceProjectTests.cs} (97%) diff --git a/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs b/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs index d15bde2324f..c07ca193ed4 100644 --- a/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs +++ b/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft; +using Microsoft.VisualStudio.Services.Common; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; using NuGet.Commands; @@ -297,6 +298,9 @@ private void EmitRestoreTelemetryEvent(IEnumerable projects, project => project.GetMetadata(NuGetProjectMetadataKeys.UniqueName)); var projectIds = sortedProjects.Select( project => project.GetMetadata(NuGetProjectMetadataKeys.ProjectId)).ToArray(); + var projectDictionary = sortedProjects + .GroupBy(x => x.ProjectStyle) + .ToDictionary(x => x.Key, y => y.Count()); var restoreTelemetryEvent = new RestoreTelemetryEvent( _nuGetProjectContext.OperationId.ToString(), @@ -308,6 +312,13 @@ private void EmitRestoreTelemetryEvent(IEnumerable projects, packageCount: _packageCount, noOpProjectsCount: _noOpProjectsCount, upToDateProjectsCount: _upToDateProjectCount, + unknownProjectsCount: projectDictionary.GetValueOrDefault(ProjectStyle.Unknown, 0), // appears in DependencyGraphRestoreUtility + projectJsonProjectsCount: projectDictionary.GetValueOrDefault(ProjectStyle.ProjectJson, 0), + packageReferenceProjectsCount: projectDictionary.GetValueOrDefault(ProjectStyle.PackageReference, 0), + legacyPackageReferenceProjectsCount: sortedProjects.Where(x => x.ProjectStyle == ProjectStyle.PackageReference && x is LegacyPackageReferenceProject).Count(), + cpsPackageReferenceProjectsCount: sortedProjects.Where(x => x.ProjectStyle == ProjectStyle.PackageReference && x is CpsPackageReferenceProject).Count(), + dotnetCliToolProjectsCount: projectDictionary.GetValueOrDefault(ProjectStyle.DotnetCliTool, 0), // appears in DependencyGraphRestoreUtility + packagesConfigProjectsCount: projectDictionary.GetValueOrDefault(ProjectStyle.PackagesConfig, 0), DateTimeOffset.Now, duration, isSolutionLoadRestore: _isSolutionLoadRestore, @@ -342,7 +353,6 @@ private async Task RestorePackageSpecProjectsAsync( var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(_settings); if (!Path.IsPathRooted(globalPackagesFolder)) { - var message = string.Format( CultureInfo.CurrentCulture, Resources.RelativeGlobalPackagesFolder, diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/RestoreTelemetryEvent.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/RestoreTelemetryEvent.cs index 8bfdce7e7a0..fa6b37cafd4 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/RestoreTelemetryEvent.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/RestoreTelemetryEvent.cs @@ -28,6 +28,13 @@ public RestoreTelemetryEvent( int packageCount, int noOpProjectsCount, int upToDateProjectsCount, + int unknownProjectsCount, + int projectJsonProjectsCount, + int packageReferenceProjectsCount, + int legacyPackageReferenceProjectsCount, + int cpsPackageReferenceProjectsCount, + int dotnetCliToolProjectsCount, + int packagesConfigProjectsCount, DateTimeOffset endTime, double duration, bool isSolutionLoadRestore, @@ -36,6 +43,13 @@ public RestoreTelemetryEvent( base[nameof(OperationSource)] = source; base[nameof(NoOpProjectsCount)] = noOpProjectsCount; base[nameof(UpToDateProjectCount)] = upToDateProjectsCount; + base[nameof(UnknownProjectsCount)] = unknownProjectsCount; + base[nameof(ProjectJsonProjectsCount)] = projectJsonProjectsCount; + base[nameof(PackageReferenceProjectsCount)] = packageReferenceProjectsCount; + base[nameof(LegacyPackageReferenceProjectsCount)] = legacyPackageReferenceProjectsCount; + base[nameof(CpsPackageReferenceProjectsCount)] = cpsPackageReferenceProjectsCount; + base[nameof(DotnetCliToolProjectsCount)] = dotnetCliToolProjectsCount; + base[nameof(PackagesConfigProjectsCount)] = packagesConfigProjectsCount; base[nameof(ForceRestore)] = forceRestore; base[nameof(IsSolutionLoadRestore)] = isSolutionLoadRestore; @@ -56,5 +70,19 @@ public RestoreTelemetryEvent( public bool IsSolutionLoadRestore => (bool)base[nameof(IsSolutionLoadRestore)]; public int UpToDateProjectCount => (int)base[nameof(UpToDateProjectCount)]; + + public int UnknownProjectsCount => (int)base[nameof(UnknownProjectsCount)]; + + public int ProjectJsonProjectsCount => (int)base[nameof(ProjectJsonProjectsCount)]; + + public int PackageReferenceProjectsCount => (int)base[nameof(PackageReferenceProjectsCount)]; + + public int LegacyPackageReferenceProjectsCount => (int)base[nameof(LegacyPackageReferenceProjectsCount)]; + + public int CpsPackageReferenceProjectsCount => (int)base[nameof(CpsPackageReferenceProjectsCount)]; + + public int DotnetCliToolProjectsCount => (int)base[nameof(DotnetCliToolProjectsCount)]; + + public int PackagesConfigProjectsCount => (int)base[nameof(PackagesConfigProjectsCount)]; } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NetCorePackageReferenceProjectTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs similarity index 97% rename from test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NetCorePackageReferenceProjectTests.cs rename to test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs index d36c03cdab6..22d82566458 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NetCorePackageReferenceProjectTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs @@ -30,7 +30,7 @@ namespace NuGet.PackageManagement.VisualStudio.Test { - public class NetCorePackageReferenceProjectTests + public class CpsPackageReferenceProjectTests { [Fact] public async Task GetInstalledVersion_WithAssetsFile_ReturnsVersionsFromAssetsSpecs() @@ -44,7 +44,7 @@ public async Task GetInstalledVersion_WithAssetsFile_ReturnsVersionsFromAssetsSp // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpec(projectName, projectFullPath, "[2.0.0, )"); @@ -94,7 +94,7 @@ public async Task GetInstalledVersion_WithFloating_WithAssetsFile_ReturnsVersion // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpec(projectName, projectFullPath, "[*, )"); @@ -147,7 +147,7 @@ public async Task GetInstalledVersion_WithoutAssetsFile_ReturnsVersionsFromPacka // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpec(projectName, projectFullPath, "[2.0.0, )"); @@ -190,7 +190,7 @@ public async Task GetInstalledVersion_WithoutPackages_ReturnsEmpty() // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpecNoPackages(projectName, projectFullPath); @@ -234,7 +234,7 @@ public async Task GetInstalledVersion_WithASpecificVersionLowerThanAvailableOne_ // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpec(projectName, projectFullPath, "[2.0.0, )"); @@ -284,7 +284,7 @@ public async Task GetInstalledVersion_WithoutPackages_WithAssets_ReturnsEmpty() // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpecNoPackages(projectName, projectFullPath); @@ -333,7 +333,7 @@ public async Task GetInstalledVersions_WhenCalledMultipleTimes_ReturnsSameResult // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpecMultipleVersions(projectName, projectFullPath); @@ -394,7 +394,7 @@ public async Task GetInstalledVersion_WithAssetsFile_ChangingPackageSpec_Returns // Project var projectCache = new ProjectSystemCache(); IVsProjectAdapter projectAdapter = (new Mock()).Object; - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var packageSpec = GetPackageSpec(projectName, projectFullPath, "[2.0.0, )"); @@ -503,7 +503,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -638,7 +638,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -788,7 +788,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -938,7 +938,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1088,7 +1088,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1238,7 +1238,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1376,7 +1376,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1510,7 +1510,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1644,7 +1644,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1784,7 +1784,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. //project.IsNu1605Error = true; @@ -1882,7 +1882,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -1990,7 +1990,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -2145,7 +2145,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( { var projectName = $"project{i}"; var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); - var project = CreateTestNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. project.IsNu1605Error = true; @@ -2271,7 +2271,7 @@ public async Task GetInstalledPackages_WithNominationUpdate_ReloadsCache() // Project var projectCache = new ProjectSystemCache(); - var project = CreateNetCorePackageReferenceProject(projectName, projectFullPath, projectCache); + var project = CreateCpsPackageReferenceProject(projectName, projectFullPath, projectCache); var projectNames = GetTestProjectNames(projectFullPath, projectName); var originalSpec = GetPackageSpec(projectName, projectFullPath, "1.0.0"); @@ -2316,11 +2316,11 @@ public async Task GetInstalledPackages_WithNominationUpdate_ReloadsCache() } } - private TestNetCorePackageReferenceProject CreateTestNetCorePackageReferenceProject(string projectName, string projectFullPath, ProjectSystemCache projectSystemCache, TestProjectSystemServices projectServices = null) + private TestCpsPackageReferenceProject CreateTestCpsPackageReferenceProject(string projectName, string projectFullPath, ProjectSystemCache projectSystemCache, TestProjectSystemServices projectServices = null) { projectServices = projectServices == null ? new TestProjectSystemServices() : projectServices; - return new TestNetCorePackageReferenceProject( + return new TestCpsPackageReferenceProject( projectName: projectName, projectUniqueName: projectName, projectFullPath: projectFullPath, @@ -2330,7 +2330,7 @@ private TestNetCorePackageReferenceProject CreateTestNetCorePackageReferenceProj projectId: projectName); } - private CpsPackageReferenceProject CreateNetCorePackageReferenceProject(string projectName, string projectFullPath, ProjectSystemCache projectSystemCache) + private CpsPackageReferenceProject CreateCpsPackageReferenceProject(string projectName, string projectFullPath, ProjectSystemCache projectSystemCache) { var projectServices = new TestProjectSystemServices(); @@ -2418,7 +2418,7 @@ private static PackageSpec GetPackageSpecMultipleVersions(string projectName, st return JsonPackageSpecReader.GetPackageSpec(referenceSpec, projectName, testDirectory).WithTestRestoreMetadata(); } - private class TestNetCorePackageReferenceProject + private class TestCpsPackageReferenceProject : CpsPackageReferenceProject , IProjectScriptHostService , IProjectSystemReferencesReader @@ -2435,7 +2435,7 @@ private class TestNetCorePackageReferenceProject public HashSet ProjectLocalSources { get; set; } = new HashSet(); - public TestNetCorePackageReferenceProject( + public TestCpsPackageReferenceProject( string projectName, string projectUniqueName, string projectFullPath, diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj index 1f515a85e56..d5a7cf31fd1 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj @@ -25,7 +25,7 @@ - + diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/RestoreTelemetryServiceTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/RestoreTelemetryServiceTests.cs index 8892ded663d..412757fe474 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/RestoreTelemetryServiceTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/RestoreTelemetryServiceTests.cs @@ -40,8 +40,6 @@ public void RestoreTelemetryService_EmitRestoreEvent_OperationSucceed(bool force noopProjectsCount = 1; } - var stausMessage = status == NuGetOperationStatus.Failed ? "Operation Failed" : string.Empty; - var operationId = Guid.NewGuid().ToString(); var restoreTelemetryData = new RestoreTelemetryEvent( @@ -54,6 +52,13 @@ public void RestoreTelemetryService_EmitRestoreEvent_OperationSucceed(bool force packageCount: 2, noOpProjectsCount: noopProjectsCount, upToDateProjectsCount: 5, + unknownProjectsCount: 0, + projectJsonProjectsCount: 0, + packageReferenceProjectsCount: 0, + legacyPackageReferenceProjectsCount: 0, + cpsPackageReferenceProjectsCount: 0, + dotnetCliToolProjectsCount: 0, + packagesConfigProjectsCount: 1, endTime: DateTimeOffset.Now, duration: 2.10, isSolutionLoadRestore: true, @@ -100,6 +105,13 @@ public void RestoreTelemetryService_EmitRestoreEvent_IntervalsAreCaptured() packageCount: 1, noOpProjectsCount: 0, upToDateProjectsCount: 0, + unknownProjectsCount: 0, + projectJsonProjectsCount: 0, + packageReferenceProjectsCount: 1, + legacyPackageReferenceProjectsCount: 0, + cpsPackageReferenceProjectsCount: 1, + dotnetCliToolProjectsCount: 0, + packagesConfigProjectsCount: 0, endTime: DateTimeOffset.Now, duration: 2.10, isSolutionLoadRestore: true, @@ -114,7 +126,7 @@ public void RestoreTelemetryService_EmitRestoreEvent_IntervalsAreCaptured() Assert.NotNull(lastTelemetryEvent); Assert.Equal(RestoreTelemetryEvent.RestoreActionEventName, lastTelemetryEvent.Name); - Assert.Equal(15, lastTelemetryEvent.Count); + Assert.Equal(22, lastTelemetryEvent.Count); Assert.Equal(restoreTelemetryData.OperationSource.ToString(), lastTelemetryEvent["OperationSource"].ToString()); @@ -127,7 +139,7 @@ private void VerifyTelemetryEventData(string operationId, RestoreTelemetryEvent { Assert.NotNull(actual); Assert.Equal(RestoreTelemetryEvent.RestoreActionEventName, actual.Name); - Assert.Equal(13, actual.Count); + Assert.Equal(20, actual.Count); Assert.Equal(expected.OperationSource.ToString(), actual["OperationSource"].ToString()); @@ -135,8 +147,22 @@ private void VerifyTelemetryEventData(string operationId, RestoreTelemetryEvent Assert.Equal(expected.ForceRestore, (bool)actual["ForceRestore"]); Assert.Equal(expected.IsSolutionLoadRestore, (bool)actual["IsSolutionLoadRestore"]); Assert.Equal(expected.UpToDateProjectCount, (int)actual["UpToDateProjectCount"]); + Assert.Equal(expected.PackageReferenceProjectsCount, (int)actual["PackageReferenceProjectsCount"]); + Assert.Equal(expected.ProjectJsonProjectsCount, (int)actual["ProjectJsonProjectsCount"]); + Assert.Equal(expected.PackagesConfigProjectsCount, (int)actual["PackagesConfigProjectsCount"]); + Assert.Equal(expected.DotnetCliToolProjectsCount, (int)actual["DotnetCliToolProjectsCount"]); + Assert.Equal(expected.UnknownProjectsCount, (int)actual["UnknownProjectsCount"]); + Assert.Equal(expected.LegacyPackageReferenceProjectsCount, (int)actual["LegacyPackageReferenceProjectsCount"]); + Assert.Equal(expected.CpsPackageReferenceProjectsCount, (int)actual["CpsPackageReferenceProjectsCount"]); + AssertProjectsCount(expected); TestTelemetryUtility.VerifyTelemetryEventData(operationId, expected, actual); } + + private void AssertProjectsCount(RestoreTelemetryEvent t) + { + Assert.True(t.ProjectsCount >= t.PackageReferenceProjectsCount + t.ProjectJsonProjectsCount + t.PackagesConfigProjectsCount + t.DotnetCliToolProjectsCount + t.UnknownProjectsCount); + Assert.True(t.PackageReferenceProjectsCount >= t.LegacyPackageReferenceProjectsCount + t.CpsPackageReferenceProjectsCount); + } } } From 956b432b25b3e0ae56a011d4390e3e55ad4d1fae Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Mon, 19 Oct 2020 17:14:26 -0700 Subject: [PATCH 009/129] added a unit test to solution explorer dependencies tree generation logic (#3622) --- .../AssetsFileDependenciesSnapshotTests.cs | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/SolutionExplorer/Models/AssetsFileDependenciesSnapshotTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/SolutionExplorer/Models/AssetsFileDependenciesSnapshotTests.cs index 771bd57acf9..02e147a85ed 100644 --- a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/SolutionExplorer/Models/AssetsFileDependenciesSnapshotTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/SolutionExplorer/Models/AssetsFileDependenciesSnapshotTests.cs @@ -1,5 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using NuGet.ProjectModel; +using NuGet.Versioning; using NuGet.VisualStudio.SolutionExplorer.Models; using Xunit; @@ -57,5 +64,82 @@ public void ParseLibraries_IgnoreCaseInDependenciesTree_Succeeds() Assert.Equal(1, dependencies.Count); Assert.True(dependencies.ContainsKey("system.runtime")); } + + [Fact] + public void ParseLibraries_LockFileTargetLibrariesWithDifferentCase_Throws() + { + // Arrange + var lockFileTarget = new LockFileTarget(); + lockFileTarget.Libraries = new List + { + new LockFileTargetLibrary() + { + Name = "packageA", + Type = "package", + Version = NuGetVersion.Parse("1.0.0") + }, + new LockFileTargetLibrary() + { + Name = "PackageA", + Type = "package", + Version = NuGetVersion.Parse("1.0.0") + } + }; + + var exception = Assert.Throws(() => AssetsFileDependenciesSnapshot.ParseLibraries(lockFileTarget)); + + Assert.Contains("PackageA", exception.Message); + } + + [Fact] + public void ParseLibraries_LockFileTargetLibrariesMatchesDependencies_Succeeds() + { + // Arrange + var lockFileTarget = new LockFileTarget(); + lockFileTarget.Libraries = new List + { + new LockFileTargetLibrary() + { + Name = "packageA", + Type = "package", + Version = NuGetVersion.Parse("1.0.0") + }, + new LockFileTargetLibrary() + { + Name = "packageB", + Type = "package", + Version = NuGetVersion.Parse("1.0.0") + }, + new LockFileTargetLibrary() + { + Name = "projectA", + Type = "project", + Version = NuGetVersion.Parse("1.0.0") + }, + new LockFileTargetLibrary() + { + Name = "projectB", + Type = "project", + Version = NuGetVersion.Parse("1.0.0") + } + }; + + ImmutableDictionary dependencies = AssetsFileDependenciesSnapshot.ParseLibraries(lockFileTarget); + + Assert.Equal(lockFileTarget.Libraries.Count, dependencies.Count); + Assert.All(lockFileTarget.Libraries, + source => + { + Assert.True(dependencies.ContainsKey(source.Name)); + + AssetsFileTargetLibrary target = dependencies[source.Name]; + Assert.Equal(source.Name, target.Name); + Assert.Equal(source.Version.ToNormalizedString(), target.Version); + + AssetsFileLibraryType sourceType; + Assert.True(Enum.TryParse(source.Type, ignoreCase: true, out sourceType)); + Assert.Equal(sourceType, target.Type); + }); + } } } From e04c6700e02c44bc401c9867d2efef1de6c8fa86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 21 Oct 2020 15:08:12 -0700 Subject: [PATCH 010/129] raise error when missing tpv and platform present (#3691) Fixes: https://github.com/NuGet/Home/issues/9441 --- .../RestoreCommand/RestoreCommand.cs | 28 ++++- .../NuGet.Commands/Strings.Designer.cs | 9 ++ src/NuGet.Core/NuGet.Commands/Strings.resx | 4 + .../NuGet.Common/Errors/NuGetLogCode.cs | 17 ++- .../PublicAPI/net45/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net472/PublicAPI.Unshipped.txt | 1 + .../netstandard2.0/PublicAPI.Unshipped.txt | 1 + .../Authoring/PackageBuilder.cs | 106 +++++++++++++++- .../NuGet.Packaging/Strings.Designer.cs | 45 +++++++ src/NuGet.Core/NuGet.Packaging/Strings.resx | 22 +++- .../RestoreCommandTests.cs | 66 ++++++++++ .../PackageBuilderTest.cs | 116 +++++++++++++++++- 12 files changed, 401 insertions(+), 15 deletions(-) diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs index c0b5b8bfe9b..571733f3229 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs @@ -181,6 +181,8 @@ public async Task ExecuteAsync(CancellationToken token) _success = false; } + _success &= HasValidPlatformVersions(); + // evaluate packages.lock.json file var packagesLockFilePath = PackagesLockFileUtilities.GetNuGetLockFilePath(_request.Project); var isLockFileValid = false; @@ -404,6 +406,26 @@ public async Task ExecuteAsync(CancellationToken token) } } + private bool HasValidPlatformVersions() + { + IEnumerable badPlatforms = _request.Project.TargetFrameworks + .Select(frameworkInfo => frameworkInfo.FrameworkName) + .Where(framework => !string.IsNullOrEmpty(framework.Platform) && (framework.PlatformVersion == FrameworkConstants.EmptyVersion)); + + if (badPlatforms.Any()) + { + _logger.Log(RestoreLogMessage.CreateError( + NuGetLogCode.NU1012, + string.Format(CultureInfo.CurrentCulture, Strings.Error_PlatformVersionNotPresent, string.Join(", ", badPlatforms)) + )); + return false; + } + else + { + return true; + } + } + private async Task AreCentralVersionRequirementsSatisfiedAsync() { // The dependencies should not have versions explicitelly defined if cpvm is enabled. @@ -627,7 +649,7 @@ private bool ValidatePackagesSha512(PackagesLockFile lockFile, LockFile assetsFi { if (!noOp) { - // Clean up to preserve the pre no-op behavior. This should not be used, but we want to be cautious. + // Clean up to preserve the pre no-op behavior. This should not be used, but we want to be cautious. _request.LockFilePath = null; _request.Project.RestoreMetadata.CacheFilePath = null; } @@ -727,7 +749,7 @@ private LockFile BuildAssetsFile( /// /// Check if the given graphs are valid and log errors/warnings. /// If fatal errors are encountered the rest of the errors/warnings - /// are not logged. This is to avoid flooding the log with long + /// are not logged. This is to avoid flooding the log with long /// dependency chains for every package. /// private async Task ValidateRestoreGraphsAsync(IEnumerable graphs, ILogger logger) @@ -1108,7 +1130,7 @@ private List GetProjectReferences(RemoteWalkContext co else { // External references were passed, but the top level project wasn't found. - // This is always due to an internal issue and typically caused by errors + // This is always due to an internal issue and typically caused by errors // building the project closure. Debug.Fail("RestoreRequest.ExternalProjects contains references, but does not contain the top level references. Add the project we are restoring for."); throw new InvalidOperationException($"Missing external reference metadata for {_request.Project.Name}"); diff --git a/src/NuGet.Core/NuGet.Commands/Strings.Designer.cs b/src/NuGet.Core/NuGet.Commands/Strings.Designer.cs index ef8dac6a044..90571007e14 100644 --- a/src/NuGet.Core/NuGet.Commands/Strings.Designer.cs +++ b/src/NuGet.Core/NuGet.Commands/Strings.Designer.cs @@ -672,6 +672,15 @@ internal static string Error_PackFailed { } } + /// + /// Looks up a localized string similar to Platform version is not present for one or more target frameworks, even though they have specified a platform: {0}. + /// + internal static string Error_PlatformVersionNotPresent { + get { + return ResourceManager.GetString("Error_PlatformVersionNotPresent", resourceCulture); + } + } + /// /// Looks up a localized string similar to Error occurred when processing file '{0}': {1}. /// diff --git a/src/NuGet.Core/NuGet.Commands/Strings.resx b/src/NuGet.Core/NuGet.Commands/Strings.resx index 6fe849ff6aa..f4ed86956b5 100644 --- a/src/NuGet.Core/NuGet.Commands/Strings.resx +++ b/src/NuGet.Core/NuGet.Commands/Strings.resx @@ -1114,4 +1114,8 @@ For more information, visit https://docs.nuget.org/docs/reference/command-line-r {0} contains more than one path + + Platform version is not present for one or more target frameworks, even though they have specified a platform: {0} + 0 - comma-separated list of TFMs missing a platform version + \ No newline at end of file diff --git a/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs b/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs index bb8068e5d7b..ea0c78d6c10 100644 --- a/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs +++ b/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs @@ -4,18 +4,18 @@ namespace NuGet.Common { /// - /// This enum is used to quantify NuGet error and warning codes. + /// This enum is used to quantify NuGet error and warning codes. /// Format - NUxyzw where NU is the prefix indicating NuGet and xyzw is a 4 digit code /// /// Numbers - xyzw /// x - 'x' is the largest digit and should be used to quantify a set of errors. /// For example 1yzw are set of restore related errors and no other code path should use the range 1000 to 1999 for errors or warnings. - /// + /// /// y - 'y' is the second largest digit and should be used for sub sections withing a broad category. - /// + /// /// For example 12zw cvould be http related errors. /// Further 'y' = 0-4 should be used for errors and 'y' = 5-9 should be warnings. - /// + /// /// zw - 'zw' are the least two digit. /// These could be used for different errors or warnings within the broad categories set by digits 'xy'. /// @@ -31,9 +31,9 @@ namespace NuGet.Common /// 1200/1700 - Compat /// 1300/1800 - Feed /// 1400/1900 - Package - /// + /// /// All new codes need a corresponding MarkDown file under https://github.com/NuGet/docs.microsoft.com-nuget/tree/master/docs/reference/errors-and-warnings. - /// + /// /// public enum NuGetLogCode { @@ -102,6 +102,11 @@ public enum NuGetLogCode /// NU1011 = 1011, + /// + /// Platform version not found. + /// + NU1012 = 1012, + /// /// Unable to resolve package, generic message for unknown type constraints. /// diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt index ea407d9c998..27e57301d51 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt index ea407d9c998..27e57301d51 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index ea407d9c998..27e57301d51 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs index 37d151cb480..a9f46c75114 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs @@ -12,11 +12,14 @@ using System.Reflection; using System.Reflection.Emit; using System.Xml.Linq; +using NuGet.Client; using NuGet.Common; +using NuGet.ContentModel; using NuGet.Frameworks; using NuGet.Packaging.Core; using NuGet.Packaging.PackageCreation.Resources; using NuGet.Packaging.Rules; +using NuGet.RuntimeModel; using NuGet.Versioning; namespace NuGet.Packaging @@ -226,7 +229,7 @@ public ISet Tags } /// - /// Exposes the additional properties extracted by the metadata + /// Exposes the additional properties extracted by the metadata /// extractor or received from the command line. /// public Dictionary Properties @@ -377,8 +380,10 @@ public void Save(Stream stream) ValidateDependencies(Version, DependencyGroups); ValidateReferenceAssemblies(Files, PackageAssemblyReferences); + ValidateFrameworkAssemblies(FrameworkReferences, FrameworkReferenceGroups); ValidateLicenseFile(Files, LicenseMetadata); ValidateIconFile(Files, Icon); + ValidateFileFrameworks(Files); using (var package = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true)) { @@ -543,6 +548,15 @@ private static bool HasXdtTransformFile(ICollection contentFiles) private static void ValidateDependencies(SemanticVersion version, IEnumerable dependencies) { + var frameworksMissingPlatformVersion = new HashSet(dependencies + .Select(group => group.TargetFramework) + .Where(groupFramework => groupFramework.HasPlatform && groupFramework.PlatformVersion == FrameworkConstants.EmptyVersion) + .Select(framework => framework.GetShortFolderName())); + if (frameworksMissingPlatformVersion.Any()) + { + throw new PackagingException(NuGetLogCode.NU1012, String.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromDependencyGroups, string.Join(", ", frameworksMissingPlatformVersion.OrderBy(str => str)))); + } + if (version == null) { // We have independent validation for null-versions. @@ -557,6 +571,15 @@ private static void ValidateDependencies(SemanticVersion version, public static void ValidateReferenceAssemblies(IEnumerable files, IEnumerable packageAssemblyReferences) { + var frameworksMissingPlatformVersion = new HashSet(packageAssemblyReferences + .Select(group => group.TargetFramework) + .Where(groupFramework => groupFramework.HasPlatform && groupFramework.PlatformVersion == FrameworkConstants.EmptyVersion) + .Select(framework => framework.GetShortFolderName())); + if (frameworksMissingPlatformVersion.Any()) + { + throw new PackagingException(NuGetLogCode.NU1012, string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromReferenceGroups, string.Join(", ", frameworksMissingPlatformVersion.OrderBy(str => str)))); + } + var libFiles = new HashSet(from file in files where !String.IsNullOrEmpty(file.Path) && file.Path.StartsWith("lib", StringComparison.OrdinalIgnoreCase) select Path.GetFileName(file.Path), StringComparer.OrdinalIgnoreCase); @@ -573,6 +596,30 @@ public static void ValidateReferenceAssemblies(IEnumerable files, } } + private static void ValidateFrameworkAssemblies(IEnumerable references, IEnumerable referenceGroups) + { + // Check standalone references + var frameworksMissingPlatformVersion = new HashSet(references + .SelectMany(reference => reference.SupportedFrameworks) + .Where(framework => framework.HasPlatform && framework.PlatformVersion == FrameworkConstants.EmptyVersion) + .Select(framework => framework.GetShortFolderName()) + ); + if (frameworksMissingPlatformVersion.Any()) + { + throw new PackagingException(NuGetLogCode.NU1012, string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromFrameworkAssemblyReferences, string.Join(", ", frameworksMissingPlatformVersion.OrderBy(str => str)))); + } + + // Check reference groups too + frameworksMissingPlatformVersion = new HashSet(referenceGroups + .Select(group => group.TargetFramework) + .Where(groupFramework => groupFramework.HasPlatform && groupFramework.PlatformVersion == FrameworkConstants.EmptyVersion) + .Select(framework => framework.GetShortFolderName())); + if (frameworksMissingPlatformVersion.Any()) + { + throw new PackagingException(NuGetLogCode.NU1012, string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromFrameworkAssemblyGroups, string.Join(", ", frameworksMissingPlatformVersion.OrderBy(str => str)))); + } + } + private void ValidateLicenseFile(IEnumerable files, LicenseMetadata licenseMetadata) { if (!PackageTypes.Contains(PackageType.SymbolsPackage) && licenseMetadata?.Type == LicenseType.File) @@ -649,6 +696,63 @@ private void ValidateIconFile(IEnumerable files, string iconPath) } } + private static void ValidateFileFrameworks(IEnumerable files) + { + var set = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var file in files.Where(t => t.Path != null).Select(t => PathUtility.GetPathWithDirectorySeparator(t.Path))) + { + set.Add(file); + } + + var managedCodeConventions = new ManagedCodeConventions(new RuntimeGraph()); + var collection = new ContentItemCollection(); + collection.Load(set.Select(path => path.Replace('\\', '/')).ToArray()); + + var patterns = managedCodeConventions.Patterns; + + var frameworkPatterns = new List() + { + patterns.RuntimeAssemblies, + patterns.CompileRefAssemblies, + patterns.CompileLibAssemblies, + patterns.NativeLibraries, + patterns.ResourceAssemblies, + patterns.MSBuildFiles, + patterns.ContentFiles, + patterns.ToolsAssemblies, + patterns.EmbedAssemblies, + patterns.MSBuildTransitiveFiles + }; + var warnPaths = new HashSet(); + + var frameworksMissingPlatformVersion = new HashSet(); + foreach (var pattern in frameworkPatterns) + { + IEnumerable targetedItemGroups = ContentExtractor.GetContentForPattern(collection, pattern); + foreach (ContentItemGroup group in targetedItemGroups) + { + foreach (ContentItem item in group.Items) + { + var framework = (NuGetFramework)item.Properties["tfm"]; + if (framework == null) + { + continue; + } + + if (framework.HasPlatform && framework.PlatformVersion == FrameworkConstants.EmptyVersion) + { + frameworksMissingPlatformVersion.Add(framework.GetShortFolderName()); + } + } + } + } + + if (frameworksMissingPlatformVersion.Any()) + { + throw new PackagingException(NuGetLogCode.NU1012, string.Format(CultureInfo.CurrentCulture, Strings.MissingTargetPlatformVersionsFromIncludedFiles, string.Join(", ", frameworksMissingPlatformVersion.OrderBy(str => str)))); + } + } + private void ReadManifest(Stream stream, string basePath, Func propertyProvider) { // Deserialize the document and extract the metadata diff --git a/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs b/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs index 8225a8209b6..df74cb33094 100644 --- a/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs +++ b/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs @@ -789,6 +789,51 @@ internal static string MissingPackageTypeName { } } + /// + /// Looks up a localized string similar to Some dependency group TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromDependencyGroups { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromDependencyGroups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some reference assembly group TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromFrameworkAssemblyGroups { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromFrameworkAssemblyGroups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some framework assembly reference TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromFrameworkAssemblyReferences { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromFrameworkAssemblyReferences", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some included files are included under TFMs which are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromIncludedFiles { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromIncludedFiles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some reference group TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromReferenceGroups { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromReferenceGroups", resourceCulture); + } + } + /// /// Looks up a localized string similar to Multiple {0} attributes are not allowed.. /// diff --git a/src/NuGet.Core/NuGet.Packaging/Strings.resx b/src/NuGet.Core/NuGet.Packaging/Strings.resx index 45c41490349..846d2a39e37 100644 --- a/src/NuGet.Core/NuGet.Packaging/Strings.resx +++ b/src/NuGet.Core/NuGet.Packaging/Strings.resx @@ -839,4 +839,24 @@ Valid from: The timestamp service responded with HTTP status code '{0}' ('{1}'). {0} is the httpResponse.StatusCode, {1} is the httpResponse.ReasonPhrase. - + + Some dependency group TFMs are missing a platform version: {0} + 0 - comma-separated list of dependency group TFMs + + + Some reference assembly group TFMs are missing a platform version: {0} + 0 - comma-separated list of reference assembly group TFMs + + + Some included files are included under TFMs which are missing a platform version: {0} + 0 - comma-separated list of files with bad TFMs + + + Some reference group TFMs are missing a platform version: {0} + 0 - comma-separated list of reference group TFMs + + + Some framework assembly reference TFMs are missing a platform version: {0} + 0 - comma-separated list of reference group TFMs + + \ No newline at end of file diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs index 9b1e57c70ae..a0496becf86 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs @@ -10,6 +10,7 @@ using FluentAssertions; using Newtonsoft.Json.Linq; using NuGet.Commands.Test; +using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; using NuGet.LibraryModel; @@ -2989,6 +2990,71 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( } } + [Fact] + public async Task RestoreCommand_WhenPlatformVersionIsEmpty_ThrowsError() + { + using (var pathContext = new SimpleTestPathContext()) + using (var context = new SourceCacheContext()) + { + var configJson = JObject.Parse(@" + { + ""frameworks"": { + ""net5.0-windows"": { + ""dependencies"": { + ""A"": { + ""version"" : ""1.0.0"", + } + } + } + } + }"); + + // Arrange + var packageA = new SimpleTestPackageContext("a", "1.0.0"); + packageA.Files.Clear(); + packageA.AddFile("lib/net5.0-windows/a.dll"); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageA); + + var sources = new List + { + new PackageSource(pathContext.PackageSource) + }; + var logger = new TestLogger(); + + var projectDirectory = Path.Combine(pathContext.SolutionRoot, "TestProject"); + var cachingSourceProvider = new CachingSourceProvider(new PackageSourceProvider(NullSettings.Instance)); + + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", Path.Combine(projectDirectory, "project.csproj")).WithTestRestoreMetadata(); + var dgSpec = new DependencyGraphSpec(); + dgSpec.AddProject(spec); + dgSpec.AddRestore(spec.Name); + + var request = new TestRestoreRequest(spec, sources, pathContext.UserPackagesFolder, logger) + { + ProjectStyle = ProjectStyle.PackageReference, + DependencyGraphSpec = dgSpec, + AllowNoOp = true, + }; + var command = new RestoreCommand(request); + + // Act + var result = await command.ExecuteAsync(); + await result.CommitAsync(logger, CancellationToken.None); + + // Assert + Assert.False(result.Success); + Assert.Equal(1, logger.ErrorMessages.Count); + logger.ErrorMessages.TryDequeue(out var errorMessage); + Assert.True(errorMessage.Contains("Platform version")); + var messagesForNU1012 = result.LockFile.LogMessages.Where(m => m.Code == NuGetLogCode.NU1012); + Assert.Equal(1, messagesForNU1012.Count()); + } + } + private static byte[] GetTestUtilityResource(string name) { return ResourceTestUtility.GetResourceBytes( diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs index d6770eda8cd..eccda8c3848 100644 --- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs +++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs @@ -139,7 +139,6 @@ public void CreatePackageWithNuspecIncludeExcludeAnyGroup() [InlineData(".NETFramework,Version=v4.7.2", ".NETFramework4.7.2")] [InlineData(".NETFramework,Version=v4.7.2,Profile=foo", ".NETFramework4.7.2-foo")] [InlineData("net5.0", "net5.0")] - [InlineData("net5.0-windows", "net5.0-windows")] [InlineData("net5.0-macos10.8", "net5.0-macos10.8")] [InlineData("net6.0", "net6.0")] public void CreatePackageTFMFormatting(string from, string to) @@ -214,8 +213,8 @@ public void CreatePackageWithNuspecIncludeExclude() var net45 = new PackageDependencyGroup(new NuGetFramework(".NETFramework", new Version(4, 5)), dependencies45); builder.DependencyGroups.Add(net45); - var net50win = new PackageDependencyGroup(new NuGetFramework(".NETCoreApp", new Version(5, 0), "windows", new Version(0, 0)), dependencies50); - builder.DependencyGroups.Add(net50win); + var net50win7 = new PackageDependencyGroup(new NuGetFramework(".NETCoreApp", new Version(5, 0), "windows", new Version(7, 0)), dependencies50); + builder.DependencyGroups.Add(net50win7); using (var ms = new MemoryStream()) { @@ -240,7 +239,7 @@ public void CreatePackageWithNuspecIncludeExclude() - + @@ -1318,6 +1317,115 @@ public void SavingPackageValidatesReferences() "Invalid assembly reference 'Bar.dll'. Ensure that a file named 'Bar.dll' exists in the lib directory."); } + [Fact] + public void SavingPackageValidatesMissingTPVInReferences() + { + // Arrange + var builder = new PackageBuilder + { + Id = "A", + Version = NuGetVersion.Parse("1.0"), + Description = "Test", + }; + builder.Authors.Add("Test"); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"lib\net5.0-windows\Foo.dll" }); + builder.PackageAssemblyReferences = new[] { new PackageReferenceSet(NuGetFramework.Parse("net5.0-windows"), new string[] { "Foo.dll" }) }; + + ExceptionAssert.Throws(() => builder.Save(new MemoryStream()), + "Some reference group TFMs are missing a platform version: net5.0-windows"); + } + + [Fact] + public void SavingPackageValidatesMissingTPVInFiles() + { + // Arrange + var builder = new PackageBuilder + { + Id = "A", + Version = NuGetVersion.Parse("1.0"), + Description = "Test", + }; + builder.Authors.Add("Test"); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"lib\net5.0-windows\Foo.dll" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"ref\net6.0-windows\Foo.dll" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"runtimes\win7-x64\lib\net7.0-windows\Foo.dll" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"runtimes\win7-x64\nativeassets\net8.0-windows\Foo.dll" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"build\net9.0-windows\foo.props" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"contentFiles\csharp\net10.0-windows\Foo.txt" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"tools\net11.0-windows\win7-x64\Foo.exe" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"embed\net12.0-windows\Foo.dll" }); + builder.Files.Add(new PhysicalPackageFile { TargetPath = @"buildTransitive\net13.0-windows\foo.props" }); + + ExceptionAssert.Throws(() => builder.Save(new MemoryStream()), + "Some included files are included under TFMs which are missing a platform version: " + string.Join(", ", new string[] + { + "net5.0-windows", + "net6.0-windows", + "net7.0-windows", + "net8.0-windows", + "net9.0-windows", + "net10.0-windows", + "net11.0-windows", + "net12.0-windows", + "net13.0-windows" + }.OrderBy(str => str))); + } + + [Fact] + public void SavingPackageValidatesMissingTPVInFrameworkReferences() + { + // Arrange + var builder = new PackageBuilder + { + Id = "A", + Version = NuGetVersion.Parse("1.0"), + Description = "Test", + }; + builder.Authors.Add("Test"); + builder.FrameworkReferences.Add(new FrameworkAssemblyReference("System.Web", new[] { NuGetFramework.Parse("net5.0-windows") })); + + ExceptionAssert.Throws(() => builder.Save(new MemoryStream()), + "Some framework assembly reference TFMs are missing a platform version: net5.0-windows"); + } + + [Fact] + public void SavingPackageValidatesMissingTPVInFrameworkReferenceGroups() + { + // Arrange + var builder = new PackageBuilder + { + Id = "A", + Version = NuGetVersion.Parse("1.0"), + Description = "Test", + }; + builder.Authors.Add("Test"); + builder.FrameworkReferenceGroups.Add(new FrameworkReferenceGroup(NuGetFramework.Parse("net5.0-windows"), new List())); + + ExceptionAssert.Throws(() => builder.Save(new MemoryStream()), + "Some reference assembly group TFMs are missing a platform version: net5.0-windows"); + } + + [Fact] + public void SavingPackageValidatesMissingTPVInDependencyGroups() + { + // Arrange + var builder = new PackageBuilder + { + Id = "A", + Version = NuGetVersion.Parse("1.0"), + Description = "Test", + }; + builder.Authors.Add("Test"); + var dependencySet = new PackageDependencyGroup(NuGetFramework.Parse("net5.0-windows"), new[] { + new PackageDependency("B", new VersionRange(NuGetVersion.Parse("2.0"), true, NuGetVersion.Parse("2.0"))) + }); + + builder.DependencyGroups.Add(dependencySet); + + ExceptionAssert.Throws(() => builder.Save(new MemoryStream()), + "Some dependency group TFMs are missing a platform version: net5.0-windows"); + } + [Fact] public void SavingPackageWithInvalidDependencyVersionMaxLessThanMinThrows() { From 5a9b71af2920c64b4e877e84114c5de93818c3e4 Mon Sep 17 00:00:00 2001 From: Andrei Grigorev Date: Wed, 21 Oct 2020 18:03:48 -0700 Subject: [PATCH 011/129] Updated the license list to bring in MIT-0 OSI approval (#3720) --- src/NuGet.Core/NuGet.Packaging/Licenses/NuGetLicenseData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NuGet.Core/NuGet.Packaging/Licenses/NuGetLicenseData.cs b/src/NuGet.Core/NuGet.Packaging/Licenses/NuGetLicenseData.cs index 3632870b9db..8a296ba1485 100644 --- a/src/NuGet.Core/NuGet.Packaging/Licenses/NuGetLicenseData.cs +++ b/src/NuGet.Core/NuGet.Packaging/Licenses/NuGetLicenseData.cs @@ -9,7 +9,7 @@ namespace NuGet.Packaging.Licenses // Auto-Generated by the GenerateLicenseList tool. DO NOT EDIT this manually. Use the update script at $repositoryRoot/scripts/utils/UpdateNuGetLicenseSPDXList.ps1 public class NuGetLicenseData { - public static string LicenseListVersion = "3.10"; + public static string LicenseListVersion = "3.10-14-g0fb8a59"; public static readonly IReadOnlyDictionary LicenseList = new Dictionary() { @@ -279,7 +279,7 @@ public class NuGetLicenseData { "MakeIndex", new LicenseData(licenseID: "MakeIndex", isOsiApproved: false, isDeprecatedLicenseId: false, isFsfLibre: false) }, { "MirOS", new LicenseData(licenseID: "MirOS", isOsiApproved: true, isDeprecatedLicenseId: false, isFsfLibre: false) }, { "MIT", new LicenseData(licenseID: "MIT", isOsiApproved: true, isDeprecatedLicenseId: false, isFsfLibre: true) }, - { "MIT-0", new LicenseData(licenseID: "MIT-0", isOsiApproved: false, isDeprecatedLicenseId: false, isFsfLibre: false) }, + { "MIT-0", new LicenseData(licenseID: "MIT-0", isOsiApproved: true, isDeprecatedLicenseId: false, isFsfLibre: false) }, { "MIT-advertising", new LicenseData(licenseID: "MIT-advertising", isOsiApproved: false, isDeprecatedLicenseId: false, isFsfLibre: false) }, { "MIT-CMU", new LicenseData(licenseID: "MIT-CMU", isOsiApproved: false, isDeprecatedLicenseId: false, isFsfLibre: false) }, { "MIT-enna", new LicenseData(licenseID: "MIT-enna", isOsiApproved: false, isDeprecatedLicenseId: false, isFsfLibre: false) }, From 63c71046267aa91de50f31fdabd631f788385c04 Mon Sep 17 00:00:00 2001 From: Rob Relyea Date: Wed, 21 Oct 2020 18:30:54 -0700 Subject: [PATCH 012/129] improve test: always create a 32x32 image for default image, even if application.current is null (#3725) --- .../Resources/Images.cs | 22 ++++++++++++++----- .../Models/PackageItemListViewModelTests.cs | 7 ++---- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs index 0b6f44ea317..9a588b2621b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Images.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -31,17 +32,28 @@ static Images() image.Freeze(); DefaultPackageIcon = image; } - else // for tests, don't actually load the icon, just use a 1x1 image. + else // for tests, don't actually load the icon, just use a 32x32 image. { + const int size = PackageItemListViewModel.DecodePixelWidth; + var bytes = new List(); + byte[] pixel = new byte[] { 0, 0, 255, 0 }; + for (int y = 0; y < size; y++) + { + for (int x = 0; x < size; x++) + { + bytes.AddRange(pixel); + } + } + BitmapSource image = BitmapSource.Create( - pixelWidth: 1, - pixelHeight: 1, + pixelWidth: size, + pixelHeight: size, dpiX: 96.0, dpiY: 96.0, PixelFormats.Bgr32, palette: null, - pixels: new byte[] { 0, 0, 255, 0 }, - stride: 32); + pixels: bytes.ToArray(), + stride: 4 * size); image.Freeze(); DefaultPackageIcon = image; } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs index c708b3ba300..23c1ce68e0b 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/PackageItemListViewModelTests.cs @@ -379,11 +379,8 @@ private static void VerifyImageResult(object result, IconBitmapStatus bitmapStat Assert.True(result is BitmapImage || result is CachedBitmap); var image = result as BitmapSource; Assert.NotNull(image); - int expectedSize = IconBitmapStatusUtility.GetIsDefaultIcon(bitmapStatus) - ? 1 - : PackageItemListViewModel.DecodePixelWidth; - Assert.Equal(expectedSize, image.PixelWidth); - Assert.Equal(expectedSize, image.PixelHeight); + Assert.Equal(PackageItemListViewModel.DecodePixelWidth, image.PixelWidth); + Assert.Equal(PackageItemListViewModel.DecodePixelWidth, image.PixelHeight); } /// From 4b6c4ac6d4626d9dc5f7cf40ce3211a317ba6240 Mon Sep 17 00:00:00 2001 From: Damon Tivel Date: Thu, 22 Oct 2020 13:57:11 -0700 Subject: [PATCH 013/129] VS OE: cache and reuse IServiceBroker instance in the client (#3724) Resolve https://github.com/NuGet/Home/issues/10141. --- .../Xamls/ConsoleContainer.xaml.cs | 5 +- ...ackagesConfigToPackageReferenceMigrator.cs | 7 +- .../Actions/UIActionEngine.cs | 30 +- .../Models/DetailControlModel.cs | 49 ++- .../Models/NuGetProjectUpgradeWindowModel.cs | 6 +- .../Models/PackageDetailControlModel.cs | 4 +- .../PackageSolutionDetailControlModel.cs | 58 +-- .../Options/PackageSourcesOptionsControl.cs | 11 +- .../PackageInstallationInfo.cs | 14 +- .../PackageItemLoader.cs | 16 +- .../PackageLoadContext.cs | 15 +- .../UserInterfaceService/INuGetUIContext.cs | 3 + .../UserInterfaceService/INuGetUIFactory.cs | 3 +- .../UserInterfaceService/NuGetUI.cs | 10 +- .../UserInterfaceService/NuGetUIContext.cs | 19 +- .../UserInterfaceService/NuGetUIFactory.cs | 11 +- .../Utility/ProjectUtility.cs | 10 +- .../Xamls/PackageManagerControl.xaml.cs | 34 +- .../Common/IProjectContextInfoExtensions.cs | 116 +++++ .../Common/PackageCollection.cs | 12 +- ...uGet.PackageManagement.VisualStudio.csproj | 2 + .../PackageFeeds/UpdatePackageFeed.cs | 38 +- .../Prompts/DotnetDeprecatedPrompt.cs | 4 +- .../Utility/IProjectContextInfoUtility.cs | 73 ++++ src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs | 27 +- .../IServiceBrokerProvider.cs | 13 + .../CachingIServiceBrokerProvider.cs | 31 ++ .../IProjectContextInfo.cs | 11 - .../ProjectContextInfo.cs | 136 ------ .../PackageManagerUICommandHandler.cs | 12 +- .../Models/LocalDetailControlModelTests.cs | 10 +- .../Models/V3DetailControlModelTests.cs | 2 + .../PackageItemLoaderTests.cs | 61 +-- .../PackageManagerListItemsTest.cs | 36 +- .../Utility/ProjectUtilityTests.cs | 70 ++- .../IProjectContextInfoExtensionsTests.cs | 401 ++++++++++++++++++ .../Feeds/UpdatePackageFeedTests.cs | 236 ++++++++--- ...PackageManagement.VisualStudio.Test.csproj | 1 + .../CachingIServiceBrokerProviderTests.cs | 30 ++ .../VsPathContextProviderTests.cs | 14 +- .../MockedVS.cs | 20 + ...et.VisualStudio.Implementation.Test.csproj | 3 +- .../NuGetApexUITestService.cs | 6 +- 43 files changed, 1270 insertions(+), 400 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/IProjectContextInfoExtensions.cs create mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/IProjectContextInfoUtility.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/IServiceBrokerProvider.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Implementation/CachingIServiceBrokerProvider.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Common/IProjectContextInfoExtensionsTests.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/CachingIServiceBrokerProviderTests.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/MockedVS.cs diff --git a/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs b/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs index 8a9d43dc6de..f8c5cc3a737 100644 --- a/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs +++ b/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs @@ -11,8 +11,8 @@ using Microsoft.VisualStudio.Shell.Interop; using NuGet.PackageManagement; using NuGet.PackageManagement.UI; -using NuGet.PackageManagement.VisualStudio; using NuGet.VisualStudio; +using NuGet.VisualStudio.Common; using NuGet.VisualStudio.Internal.Contracts; namespace NuGetConsole @@ -34,7 +34,8 @@ public ConsoleContainer() await System.Threading.Tasks.Task.Run( async () => { - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBrokerProvider serviceBrokerProvider = await ServiceLocator.GetInstanceAsync(); + IServiceBroker serviceBroker = await serviceBrokerProvider.GetAsync(); _solutionManager = await serviceBroker.GetProxyAsync( NuGetServices.SolutionManagerService, diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/PackagesConfigToPackageReferenceMigrator.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/PackagesConfigToPackageReferenceMigrator.cs index b21ca503fdc..f30d1998d4e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/PackagesConfigToPackageReferenceMigrator.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/PackagesConfigToPackageReferenceMigrator.cs @@ -47,7 +47,7 @@ internal static async Task DoUpgradeAsync( return null; } - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBroker serviceBroker = context.ServiceBroker; using (INuGetProjectUpgraderService projectUpgrader = await serviceBroker.GetProxyAsync( NuGetServices.ProjectUpgraderService, @@ -160,7 +160,10 @@ await projectUpgrader.InstallPackagesAsync( } finally { - IEnumerable projectIds = await ProjectUtility.GetSortedProjectIdsAsync(uiService.Projects, token); + IEnumerable projectIds = await ProjectUtility.GetSortedProjectIdsAsync( + uiService.UIContext.ServiceBroker, + uiService.Projects, + token); upgradeInformationTelemetryEvent.SetResult(projectIds, status, packagesCount); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs index 04f42fd471e..db921c3e900 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs @@ -93,7 +93,7 @@ await context.PackageRestoreManager.RestoreMissingPackagesInSolutionAsync( new LoggerAdapter(uiService.ProjectContext), CancellationToken.None); - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBroker serviceBroker = context.ServiceBroker; NuGetProjectUpgradeWindowModel upgradeInformationWindowModel; using (INuGetProjectManagerService projectManager = await serviceBroker.GetProxyAsync( @@ -108,6 +108,7 @@ await context.PackageRestoreManager.RestoreMissingPackagesInSolutionAsync( CancellationToken.None); upgradeInformationWindowModel = await NuGetProjectUpgradeWindowModel.CreateAsync( + serviceBroker, project, packagesDependencyInfo.ToList(), CancellationToken.None); @@ -120,7 +121,10 @@ await context.PackageRestoreManager.RestoreMissingPackagesInSolutionAsync( var packagesCount = upgradeInformationWindowModel.UpgradeDependencyItems.Count; var upgradeTelemetryEvent = new UpgradeInformationTelemetryEvent(); - IEnumerable projectIds = await ProjectUtility.GetSortedProjectIdsAsync(uiService.Projects, CancellationToken.None); + IEnumerable projectIds = await ProjectUtility.GetSortedProjectIdsAsync( + uiService.UIContext.ServiceBroker, + uiService.Projects, + CancellationToken.None); upgradeTelemetryEvent.SetResult( projectIds, @@ -133,7 +137,9 @@ await context.PackageRestoreManager.RestoreMissingPackagesInSolutionAsync( } var progressDialogData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage); - string projectName = await project.GetUniqueNameOrNameAsync(CancellationToken.None); + string projectName = await project.GetUniqueNameOrNameAsync( + uiService.UIContext.ServiceBroker, + CancellationToken.None); string backupPath; var windowTitle = string.Format( @@ -195,7 +201,7 @@ public async Task PerformUpdateAsync( List packagesToUpdate, CancellationToken cancellationToken) { - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBroker serviceBroker = uiService.UIContext.ServiceBroker; using (INuGetProjectManagerService projectManagerService = await serviceBroker.GetProxyAsync( NuGetServices.ProjectManagerService, @@ -247,7 +253,7 @@ private async Task PerformActionAsync( ResolveActionsAsync resolveActionsAsync, CancellationToken cancellationToken) { - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBroker serviceBroker = uiService.UIContext.ServiceBroker; using (INuGetProjectManagerService projectManagerService = await serviceBroker.GetProxyAsync( NuGetServices.ProjectManagerService, @@ -307,7 +313,9 @@ private async Task PerformActionImplAsync( // collect the install state of the existing packages foreach (IProjectContextInfo project in uiService.Projects) { - IEnumerable installedPackages = await project.GetInstalledPackagesAsync(cancellationToken); + IEnumerable installedPackages = await project.GetInstalledPackagesAsync( + uiService.UIContext.ServiceBroker, + cancellationToken); foreach (IPackageReferenceContextInfo package in installedPackages) { @@ -485,7 +493,10 @@ await projectManagerService.ExecuteActionsAsync( PackageLoadContext plc = new PackageLoadContext(sourceRepositories: null, isSolution: false, uiService.UIContext); var frameworks = (await plc.GetSupportedFrameworksAsync()).ToList(); - string[] projectIds = (await ProjectUtility.GetSortedProjectIdsAsync(uiService.Projects, cancellationToken)).ToArray(); + string[] projectIds = (await ProjectUtility.GetSortedProjectIdsAsync( + uiService.UIContext.ServiceBroker, + uiService.Projects, + cancellationToken)).ToArray(); var actionTelemetryEvent = new VSActionsTelemetryEvent( uiService.ProjectContext.OperationId.ToString(), @@ -661,7 +672,10 @@ private async Task CheckPackageManagementFormatAsync( } Task[] tasks = upgradeableProjects - .Select(project => project.GetMetadataAsync(cancellationToken).AsTask()) + .Select(project => project.GetMetadataAsync( + uiService.UIContext.ServiceBroker, + cancellationToken) + .AsTask()) .ToArray(); IProjectMetadataContextInfo[] projectMetadatas = await Task.WhenAll(tasks); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs index 5bbe6aa77af..859c38f4fd0 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/DetailControlModel.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Media.Imaging; +using Microsoft.ServiceHub.Framework; using NuGet.PackageManagement.VisualStudio; using NuGet.Packaging; using NuGet.Packaging.Core; @@ -46,9 +47,12 @@ public abstract class DetailControlModel : INotifyPropertyChanged private Dictionary _metadataDict; - protected DetailControlModel(IEnumerable projects) + protected DetailControlModel( + IServiceBroker serviceBroker, + IEnumerable projects) { _nugetProjects = projects; + ServiceBroker = serviceBroker; _options = new Options(); // Show dependency behavior and file conflict options if any of the projects are non-build integrated @@ -73,6 +77,8 @@ public virtual void CleanUp() public bool RecommendPackages { get; private set; } public (string modelVersion, string vsixVersion)? RecommenderVersion { get; private set; } + protected IServiceBroker ServiceBroker { get; } + /// /// Sets the current selection info /// @@ -119,14 +125,19 @@ public async virtual Task SetCurrentPackage( if (project.ProjectKind == NuGetProjectKind.PackagesConfig) { // cache allowed version range for each nuget project for current selected package - var packageReference = (await project.GetInstalledPackagesAsync(CancellationToken.None)) + IReadOnlyCollection installedPackages = await project.GetInstalledPackagesAsync( + ServiceBroker, + CancellationToken.None); + IPackageReferenceContextInfo packageReference = installedPackages .FirstOrDefault(r => StringComparer.OrdinalIgnoreCase.Equals(r.Identity.Id, searchResultPackage.Id)); var range = packageReference?.AllowedVersions; if (range != null && !VersionRange.All.Equals(range)) { - IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync(CancellationToken.None); + IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync( + ServiceBroker, + CancellationToken.None); var constraint = new ProjectVersionConstraint() { ProjectName = projectMetadata.Name, @@ -139,18 +150,23 @@ public async virtual Task SetCurrentPackage( } else if (project.ProjectKind == NuGetProjectKind.PackageReference) { - var packageReferences = await project.GetInstalledPackagesAsync(CancellationToken.None); + IReadOnlyCollection packageReferences = await project.GetInstalledPackagesAsync( + ServiceBroker, + CancellationToken.None); // First the lowest auto referenced version of this package. - var autoReferenced = packageReferences.Where(e => StringComparer.OrdinalIgnoreCase.Equals(searchResultPackage.Id, e.Identity.Id) - && e.Identity.Version != null) - .Where(e => e.IsAutoReferenced) - .OrderBy(e => e.Identity.Version) - .FirstOrDefault(); + IPackageReferenceContextInfo autoReferenced = packageReferences + .Where(e => StringComparer.OrdinalIgnoreCase.Equals(searchResultPackage.Id, e.Identity.Id) + && e.Identity.Version != null) + .Where(e => e.IsAutoReferenced) + .OrderBy(e => e.Identity.Version) + .FirstOrDefault(); if (autoReferenced != null) { - IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync(CancellationToken.None); + IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync( + ServiceBroker, + CancellationToken.None); // Add constraint for auto referenced package. var constraint = new ProjectVersionConstraint() @@ -239,7 +255,10 @@ public virtual IEnumerable InstalledPackages var installedPackages = new List(); foreach (var project in _nugetProjects) { - var projectInstalledPackages = await project.GetInstalledPackagesAsync(CancellationToken.None); + IReadOnlyCollection projectInstalledPackages = await project.GetInstalledPackagesAsync( + ServiceBroker, + CancellationToken.None); + installedPackages.AddRange(projectInstalledPackages); } return installedPackages.Select(e => e.Identity).Distinct(PackageIdentity.Comparer); @@ -268,13 +287,15 @@ public virtual IEnumerable InstalledPackageDep } } - private static async Task> GetDependencies(IProjectContextInfo project) + private async Task> GetDependencies(IProjectContextInfo project) { var results = new List(); - var projectInstalledPackages = await project.GetInstalledPackagesAsync(CancellationToken.None); + IReadOnlyCollection projectInstalledPackages = await project.GetInstalledPackagesAsync( + ServiceBroker, + CancellationToken.None); - foreach (var package in projectInstalledPackages) + foreach (IPackageReferenceContextInfo package in projectInstalledPackages) { VersionRange range; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/NuGetProjectUpgradeWindowModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/NuGetProjectUpgradeWindowModel.cs index afdd690cd19..c95169126ea 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/NuGetProjectUpgradeWindowModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/NuGetProjectUpgradeWindowModel.cs @@ -9,7 +9,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft; +using Microsoft.ServiceHub.Framework; using NuGet.Common; +using NuGet.PackageManagement.VisualStudio; using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.Packaging.Rules; @@ -49,6 +51,7 @@ private NuGetProjectUpgradeWindowModel( } public static async Task CreateAsync( + IServiceBroker serviceBroker, IProjectContextInfo project, IList packageDependencyInfos, CancellationToken cancellationToken) @@ -58,7 +61,7 @@ public static async Task CreateAsync( cancellationToken.ThrowIfCancellationRequested(); - string projectName = await project.GetUniqueNameOrNameAsync(CancellationToken.None); + string projectName = await project.GetUniqueNameOrNameAsync(serviceBroker, CancellationToken.None); string title = string.Format(CultureInfo.CurrentCulture, Resources.WindowTitle_NuGetMigrator, projectName); var notFoundPackages = new HashSet(); var hasIssues = false; @@ -70,6 +73,7 @@ public static async Task CreateAsync( foreach (NuGetProjectUpgradeDependencyItem dependencyItem in dependencyItems) { (bool _, string packagePath) = await project.TryGetInstalledPackageFilePathAsync( + serviceBroker, dependencyItem.Identity, cancellationToken); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageDetailControlModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageDetailControlModel.cs index d10738489c3..c5fb6ed0e04 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageDetailControlModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageDetailControlModel.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Microsoft.ServiceHub.Framework; using NuGet.Packaging.Core; using NuGet.Versioning; using NuGet.VisualStudio.Internal.Contracts; @@ -19,9 +20,10 @@ public class PackageDetailControlModel : DetailControlModel private readonly INuGetSolutionManagerService _solutionManager; public PackageDetailControlModel( + IServiceBroker serviceBroker, INuGetSolutionManagerService solutionManager, IEnumerable projects) - : base(projects) + : base(serviceBroker, projects) { _solutionManager = solutionManager; _solutionManager.ProjectUpdated += ProjectChanged; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs index 9f7082b3a08..a042b31a60b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs @@ -11,7 +11,6 @@ using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Shell; using NuGet.PackageManagement.VisualStudio; -using NuGet.ProjectManagement; using NuGet.ProjectModel; using NuGet.Versioning; using NuGet.VisualStudio; @@ -35,8 +34,10 @@ internal class PackageSolutionDetailControlModel : DetailControlModel private bool? _selectCheckBoxState; private List _projects; // List of projects in the solution - private PackageSolutionDetailControlModel(IEnumerable projects) - : base(projects) + private PackageSolutionDetailControlModel( + IServiceBroker serviceBroker, + IEnumerable projects) + : base(serviceBroker, projects) { IsRequestedVisible = projects.Any(p => p.ProjectStyle == ProjectStyle.PackageReference); } @@ -44,7 +45,6 @@ private PackageSolutionDetailControlModel(IEnumerable proje private async ValueTask InitializeAsync( INuGetSolutionManagerService solutionManager, IEnumerable packageManagerProviders, - IServiceBroker serviceBroker, CancellationToken cancellationToken) { _solutionManager = solutionManager; @@ -64,17 +64,18 @@ private async ValueTask InitializeAsync( _packageManagerProviders = packageManagerProviders; - await CreateProjectListsAsync(serviceBroker, cancellationToken); + await CreateProjectListsAsync(cancellationToken); } public static async ValueTask CreateAsync( + IServiceBroker serviceBroker, INuGetSolutionManagerService solutionManager, IEnumerable projects, IEnumerable packageManagerProviders, CancellationToken cancellationToken) { - var packageSolutionDetailControlModel = new PackageSolutionDetailControlModel(projects); - await packageSolutionDetailControlModel.InitializeAsync(solutionManager, packageManagerProviders, serviceBroker: null, cancellationToken); + var packageSolutionDetailControlModel = new PackageSolutionDetailControlModel(serviceBroker, projects); + await packageSolutionDetailControlModel.InitializeAsync(solutionManager, packageManagerProviders, cancellationToken); return packageSolutionDetailControlModel; } @@ -85,8 +86,8 @@ internal static async ValueTask CreateAsync( IServiceBroker serviceBroker, CancellationToken cancellationToken) { - var packageSolutionDetailControlModel = new PackageSolutionDetailControlModel(projects); - await packageSolutionDetailControlModel.InitializeAsync(solutionManager, packageManagerProviders, serviceBroker, cancellationToken); + var packageSolutionDetailControlModel = new PackageSolutionDetailControlModel(serviceBroker, projects); + await packageSolutionDetailControlModel.InitializeAsync(solutionManager, packageManagerProviders, cancellationToken); return packageSolutionDetailControlModel; } @@ -183,11 +184,16 @@ private async Task UpdateInstalledVersionsAsync(CancellationToken cancellationTo /// This method is called from several methods that are called from properties and LINQ queries /// It is likely not called more than once in an action. /// - private static async Task GetInstalledPackageAsync(IProjectContextInfo project, string id, CancellationToken cancellationToken) + private async Task GetInstalledPackageAsync( + IProjectContextInfo project, + string packageId, + CancellationToken cancellationToken) { - IEnumerable installedPackages = await project.GetInstalledPackagesAsync(cancellationToken); + IEnumerable installedPackages = await project.GetInstalledPackagesAsync( + ServiceBroker, + cancellationToken); IPackageReferenceContextInfo installedPackage = installedPackages - .Where(p => StringComparer.OrdinalIgnoreCase.Equals(p.Identity.Id, id)) + .Where(p => StringComparer.OrdinalIgnoreCase.Equals(p.Identity.Id, packageId)) .FirstOrDefault(); return installedPackage; } @@ -268,7 +274,7 @@ public int InstalledVersionsCount // The event handler that is called when a project is added, removed or renamed. private void SolutionProjectChanged(object sender, IProjectContextInfo project) { - NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(() => CreateProjectListsAsync(serviceBroker: null, CancellationToken.None)) + NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(() => CreateProjectListsAsync(CancellationToken.None)) .PostOnFailure(nameof(PackageSolutionDetailControlModel), nameof(SolutionProjectChanged)); } @@ -297,7 +303,7 @@ public override void CleanUp() } // Creates the project lists. Also called after a project is added/removed/renamed. - private async Task CreateProjectListsAsync(IServiceBroker serviceBroker, CancellationToken cancellationToken) + private async Task CreateProjectListsAsync(CancellationToken cancellationToken) { // unhook event handler if (Projects != null) @@ -310,21 +316,20 @@ private async Task CreateProjectListsAsync(IServiceBroker serviceBroker, Cancell IReadOnlyCollection projectContexts; - if (serviceBroker == null) + using (INuGetProjectManagerService projectManagerService = await ServiceBroker.GetProxyAsync( + NuGetServices.ProjectManagerService)) { - serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); - } - - using (var nugetProjectManagerService = await serviceBroker.GetProxyAsync(NuGetServices.ProjectManagerService)) - { - Assumes.NotNull(nugetProjectManagerService); - projectContexts = await nugetProjectManagerService.GetProjectsAsync(cancellationToken); + Assumes.NotNull(projectManagerService); + projectContexts = await projectManagerService.GetProjectsAsync(cancellationToken); } var packageInstallationInfos = new List(); foreach (IProjectContextInfo project in projectContexts) { - var packageInstallationInfo = await PackageInstallationInfo.CreateAsync(project, cancellationToken); + PackageInstallationInfo packageInstallationInfo = await PackageInstallationInfo.CreateAsync( + ServiceBroker, + project, + cancellationToken); packageInstallationInfos.Add(packageInstallationInfo); } @@ -426,12 +431,15 @@ private void UpdateCanInstallAndCanUninstall() VersionComparer.Default.Compare(SelectedVersion.Version, project.InstalledVersion) != 0); } - private async ValueTask> GetConstraintsForSelectedProjectsAsync(CancellationToken cancellationToken) + private async ValueTask> GetConstraintsForSelectedProjectsAsync( + CancellationToken cancellationToken) { var selectedProjectsNames = new List(); foreach (PackageInstallationInfo project in Projects.Where(p => p.IsSelected).ToList()) { - IProjectMetadataContextInfo projectMetadata = await project.NuGetProject.GetMetadataAsync(cancellationToken); + IProjectMetadataContextInfo projectMetadata = await project.NuGetProject.GetMetadataAsync( + ServiceBroker, + cancellationToken); selectedProjectsNames.Add(projectMetadata.Name); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Options/PackageSourcesOptionsControl.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Options/PackageSourcesOptionsControl.cs index e185097e4e6..8685975db43 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Options/PackageSourcesOptionsControl.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Options/PackageSourcesOptionsControl.cs @@ -12,13 +12,14 @@ using System.Threading.Tasks; using System.Windows.Forms; using Microsoft; +using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using NuGet.Configuration; using NuGet.PackageManagement.UI; -using NuGet.PackageManagement.VisualStudio; using NuGet.VisualStudio; +using NuGet.VisualStudio.Common; using NuGet.VisualStudio.Internal.Contracts; using Task = System.Threading.Tasks.Task; @@ -154,9 +155,13 @@ internal async Task InitializeOnActivatedAsync(CancellationToken cancellationTok _initialized = true; - var remoteBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBrokerProvider serviceBrokerProvider = await ServiceLocator.GetInstanceAsync(); + IServiceBroker serviceBroker = await serviceBrokerProvider.GetAsync(); + #pragma warning disable ISB001 // Dispose of proxies, disposed in disposing event or in ClearSettings - _nugetSourcesService = await remoteBroker.GetProxyAsync(NuGetServices.SourceProviderService, cancellationToken: cancellationToken); + _nugetSourcesService = await serviceBroker.GetProxyAsync( + NuGetServices.SourceProviderService, + cancellationToken: cancellationToken); #pragma warning restore ISB001 // Dispose of proxies, disposed in disposing event or in ClearSettings Assumes.NotNull(_nugetSourcesService); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageInstallationInfo.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageInstallationInfo.cs index 750b6a68f44..2b3e2c8518f 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageInstallationInfo.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageInstallationInfo.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using NuGet.PackageManagement.VisualStudio; using NuGet.Versioning; using NuGet.VisualStudio.Internal.Contracts; @@ -23,22 +24,27 @@ public class PackageInstallationInfo : IComparable, INo private bool _isSelected; private string _projectName; private AlternativePackageManagerProviders _providers; + private readonly IServiceBroker _serviceBroker; - private PackageInstallationInfo(IProjectContextInfo project) + private PackageInstallationInfo(IServiceBroker serviceBroker, IProjectContextInfo project) { + _serviceBroker = serviceBroker; NuGetProject = project; } - public static async ValueTask CreateAsync(IProjectContextInfo project, CancellationToken cancellationToken) + public static async ValueTask CreateAsync( + IServiceBroker serviceBroker, + IProjectContextInfo project, + CancellationToken cancellationToken) { - var packageInstallationInfo = new PackageInstallationInfo(project); + var packageInstallationInfo = new PackageInstallationInfo(serviceBroker, project); await packageInstallationInfo.InitializeAsync(cancellationToken); return packageInstallationInfo; } private async ValueTask InitializeAsync(CancellationToken cancellationToken) { - _projectName = await NuGetProject.GetUniqueNameOrNameAsync(cancellationToken); + _projectName = await NuGetProject.GetUniqueNameOrNameAsync(_serviceBroker, cancellationToken); } private NuGetVersion _versionInstalled; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageItemLoader.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageItemLoader.cs index d247cf2b87f..5f52b794ca2 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageItemLoader.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageItemLoader.cs @@ -251,8 +251,10 @@ public async Task UpdateStateAndReportAsync(SearchResult // but for project view, get the allowed version range and pass it to package item view model to choose the latest version based on that if (_packageReferences == null && !_context.IsSolution) { - var tasks = _context.Projects - .Select(project => project.GetInstalledPackagesAsync(cancellationToken).AsTask()); + IEnumerable>> tasks = _context.Projects + .Select(project => project.GetInstalledPackagesAsync( + _context.ServiceBroker, + cancellationToken).AsTask()); _packageReferences = (await Task.WhenAll(tasks)).SelectMany(p => p).Where(p => p != null); } @@ -314,8 +316,14 @@ public IEnumerable GetCurrent() listItem.ProvidersLoader = AsyncLazy.New( async () => { - string uniqueProjectName = await _context.Projects[0].GetUniqueNameOrNameAsync(CancellationToken.None); - return await AlternativePackageManagerProviders.CalculateAlternativePackageManagersAsync(_context.PackageManagerProviders, listItem.Id, uniqueProjectName); + string uniqueProjectName = await _context.Projects[0].GetUniqueNameOrNameAsync( + _context.ServiceBroker, + CancellationToken.None); + + return await AlternativePackageManagerProviders.CalculateAlternativePackageManagersAsync( + _context.PackageManagerProviders, + listItem.Id, + uniqueProjectName); }); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageLoadContext.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageLoadContext.cs index 081d790e2a0..b76e7b1841b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageLoadContext.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageLoadContext.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using NuGet.Frameworks; using NuGet.PackageManagement.VisualStudio; using NuGet.Protocol.Core.Types; @@ -33,6 +34,8 @@ internal class PackageLoadContext public INuGetSolutionManagerService SolutionManager { get; } + internal IServiceBroker ServiceBroker { get; } + public PackageLoadContext( IEnumerable sourceRepositories, bool isSolution, @@ -44,8 +47,12 @@ public PackageLoadContext( Projects = (uiContext.Projects ?? Enumerable.Empty()).ToArray(); PackageManagerProviders = uiContext.PackageManagerProviders; SolutionManager = uiContext.SolutionManagerService; + ServiceBroker = uiContext.ServiceBroker; - _installedPackagesTask = PackageCollection.FromProjectsAsync(Projects, CancellationToken.None); + _installedPackagesTask = PackageCollection.FromProjectsAsync( + ServiceBroker, + Projects, + CancellationToken.None); } public Task GetInstalledPackagesAsync() => _installedPackagesTask; @@ -55,9 +62,11 @@ public async Task> GetSupportedFrameworksAsync() { var frameworks = new HashSet(StringComparer.OrdinalIgnoreCase); - foreach (var project in Projects) + foreach (IProjectContextInfo project in Projects) { - IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync(CancellationToken.None); + IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync( + ServiceBroker, + CancellationToken.None); NuGetFramework framework = projectMetadata.TargetFramework; if (framework != null) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIContext.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIContext.cs index 0bb85b52ade..9f119218af5 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIContext.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIContext.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using NuGet.PackageManagement.VisualStudio; using NuGet.Protocol.Core.Types; using NuGet.VisualStudio; @@ -16,6 +17,8 @@ public interface INuGetUIContext : IDisposable { event EventHandler> ProjectActionsExecuted; + IServiceBroker ServiceBroker { get; } + ISourceRepositoryProvider SourceProvider { get; } IVsSolutionManager SolutionManager { get; } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIFactory.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIFactory.cs index c01f1e8008a..0edeb3eb7b5 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIFactory.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/INuGetUIFactory.cs @@ -2,12 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using NuGet.VisualStudio.Internal.Contracts; namespace NuGet.PackageManagement.UI { public interface INuGetUIFactory { - ValueTask CreateAsync(params IProjectContextInfo[] projects); + ValueTask CreateAsync(IServiceBroker serviceBroker, params IProjectContextInfo[] projects); } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs index 8091ddeb647..150085c4e10 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUI.cs @@ -64,6 +64,7 @@ internal NuGetUI( } public static async Task CreateAsync( + IServiceBroker serviceBroker, ICommonOperations commonOperations, NuGetUIProjectContext projectContext, ISourceRepositoryProvider sourceRepositoryProvider, @@ -80,6 +81,7 @@ public static async Task CreateAsync( CancellationToken cancellationToken, params IProjectContextInfo[] projects) { + Assumes.NotNull(serviceBroker); Assumes.NotNull(commonOperations); Assumes.NotNull(projectContext); Assumes.NotNull(sourceRepositoryProvider); @@ -102,6 +104,7 @@ public static async Task CreateAsync( logger) { UIContext = await NuGetUIContext.CreateAsync( + serviceBroker, sourceRepositoryProvider, settings, solutionManager, @@ -123,7 +126,10 @@ public async Task WarnAboutDotnetDeprecationAsync(IEnumerable { result = WarnAboutDotnetDeprecationImpl(dataContext); }); @@ -207,7 +213,7 @@ public async Task UpgradeProjectsToPackageReferenceAsync(IEnumerable projects = Projects.ToList(); - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); + IServiceBroker serviceBroker = UIContext.ServiceBroker; using (INuGetProjectUpgraderService projectUpgrader = await serviceBroker.GetProxyAsync( NuGetServices.ProjectUpgraderService, diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIContext.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIContext.cs index c5907397259..35a11e53f99 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIContext.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIContext.cs @@ -25,7 +25,6 @@ namespace NuGet.PackageManagement.UI /// public sealed class NuGetUIContext : INuGetUIContext { - private readonly IServiceBroker _serviceBroker; private readonly NuGetSolutionManagerServiceWrapper _solutionManagerService; private IProjectContextInfo[] _projects; @@ -45,7 +44,7 @@ internal NuGetUIContext( IEnumerable packageManagerProviders) { SourceProvider = sourceProvider; - _serviceBroker = serviceBroker; + ServiceBroker = serviceBroker; SolutionManager = solutionManager; _solutionManagerService = solutionManagerService; PackageManager = packageManager; @@ -56,10 +55,12 @@ internal NuGetUIContext( UserSettingsManager = userSettingsManager; PackageManagerProviders = packageManagerProviders; - _serviceBroker.AvailabilityChanged += OnAvailabilityChanged; + ServiceBroker.AvailabilityChanged += OnAvailabilityChanged; SolutionManager.ActionsExecuted += OnActionsExecuted; } + public IServiceBroker ServiceBroker { get; } + public ISourceRepositoryProvider SourceProvider { get; } public IVsSolutionManager SolutionManager { get; } @@ -94,7 +95,7 @@ public IEnumerable Projects public void Dispose() { - _serviceBroker.AvailabilityChanged -= OnAvailabilityChanged; + ServiceBroker.AvailabilityChanged -= OnAvailabilityChanged; SolutionManager.ActionsExecuted -= OnActionsExecuted; _solutionManagerService.Dispose(); @@ -104,7 +105,7 @@ public void Dispose() public async Task IsNuGetProjectUpgradeableAsync(IProjectContextInfo project, CancellationToken cancellationToken) { - return await project.IsUpgradeableAsync(cancellationToken); + return await project.IsUpgradeableAsync(ServiceBroker, cancellationToken); } public async Task StartModalProgressDialogAsync(string caption, ProgressDialogData initialData, INuGetUI uiService) @@ -124,6 +125,7 @@ public async Task StartModalProgressDialogAsync(str } public static async ValueTask CreateAsync( + IServiceBroker serviceBroker, ISourceRepositoryProvider sourceRepositoryProvider, ISettings settings, IVsSolutionManager solutionManager, @@ -135,6 +137,7 @@ public static async ValueTask CreateAsync( INuGetLockService lockService, CancellationToken cancellationToken) { + Assumes.NotNull(serviceBroker); Assumes.NotNull(sourceRepositoryProvider); Assumes.NotNull(settings); Assumes.NotNull(solutionManager); @@ -147,10 +150,8 @@ public static async ValueTask CreateAsync( cancellationToken.ThrowIfCancellationRequested(); - IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); - var solutionManagerServiceWrapper = new NuGetSolutionManagerServiceWrapper(); - var solutionManagerService = await GetSolutionManagerServiceAsync(serviceBroker, cancellationToken); + INuGetSolutionManagerService solutionManagerService = await GetSolutionManagerServiceAsync(serviceBroker, cancellationToken); // The initial Swap(...) should return a null implementation of the interface that does not require disposal. // However, there's no harm in following form. @@ -214,7 +215,7 @@ private void OnAvailabilityChanged(object sender, BrokeredServicesChangedEventAr NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async () => { INuGetSolutionManagerService newService = await GetSolutionManagerServiceAsync( - _serviceBroker, + ServiceBroker, CancellationToken.None); using (_solutionManagerService.Swap(newService)) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIFactory.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIFactory.cs index 5944105074a..9020fc92c47 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIFactory.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/UserInterfaceService/NuGetUIFactory.cs @@ -6,6 +6,7 @@ using System.ComponentModel.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Utilities; using NuGet.Configuration; using NuGet.PackageManagement.VisualStudio; @@ -73,8 +74,15 @@ public NuGetUIFactory( /// /// Returns the UI for the project or given set of projects. /// - public async ValueTask CreateAsync(params IProjectContextInfo[] projects) + public async ValueTask CreateAsync( + IServiceBroker serviceBroker, + params IProjectContextInfo[] projects) { + if (serviceBroker is null) + { + throw new ArgumentNullException(nameof(serviceBroker)); + } + var adapterLogger = new LoggerAdapter(ProjectContext); ProjectContext.PackageExtractionContext = new PackageExtractionContext( @@ -89,6 +97,7 @@ public async ValueTask CreateAsync(params IProjectContextInfo[] projec PackageManagerProviders, MaxPackageManager); return await NuGetUI.CreateAsync( + serviceBroker, CommonOperations, ProjectContext, SourceRepositoryProvider.Value, diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/ProjectUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/ProjectUtility.cs index 4d24e6987eb..947c17cae1a 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/ProjectUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Utility/ProjectUtility.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; +using NuGet.PackageManagement.VisualStudio; using NuGet.VisualStudio.Internal.Contracts; namespace NuGet.PackageManagement.UI @@ -13,9 +15,15 @@ namespace NuGet.PackageManagement.UI internal static class ProjectUtility { internal static async ValueTask> GetSortedProjectIdsAsync( + IServiceBroker serviceBroker, IEnumerable projects, CancellationToken cancellationToken) { + if (serviceBroker is null) + { + throw new ArgumentNullException(nameof(serviceBroker)); + } + if (projects is null) { throw new ArgumentNullException(nameof(projects)); @@ -24,7 +32,7 @@ internal static async ValueTask> GetSortedProjectIdsAsync( cancellationToken.ThrowIfCancellationRequested(); IEnumerable> tasks = projects.Select( - project => project.GetMetadataAsync(cancellationToken).AsTask()); + project => project.GetMetadataAsync(serviceBroker, cancellationToken).AsTask()); IProjectMetadataContextInfo[] projectMetadatas = await Task.WhenAll(tasks); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs index 8dcc49f435e..77de5b7aef1 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs @@ -96,6 +96,7 @@ private async ValueTask InitializeAsync(PackageManagerModel model, INuGetUILogge if (Model.IsSolution) { _detailModel = await PackageSolutionDetailControlModel.CreateAsync( + Model.Context.ServiceBroker, Model.Context.SolutionManagerService, Model.Context.Projects, Model.Context.PackageManagerProviders, @@ -103,7 +104,10 @@ private async ValueTask InitializeAsync(PackageManagerModel model, INuGetUILogge } else { - _detailModel = new PackageDetailControlModel(Model.Context.SolutionManagerService, Model.Context.Projects); + _detailModel = new PackageDetailControlModel( + Model.Context.ServiceBroker, + Model.Context.SolutionManagerService, + Model.Context.Projects); } if (_windowSearchHostFactory != null) @@ -220,8 +224,12 @@ private async Task SolutionManager_ProjectRenamedAsync(IProjectContextInfo proje IProjectContextInfo currentNugetProject = Model.Context.Projects.First(); - IProjectMetadataContextInfo currentProjectMetadata = await currentNugetProject.GetMetadataAsync(CancellationToken.None); - IProjectMetadataContextInfo renamedProjectMetadata = await project.GetMetadataAsync(CancellationToken.None); + IProjectMetadataContextInfo currentProjectMetadata = await currentNugetProject.GetMetadataAsync( + Model.Context.ServiceBroker, + CancellationToken.None); + IProjectMetadataContextInfo renamedProjectMetadata = await project.GetMetadataAsync( + Model.Context.ServiceBroker, + CancellationToken.None); if (currentProjectMetadata.FullPath == renamedProjectMetadata.FullPath) { @@ -317,7 +325,9 @@ private async Task SolutionManager_CacheUpdatedAsync(TimeSpan timeSpan, string e { // This is a project package manager, so there is one and only one project. IProjectContextInfo project = Model.Context.Projects.First(); - IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync(CancellationToken.None); + IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync( + Model.Context.ServiceBroker, + CancellationToken.None); // This ensures that we refresh the UI only if the event.project.FullName matches the NuGetProject.FullName. // We also refresh the UI if projectFullPath is not present. @@ -521,7 +531,9 @@ private async Task GetSettingsKeyAsync(CancellationToken cancellationTok if (!Model.IsSolution) { IProjectContextInfo project = Model.Context.Projects.First(); - IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync(cancellationToken); + IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync( + Model.Context.ServiceBroker, + cancellationToken); string projectName; if (string.IsNullOrEmpty(projectMetadata.Name)) @@ -690,7 +702,9 @@ private async Task SetTitleAsync(IProjectMetadataContextInfo projectMetadata = n if (projectMetadata is null) { IProjectContextInfo project = Model.Context.Projects.First(); - IProjectMetadataContextInfo metadata = await project.GetMetadataAsync(CancellationToken.None); + IProjectMetadataContextInfo metadata = await project.GetMetadataAsync( + Model.Context.ServiceBroker, + CancellationToken.None); projectName = metadata.Name; } @@ -1139,6 +1153,7 @@ private void EmitSearchSelectionTelemetry(PackageItemListViewModel selectedPacka if (filter == ItemFilter.UpdatesAvailable) { packageFeeds.mainFeed = new UpdatePackageFeed( + context.ServiceBroker, installedPackages, metadataProvider, context.Projects, @@ -1253,7 +1268,12 @@ private void Refresh() NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async () => { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - var installedPackages = await PackageCollection.FromProjectsAsync(Model.Context.Projects, CancellationToken.None); + + PackageCollection installedPackages = await PackageCollection.FromProjectsAsync( + Model.Context.ServiceBroker, + Model.Context.Projects, + CancellationToken.None); + _packageList.UpdatePackageStatus(installedPackages.ToArray()); }) .PostOnFailure(nameof(PackageManagerControl), nameof(Refresh)); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/IProjectContextInfoExtensions.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/IProjectContextInfoExtensions.cs new file mode 100644 index 00000000000..e054cef1de3 --- /dev/null +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/IProjectContextInfoExtensions.cs @@ -0,0 +1,116 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft; +using Microsoft.ServiceHub.Framework; +using NuGet.Packaging.Core; +using NuGet.VisualStudio.Internal.Contracts; + +namespace NuGet.PackageManagement.VisualStudio +{ + public static class IProjectContextInfoExtensions + { + public static async ValueTask IsUpgradeableAsync( + this IProjectContextInfo projectContextInfo, + IServiceBroker serviceBroker, + CancellationToken cancellationToken) + { + Assumes.NotNull(projectContextInfo); + Assumes.NotNull(serviceBroker); + + cancellationToken.ThrowIfCancellationRequested(); + + using (INuGetProjectUpgraderService? projectUpgrader = await serviceBroker.GetProxyAsync( + NuGetServices.ProjectUpgraderService, + cancellationToken: cancellationToken)) + { + Assumes.NotNull(projectUpgrader); + + return await projectUpgrader.IsProjectUpgradeableAsync(projectContextInfo.ProjectId, cancellationToken); + } + } + + public static async ValueTask> GetInstalledPackagesAsync( + this IProjectContextInfo projectContextInfo, + IServiceBroker serviceBroker, + CancellationToken cancellationToken) + { + Assumes.NotNull(projectContextInfo); + Assumes.NotNull(serviceBroker); + + cancellationToken.ThrowIfCancellationRequested(); + + using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(serviceBroker, cancellationToken)) + { + return await projectManager.GetInstalledPackagesAsync(new string[] { projectContextInfo.ProjectId }, cancellationToken); + } + } + + public static async ValueTask GetMetadataAsync( + this IProjectContextInfo projectContextInfo, + IServiceBroker serviceBroker, + CancellationToken cancellationToken) + { + Assumes.NotNull(projectContextInfo); + Assumes.NotNull(serviceBroker); + + cancellationToken.ThrowIfCancellationRequested(); + + using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(serviceBroker, cancellationToken)) + { + return await projectManager.GetMetadataAsync(projectContextInfo.ProjectId, cancellationToken); + } + } + + public static async ValueTask GetUniqueNameOrNameAsync( + this IProjectContextInfo projectContextInfo, + IServiceBroker serviceBroker, + CancellationToken cancellationToken) + { + IProjectMetadataContextInfo metadata = await GetMetadataAsync(projectContextInfo, serviceBroker, cancellationToken); + + return metadata.UniqueName ?? metadata.Name; + } + + public static async ValueTask<(bool, string?)> TryGetInstalledPackageFilePathAsync( + this IProjectContextInfo projectContextInfo, + IServiceBroker serviceBroker, + PackageIdentity packageIdentity, + CancellationToken cancellationToken) + { + Assumes.NotNull(projectContextInfo); + Assumes.NotNull(serviceBroker); + Assumes.NotNull(packageIdentity); + + cancellationToken.ThrowIfCancellationRequested(); + + using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(serviceBroker, cancellationToken)) + { + return await projectManager.TryGetInstalledPackageFilePathAsync( + projectContextInfo.ProjectId, + packageIdentity, + cancellationToken); + } + } + + private static async ValueTask GetProjectManagerAsync( + IServiceBroker serviceBroker, + CancellationToken cancellationToken) + { +#pragma warning disable ISB001 // Dispose of proxies + INuGetProjectManagerService? projectManager = await serviceBroker.GetProxyAsync( + NuGetServices.ProjectManagerService, + cancellationToken: cancellationToken); +#pragma warning restore ISB001 // Dispose of proxies + + Assumes.NotNull(projectManager); + + return projectManager; + } + } +} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/PackageCollection.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/PackageCollection.cs index c46d2489ba7..d2d651dd655 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/PackageCollection.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Common/PackageCollection.cs @@ -9,6 +9,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft; +using Microsoft.ServiceHub.Framework; using NuGet.VisualStudio.Internal.Contracts; namespace NuGet.PackageManagement.VisualStudio @@ -39,11 +41,17 @@ IEnumerator IEnumerable.GetEnumerator() public bool ContainsId(string packageId) => _uniqueIds.Contains(packageId); - public static async Task FromProjectsAsync(IEnumerable projects, CancellationToken cancellationToken) + public static async Task FromProjectsAsync( + IServiceBroker serviceBroker, + IEnumerable projects, + CancellationToken cancellationToken) { + Assumes.NotNull(serviceBroker); + Assumes.NotNull(projects); + // Read package references from all projects. IEnumerable>>? tasks = projects - .Select(project => project.GetInstalledPackagesAsync(cancellationToken).AsTask()); + .Select(project => project.GetInstalledPackagesAsync(serviceBroker, cancellationToken).AsTask()); IEnumerable[]? packageReferences = await Task.WhenAll(tasks); // Group all package references for an id/version into a single item. diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj index 3f02016b1e8..d3b3eabdf24 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj @@ -69,6 +69,7 @@ + @@ -181,6 +182,7 @@ + diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/PackageFeeds/UpdatePackageFeed.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/PackageFeeds/UpdatePackageFeed.cs index a0608740752..eeda8297aec 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/PackageFeeds/UpdatePackageFeed.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/PackageFeeds/UpdatePackageFeed.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using NuGet.Protocol.Core.Types; using NuGet.Versioning; using NuGet.VisualStudio.Internal.Contracts; @@ -22,43 +23,22 @@ public sealed class UpdatePackageFeed : PlainPackageFeedBase private readonly PackageSearchMetadataCache _cachedUpdates; private readonly Common.ILogger _logger; private readonly IProjectContextInfo[] _projects; + private readonly IServiceBroker _serviceBroker; public UpdatePackageFeed( + IServiceBroker serviceBroker, IEnumerable installedPackages, IPackageMetadataProvider metadataProvider, IProjectContextInfo[] projects, PackageSearchMetadataCache optionalCachedUpdates, Common.ILogger logger) { - if (installedPackages == null) - { - throw new ArgumentNullException(nameof(installedPackages)); - } - - _installedPackages = installedPackages; - - if (metadataProvider == null) - { - throw new ArgumentNullException(nameof(metadataProvider)); - } - - _metadataProvider = metadataProvider; - - if (projects == null) - { - throw new ArgumentNullException(nameof(projects)); - } - - _projects = projects; - + _installedPackages = installedPackages ?? throw new ArgumentNullException(nameof(installedPackages)); + _metadataProvider = metadataProvider ?? throw new ArgumentNullException(nameof(metadataProvider)); + _projects = projects ?? throw new ArgumentNullException(nameof(projects)); _cachedUpdates = optionalCachedUpdates; - - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - _logger = logger; + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _serviceBroker = serviceBroker ?? throw new ArgumentNullException(nameof(serviceBroker)); } public override async Task> ContinueSearchAsync(ContinuationToken continuationToken, CancellationToken cancellationToken) @@ -120,7 +100,7 @@ public async Task> GetPackagesWithUpdatesAsy var packagesWithUpdates = new List(); foreach (var project in _projects) { - var installed = await project.GetInstalledPackagesAsync(cancellationToken); + var installed = await project.GetInstalledPackagesAsync(_serviceBroker, cancellationToken); foreach (var installedPackage in installed) { var installedVersion = installedPackage.Identity.Version; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Prompts/DotnetDeprecatedPrompt.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Prompts/DotnetDeprecatedPrompt.cs index 282251b09f0..25f1d646ac5 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Prompts/DotnetDeprecatedPrompt.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Prompts/DotnetDeprecatedPrompt.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using NuGet.Frameworks; using NuGet.ProjectManagement; using NuGet.VisualStudio.Internal.Contracts; @@ -35,11 +36,12 @@ public static DeprecatedFrameworkModel GetDeprecatedFrameworkModel(IEnumerable GetDeprecatedFrameworkModelAsync( + IServiceBroker serviceBroker, IEnumerable affectedProjects, CancellationToken cancellationToken) { Task[] tasks = affectedProjects - .Select(project => project.GetUniqueNameOrNameAsync(cancellationToken).AsTask()) + .Select(project => project.GetUniqueNameOrNameAsync(serviceBroker, cancellationToken).AsTask()) .ToArray(); string[] projectNames = await Task.WhenAll(tasks); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/IProjectContextInfoUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/IProjectContextInfoUtility.cs new file mode 100644 index 00000000000..2c67bfe1b14 --- /dev/null +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/IProjectContextInfoUtility.cs @@ -0,0 +1,73 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; +using NuGet.VisualStudio.Internal.Contracts; + +namespace NuGet.PackageManagement.VisualStudio +{ + public static class IProjectContextInfoUtility + { + private const string LiveShareUriScheme = "vsls"; + private const string ProjectGuidQueryString = "projectGuid"; + + public static async Task CreateAsync(IServiceBroker serviceBroker, string projectId, CancellationToken cancellationToken) + { + using (INuGetProjectManagerService projectManager = await serviceBroker.GetProxyAsync( + NuGetServices.ProjectManagerService, + CancellationToken.None)) + { + return await projectManager.GetProjectAsync(projectId, cancellationToken); + } + } + + public static string GetProjectGuidStringFromVslsQueryString(string queryString) + { + if (Uri.TryCreate(queryString, UriKind.Absolute, out Uri pathUri)) + { + if (string.Equals(pathUri.Scheme, LiveShareUriScheme, StringComparison.OrdinalIgnoreCase)) + { + Dictionary queryStrings = ParseQueryString(pathUri); + if (queryStrings.TryGetValue(ProjectGuidQueryString, out var projectGuid) && Guid.TryParse(projectGuid, out Guid result)) + { + return result.ToString(); + } + } + } + + return Guid.Empty.ToString(); + } + + private static Dictionary ParseQueryString(Uri uri) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + string queryString = uri.Query; + + if (queryString.StartsWith("?", StringComparison.Ordinal)) + { + queryString = queryString.Substring(1); + } + + if (queryString.Length == 0) + { + return result; + } + + var queries = queryString.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var query in queries) + { + var nameValue = query.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); + if (nameValue.Length == 2) + { + result.Add(nameValue[0], nameValue[1]); + } + } + + return result; + } + } +} diff --git a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs index 7aebcaa404f..213ab598e44 100644 --- a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs +++ b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs @@ -25,6 +25,7 @@ using NuGet.PackageManagement.VisualStudio; using NuGet.ProjectManagement; using NuGet.VisualStudio; +using NuGet.VisualStudio.Common; using NuGet.VisualStudio.Implementation.Extensibility; using NuGet.VisualStudio.Internal.Contracts; using NuGet.VisualStudio.Telemetry; @@ -138,6 +139,9 @@ public NuGetPackage() private INuGetProjectManagerServiceState _projectManagerServiceState; + [Import] + private Lazy ServiceBrokerProvider { get; set; } + /// /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. @@ -404,7 +408,10 @@ private async Task FindExistingWindowFrameAsync(Project project) } IProjectContextInfo existingProject = projects.First(); - IProjectMetadataContextInfo projectMetadata = await existingProject.GetMetadataAsync(CancellationToken.None); + IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); + IProjectMetadataContextInfo projectMetadata = await existingProject.GetMetadataAsync( + serviceBroker, + CancellationToken.None); if (string.Equals(projectMetadata.Name, project.Name, StringComparison.OrdinalIgnoreCase)) { @@ -495,8 +502,9 @@ private async Task CreateDocWindowAsync( // is thrown, an error dialog will pop up and this doc window will not be created. _ = await nugetProject.GetInstalledPackagesAsync(CancellationToken.None); + IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); IProjectContextInfo contextInfo = await ProjectContextInfo.CreateAsync(nugetProject, CancellationToken.None); - INuGetUI uiController = await UIFactory.Value.CreateAsync(contextInfo); + INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, contextInfo); // This model takes ownership of --- and Dispose() responsibility for --- the INuGetUI instance. var model = new PackageManagerModel( @@ -593,10 +601,11 @@ private async Task ExecuteUpgradeNuGetProjectCommandAsync(object sender, EventAr IVsWindowFrame windowFrame = await FindExistingWindowFrameAsync(project); windowFrame?.CloseFrame((uint)__FRAMECLOSE.FRAMECLOSE_SaveIfDirty); + IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); NuGetProject nuGetProject = await SolutionManager.Value.GetNuGetProjectAsync(uniqueName); IProjectContextInfo projectContextInfo = await ProjectContextInfo.CreateAsync(nuGetProject, CancellationToken.None); - using (INuGetUI uiController = await UIFactory.Value.CreateAsync(projectContextInfo)) + using (INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, projectContextInfo)) { await uiController.UIContext.UIActionEngine.UpgradeNuGetProjectAsync(uiController, projectContextInfo); @@ -721,12 +730,14 @@ private async Task CreateDocWindowForSolutionAsync() throw new InvalidOperationException(Resources.SolutionIsNotSaved); } + IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); IReadOnlyCollection projectContexts; - IServiceBroker remoteBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); - using (var nugetProjectManagerService = await remoteBroker.GetProxyAsync(NuGetServices.ProjectManagerService)) + + using (INuGetProjectManagerService projectManagerService = await serviceBroker.GetProxyAsync( + NuGetServices.ProjectManagerService)) { - Assumes.NotNull(nugetProjectManagerService); - projectContexts = await nugetProjectManagerService.GetProjectsAsync(CancellationToken.None); + Assumes.NotNull(projectManagerService); + projectContexts = await projectManagerService.GetProjectsAsync(CancellationToken.None); if (projectContexts.Count == 0) { @@ -735,7 +746,7 @@ private async Task CreateDocWindowForSolutionAsync() } } - INuGetUI uiController = await UIFactory.Value.CreateAsync(projectContexts.ToArray()); + INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, projectContexts.ToArray()); var solutionName = (string)_dte.Solution.Properties.Item("Name").Value; // This model takes ownership of --- and Dispose() responsibility for --- the INuGetUI instance. diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IServiceBrokerProvider.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IServiceBrokerProvider.cs new file mode 100644 index 00000000000..38659bcaa77 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IServiceBrokerProvider.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; + +namespace NuGet.VisualStudio.Common +{ + public interface IServiceBrokerProvider + { + ValueTask GetAsync(); + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/CachingIServiceBrokerProvider.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/CachingIServiceBrokerProvider.cs new file mode 100644 index 00000000000..9b65c984ce3 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/CachingIServiceBrokerProvider.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.ComponentModel.Composition; +using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Threading; +using NuGet.PackageManagement.VisualStudio; +using NuGet.VisualStudio.Common; + +namespace NuGet.VisualStudio.Implementation +{ + [Export(typeof(IServiceBrokerProvider))] + [PartCreationPolicy(CreationPolicy.Shared)] + internal sealed class CachingIServiceBrokerProvider : IServiceBrokerProvider + { + private readonly AsyncLazy _serviceBroker; + + internal CachingIServiceBrokerProvider() + { + _serviceBroker = new AsyncLazy( + () => BrokeredServicesUtilities.GetRemoteServiceBrokerAsync().AsTask(), + NuGetUIThreadHelper.JoinableTaskFactory); + } + + public async ValueTask GetAsync() + { + return await _serviceBroker.GetValueAsync(); + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs index 14fc1dab182..f0f1d03a1e3 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs @@ -3,10 +3,6 @@ #nullable enable -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using NuGet.Packaging.Core; using NuGet.ProjectModel; namespace NuGet.VisualStudio.Internal.Contracts @@ -19,12 +15,5 @@ public interface IProjectContextInfo string ProjectId { get; } ProjectStyle ProjectStyle { get; } NuGetProjectKind ProjectKind { get; } - ValueTask IsUpgradeableAsync(CancellationToken cancellationToken); - ValueTask> GetInstalledPackagesAsync(CancellationToken cancellationToken); - ValueTask GetMetadataAsync(CancellationToken cancellationToken); - ValueTask GetUniqueNameOrNameAsync(CancellationToken cancellationToken); - ValueTask<(bool, string?)> TryGetInstalledPackageFilePathAsync( - PackageIdentity packageIdentity, - CancellationToken cancellationToken); } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs index 1b693226eaa..98b30add36c 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs @@ -4,14 +4,9 @@ #nullable enable using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft; -using Microsoft.ServiceHub.Framework; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.ServiceBroker; -using NuGet.Packaging.Core; using NuGet.ProjectManagement; using NuGet.ProjectManagement.Projects; using NuGet.ProjectModel; @@ -20,9 +15,6 @@ namespace NuGet.VisualStudio.Internal.Contracts { public sealed class ProjectContextInfo : IProjectContextInfo { - private const string LiveShareUriScheme = "vsls"; - private const string ProjectGuidQueryString = "projectGuid"; - public ProjectContextInfo(string projectId, ProjectStyle projectStyle, NuGetProjectKind projectKind) { ProjectId = projectId; @@ -34,59 +26,6 @@ public ProjectContextInfo(string projectId, ProjectStyle projectStyle, NuGetProj public NuGetProjectKind ProjectKind { get; } public ProjectStyle ProjectStyle { get; } - public async ValueTask IsUpgradeableAsync(CancellationToken cancellationToken) - { - IServiceBroker remoteBroker = await GetRemoteServiceBrokerAsync(); - - using (INuGetProjectUpgraderService? projectUpgrader = await remoteBroker.GetProxyAsync( - NuGetServices.ProjectUpgraderService, - cancellationToken: cancellationToken)) - { - Assumes.NotNull(projectUpgrader); - - return await projectUpgrader.IsProjectUpgradeableAsync(ProjectId, cancellationToken); - } - } - - public async ValueTask> GetInstalledPackagesAsync(CancellationToken cancellationToken) - { - using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(cancellationToken)) - { - return await projectManager.GetInstalledPackagesAsync(new string[] { ProjectId }, cancellationToken); - } - } - - public async ValueTask GetMetadataAsync(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(cancellationToken)) - { - return await projectManager.GetMetadataAsync(ProjectId, cancellationToken); - } - } - - public async ValueTask GetUniqueNameOrNameAsync(CancellationToken cancellationToken) - { - IProjectMetadataContextInfo metadata = await GetMetadataAsync(cancellationToken); - - return metadata.UniqueName ?? metadata.Name; - } - - public async ValueTask<(bool, string?)> TryGetInstalledPackageFilePathAsync( - PackageIdentity packageIdentity, - CancellationToken cancellationToken) - { - Assumes.NotNull(packageIdentity); - - cancellationToken.ThrowIfCancellationRequested(); - - using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(cancellationToken)) - { - return await projectManager.TryGetInstalledPackageFilePathAsync(ProjectId, packageIdentity, cancellationToken); - } - } - public static ValueTask CreateAsync(NuGetProject nugetProject, CancellationToken cancellationToken) { Assumes.NotNull(nugetProject); @@ -102,14 +41,6 @@ public static ValueTask CreateAsync(NuGetProject nugetProje return new ValueTask(new ProjectContextInfo(projectId, projectStyle, projectKind)); } - public static async ValueTask CreateAsync(string projectId, CancellationToken cancellationToken) - { - using (INuGetProjectManagerService projectManager = await GetProjectManagerAsync(cancellationToken)) - { - return await projectManager.GetProjectAsync(projectId, cancellationToken); - } - } - private static NuGetProjectKind GetProjectKind(NuGetProject nugetProject) { // Order matters @@ -129,72 +60,5 @@ private static NuGetProjectKind GetProjectKind(NuGetProject nugetProject) return projectKind; } - - public static string GetProjectGuidStringFromVslsQueryString(string queryString) - { - if (Uri.TryCreate(queryString, UriKind.Absolute, out Uri pathUri)) - { - if (string.Equals(pathUri.Scheme, LiveShareUriScheme, StringComparison.OrdinalIgnoreCase)) - { - Dictionary queryStrings = ParseQueryString(pathUri); - if (queryStrings.TryGetValue(ProjectGuidQueryString, out var projectGuid) && Guid.TryParse(projectGuid, out Guid result)) - { - return result.ToString(); - } - } - } - - return Guid.Empty.ToString(); - } - - private static Dictionary ParseQueryString(Uri uri) - { - var result = new Dictionary(StringComparer.OrdinalIgnoreCase); - string queryString = uri.Query; - - if (queryString.StartsWith("?", StringComparison.Ordinal)) - { - queryString = queryString.Substring(1); - } - - if (queryString.Length == 0) - { - return result; - } - - var queries = queryString.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var query in queries) - { - var nameValue = query.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); - if (nameValue.Length == 2) - { - result.Add(nameValue[0], nameValue[1]); - } - } - - return result; - } - - private static async ValueTask GetProjectManagerAsync(CancellationToken cancellationToken) - { - IServiceBroker serviceBroker = await GetRemoteServiceBrokerAsync(); - -#pragma warning disable ISB001 // Dispose of proxies - INuGetProjectManagerService? projectManager = await serviceBroker.GetProxyAsync( - NuGetServices.ProjectManagerService, - cancellationToken: cancellationToken); -#pragma warning restore ISB001 // Dispose of proxies - - Assumes.NotNull(projectManager); - - return projectManager; - } - - private static async ValueTask GetRemoteServiceBrokerAsync() - { - var serviceBrokerContainer = await AsyncServiceProvider.GlobalProvider.GetServiceAsync(); - Assumes.NotNull(serviceBrokerContainer); - return serviceBrokerContainer.GetFullAccessServiceBroker(); - } } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/PackageManagerUICommandHandler.cs b/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/PackageManagerUICommandHandler.cs index 282107ff3fe..76cfc992b3a 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/PackageManagerUICommandHandler.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/PackageManagerUICommandHandler.cs @@ -23,6 +23,7 @@ using NuGet.PackageManagement.UI; using NuGet.PackageManagement.VisualStudio; using NuGet.ProjectManagement; +using NuGet.VisualStudio.Common; using NuGet.VisualStudio.Internal.Contracts; using IAsyncServiceProvider = Microsoft.VisualStudio.Shell.IAsyncServiceProvider; using Resx = NuGet.PackageManagement.UI.Resources; @@ -92,6 +93,9 @@ public PackageManagerUICommandHandler(JoinableTaskFactory joinableTaskFactory, I private IDisposable ProjectUpgradeHandler { get; set; } + [Import] + private Lazy ServiceBrokerProvider { get; set; } + private void Initialize() { _vsMonitorSelection = new AsyncLazy( @@ -245,7 +249,7 @@ private async ValueTask CreateToolWindowAsync(WorkspaceVisualNod { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - if (!Guid.TryParse(ProjectContextInfo.GetProjectGuidStringFromVslsQueryString(workspaceVisualNodeBase.VSSelectionMoniker), out Guid projectGuid)) + if (!Guid.TryParse(IProjectContextInfoUtility.GetProjectGuidStringFromVslsQueryString(workspaceVisualNodeBase.VSSelectionMoniker), out Guid projectGuid)) { throw new InvalidOperationException(); } @@ -280,8 +284,9 @@ private async ValueTask CreateToolWindowAsync(WorkspaceVisualNod if (windowFrame == null) { - IProjectContextInfo projectContextInfo = await ProjectContextInfo.CreateAsync(projectGuid.ToString(), CancellationToken.None); - INuGetUI uiController = await UIFactory.Value.CreateAsync(projectContextInfo); + IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); + IProjectContextInfo projectContextInfo = await IProjectContextInfoUtility.CreateAsync(serviceBroker, projectGuid.ToString(), CancellationToken.None); + INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, projectContextInfo); // This model takes ownership of --- and Dispose() responsibility for --- the INuGetUI instance. var model = new PackageManagerModel(uiController, isSolution: false, editorFactoryGuid: GuidList.NuGetEditorType); var control = await PackageManagerControl.CreateAsync(model, OutputConsoleLogger.Value); @@ -393,6 +398,5 @@ private bool ShouldMEFBeInitialized() return !_initialized; } - } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/LocalDetailControlModelTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/LocalDetailControlModelTests.cs index 1bd9849d63c..be9bf9c28aa 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/LocalDetailControlModelTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/LocalDetailControlModelTests.cs @@ -72,6 +72,7 @@ public LocalPackageDetailControlModelTests(LocalPackageSearchMetadataFixture tes { var solMgr = new Mock(); _testInstance = new PackageDetailControlModel( + Mock.Of(), solutionManager: solMgr.Object, projects: new List()); @@ -104,7 +105,8 @@ public void Options_ShowClassicOptions_WhenProjectKindIsNotProjectConfig_Returns .Returns(projectKind); var model = new PackageDetailControlModel( - solutionManager: Mock.Of(), + Mock.Of(), + Mock.Of(), projects: new[] { project.Object }); Assert.False(model.Options.ShowClassicOptions); @@ -119,7 +121,8 @@ public void Options_ShowClassicOptions_WhenProjectKindIsProjectConfig_ReturnsTru .Returns(NuGetProjectKind.PackagesConfig); var model = new PackageDetailControlModel( - solutionManager: Mock.Of(), + Mock.Of(), + Mock.Of(), projects: new[] { project.Object }); Assert.True(model.Options.ShowClassicOptions); @@ -129,6 +132,7 @@ public void Options_ShowClassicOptions_WhenProjectKindIsProjectConfig_ReturnsTru public void IsSelectedVersionInstalled_WhenSelectedVersionAndInstalledVersionAreNull_ReturnsFalse() { var model = new PackageDetailControlModel( + Mock.Of(), Mock.Of(), Enumerable.Empty()); @@ -141,6 +145,7 @@ public void IsSelectedVersionInstalled_WhenSelectedVersionAndInstalledVersionAre public async Task IsSelectedVersionInstalled_WhenSelectedVersionAndInstalledVersionAreNotEqual_ReturnsFalse() { var model = new PackageDetailControlModel( + Mock.Of(), Mock.Of(), Enumerable.Empty()); @@ -168,6 +173,7 @@ await model.SetCurrentPackage( public async Task IsSelectedVersionInstalled_WhenSelectedVersionAndInstalledVersionAreEqual_ReturnsTrue() { var model = new PackageDetailControlModel( + Mock.Of(), Mock.Of(), Enumerable.Empty()); diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/V3DetailControlModelTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/V3DetailControlModelTests.cs index f13d132bfe2..5d41760acbb 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/V3DetailControlModelTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Models/V3DetailControlModelTests.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Threading; using Moq; using NuGet.Common; @@ -96,6 +97,7 @@ public V3PackageDetailControlModelTests(V3PackageSearchMetadataFixture testData) { var solMgr = new Mock(); _testInstance = new PackageDetailControlModel( + Mock.Of(), solutionManager: solMgr.Object, Array.Empty()); _testInstance.SetCurrentPackage( diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageItemLoaderTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageItemLoaderTests.cs index 984c636ad53..c99e39349b8 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageItemLoaderTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageItemLoaderTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using Moq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -32,18 +33,21 @@ public class PackageItemLoaderTests public async Task MultipleSources_Works() { var solutionManager = Mock.Of(); - var uiContext = Mock.Of(); - Mock.Get(uiContext) - .Setup(x => x.SolutionManagerService) + var uiContext = new Mock(); + + uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); + uiContext.Setup(x => x.ServiceBroker) + .Returns(Mock.Of()); + var source1 = new PackageSource("https://pkgs.dev.azure.com/dnceng/public/_packaging/nuget-build/nuget/v3/index.json", "NuGetBuild"); var source2 = new PackageSource("https://api.nuget.org/v3/index.json", "NuGet.org"); var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(new[] { source1, source2 }); var repositories = sourceRepositoryProvider.GetRepositories(); - var context = new PackageLoadContext(repositories, false, uiContext); + var context = new PackageLoadContext(repositories, isSolution: false, uiContext.Object); var packageFeed = new MultiSourcePackageFeed(repositories, logger: null, telemetryService: null); var loader = new PackageItemLoader(context, packageFeed, "nuget"); @@ -55,7 +59,7 @@ public async Task MultipleSources_Works() while (loader.State.LoadingStatus == LoadingStatus.Loading) { await Task.Delay(TimeSpan.FromSeconds(1)); - await loader.UpdateStateAsync(null, CancellationToken.None); + await loader.UpdateStateAsync(progress: null, CancellationToken.None); } var items = loader.GetCurrent(); @@ -81,11 +85,14 @@ public async Task EmitsSearchTelemetryEvents() { // Arrange var solutionManager = Mock.Of(); - var uiContext = Mock.Of(); - Mock.Get(uiContext) - .Setup(x => x.SolutionManagerService) + var uiContext = new Mock(); + + uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); + uiContext.Setup(x => x.ServiceBroker) + .Returns(Mock.Of()); + var telemetryService = new Mock(); var eventsQueue = new ConcurrentQueue(); telemetryService @@ -119,14 +126,14 @@ public async Task EmitsSearchTelemetryEvents() var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(new[] { new PackageSource(source) }, new Lazy[] { new Lazy(() => new TestHttpSourceResourceProvider(injectedHttpSources)) }); var repositories = sourceRepositoryProvider.GetRepositories(); - var context = new PackageLoadContext(repositories, false, uiContext); + var context = new PackageLoadContext(repositories, isSolution: false, uiContext.Object); var packageFeed = new MultiSourcePackageFeed(repositories, logger: null, telemetryService: telemetryService.Object); // Act var loader = new PackageItemLoader(context, packageFeed, searchText: "nuget", includePrerelease: true); - await loader.LoadNextAsync(null, CancellationToken.None); - await loader.LoadNextAsync(null, CancellationToken.None); + await loader.LoadNextAsync(progress: null, CancellationToken.None); + await loader.LoadNextAsync(progress: null, CancellationToken.None); // Assert var events = eventsQueue.ToArray(); @@ -194,14 +201,17 @@ public async Task GetTotalCountAsync_Works() public async Task LoadNextAsync_Works() { var solutionManager = Mock.Of(); - var uiContext = Mock.Of(); - Mock.Get(uiContext) - .Setup(x => x.SolutionManagerService) + var uiContext = new Mock(); + + uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); - var context = new PackageLoadContext(null, false, uiContext); + uiContext.Setup(x => x.ServiceBroker) + .Returns(Mock.Of()); + + var context = new PackageLoadContext(sourceRepositories: null, isSolution: false, uiContext.Object); var packageFeed = new TestPackageFeed(); - var loader = new PackageItemLoader(context, packageFeed, TestSearchTerm, true); + var loader = new PackageItemLoader(context, packageFeed, TestSearchTerm, includePrerelease: true); Assert.Equal(LoadingStatus.Unknown, loader.State.LoadingStatus); var initial = loader.GetCurrent(); @@ -209,20 +219,20 @@ public async Task LoadNextAsync_Works() var loaded = new List(); - await loader.LoadNextAsync(null, CancellationToken.None); + await loader.LoadNextAsync(progress: null, CancellationToken.None); Assert.Equal(LoadingStatus.Loading, loader.State.LoadingStatus); var partial = loader.GetCurrent(); Assert.Empty(partial); await Task.Delay(TimeSpan.FromSeconds(1)); - await loader.UpdateStateAsync(null, CancellationToken.None); + await loader.UpdateStateAsync(progress: null, CancellationToken.None); Assert.NotEqual(LoadingStatus.Loading, loader.State.LoadingStatus); loaded.AddRange(loader.GetCurrent()); Assert.Equal(LoadingStatus.Ready, loader.State.LoadingStatus); - await loader.LoadNextAsync(null, CancellationToken.None); + await loader.LoadNextAsync(progress: null, CancellationToken.None); Assert.Equal(LoadingStatus.NoMoreItems, loader.State.LoadingStatus); loaded.AddRange(loader.GetCurrent()); @@ -235,11 +245,14 @@ public async Task PackageReader_NotNull() { // Prepare var solutionManager = Mock.Of(); - var uiContext = Mock.Of(); - Mock.Get(uiContext) - .Setup(x => x.SolutionManagerService) + var uiContext = new Mock(); + + uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); + uiContext.Setup(x => x.ServiceBroker) + .Returns(Mock.Of()); + using (var localFeedDir = TestDirectory.Create()) // local feed { // create test package @@ -254,13 +267,13 @@ public async Task PackageReader_NotNull() var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(new[] { localSource }); var repositories = sourceRepositoryProvider.GetRepositories(); - var context = new PackageLoadContext(repositories, false, uiContext); + var context = new PackageLoadContext(repositories, isSolution: false, uiContext.Object); var packageFeed = new MultiSourcePackageFeed(repositories, logger: null, telemetryService: null); var loader = new PackageItemLoader(context, packageFeed, "nuget"); // Act - await loader.LoadNextAsync(null, CancellationToken.None); + await loader.LoadNextAsync(progress: null, CancellationToken.None); var results = loader.GetCurrent(); // Assert diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageManagerListItemsTest.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageManagerListItemsTest.cs index cb145bd0bf7..ed75e4e4977 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageManagerListItemsTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageManagerListItemsTest.cs @@ -1,8 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using Moq; using NuGet.PackageManagement.VisualStudio; using NuGet.Protocol.Core.Types; @@ -18,11 +22,14 @@ public class PackageManagerListItemsTest public async Task PackagePrefixReservation_FromOneSource() { var solutionManager = Mock.Of(); - var uiContext = Mock.Of(); - Mock.Get(uiContext) - .Setup(x => x.SolutionManagerService) + var uiContext = new Mock(); + + uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); + uiContext.Setup(x => x.ServiceBroker) + .Returns(Mock.Of()); + // Arrange var responses = new Dictionary { @@ -39,19 +46,19 @@ public async Task PackagePrefixReservation_FromOneSource() repo }; - var context = new PackageLoadContext(repositories, false, uiContext); + var context = new PackageLoadContext(repositories, isSolution: false, uiContext.Object); var packageFeed = new MultiSourcePackageFeed(repositories, logger: null, telemetryService: null); - var loader = new PackageItemLoader(context, packageFeed, "EntityFramework", false); + var loader = new PackageItemLoader(context, packageFeed, "EntityFramework", includePrerelease: false); var loaded = new List(); foreach (var page in Enumerable.Range(0, 5)) { - await loader.LoadNextAsync(null, CancellationToken.None); + await loader.LoadNextAsync(progress: null, CancellationToken.None); while (loader.State.LoadingStatus == LoadingStatus.Loading) { await Task.Delay(TimeSpan.FromSeconds(1)); - await loader.UpdateStateAsync(null, CancellationToken.None); + await loader.UpdateStateAsync(progress: null, CancellationToken.None); } var items = loader.GetCurrent(); @@ -72,11 +79,14 @@ public async Task PackagePrefixReservation_FromOneSource() public async Task PackagePrefixReservation_FromMultiSource() { var solutionManager = Mock.Of(); - var uiContext = Mock.Of(); - Mock.Get(uiContext) - .Setup(x => x.SolutionManagerService) + var uiContext = new Mock(); + + uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); + uiContext.Setup(x => x.ServiceBroker) + .Returns(Mock.Of()); + // Arrange var responses = new Dictionary { @@ -97,10 +107,10 @@ public async Task PackagePrefixReservation_FromMultiSource() repo1 }; - var context = new PackageLoadContext(repositories, false, uiContext); + var context = new PackageLoadContext(repositories, isSolution: false, uiContext.Object); var packageFeed = new MultiSourcePackageFeed(repositories, logger: null, telemetryService: null); - var loader = new PackageItemLoader(context, packageFeed, "EntityFramework", false); + var loader = new PackageItemLoader(context, packageFeed, "EntityFramework", includePrerelease: false); var loaded = new List(); foreach (var page in Enumerable.Range(0, 5)) @@ -109,7 +119,7 @@ public async Task PackagePrefixReservation_FromMultiSource() while (loader.State.LoadingStatus == LoadingStatus.Loading) { await Task.Delay(TimeSpan.FromSeconds(1)); - await loader.UpdateStateAsync(null, CancellationToken.None); + await loader.UpdateStateAsync(progress: null, CancellationToken.None); } var items = loader.GetCurrent(); diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Utility/ProjectUtilityTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Utility/ProjectUtilityTests.cs index 49f4d94edec..00bce91c405 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Utility/ProjectUtilityTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/Utility/ProjectUtilityTests.cs @@ -6,7 +6,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using Moq; +using NuGet.PackageManagement.VisualStudio; using NuGet.VisualStudio.Internal.Contracts; using Xunit; @@ -14,11 +16,26 @@ namespace NuGet.PackageManagement.UI.Test { public class ProjectUtilityTests { + [Fact] + public async Task GetSortedProjectIdsAsync_WhenServiceBrokerIsNull_Throws() + { + ArgumentNullException exception = await Assert.ThrowsAsync( + () => ProjectUtility.GetSortedProjectIdsAsync( + serviceBroker: null, + projects: null, + CancellationToken.None).AsTask()); + + Assert.Equal("serviceBroker", exception.ParamName); + } + [Fact] public async Task GetSortedProjectIdsAsync_WhenProjectsIsNull_Throws() { ArgumentNullException exception = await Assert.ThrowsAsync( - () => ProjectUtility.GetSortedProjectIdsAsync(projects: null, CancellationToken.None).AsTask()); + () => ProjectUtility.GetSortedProjectIdsAsync( + Mock.Of(), + projects: null, + CancellationToken.None).AsTask()); Assert.Equal("projects", exception.ParamName); } @@ -28,6 +45,7 @@ public async Task GetSortedProjectIdsAsync_WhenCancellationTokenIsCancelled_Thro { await Assert.ThrowsAsync( () => ProjectUtility.GetSortedProjectIdsAsync( + Mock.Of(), Enumerable.Empty(), new CancellationToken(canceled: true)).AsTask()); } @@ -35,19 +53,40 @@ await Assert.ThrowsAsync( [Fact] public async Task GetSortedProjectIdsAsync_WhenProjectsUnsorted_ReturnsSortedProjectIds() { + string projectIdA = Guid.NewGuid().ToString(); + string projectIdB = Guid.NewGuid().ToString(); + string projectIdC = Guid.NewGuid().ToString(); var projectA = new Mock(); var projectB = new Mock(); var projectC = new Mock(); var projectAMetadata = new Mock(); var projectBMetadata = new Mock(); var projectCMetadata = new Mock(); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); + + projectManagerService.Setup( + x => x.GetMetadataAsync( + It.Is(projectId => projectId == projectIdA), + It.IsAny())) + .Returns(new ValueTask(projectAMetadata.Object)); + projectManagerService.Setup( + x => x.GetMetadataAsync( + It.Is(projectId => projectId == projectIdB), + It.IsAny())) + .Returns(new ValueTask(projectBMetadata.Object)); + projectManagerService.Setup( + x => x.GetMetadataAsync( + It.Is(projectId => projectId == projectIdC), + It.IsAny())) + .Returns(new ValueTask(projectCMetadata.Object)); - projectA.Setup(x => x.GetMetadataAsync(It.IsAny())) - .ReturnsAsync(projectAMetadata.Object); - projectB.Setup(x => x.GetMetadataAsync(It.IsAny())) - .ReturnsAsync(projectBMetadata.Object); - projectC.Setup(x => x.GetMetadataAsync(It.IsAny())) - .ReturnsAsync(projectCMetadata.Object); + projectA.SetupGet(x => x.ProjectId) + .Returns(projectIdA); + projectB.SetupGet(x => x.ProjectId) + .Returns(projectIdB); + projectC.SetupGet(x => x.ProjectId) + .Returns(projectIdC); projectAMetadata.SetupGet(x => x.UniqueName) .Returns("a"); @@ -67,10 +106,27 @@ public async Task GetSortedProjectIdsAsync_WhenProjectsUnsorted_ReturnsSortedPro .Returns(expectedResults[2]); IEnumerable actualResults = await ProjectUtility.GetSortedProjectIdsAsync( + serviceBroker.Object, new[] { projectB.Object, projectA.Object, projectC.Object }, CancellationToken.None); Assert.Equal(expectedResults, actualResults.ToArray()); } + + private static Mock SetupProjectManagerService(Mock serviceBroker) + { + var projectManagerService = new Mock(); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(s => s == NuGetServices.ProjectManagerService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectManagerService.Object)); + + return projectManagerService; + } } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Common/IProjectContextInfoExtensionsTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Common/IProjectContextInfoExtensionsTests.cs new file mode 100644 index 00000000000..3cf314e6a34 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Common/IProjectContextInfoExtensionsTests.cs @@ -0,0 +1,401 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; +using Moq; +using NuGet.Packaging.Core; +using NuGet.ProjectManagement; +using NuGet.Versioning; +using NuGet.VisualStudio.Internal.Contracts; +using Xunit; + +namespace NuGet.PackageManagement.VisualStudio.Test +{ + public class IProjectContextInfoExtensionsTests + { + private static readonly PackageIdentity PackageIdentity = new PackageIdentity(id: "a", NuGetVersion.Parse("1.0.0")); + + [Fact] + public async Task IsUpgradeableAsync_WhenProjectContextInfoIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.IsUpgradeableAsync( + projectContextInfo: null, + Mock.Of(), + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task IsUpgradeableAsync_WhenServiceBrokerIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.IsUpgradeableAsync( + Mock.Of(), + serviceBroker: null, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task IsUpgradeableAsync_WhenCancellationTokenIsCancelled_Throws() + { + await Assert.ThrowsAsync( + () => IProjectContextInfoExtensions.IsUpgradeableAsync( + Mock.Of(), + Mock.Of(), + new CancellationToken(canceled: true)) + .AsTask()); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task IsUpgradeableAsync_WhenArgumentsAreValid_ReturnsBoolean(bool expectedResult) + { + var serviceBroker = new Mock(); + var projectUpgraderService = new Mock(); + var project = new Mock(); + string projectId = Guid.NewGuid().ToString(); + + project.SetupGet(x => x.ProjectId) + .Returns(projectId); + + projectUpgraderService.Setup( + x => x.IsProjectUpgradeableAsync( + It.Is(id => string.Equals(projectId, id)), + It.IsAny())) + .Returns(new ValueTask(expectedResult)); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(descriptor => descriptor == NuGetServices.ProjectUpgraderService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectUpgraderService.Object)); + + bool actualResult = await IProjectContextInfoExtensions.IsUpgradeableAsync( + project.Object, + serviceBroker.Object, + CancellationToken.None); + + Assert.Equal(expectedResult, actualResult); + } + + [Fact] + public async Task GetInstalledPackagesAsync_WhenProjectContextInfoIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.GetInstalledPackagesAsync( + projectContextInfo: null, + Mock.Of(), + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task GetInstalledPackagesAsync_WhenServiceBrokerIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.GetInstalledPackagesAsync( + Mock.Of(), + serviceBroker: null, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task GetInstalledPackagesAsync_WhenCancellationTokenIsCancelled_Throws() + { + await Assert.ThrowsAsync( + () => IProjectContextInfoExtensions.GetInstalledPackagesAsync( + Mock.Of(), + Mock.Of(), + new CancellationToken(canceled: true)) + .AsTask()); + } + + [Fact] + public async Task GetInstalledPackagesAsync_WhenArgumentsAreValid_ReturnsInstalledPackages() + { + var serviceBroker = new Mock(); + var projectManagerService = new Mock(); + var project = new Mock(); + string projectId = Guid.NewGuid().ToString(); + var expectedResult = new List(); + + project.SetupGet(x => x.ProjectId) + .Returns(projectId); + + projectManagerService.Setup( + x => x.GetInstalledPackagesAsync( + It.Is(projectIds => projectIds.Length == 1 && string.Equals(projectId, projectIds[0])), + It.IsAny())) + .Returns(new ValueTask>(expectedResult)); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(descriptor => descriptor == NuGetServices.ProjectManagerService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectManagerService.Object)); + + IReadOnlyCollection actualResult = await IProjectContextInfoExtensions.GetInstalledPackagesAsync( + project.Object, + serviceBroker.Object, + CancellationToken.None); + + Assert.Same(expectedResult, actualResult); + } + + [Fact] + public async Task GetMetadataAsync_WhenProjectContextInfoIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.GetMetadataAsync( + projectContextInfo: null, + Mock.Of(), + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task GetMetadataAsync_WhenServiceBrokerIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.GetMetadataAsync( + Mock.Of(), + serviceBroker: null, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task GetMetadataAsync_WhenCancellationTokenIsCancelled_Throws() + { + await Assert.ThrowsAsync( + () => IProjectContextInfoExtensions.GetMetadataAsync( + Mock.Of(), + Mock.Of(), + new CancellationToken(canceled: true)) + .AsTask()); + } + + [Fact] + public async Task GetMetadataAsync_WhenArgumentsAreValid_ReturnsProjectMetadata() + { + var serviceBroker = new Mock(); + var projectManagerService = new Mock(); + var project = new Mock(); + string projectId = Guid.NewGuid().ToString(); + var expectedResult = Mock.Of(); + + project.SetupGet(x => x.ProjectId) + .Returns(projectId); + + projectManagerService.Setup( + x => x.GetMetadataAsync( + It.Is(id => string.Equals(projectId, id)), + It.IsAny())) + .Returns(new ValueTask(expectedResult)); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(descriptor => descriptor == NuGetServices.ProjectManagerService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectManagerService.Object)); + + IProjectMetadataContextInfo actualResult = await IProjectContextInfoExtensions.GetMetadataAsync( + project.Object, + serviceBroker.Object, + CancellationToken.None); + + Assert.Same(expectedResult, actualResult); + } + + [Fact] + public async Task GetUniqueNameOrNameAsync_WhenProjectContextInfoIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.GetUniqueNameOrNameAsync( + projectContextInfo: null, + Mock.Of(), + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task GetUniqueNameOrNameAsync_WhenServiceBrokerIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.GetUniqueNameOrNameAsync( + Mock.Of(), + serviceBroker: null, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task GetUniqueNameOrNameAsync_WhenCancellationTokenIsCancelled_Throws() + { + await Assert.ThrowsAsync( + () => IProjectContextInfoExtensions.GetUniqueNameOrNameAsync( + Mock.Of(), + Mock.Of(), + new CancellationToken(canceled: true)) + .AsTask()); + } + + [Theory] + [InlineData("unique", null)] + [InlineData(null, "name")] + [InlineData("unique", "name")] + public async Task GetUniqueNameOrNameAsync_WhenArgumentsAreValid_ReturnsString( + string uniqueName, + string name) + { + var serviceBroker = new Mock(); + var projectManagerService = new Mock(); + var project = new Mock(); + string projectId = Guid.NewGuid().ToString(); + var projectMetadata = new Mock(); + + projectMetadata.SetupGet(x => x.Name) + .Returns(name); + + projectMetadata.SetupGet(x => x.UniqueName) + .Returns(uniqueName); + + string expectedResult = uniqueName ?? name; + + project.SetupGet(x => x.ProjectId) + .Returns(projectId); + + projectManagerService.Setup( + x => x.GetMetadataAsync( + It.Is(id => string.Equals(projectId, id)), + It.IsAny())) + .Returns(new ValueTask(projectMetadata.Object)); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(descriptor => descriptor == NuGetServices.ProjectManagerService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectManagerService.Object)); + + string actualResult = await IProjectContextInfoExtensions.GetUniqueNameOrNameAsync( + project.Object, + serviceBroker.Object, + CancellationToken.None); + + Assert.Equal(expectedResult, actualResult); + } + + [Fact] + public async Task TryGetInstalledPackageFilePathAsync_WhenProjectContextInfoIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.TryGetInstalledPackageFilePathAsync( + projectContextInfo: null, + Mock.Of(), + PackageIdentity, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task TryGetInstalledPackageFilePathAsync_WhenServiceBrokerIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.TryGetInstalledPackageFilePathAsync( + Mock.Of(), + serviceBroker: null, + PackageIdentity, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task TryGetInstalledPackageFilePathAsync_WhenPackageIdentityIsNull_Throws() + { + await VerifyMicrosoftAssumesExceptionAsync( + () => IProjectContextInfoExtensions.TryGetInstalledPackageFilePathAsync( + Mock.Of(), + Mock.Of(), + packageIdentity: null, + CancellationToken.None) + .AsTask()); + } + + [Fact] + public async Task TryGetInstalledPackageFilePathAsync_WhenCancellationTokenIsCancelled_Throws() + { + await Assert.ThrowsAsync( + () => IProjectContextInfoExtensions.TryGetInstalledPackageFilePathAsync( + Mock.Of(), + Mock.Of(), + PackageIdentity, + new CancellationToken(canceled: true)) + .AsTask()); + } + + [Fact] + public async Task TryGetInstalledPackageFilePathAsync_WhenArgumentsAreValid_ReturnsString() + { + var serviceBroker = new Mock(); + var projectManagerService = new Mock(); + var project = new Mock(); + string projectId = Guid.NewGuid().ToString(); + (bool, string) expectedResult = (true, "a"); + + project.SetupGet(x => x.ProjectId) + .Returns(projectId); + + projectManagerService.Setup( + x => x.TryGetInstalledPackageFilePathAsync( + It.Is(id => string.Equals(projectId, id)), + It.Is(pi => ReferenceEquals(PackageIdentity, pi)), + It.IsAny())) + .Returns(new ValueTask<(bool, string)>(expectedResult)); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(descriptor => descriptor == NuGetServices.ProjectManagerService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectManagerService.Object)); + + (bool, string) actualResult = await IProjectContextInfoExtensions.TryGetInstalledPackageFilePathAsync( + project.Object, + serviceBroker.Object, + PackageIdentity, + CancellationToken.None); + + Assert.Equal(expectedResult.Item1, actualResult.Item1); + Assert.Equal(expectedResult.Item2, actualResult.Item2); + } + + private static async Task VerifyMicrosoftAssumesExceptionAsync(Func test) + { + Exception exception = await Assert.ThrowsAnyAsync(test); + + Assert.Equal(typeof(Microsoft.Assumes), exception.GetType().DeclaringType); + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Feeds/UpdatePackageFeedTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Feeds/UpdatePackageFeedTests.cs index 88b55325d55..68666aaaa6e 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Feeds/UpdatePackageFeedTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Feeds/UpdatePackageFeedTests.cs @@ -6,12 +6,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; using Moq; +using NuGet.Common; using NuGet.Frameworks; using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.Protocol.Core.Types; -using NuGet.Test.Utility; using NuGet.Versioning; using NuGet.VisualStudio.Internal.Contracts; using Xunit; @@ -36,7 +37,6 @@ public UpdatePackageFeedTests() .Setup(x => x.ResourceType) .Returns(typeof(PackageMetadataResource)); - var logger = new TestLogger(); var packageSource = new Configuration.PackageSource("http://fake-source"); var source = new SourceRepository(packageSource, new[] { provider }); @@ -45,7 +45,7 @@ public UpdatePackageFeedTests() new[] { source }, optionalLocalRepository: null, optionalGlobalLocalRepositories: null, - logger: logger); + logger: NullLogger.Instance); } [Fact] @@ -53,22 +53,32 @@ public async Task GetPackagesWithUpdatesAsync_WithAllVersions_RetrievesSingleUpd { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", new NuGetVersion("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); - var projectA = SetupProject("FakePackage", "1.0.0"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "1.0.0"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); // Assert Assert.Single(packages); - var updateCandidate = packages.Single(); + IPackageSearchMetadata updateCandidate = packages.Single(); Assert.Equal("2.0.1", updateCandidate.Identity.Version.ToString()); - var actualVersions = await updateCandidate.GetVersionsAsync(); + IEnumerable actualVersions = await updateCandidate.GetVersionsAsync(); Assert.NotEmpty(actualVersions); Assert.Equal( new[] { "2.0.1", "2.0.0", "1.0.1", "1.0.0", "0.0.1" }, @@ -80,22 +90,32 @@ public async Task GetPackagesWithUpdatesAsync_WithAllowedVersions_RetrievesSingl { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", new NuGetVersion("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); - var projectA = SetupProject("FakePackage", "1.0.0", "[1,2)"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "1.0.0", "[1,2)"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); // Assert Assert.Single(packages); - var updateCandidate = packages.Single(); + IPackageSearchMetadata updateCandidate = packages.Single(); Assert.Equal("1.0.1", updateCandidate.Identity.Version.ToString()); - var actualVersions = await updateCandidate.GetVersionsAsync(); + IEnumerable actualVersions = await updateCandidate.GetVersionsAsync(); Assert.NotEmpty(actualVersions); Assert.Equal( new[] { "2.0.1", "2.0.0", "1.0.1", "1.0.0", "0.0.1" }, @@ -107,27 +127,37 @@ public async Task GetPackagesWithUpdatesAsync_WithMultipleProjects_RetrievesSing { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", new NuGetVersion("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); // Both projects need to be updated to different versions // projectA: 1.0.0 => 2.0.1 // projectB: 1.0.0 => 1.0.1 - var projectA = SetupProject("FakePackage", "1.0.0"); - var projectB = SetupProject("FakePackage", "1.0.0", "[1,2)"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "1.0.0"); + IProjectContextInfo projectB = SetupProject(projectManagerService, "FakePackage", "1.0.0", "[1,2)"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA, projectB }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA, projectB }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); // Assert // Should retrieve a single update item with the lowest version and full list of available versions Assert.Single(packages); - var updateCandidate = packages.Single(); + IPackageSearchMetadata updateCandidate = packages.Single(); Assert.Equal("1.0.1", updateCandidate.Identity.Version.ToString()); - var actualVersions = await updateCandidate.GetVersionsAsync(); + IEnumerable actualVersions = await updateCandidate.GetVersionsAsync(); Assert.NotEmpty(actualVersions); Assert.Equal( new[] { "2.0.1", "2.0.0", "1.0.1", "1.0.0", "0.0.1" }, @@ -139,27 +169,37 @@ public async Task GetPackagesWithUpdatesAsync_WithMultipleProjects_RetrievesSing { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", NuGetVersion.Parse("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); // Only one project needs to be updated // projectA: 2.0.0 => 2.0.1 // projectB: 1.0.1 => None - var projectA = SetupProject("FakePackage", "2.0.0"); - var projectB = SetupProject("FakePackage", "1.0.1", "[1,2)"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "2.0.0"); + IProjectContextInfo projectB = SetupProject(projectManagerService, "FakePackage", "1.0.1", "[1,2)"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA, projectB }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA, projectB }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); // Assert // Should retrieve a single update item with the lowest version and full list of available versions Assert.Single(packages); - var updateCandidate = packages.Single(); + IPackageSearchMetadata updateCandidate = packages.Single(); Assert.Equal("2.0.1", updateCandidate.Identity.Version.ToString()); - var actualVersions = await updateCandidate.GetVersionsAsync(); + IEnumerable actualVersions = await updateCandidate.GetVersionsAsync(); Assert.NotEmpty(actualVersions); Assert.Equal( new[] { "2.0.1", "2.0.0", "1.0.1", "1.0.0", "0.0.1" }, @@ -171,27 +211,37 @@ public async Task GetPackagesWithUpdatesAsync_WithMultipleProjects_RetrievesSing { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", NuGetVersion.Parse("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); // Only one project needs to be updated // projectA: 2.0.1 => None // projectB: 1.0.0 => 1.0.1 - var projectA = SetupProject("FakePackage", "2.0.1"); - var projectB = SetupProject("FakePackage", "1.0.0", "[1,2)"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "2.0.1"); + IProjectContextInfo projectB = SetupProject(projectManagerService, "FakePackage", "1.0.0", "[1,2)"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA, projectB }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA, projectB }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); // Assert // Should retrieve a single update item with the lowest version and full list of available versions Assert.Single(packages); - var updateCandidate = packages.Single(); + IPackageSearchMetadata updateCandidate = packages.Single(); Assert.Equal("1.0.1", updateCandidate.Identity.Version.ToString()); - var actualVersions = await updateCandidate.GetVersionsAsync(); + IEnumerable actualVersions = await updateCandidate.GetVersionsAsync(); Assert.NotEmpty(actualVersions); Assert.Equal( new[] { "2.0.1", "2.0.0", "1.0.1", "1.0.0", "0.0.1" }, @@ -203,16 +253,26 @@ public async Task GetPackagesWithUpdatesAsync_WithMultipleProjects_RetrievesNoUp { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", NuGetVersion.Parse("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); - var projectA = SetupProject("FakePackage", "2.0.1"); - var projectB = SetupProject("FakePackage", "1.0.1", "[1,2)"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "2.0.1"); + IProjectContextInfo projectB = SetupProject(projectManagerService, "FakePackage", "1.0.1", "[1,2)"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA, projectB }, null, new TestLogger()); + UpdatePackageFeed _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA, projectB }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); // Assert Assert.Empty(packages); @@ -223,41 +283,57 @@ public async Task GetPackagesWithUpdatesAsync_WithHttpCache_RetrievesUpdate() { // Arrange var testPackageIdentity = new PackageCollectionItem("FakePackage", new NuGetVersion("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); - var projectA = SetupProject("FakePackage", "1.0.0"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "1.0.0"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.0"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity }, _metadataProvider, new[] { projectA }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity }, + _metadataProvider, + new[] { projectA }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); Assert.Single(packages); - var updateCandidate = packages.Single(); + IPackageSearchMetadata updateCandidate = packages.Single(); Assert.Equal("2.0.0", updateCandidate.Identity.Version.ToString()); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); Assert.Single(packages); updateCandidate = packages.Single(); Assert.Equal("2.0.1", updateCandidate.Identity.Version.ToString()); - var actualVersions = await updateCandidate.GetVersionsAsync(); + IEnumerable actualVersions = await updateCandidate.GetVersionsAsync(); Assert.NotEmpty(actualVersions); Assert.Equal( new[] { "2.0.1", "2.0.0", "1.0.1", "1.0.0", "0.0.1" }, actualVersions.Select(v => v.Version.ToString()).ToArray()); } - private IProjectContextInfo SetupProject(string packageId, string packageVersion, string allowedVersions = null) + private IProjectContextInfo SetupProject( + Mock projectManagerService, + string packageId, + string packageVersion, + string allowedVersions = null) { var packageIdentity = new PackageIdentity(packageId, NuGetVersion.Parse(packageVersion)); - var installedPackages = new[] + var installedPackages = new PackageReferenceContextInfo[] { PackageReferenceContextInfo.Create( new PackageReference( @@ -269,16 +345,25 @@ private IProjectContextInfo SetupProject(string packageId, string packageVersion allowedVersions: allowedVersions != null ? VersionRange.Parse(allowedVersions) : null)) }; - var project = Mock.Of(); - Mock.Get(project) - .Setup(x => x.GetInstalledPackagesAsync(It.IsAny())) + string projectId = Guid.NewGuid().ToString(); + + projectManagerService.Setup( + x => x.GetInstalledPackagesAsync( + It.Is>(projectIds => projectIds.Single() == projectId), + It.IsAny())) .Returns(new ValueTask>(installedPackages)); - return project; + + var project = new Mock(); + + project.SetupGet(x => x.ProjectId) + .Returns(projectId); + + return project.Object; } private void SetupRemotePackageMetadata(string id, params string[] versions) { - var metadata = versions + IEnumerable metadata = versions .Select(v => PackageSearchMetadataBuilder .FromIdentity(new PackageIdentity(id, new NuGetVersion(v))) .Build()); @@ -295,26 +380,51 @@ public async Task GetPackagesWithUpdatesAsync_WithMultiplePackages_SortedByPacka var testPackageIdentity = new PackageCollectionItem("FakePackage", NuGetVersion.Parse("1.0.0"), null); var testPackageIdentity2 = new PackageCollectionItem("AFakePackage", NuGetVersion.Parse("1.0.0"), null); var testPackageIdentity3 = new PackageCollectionItem("ZFakePackage", NuGetVersion.Parse("1.0.0"), null); + var serviceBroker = new Mock(); + Mock projectManagerService = SetupProjectManagerService(serviceBroker); - var projectA = SetupProject("FakePackage", "1.0.0"); - var projectB = SetupProject("ZFakePackage", "1.0.0"); - var projectC = SetupProject("AFakePackage", "1.0.0"); + IProjectContextInfo projectA = SetupProject(projectManagerService, "FakePackage", "1.0.0"); + IProjectContextInfo projectB = SetupProject(projectManagerService, "ZFakePackage", "1.0.0"); + IProjectContextInfo projectC = SetupProject(projectManagerService, "AFakePackage", "1.0.0"); SetupRemotePackageMetadata("FakePackage", "0.0.1", "1.0.0", "2.0.1", "2.0.0", "1.0.1"); SetupRemotePackageMetadata("ZFakePackage", "0.0.1", "1.0.0", "4.0.0"); SetupRemotePackageMetadata("AFakePackage", "1.0.0", "3.0.1"); - var _target = new UpdatePackageFeed(new[] { testPackageIdentity, testPackageIdentity2, testPackageIdentity3 } - , _metadataProvider, new[] { projectA, projectB, projectC }, null, new TestLogger()); + var _target = new UpdatePackageFeed( + serviceBroker.Object, + new[] { testPackageIdentity, testPackageIdentity2, testPackageIdentity3 }, + _metadataProvider, + new[] { projectA, projectB, projectC }, + optionalCachedUpdates: null, + NullLogger.Instance); // Act - var packages = await _target.GetPackagesWithUpdatesAsync( - "fake", new SearchFilter(includePrerelease: false), CancellationToken.None); + IEnumerable packages = await _target.GetPackagesWithUpdatesAsync( + searchText: "fake", + new SearchFilter(includePrerelease: false), + CancellationToken.None); - var actualPackageIds = packages.Select(p => p.Identity.Id); + IEnumerable actualPackageIds = packages.Select(p => p.Identity.Id); // Assert var expectedPackageIdsSorted = new List() { "AFakePackage", "FakePackage", "ZFakePackage" }; Assert.Equal(expectedPackageIdsSorted, actualPackageIds); //Equal considers sort order of collections. } + + private static Mock SetupProjectManagerService(Mock serviceBroker) + { + var projectManagerService = new Mock(); + + serviceBroker.Setup( +#pragma warning disable ISB001 // Dispose of proxies + x => x.GetProxyAsync( + It.Is(s => s == NuGetServices.ProjectManagerService), + It.IsAny(), + It.IsAny())) +#pragma warning restore ISB001 // Dispose of proxies + .Returns(new ValueTask(projectManagerService.Object)); + + return projectManagerService; + } } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj index d5a7cf31fd1..23a92187952 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj @@ -23,6 +23,7 @@ + diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/CachingIServiceBrokerProviderTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/CachingIServiceBrokerProviderTests.cs new file mode 100644 index 00000000000..d8960411a6a --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/CachingIServiceBrokerProviderTests.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Sdk.TestFramework; +using Xunit; + +namespace NuGet.VisualStudio.Implementation.Test +{ + [Collection(MockedVs.CollectionName)] + public class CachingIServiceBrokerProviderTests + { + public CachingIServiceBrokerProviderTests(GlobalServiceProvider serviceProvider) + { + serviceProvider.Reset(); + } + + [Fact] + public async Task GetAsync_Always_IsIdempotent() + { + var provider = new CachingIServiceBrokerProvider(); + + IServiceBroker serviceBroker1 = await provider.GetAsync(); + IServiceBroker serviceBroker2 = await provider.GetAsync(); + + Assert.Same(serviceBroker1, serviceBroker2); + } + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/Extensibility/VsPathContextProviderTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/Extensibility/VsPathContextProviderTests.cs index bcb7939c244..46cd5b47446 100644 --- a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/Extensibility/VsPathContextProviderTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/Extensibility/VsPathContextProviderTests.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft; +using Microsoft.VisualStudio.Sdk.TestFramework; using Microsoft.VisualStudio.Threading; using Moq; using NuGet.Common; @@ -22,22 +22,16 @@ using NuGet.ProjectModel; using NuGet.Test.Utility; using NuGet.Versioning; -using Test.Utility.Threading; using Xunit; namespace NuGet.VisualStudio.Implementation.Test.Extensibility { - [Collection(DispatcherThreadCollection.CollectionName)] + [Collection(MockedVs.CollectionName)] public class VsPathContextProviderTests { - private readonly JoinableTaskFactory _jtf; - - public VsPathContextProviderTests(DispatcherThreadFixture fixture) + public VsPathContextProviderTests(GlobalServiceProvider serviceProvider) { - Assumes.Present(fixture); - - _jtf = fixture.JoinableTaskFactory; - NuGetUIThreadHelper.SetCustomJoinableTaskFactory(_jtf); + serviceProvider.Reset(); } [Fact] diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/MockedVS.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/MockedVS.cs new file mode 100644 index 00000000000..7418237bf0a --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/MockedVS.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.VisualStudio.Sdk.TestFramework; +using Xunit; + +namespace NuGet.VisualStudio.Implementation.Test +{ + /// + /// Defines the "MockedVS" xunit test collection. + /// + [CollectionDefinition(CollectionName)] + public class MockedVs : ICollectionFixture, ICollectionFixture + { + /// + /// The name of the xunit test collection. + /// + public const string CollectionName = "MockedVS"; + } +} diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/NuGet.VisualStudio.Implementation.Test.csproj b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/NuGet.VisualStudio.Implementation.Test.csproj index 2e4d7e0a946..9defe9ad0d0 100644 --- a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/NuGet.VisualStudio.Implementation.Test.csproj +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/NuGet.VisualStudio.Implementation.Test.csproj @@ -55,7 +55,8 @@ - + + diff --git a/test/NuGet.Tests.Apex/NuGet.PackageManagement.UI.TestContract/NuGetApexUITestService.cs b/test/NuGet.Tests.Apex/NuGet.PackageManagement.UI.TestContract/NuGetApexUITestService.cs index b677059de4d..c079179f17d 100644 --- a/test/NuGet.Tests.Apex/NuGet.PackageManagement.UI.TestContract/NuGetApexUITestService.cs +++ b/test/NuGet.Tests.Apex/NuGet.PackageManagement.UI.TestContract/NuGetApexUITestService.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using System.Threading; +using Microsoft.ServiceHub.Framework; using Microsoft.TeamFoundation.WorkItemTracking.Process.WebApi.Models; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell.Interop; @@ -77,7 +78,10 @@ private PackageManagerControl GetProjectPackageManagerControl(string projectUniq } IProjectContextInfo existingProject = projects.First(); - IProjectMetadataContextInfo projectMetadata = await existingProject.GetMetadataAsync(CancellationToken.None); + IServiceBroker serviceBroker = packageManagerWindowPane.Model.Context.ServiceBroker; + IProjectMetadataContextInfo projectMetadata = await existingProject.GetMetadataAsync( + serviceBroker, + CancellationToken.None); if (string.Equals(projectMetadata.Name, projectUniqueName, StringComparison.OrdinalIgnoreCase)) { From bc84d5d0f6ca19e7a131d4ec258b6269c2d3cfaa Mon Sep 17 00:00:00 2001 From: Andy Zivkovic Date: Thu, 22 Oct 2020 17:45:35 -0700 Subject: [PATCH 014/129] Use CPSPackageReferenceNuGetProject only when both CPS and PR capabilities are set (#3726) --- .../CpsPackageReferenceProjectProvider.cs | 6 +- .../Projects/VsProjectAdapter.cs | 8 +++ .../IDE/ProjectCapabilities.cs | 30 +++++++++ .../IDE/VsHierarchyUtility.cs | 12 ++-- .../IVsProjectAdapter.cs | 5 ++ ...PackageManagement.VisualStudio.Test.csproj | 1 + .../ProjectSystems/TestVSProjectAdapter.cs | 5 ++ ...CpsPackageReferenceProjectProviderTests.cs | 66 +++++++++++++++++++ 8 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/ProjectCapabilities.cs create mode 100644 test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Projects/CpsPackageReferenceProjectProviderTests.cs diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs index a8b9b5d821d..03a193ff2ca 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs @@ -74,9 +74,9 @@ public async Task TryCreateNuGetProjectAsync( return null; } - // Check if the project is not CPS capable or if it is CPS capable that its opt'd in PackageReferences - if (!VsHierarchyUtility.IsCPSCapabilityCompliant(hierarchy) || - !VsHierarchyUtility.IsProjectCapabilityCompliant(hierarchy)) + // Check that the project supports both CPS and PackageReferences + if (!(await vsProject.IsCapabilityMatchAsync(NuGet.VisualStudio.IDE.ProjectCapabilities.Cps) && + await vsProject.IsCapabilityMatchAsync(NuGet.VisualStudio.IDE.ProjectCapabilities.PackageReferences))) { return null; } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs index 2d18cd80d76..bee0a4c3834 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs @@ -9,6 +9,7 @@ using System.Runtime.Versioning; using System.Threading.Tasks; using Microsoft; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using NuGet.Commands; using NuGet.Common; @@ -444,6 +445,13 @@ private async Task GetTargetFrameworkStringAsync() return frameworkStrings.FirstOrDefault(); } + public async Task IsCapabilityMatchAsync(string capabilityExpression) + { + await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); + + return VsHierarchy.IsCapabilityMatch(capabilityExpression); + } + #endregion Getters } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/ProjectCapabilities.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/ProjectCapabilities.cs new file mode 100644 index 00000000000..aad0b11f407 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/ProjectCapabilities.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace NuGet.VisualStudio.IDE +{ + public static class ProjectCapabilities + { + /// + /// All CPS projects will have CPS capability except VisualC projects. + /// So checking for VisualC explicitly with a OR flag. + /// + /// This does not mean the project uses PackageReference. + public const string Cps = "CPS | VisualC"; + + /// + /// Capability string for projects that want to support PackageReferences + /// + /// There are multiple project systems that support PackageReferences, we can't assume which one without more information. + public const string PackageReferences = "PackageReferences"; + + /// + /// Capability expression to try to determine if the (MSBuild based) project supports NuGet. + /// + /// + /// VS project systems that are not MSBuild based (project.json) will not get detected by this. + /// Similarly, there are multiple project systems that match this expression, so additional information is needed to determine which project system. + /// + public const string SupportsNuGet = "(AssemblyReferences + DeclaredSourceItems + UserSourceItems) | PackageReferences"; + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs index 5cfa1d98b6d..bcf516bfb76 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs @@ -43,13 +43,17 @@ public static bool IsSupported(IVsHierarchy hierarchy, string projectTypeGuid) return !string.IsNullOrEmpty(projectTypeGuid) && SupportedProjectTypes.IsSupported(projectTypeGuid) && !HasUnsupportedProjectCapability(hierarchy); } + /// Check if this project appears to support NuGet. + /// IVsHierarchy representing the project in the solution. + /// True if NuGet should enable this project, false if NuGet should ignore the project. + /// The project may be packages.config or PackageReference. This method does not tell you which. public static bool IsProjectCapabilityCompliant(IVsHierarchy hierarchy) { ThreadHelper.ThrowIfNotOnUIThread(); // NOTE: (AssemblyReferences + DeclaredSourceItems + UserSourceItems) exists solely for compatibility reasons // with existing custom CPS-based projects that existed before "PackageReferences" capability was introduced. - return hierarchy.IsCapabilityMatch("(AssemblyReferences + DeclaredSourceItems + UserSourceItems) | PackageReferences"); + return hierarchy.IsCapabilityMatch(IDE.ProjectCapabilities.SupportsNuGet); } public static bool HasUnsupportedProjectCapability(IVsHierarchy hierarchy) @@ -80,14 +84,14 @@ public static string[] GetProjectTypeGuids(IVsHierarchy hierarchy, string defaul } /// - /// Check for CPS capability in IVsHierarchy. All CPS projects will have CPS capability except VisualC projects. - /// So checking for VisualC explicitly with a OR flag. + /// Check for CPS capability in IVsHierarchy. /// + /// This does not mean the project also supports PackageReference! public static bool IsCPSCapabilityCompliant(IVsHierarchy hierarchy) { ThreadHelper.ThrowIfNotOnUIThread(); - return hierarchy.IsCapabilityMatch("CPS | VisualC"); + return hierarchy.IsCapabilityMatch(IDE.ProjectCapabilities.Cps); } /// diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs index 5b3388e58a0..407e19ed476 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs @@ -159,5 +159,10 @@ public interface IVsProjectAdapter /// The metadata names to read. /// An containing the itemId and the metadata values. Task> GetBuildItemInformationAsync(string itemName, params string[] metadataNames); + + /// + /// See + /// + Task IsCapabilityMatchAsync(string capabilityExpression); } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj index 23a92187952..c16e6325982 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj @@ -37,6 +37,7 @@ + diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs index 79354ce663c..24378be42e3 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs @@ -246,5 +246,10 @@ public async Task GetPropertyValueAsync(string propertyName) return string.Empty; } + + public Task IsCapabilityMatchAsync(string capabilityExpression) + { + throw new NotImplementedException(); + } } } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Projects/CpsPackageReferenceProjectProviderTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Projects/CpsPackageReferenceProjectProviderTests.cs new file mode 100644 index 00000000000..c1aa0783ad9 --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Projects/CpsPackageReferenceProjectProviderTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using Microsoft; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Threading; +using Moq; +using NuGet.ProjectManagement; +using NuGet.VisualStudio; +using Test.Utility.Threading; +using Xunit; + +namespace NuGet.PackageManagement.VisualStudio.Test.Projects +{ + [Collection(DispatcherThreadCollection.CollectionName)] + public class CpsPackageReferenceProjectProviderTests + { + private readonly JoinableTaskFactory _jtf; + + public CpsPackageReferenceProjectProviderTests(DispatcherThreadFixture fixture) + { + Assumes.Present(fixture); + + _jtf = fixture.JoinableTaskFactory; + + NuGetUIThreadHelper.SetCustomJoinableTaskFactory(_jtf); + } + + // As of October 2020, Service Fabric projects (sfproj) uses CPS, but does not support PackageReference. Make sure non-PR CPS projects do not use this project system. + [Fact] + public async Task TryCreateNuGetProjectAsync_CpsProjectWithoutPackageReferencesCapability_ReturnsNull() + { + // Arrange + var hierarchy = new Mock(); + + var projectAdapter = new Mock(); + projectAdapter.SetupGet(a => a.VsHierarchy) + .Returns(hierarchy.Object); + projectAdapter.Setup(a => a.IsCapabilityMatchAsync(NuGet.VisualStudio.IDE.ProjectCapabilities.Cps)) + .Returns(Task.FromResult(true)); + projectAdapter.Setup(a => a.IsCapabilityMatchAsync(NuGet.VisualStudio.IDE.ProjectCapabilities.PackageReferences)) + .Returns(Task.FromResult(false)); + + var nugetProjectContext = new Mock(); + + var ppc = new ProjectProviderContext(nugetProjectContext.Object, packagesPathFactory: () => throw new NotImplementedException()); + + var projectSystemCache = new Mock(); + var target = new CpsPackageReferenceProjectProvider(projectSystemCache.Object); + + // Act + NuGetProject actual = await _jtf.RunAsync(async () => + { + await _jtf.SwitchToMainThreadAsync(); + return await target.TryCreateNuGetProjectAsync(projectAdapter.Object, ppc, forceProjectType: false); + }); + + // Assert + Assert.Null(actual); + projectAdapter.Verify(a => a.IsCapabilityMatchAsync(NuGet.VisualStudio.IDE.ProjectCapabilities.Cps), Times.Once); + projectAdapter.Verify(a => a.IsCapabilityMatchAsync(NuGet.VisualStudio.IDE.ProjectCapabilities.PackageReferences), Times.Once); + } + } +} From e7403cc4ebe6825aadf6e09c0e266888bf8522f1 Mon Sep 17 00:00:00 2001 From: Erdembayar Yondon Date: Fri, 23 Oct 2020 11:20:44 -0500 Subject: [PATCH 015/129] Perf optimization: Make creation of uninstall actions run in parallel (#3703) * Made creation of uninstall actions run in parallel. * Address code review comments by @dtivel * Add unit tests for covering new `PreviewProjectsUninstallPackageAsync` method in NuGetPackageManager. * Address 1 more code review comment from dtivel. * Add unhappy path unit test. * Address more code review comments by dtivel. * Fix rebasing to dev. * Add another perf improvement for BuildIntegratedNuGetProject type projects. BuildIntegratedNuGetProject project can batch eval of DependencyGraphRestoreUtility.PreviewRestoreProjectsAsync. * Fix logic error for non-builtIntegrated projects. * Remove optimization for msbuild package.config type projects since they're not part of this optimization scope. * Remove unnecessary comment. * Fix formatting. * Address review by Nikolche. * Fix flaky test due. * Remove unused variables from test. Co-authored-by: Erick Yondon --- .../Actions/UIActionEngine.cs | 27 +- .../Services/NuGetProjectManagerService.cs | 55 +- .../INuGetProjectManagerService.cs | 2 +- .../SolutionExplorer/RestoreCommandHandler.cs | 2 +- .../GlobalSuppressions.cs | 1 + .../NuGetPackageManager.cs | 140 ++++ .../PublicAPI.Unshipped.txt | 1 + .../CpsPackageReferenceProjectTests.cs | 693 ++++++++++++++++++ 8 files changed, 866 insertions(+), 55 deletions(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs index db921c3e900..d1082afc66d 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs @@ -782,14 +782,14 @@ private async Task> GetActionsAsync( userAction.Version.IsPrerelease == true; IReadOnlyList packageSourceNames = uiService.ActiveSources.Select(source => source.PackageSource.Name).ToList(); + string[] projectIds = projects + .Select(project => project.ProjectId) + .Distinct() + .ToArray(); if (userAction.Action == NuGetProjectActionType.Install) { var packageIdentity = new PackageIdentity(userAction.PackageId, userAction.Version); - string[] projectIds = projects - .Select(project => project.ProjectId) - .Distinct() - .ToArray(); IReadOnlyList actions = await projectManagerService.GetInstallActionsAsync( projectIds, @@ -806,17 +806,14 @@ private async Task> GetActionsAsync( { var packageIdentity = new PackageIdentity(userAction.PackageId, version: null); - foreach (ProjectContextInfo project in projects) - { - IEnumerable actions = await projectManagerService.GetUninstallActionsAsync( - project.ProjectId, - packageIdentity, - removeDependencies, - forceRemove, - token); - - results.AddRange(actions); - } + IReadOnlyList actions = await projectManagerService.GetUninstallActionsAsync( + projectIds, + packageIdentity, + removeDependencies, + forceRemove, + token); + + results.AddRange(actions); } return results; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs index 29634544ca5..8752b0849e1 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs @@ -13,6 +13,7 @@ using Microsoft.ServiceHub.Framework; using Microsoft.ServiceHub.Framework.Services; using Microsoft.VisualStudio.Threading; +using NuGet.Common; using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.Packaging.Signing; @@ -354,49 +355,45 @@ public async ValueTask> GetInstallActionsAsync( } public async ValueTask> GetUninstallActionsAsync( - string projectId, + IReadOnlyCollection projectIds, PackageIdentity packageIdentity, bool removeDependencies, bool forceRemove, CancellationToken cancellationToken) { - Assumes.NotNullOrEmpty(projectId); + Assumes.NotNullOrEmpty(projectIds); Assumes.NotNull(packageIdentity); Assumes.False(packageIdentity.HasVersion); Assumes.NotNull(_state.SourceCacheContext); - Assumes.NotNull(_state.ResolvedActions); Assumes.Null(_state.PackageIdentity); + Assumes.True(_state.ResolvedActions.Count == 0); cancellationToken.ThrowIfCancellationRequested(); return await CatchAndRethrowExceptionAsync(async () => { - INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); - (bool success, NuGetProject? project) = await TryGetNuGetProjectMatchingProjectIdAsync(projectId); - - Assumes.True(success); - Assumes.NotNull(project); + IReadOnlyList projects = await GetProjectsAsync(projectIds, cancellationToken); var projectActions = new List(); var uninstallationContext = new UninstallationContext(removeDependencies, forceRemove); NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); - IEnumerable actions = await packageManager.PreviewUninstallPackageAsync( - project, + IEnumerable projectsWithActions = await packageManager.PreviewProjectsUninstallPackageAsync( + projects, packageIdentity.Id, uninstallationContext, projectContext, cancellationToken); - foreach (NuGetProjectAction action in actions) + foreach (NuGetProjectAction projectWithActions in projectsWithActions) { - var resolvedAction = new ResolvedAction(project, action); + var resolvedAction = new ResolvedAction(projectWithActions.Project, projectWithActions); var projectAction = new ProjectAction( CreateProjectActionId(), - projectId, - action.PackageIdentity, - action.NuGetProjectActionType, + projectWithActions.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId), + projectWithActions.PackageIdentity, + projectWithActions.NuGetProjectActionType, implicitActions: null); _state.ResolvedActions[projectAction.Id] = resolvedAction; @@ -447,17 +444,7 @@ public async ValueTask> GetUpdateActionsAsync( } INuGetProjectContext projectContext = await ServiceLocator.GetInstanceAsync(); - var projects = new List(); - - foreach (string projectId in projectIds) - { - (bool success, NuGetProject? project) = await TryGetNuGetProjectMatchingProjectIdAsync(projectId); - - Assumes.True(success); - Assumes.NotNull(project); - - projects.Add(project); - } + IReadOnlyList projects = await GetProjectsAsync(projectIds, cancellationToken); var resolutionContext = new ResolutionContext( dependencyBehavior, @@ -526,13 +513,16 @@ private async Task> GetProjectsAsync( Assumes.NotNull(solutionManager); Dictionary? projects = (await solutionManager.GetNuGetProjectsAsync()) - .ToDictionary(project => project.GetMetadata(NuGetProjectMetadataKeys.ProjectId), _ => _); + .ToDictionary(project => project.GetMetadata(NuGetProjectMetadataKeys.ProjectId), _ => _, StringComparer.OrdinalIgnoreCase); var matchingProjects = new List(capacity: projectIds.Count); foreach (string projectId in projectIds) { + Assumes.NotNullOrEmpty(projectId); + if (projects.TryGetValue(projectId, out NuGetProject project)) { + Assumes.NotNull(project); matchingProjects.Add(project); } else @@ -572,17 +562,6 @@ private bool IsDirectInstall(IReadOnlyList projectActions) && projectActions.Any(projectAction => projectAction.ProjectActionType == NuGetProjectActionType.Install); } - private async ValueTask<(bool, NuGetProject?)> TryGetNuGetProjectMatchingProjectIdAsync(string projectId) - { - var solutionManager = await ServiceLocator.GetInstanceAsync(); - Assumes.NotNull(solutionManager); - - NuGetProject project = (await solutionManager.GetNuGetProjectsAsync()) - .FirstOrDefault(p => projectId.Equals(p.GetMetadata(NuGetProjectMetadataKeys.ProjectId), StringComparison.OrdinalIgnoreCase)); - - return (project != null, project); - } - private async ValueTask CatchAndRethrowExceptionAsync(Func taskFunc) { try diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs index 86bf4173c37..3947e38d4de 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs @@ -46,7 +46,7 @@ ValueTask> GetInstallActionsAsync( CancellationToken cancellationToken); ValueTask> GetUninstallActionsAsync( - string projectId, + IReadOnlyCollection projectIds, PackageIdentity packageIdentity, bool removeDependencies, bool forceRemove, diff --git a/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/RestoreCommandHandler.cs b/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/RestoreCommandHandler.cs index 7fdc6f040c8..4665539ca65 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/RestoreCommandHandler.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.OnlineEnvironment.Client/SolutionExplorer/RestoreCommandHandler.cs @@ -8,10 +8,10 @@ using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using SB = Microsoft.VisualStudio.Shell.ServiceBroker; using Microsoft.VisualStudio.Threading; using NuGet.VisualStudio.Internal.Contracts; using IAsyncServiceProvider = Microsoft.VisualStudio.Shell.IAsyncServiceProvider; +using SB = Microsoft.VisualStudio.Shell.ServiceBroker; using Task = System.Threading.Tasks.Task; namespace NuGet.VisualStudio.OnlineEnvironment.Client diff --git a/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs index 676aa610806..ce05168b8b5 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs @@ -176,3 +176,4 @@ [assembly: SuppressMessage("Build", "CA1063:Provide an overridable implementation of Dispose(bool) on 'PackagePreFetcherResult' or mark the type as sealed. A call to Dispose(false) should only clean up native resources. A call to Dispose(true) should clean up both managed and native resources.", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.PackagePreFetcherResult")] [assembly: SuppressMessage("Build", "CA2237:Add [Serializable] to PackageReferenceRollbackException as this type implements ISerializable", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.PackageReferenceRollbackException")] [assembly: SuppressMessage("Build", "CA1067:Type NuGet.ProjectManagement.FileTransformExtensions should override Equals because it implements IEquatable", Justification = "", Scope = "type", Target = "~T:NuGet.ProjectManagement.FileTransformExtensions")] +[assembly: SuppressMessage("Usage", "CA2208:Instantiate argument exceptions correctly", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.NuGetPackageManager.PreviewProjectsUninstallPackageAsync(System.Collections.Generic.IReadOnlyCollection{NuGet.ProjectManagement.NuGetProject},System.String,NuGet.PackageManagement.UninstallationContext,NuGet.ProjectManagement.INuGetProjectContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Collections.Generic.IEnumerable{NuGet.PackageManagement.NuGetProjectAction}}")] diff --git a/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs b/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs index 49d21ab0939..903ccdf58c2 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs @@ -1990,6 +1990,146 @@ private static async Task GetSourceRepository(PackageIdentity return source; } + /// + /// Gives the preview as a list of NuGetProjectActions that will be performed to uninstall for many NuGetProjects. + /// + /// + /// + /// + /// + /// + /// + public async Task> PreviewProjectsUninstallPackageAsync( + IReadOnlyCollection nuGetProjects, + string packageId, + UninstallationContext uninstallationContext, + INuGetProjectContext nuGetProjectContext, + CancellationToken token) + { + if (nuGetProjects == null) + { + throw new ArgumentNullException(nameof(nuGetProjects)); + } + + if (packageId == null) + { + throw new ArgumentNullException(nameof(packageId)); + } + + if (uninstallationContext == null) + { + throw new ArgumentNullException(nameof(uninstallationContext)); + } + + if (nuGetProjectContext == null) + { + throw new ArgumentNullException(nameof(nuGetProjectContext)); + } + + token.ThrowIfCancellationRequested(); + + var results = new List(); + + var buildIntegratedProjectsToUpdate = new List(); + var otherTargetProjectsToUpdate = new List(); + + foreach (var project in nuGetProjects) + { + if (project == null) + { + throw new ArgumentNullException(nameof(project)); + } + + if (project is BuildIntegratedNuGetProject buildIntegratedNuGetProject) + { + buildIntegratedProjectsToUpdate.Add(buildIntegratedNuGetProject); + } + else + { + otherTargetProjectsToUpdate.Add(project); + } + } + + if (buildIntegratedProjectsToUpdate.Count != 0) + { + // Run build integrated project preview for all projects at the same time + // There we can do evaluation DependencyGraphRestoreUtility.PreviewRestoreProjectsAsync in batch projects instead of one by one projects. + // So for BuildIntegratedNuGetProject type we share same method 'PreviewBuildIntegratedProjectsActionsAsync' for both install and uninstall actions. + var uninstallActions = await PreviewBuildIntegratedNuGetProjectsUninstallPackageInternalAsync( + buildIntegratedProjectsToUpdate, + packageId, + nuGetProjectContext, + token); + + results.AddRange(uninstallActions); + } + + foreach (var project in otherTargetProjectsToUpdate) + { + if (project == null) + { + throw new ArgumentNullException(nameof(project)); + } + + // Step-1: Get the packageIdentity corresponding to packageId and check if it exists to be uninstalled + var installedPackages = await project.GetInstalledPackagesAsync(token); + var packageReference = installedPackages.FirstOrDefault(pr => pr.PackageIdentity.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase)); + if (packageReference?.PackageIdentity == null) + { + throw new ArgumentException(string.Format(Strings.PackageToBeUninstalledCouldNotBeFound, + packageId, project.GetMetadata(NuGetProjectMetadataKeys.Name))); + } + + IEnumerable uninstallActions = await PreviewUninstallPackageInternalAsync(project, packageReference, uninstallationContext, nuGetProjectContext, token); + + results.AddRange(uninstallActions); + } + + return results; + } + + private async Task> PreviewBuildIntegratedNuGetProjectsUninstallPackageInternalAsync( + IReadOnlyList buildIntegratedProjects, + string packageId, + INuGetProjectContext nuGetProjectContext, + CancellationToken token) + { + if (SolutionManager == null) + { + throw new InvalidOperationException(Strings.SolutionManagerNotAvailableForUninstall); + } + + var nugetProjectActionsLookup = new Dictionary(PathUtility.GetStringComparerBasedOnOS()); + + foreach (BuildIntegratedNuGetProject buildIntegratedProject in buildIntegratedProjects) + { + // Get the packageIdentity corresponding to packageId and check if it exists to be uninstalled + var installedPackages = await buildIntegratedProject.GetInstalledPackagesAsync(token); + var packageReference = installedPackages.FirstOrDefault(pr => pr.PackageIdentity.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase)); + if (packageReference?.PackageIdentity == null) + { + throw new ArgumentException(string.Format(Strings.PackageToBeUninstalledCouldNotBeFound, + packageId, buildIntegratedProject.GetMetadata(NuGetProjectMetadataKeys.Name))); + } + + NuGetProjectAction action = NuGetProjectAction.CreateUninstallProjectAction(packageReference.PackageIdentity, buildIntegratedProject); + NuGetProjectAction[] actions = new[] { action }; + + nugetProjectActionsLookup[buildIntegratedProject.MSBuildProjectPath] = actions; + } + + IEnumerable resolvedActions = await PreviewBuildIntegratedProjectsActionsAsync( + buildIntegratedProjects, + nugetProjectActionsLookup, + packageIdentity: null, // since we have nuGetProjectActions no need packageIdentity + primarySources: null, // since we have nuGetProjectActions no need primarySources + nuGetProjectContext, + token + ); + + return resolvedActions.Select(r => r.Action as BuildIntegratedProjectAction); + } + /// /// Gives the preview as a list of NuGetProjectActions that will be performed to uninstall /// into diff --git a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt index 3f360850c1c..6c6d7def642 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ NuGet.PackageManagement.NuGetPackageManager.PreviewProjectsInstallPackageAsync(System.Collections.Generic.IReadOnlyCollection nuGetProjects, NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Collections.Generic.IReadOnlyCollection activeSources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> +NuGet.PackageManagement.NuGetPackageManager.PreviewProjectsUninstallPackageAsync(System.Collections.Generic.IReadOnlyCollection nuGetProjects, string packageId, NuGet.PackageManagement.UninstallationContext uninstallationContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.ProjectManagement.BuildIntegratedPackageReference.BuildIntegratedPackageReference(NuGet.LibraryModel.LibraryDependency dependency, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Packaging.Core.PackageIdentity installedVersion) -> void NuGet.ProjectManagement.MessageLevelExtensions const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkIdentifier = "TargetFrameworkIdentifier" -> string diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs index 22d82566458..b6cbc8edcd8 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs @@ -2316,6 +2316,699 @@ public async Task GetInstalledPackages_WithNominationUpdate_ReloadsCache() } } + [Fact] + public async Task TestPackageManager_PreviewProjectsUninstallPackageAsync_AllProjects_UninstallExistingPackage_Success() + { + using (var testDirectory = TestDirectory.Create()) + using (var testSolutionManager = new TestSolutionManager()) + { + // Set up Package Source + var sources = new List(); + var packageA_Version100 = new SimpleTestPackageContext("packageA", "1.0.0"); + var packageB_Version100 = new SimpleTestPackageContext("packageB", "1.0.0"); + PackageIdentity packageA = packageA_Version100.Identity; + PackageIdentity packageB = packageB_Version100.Identity; + string packageSource = Path.Combine(testDirectory, "packageSource"); + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + packageSource, + PackageSaveMode.Defaultv3, + packageA_Version100, + packageB_Version100); + + sources.Add(new PackageSource(packageSource)); + var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(sources); + + // Project + int numberOfProjects = 4; + var projectCache = new ProjectSystemCache(); + IVsProjectAdapter projectAdapter = Mock.Of(); + UninstallationContext uninstallationContext = new UninstallationContext(); + var packageSpecs = new PackageSpec[numberOfProjects]; + var projectFullPaths = new string[numberOfProjects]; + var deleteOnRestartManager = new TestDeleteOnRestartManager(); + var nuGetPackageManager = new NuGetPackageManager( + sourceRepositoryProvider, + NullSettings.Instance, + testSolutionManager, + deleteOnRestartManager); + + var testNuGetProjectContext = new TestNuGetProjectContext() { EnableLogging = true }; + var netCorePackageReferenceProjects = new List(); + string prevProjectFullPath = null; + PackageSpec prevPackageSpec = null; + + // Create projects + for (var i = numberOfProjects - 1; i >= 0; i--) + { + string projectName = $"project{i}"; + string projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); + TestCpsPackageReferenceProject project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); + + // We need to treat NU1605 warning as error. + project.IsNu1605Error = true; + netCorePackageReferenceProjects.Add(project); + testSolutionManager.NuGetProjects.Add(project); + + //Let new project pickup my custom package source. + project.ProjectLocalSources.AddRange(sources); + ProjectNames projectNames = GetTestProjectNames(projectFullPath, projectName); + PackageSpec packageSpec = GetPackageSpec( + projectName, + projectFullPath, + packageA_Version100.Version); + + if (prevPackageSpec != null) + { + packageSpec = packageSpec.WithTestProjectReference(prevPackageSpec); + } + + // Restore info + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + projectCache.AddProject(projectNames, projectAdapter, project).Should().BeTrue(); + prevProjectFullPath = projectFullPath; + packageSpecs[i] = packageSpec; + prevPackageSpec = packageSpec; + projectFullPaths[i] = projectFullPath; + } + + for (int i = 0; i < numberOfProjects; i++) + { + // Install packageB since packageA is already there. + await nuGetPackageManager.InstallPackageAsync(netCorePackageReferenceProjects[i], packageB, new ResolutionContext(), new TestNuGetProjectContext(), + sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); + + // This code added because nuGetPackageManager.InstallPackageAsync doesn't do updating ProjectSystemCache + var installed = new LibraryDependency + { + LibraryRange = new LibraryRange( + name: packageB.Id, + versionRange: new VersionRange(packageB.Version), + typeConstraint: LibraryDependencyTarget.Package), + }; + + PackageSpec packageSpec = packageSpecs[i]; + packageSpec.TargetFrameworks.First().Dependencies.Add(installed); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + ProjectNames projectNames = GetTestProjectNames(projectFullPaths[i], $"project{i}"); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + } + + IEnumerable initialInstalledPackages = (await netCorePackageReferenceProjects[numberOfProjects - 1].GetInstalledPackagesAsync(CancellationToken.None)).ToList(); + + // Act + IEnumerable actions = await nuGetPackageManager.PreviewProjectsUninstallPackageAsync( + netCorePackageReferenceProjects, // All projects + packageB.Id, + uninstallationContext, + testNuGetProjectContext, + CancellationToken.None); + using (SourceCacheContext sourceCacheContext = new SourceCacheContext()) + { + await nuGetPackageManager.ExecuteNuGetProjectActionsAsync( + netCorePackageReferenceProjects, + actions, + testNuGetProjectContext, + sourceCacheContext, + CancellationToken.None); + } + + // Assert + Assert.Equal(initialInstalledPackages.Count(), 2); + List builtIntegratedActions = actions.OfType().ToList(); + Assert.Equal(actions.Count(), builtIntegratedActions.Count); + Assert.True(builtIntegratedActions.All(b => b.RestoreResult.Success)); + Assert.True(builtIntegratedActions.All(b => !b.RestoreResult.LogMessages.Any())); // There should be no error or warning. + List uninstalledLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Successfully uninstalled ")).ToList(); + Assert.True(uninstalledLogs.Count() > 0); + List restoringLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restoring packages for ")).ToList(); + List restoredLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restored ")).ToList(); + // Making sure project0 restored only once, not many. + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project0.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project0.csproj")), 1); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project1.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project1.csproj")), 1); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project2.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project2.csproj")), 1); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project3.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project3.csproj")), 1); + List writingAssetsLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Writing assets file to disk.")).ToList(); + // Only 4 write to assets for above 4 projects, not more than that. + Assert.Equal(writingAssetsLogs.Count, 4); + } + } + + [Fact] + public async Task TestPackageManager_PreviewProjectsUninstallPackageAsync_TopParentProject_UninstallExistingPackage_Success() + { + using (var testDirectory = TestDirectory.Create()) + using (var testSolutionManager = new TestSolutionManager()) + { + // Set up Package Source + var sources = new List(); + var packageA_Version100 = new SimpleTestPackageContext("packageA", "1.0.0"); + var packageB_Version100 = new SimpleTestPackageContext("packageB", "1.0.0"); + PackageIdentity packageA = packageA_Version100.Identity; + PackageIdentity packageB = packageB_Version100.Identity; + string packageSource = Path.Combine(testDirectory, "packageSource"); + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + packageSource, + PackageSaveMode.Defaultv3, + packageA_Version100, + packageB_Version100); + + sources.Add(new PackageSource(packageSource)); + var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(sources); + + // Project + int numberOfProjects = 4; + var projectCache = new ProjectSystemCache(); + IVsProjectAdapter projectAdapter = Mock.Of(); + UninstallationContext uninstallationContext = new UninstallationContext(); + var packageSpecs = new PackageSpec[numberOfProjects]; + var projectFullPaths = new string[numberOfProjects]; + var deleteOnRestartManager = new TestDeleteOnRestartManager(); + var nuGetPackageManager = new NuGetPackageManager( + sourceRepositoryProvider, + NullSettings.Instance, + testSolutionManager, + deleteOnRestartManager); + + var testNuGetProjectContext = new TestNuGetProjectContext() { EnableLogging = true }; + var netCorePackageReferenceProjects = new List(); + string prevProjectFullPath = null; + PackageSpec prevPackageSpec = null; + + // Create projects + for (var i = numberOfProjects - 1; i >= 0; i--) + { + string projectName = $"project{i}"; + string projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); + TestCpsPackageReferenceProject project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); + + // We need to treat NU1605 warning as error. + project.IsNu1605Error = true; + netCorePackageReferenceProjects.Add(project); + testSolutionManager.NuGetProjects.Add(project); + + //Let new project pickup my custom package source. + project.ProjectLocalSources.AddRange(sources); + ProjectNames projectNames = GetTestProjectNames(projectFullPath, projectName); + PackageSpec packageSpec = GetPackageSpec( + projectName, + projectFullPath, + packageA_Version100.Version); + + if (prevPackageSpec != null) + { + packageSpec = packageSpec.WithTestProjectReference(prevPackageSpec); + } + + // Restore info + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + projectCache.AddProject(projectNames, projectAdapter, project).Should().BeTrue(); + prevProjectFullPath = projectFullPath; + packageSpecs[i] = packageSpec; + prevPackageSpec = packageSpec; + projectFullPaths[i] = projectFullPath; + } + + for (int i = 0; i < numberOfProjects; i++) + { + // Install packageB since packageA is already there. + await nuGetPackageManager.InstallPackageAsync(netCorePackageReferenceProjects[i], packageB, new ResolutionContext(), new TestNuGetProjectContext(), + sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); + + // This code added because nuGetPackageManager.InstallPackageAsync doesn't do updating ProjectSystemCache + var installed = new LibraryDependency + { + LibraryRange = new LibraryRange( + name: packageB.Id, + versionRange: new VersionRange(packageB.Version), + typeConstraint: LibraryDependencyTarget.Package), + }; + + PackageSpec packageSpec = packageSpecs[i]; + packageSpec.TargetFrameworks.First().Dependencies.Add(installed); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + ProjectNames projectNames = GetTestProjectNames(projectFullPaths[i], $"project{i}"); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + } + + IEnumerable initialInstalledPackages = (await netCorePackageReferenceProjects[numberOfProjects - 1].GetInstalledPackagesAsync(CancellationToken.None)).ToList(); + var targetProjects = new List() + { + netCorePackageReferenceProjects[numberOfProjects-1] // Top parent project. + }; + + // Act + IEnumerable actions = await nuGetPackageManager.PreviewProjectsUninstallPackageAsync( + targetProjects, + packageB.Id, + uninstallationContext, + testNuGetProjectContext, + CancellationToken.None); + using (SourceCacheContext sourceCacheContext = new SourceCacheContext()) + { + await nuGetPackageManager.ExecuteNuGetProjectActionsAsync( + netCorePackageReferenceProjects, + actions, + testNuGetProjectContext, + sourceCacheContext, + CancellationToken.None); + } + + // Assert + Assert.Equal(initialInstalledPackages.Count(), 2); + List builtIntegratedActions = actions.OfType().ToList(); + Assert.Equal(actions.Count(), builtIntegratedActions.Count); + Assert.True(builtIntegratedActions.All(b => b.RestoreResult.Success)); + Assert.True(builtIntegratedActions.All(b => !b.RestoreResult.LogMessages.Any())); // There should be no error or warning. + List restoringLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restoring packages for ")).ToList(); + List restoredLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restored ")).ToList(); + // Making sure project0 restored only once, not many. + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project0.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project0.csproj")), 1); + // It shouldn't trigger restore of child projects. + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project1.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project1.csproj")), 0); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project2.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project2.csproj")), 0); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project3.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project3.csproj")), 0); + List writingAssetsLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Writing assets file to disk.")).ToList(); + // Only 1 write to assets for above 4 projects, not more than that. + Assert.Equal(writingAssetsLogs.Count, 1); + } + } + + [Fact] + public async Task TestPackageManager_PreviewProjectsUninstallPackageAsync_MiddleParentProject_UninstallExistingPackage_Success() + { + using (var testDirectory = TestDirectory.Create()) + using (var testSolutionManager = new TestSolutionManager()) + { + // Set up Package Source + var sources = new List(); + var packageA_Version100 = new SimpleTestPackageContext("packageA", "1.0.0"); + var packageB_Version100 = new SimpleTestPackageContext("packageB", "1.0.0"); + PackageIdentity packageA = packageA_Version100.Identity; + PackageIdentity packageB = packageB_Version100.Identity; + string packageSource = Path.Combine(testDirectory, "packageSource"); + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + packageSource, + PackageSaveMode.Defaultv3, + packageA_Version100, + packageB_Version100); + + sources.Add(new PackageSource(packageSource)); + var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(sources); + + // Project + int numberOfProjects = 4; + var projectCache = new ProjectSystemCache(); + IVsProjectAdapter projectAdapter = Mock.Of(); + UninstallationContext uninstallationContext = new UninstallationContext(); + var packageSpecs = new PackageSpec[numberOfProjects]; + var projectFullPaths = new string[numberOfProjects]; + var deleteOnRestartManager = new TestDeleteOnRestartManager(); + var nuGetPackageManager = new NuGetPackageManager( + sourceRepositoryProvider, + NullSettings.Instance, + testSolutionManager, + deleteOnRestartManager); + + var testNuGetProjectContext = new TestNuGetProjectContext() { EnableLogging = true }; + var netCorePackageReferenceProjects = new List(); + string prevProjectFullPath = null; + PackageSpec prevPackageSpec = null; + + // Create projects + for (var i = numberOfProjects - 1; i >= 0; i--) + { + string projectName = $"project{i}"; + string projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); + TestCpsPackageReferenceProject project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); + + // We need to treat NU1605 warning as error. + project.IsNu1605Error = true; + netCorePackageReferenceProjects.Add(project); + testSolutionManager.NuGetProjects.Add(project); + + //Let new project pickup my custom package source. + project.ProjectLocalSources.AddRange(sources); + ProjectNames projectNames = GetTestProjectNames(projectFullPath, projectName); + PackageSpec packageSpec = GetPackageSpec( + projectName, + projectFullPath, + packageA_Version100.Version); + + if (prevPackageSpec != null) + { + packageSpec = packageSpec.WithTestProjectReference(prevPackageSpec); + } + + // Restore info + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + projectCache.AddProject(projectNames, projectAdapter, project).Should().BeTrue(); + prevProjectFullPath = projectFullPath; + packageSpecs[i] = packageSpec; + prevPackageSpec = packageSpec; + projectFullPaths[i] = projectFullPath; + } + + for (int i = 0; i < numberOfProjects; i++) + { + // Install packageB since packageA is already there. + await nuGetPackageManager.InstallPackageAsync(netCorePackageReferenceProjects[i], packageB, new ResolutionContext(), new TestNuGetProjectContext(), + sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); + + // This code added because nuGetPackageManager.InstallPackageAsync doesn't do updating ProjectSystemCache + var installed = new LibraryDependency + { + LibraryRange = new LibraryRange( + name: packageB.Id, + versionRange: new VersionRange(packageB.Version), + typeConstraint: LibraryDependencyTarget.Package), + }; + + PackageSpec packageSpec = packageSpecs[i]; + packageSpec.TargetFrameworks.First().Dependencies.Add(installed); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + ProjectNames projectNames = GetTestProjectNames(projectFullPaths[i], $"project{i}"); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + } + + IEnumerable initialInstalledPackages = (await netCorePackageReferenceProjects[numberOfProjects - 1].GetInstalledPackagesAsync(CancellationToken.None)).ToList(); + var targetProjects = new List() + { + netCorePackageReferenceProjects[numberOfProjects-2] // Middle parent project. + }; + + // Act + IEnumerable actions = await nuGetPackageManager.PreviewProjectsUninstallPackageAsync( + targetProjects, + packageB.Id, + uninstallationContext, + testNuGetProjectContext, + CancellationToken.None); + using (SourceCacheContext sourceCacheContext = new SourceCacheContext()) + { + await nuGetPackageManager.ExecuteNuGetProjectActionsAsync( + netCorePackageReferenceProjects, + actions, + testNuGetProjectContext, + sourceCacheContext, + CancellationToken.None); + } + + // Assert + Assert.Equal(initialInstalledPackages.Count(), 2); + List builtIntegratedActions = actions.OfType().ToList(); + Assert.Equal(actions.Count(), builtIntegratedActions.Count); + Assert.True(builtIntegratedActions.All(b => b.RestoreResult.Success)); + Assert.True(builtIntegratedActions.All(b => !b.RestoreResult.LogMessages.Any())); // There should be no error or warning. + List restoringLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restoring packages for ")).ToList(); + List restoredLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restored ")).ToList(); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project0.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project0.csproj")), 0); + // Making sure project1 restored only once, not many. + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project1.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project1.csproj")), 1); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project2.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project2.csproj")), 0); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project3.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project3.csproj")), 0); + List writingAssetsLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Writing assets file to disk.")).ToList(); + // Only 1 write to assets for above 4 projects, not more than that. + Assert.Equal(writingAssetsLogs.Count, 1); + } + } + + [Fact] + public async Task TestPackageManager_PreviewProjectsUninstallPackageAsync_BottomChildProject_UninstallExistingPackage_Success() + { + using (var testDirectory = TestDirectory.Create()) + using (var testSolutionManager = new TestSolutionManager()) + { + // Set up Package Source + var sources = new List(); + var packageA_Version100 = new SimpleTestPackageContext("packageA", "1.0.0"); + var packageB_Version100 = new SimpleTestPackageContext("packageB", "1.0.0"); + PackageIdentity packageA = packageA_Version100.Identity; + PackageIdentity packageB = packageB_Version100.Identity; + string packageSource = Path.Combine(testDirectory, "packageSource"); + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + packageSource, + PackageSaveMode.Defaultv3, + packageA_Version100, + packageB_Version100); + + sources.Add(new PackageSource(packageSource)); + var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(sources); + + // Project + int numberOfProjects = 4; + var projectCache = new ProjectSystemCache(); + IVsProjectAdapter projectAdapter = Mock.Of(); + UninstallationContext uninstallationContext = new UninstallationContext(); + var packageSpecs = new PackageSpec[numberOfProjects]; + var projectFullPaths = new string[numberOfProjects]; + var deleteOnRestartManager = new TestDeleteOnRestartManager(); + var nuGetPackageManager = new NuGetPackageManager( + sourceRepositoryProvider, + NullSettings.Instance, + testSolutionManager, + deleteOnRestartManager); + + var testNuGetProjectContext = new TestNuGetProjectContext() { EnableLogging = true }; + var netCorePackageReferenceProjects = new List(); + string prevProjectFullPath = null; + PackageSpec prevPackageSpec = null; + + // Create projects + for (var i = numberOfProjects - 1; i >= 0; i--) + { + string projectName = $"project{i}"; + string projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); + TestCpsPackageReferenceProject project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); + + // We need to treat NU1605 warning as error. + project.IsNu1605Error = true; + netCorePackageReferenceProjects.Add(project); + testSolutionManager.NuGetProjects.Add(project); + + //Let new project pickup my custom package source. + project.ProjectLocalSources.AddRange(sources); + ProjectNames projectNames = GetTestProjectNames(projectFullPath, projectName); + PackageSpec packageSpec = GetPackageSpec( + projectName, + projectFullPath, + packageA_Version100.Version); + + if (prevPackageSpec != null) + { + packageSpec = packageSpec.WithTestProjectReference(prevPackageSpec); + } + + // Restore info + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + projectCache.AddProject(projectNames, projectAdapter, project).Should().BeTrue(); + prevProjectFullPath = projectFullPath; + packageSpecs[i] = packageSpec; + prevPackageSpec = packageSpec; + projectFullPaths[i] = projectFullPath; + } + + for (int i = 0; i < numberOfProjects; i++) + { + // Install packageB since packageA is already there. + await nuGetPackageManager.InstallPackageAsync(netCorePackageReferenceProjects[i], packageB, new ResolutionContext(), new TestNuGetProjectContext(), + sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); + + // This code added because nuGetPackageManager.InstallPackageAsync doesn't do updating ProjectSystemCache + var installed = new LibraryDependency + { + LibraryRange = new LibraryRange( + name: packageB.Id, + versionRange: new VersionRange(packageB.Version), + typeConstraint: LibraryDependencyTarget.Package), + }; + + PackageSpec packageSpec = packageSpecs[i]; + packageSpec.TargetFrameworks.First().Dependencies.Add(installed); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + ProjectNames projectNames = GetTestProjectNames(projectFullPaths[i], $"project{i}"); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + } + + IEnumerable initialInstalledPackages = (await netCorePackageReferenceProjects[numberOfProjects - 1].GetInstalledPackagesAsync(CancellationToken.None)).ToList(); + var targetProjects = new List() + { + netCorePackageReferenceProjects[0] // Bottom child project. + }; + + // Act + IEnumerable actions = await nuGetPackageManager.PreviewProjectsUninstallPackageAsync( + targetProjects, + packageB.Id, + uninstallationContext, + testNuGetProjectContext, + CancellationToken.None); + using (SourceCacheContext sourceCacheContext = new SourceCacheContext()) + { + await nuGetPackageManager.ExecuteNuGetProjectActionsAsync( + netCorePackageReferenceProjects, + actions, + testNuGetProjectContext, + sourceCacheContext, + CancellationToken.None); + } + + // Assert + Assert.Equal(initialInstalledPackages.Count(), 2); + List builtIntegratedActions = actions.OfType().ToList(); + Assert.Equal(actions.Count(), builtIntegratedActions.Count); + Assert.True(builtIntegratedActions.All(b => b.RestoreResult.Success)); + Assert.True(builtIntegratedActions.All(b => !b.RestoreResult.LogMessages.Any())); // There should be no error or warning. + List uninstalledLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Successfully uninstalled ")).ToList(); + Assert.True(uninstalledLogs.Count() > 0); + List restoringLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restoring packages for ")).ToList(); + List restoredLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Restored ")).ToList(); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project0.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project0.csproj")), 0); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project1.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project1.csproj")), 0); + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project2.csproj...")), 0); + Assert.Equal(restoredLogs.Count(l => l.Contains("project2.csproj")), 0); + // Making sure project3 restored only once, not many. + Assert.Equal(restoringLogs.Count(l => l.EndsWith("project3.csproj...")), 1); + Assert.Equal(restoredLogs.Count(l => l.Contains("project3.csproj")), 1); + List writingAssetsLogs = testNuGetProjectContext.Logs.Value.Where(l => l.StartsWith("Writing assets file to disk.")).ToList(); + // Only 1 write to assets for above 4 projects, not more than that. + Assert.Equal(writingAssetsLogs.Count, 1); + } + } + + [Fact] + public async Task TestPackageManager_PreviewProjectsUninstallPackageAsync_UninstallNonExistingPackage_Fail() + { + using (var testDirectory = TestDirectory.Create()) + using (var testSolutionManager = new TestSolutionManager()) + { + // Set up Package Source + var sources = new List(); + var packageA_Version100 = new SimpleTestPackageContext("packageA", "1.0.0"); + var packageB_Version100 = new SimpleTestPackageContext("packageB", "1.0.0"); + PackageIdentity packageA = packageA_Version100.Identity; + PackageIdentity packageB = packageB_Version100.Identity; + string packageSource = Path.Combine(testDirectory, "packageSource"); + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + packageSource, + PackageSaveMode.Defaultv3, + packageA_Version100, + packageB_Version100); + + sources.Add(new PackageSource(packageSource)); + var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(sources); + + // Project + int numberOfProjects = 4; + var projectCache = new ProjectSystemCache(); + IVsProjectAdapter projectAdapter = Mock.Of(); + UninstallationContext uninstallationContext = new UninstallationContext(); + var packageSpecs = new PackageSpec[numberOfProjects]; + var projectFullPaths = new string[numberOfProjects]; + var deleteOnRestartManager = new TestDeleteOnRestartManager(); + var nuGetPackageManager = new NuGetPackageManager( + sourceRepositoryProvider, + NullSettings.Instance, + testSolutionManager, + deleteOnRestartManager); + + var testNuGetProjectContext = new TestNuGetProjectContext() { EnableLogging = true }; + var netCorePackageReferenceProjects = new List(); + string prevProjectFullPath = null; + PackageSpec prevPackageSpec = null; + + // Create projects + for (var i = numberOfProjects - 1; i >= 0; i--) + { + string projectName = $"project{i}"; + string projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); + TestCpsPackageReferenceProject project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); + + // We need to treat NU1605 warning as error. + project.IsNu1605Error = true; + netCorePackageReferenceProjects.Add(project); + testSolutionManager.NuGetProjects.Add(project); + + //Let new project pickup my custom package source. + project.ProjectLocalSources.AddRange(sources); + ProjectNames projectNames = GetTestProjectNames(projectFullPath, projectName); + PackageSpec packageSpec = GetPackageSpec( + projectName, + projectFullPath, + packageA_Version100.Version); + + if (prevPackageSpec != null) + { + packageSpec = packageSpec.WithTestProjectReference(prevPackageSpec); + } + + // Restore info + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + projectCache.AddProject(projectNames, projectAdapter, project).Should().BeTrue(); + prevProjectFullPath = projectFullPath; + packageSpecs[i] = packageSpec; + prevPackageSpec = packageSpec; + projectFullPaths[i] = projectFullPath; + } + + for (int i = 0; i < numberOfProjects; i++) + { + // Install packageB since packageA is already there. + await nuGetPackageManager.InstallPackageAsync(netCorePackageReferenceProjects[i], packageB, new ResolutionContext(), new TestNuGetProjectContext(), + sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); + + // This code added because nuGetPackageManager.InstallPackageAsync doesn't do updating ProjectSystemCache + var installed = new LibraryDependency + { + LibraryRange = new LibraryRange( + name: packageB.Id, + versionRange: new VersionRange(packageB.Version), + typeConstraint: LibraryDependencyTarget.Package), + }; + + PackageSpec packageSpec = packageSpecs[i]; + packageSpec.TargetFrameworks.First().Dependencies.Add(installed); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + ProjectNames projectNames = GetTestProjectNames(projectFullPaths[i], $"project{i}"); + projectCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, new List()); + } + + var initialInstalledPackages = (await netCorePackageReferenceProjects[numberOfProjects - 1].GetInstalledPackagesAsync(CancellationToken.None)).ToList(); + + // Act + string nonexistingPackage = packageB.Id + "NonExist"; + ArgumentException exception = await Assert.ThrowsAsync( + () => nuGetPackageManager.PreviewProjectsUninstallPackageAsync( + netCorePackageReferenceProjects, + nonexistingPackage, + uninstallationContext, + testNuGetProjectContext, + CancellationToken.None)); + + // Assert + Assert.NotNull(exception); + Assert.True(exception.Message.StartsWith($"Package '{nonexistingPackage}' to be uninstalled could not be found in project")); + } + } + private TestCpsPackageReferenceProject CreateTestCpsPackageReferenceProject(string projectName, string projectFullPath, ProjectSystemCache projectSystemCache, TestProjectSystemServices projectServices = null) { projectServices = projectServices == null ? new TestProjectSystemServices() : projectServices; From 263da831216fd1f9d3c5f10bdc86b2fee884c208 Mon Sep 17 00:00:00 2001 From: Marcin Krystianc Date: Fri, 23 Oct 2020 19:51:21 +0200 Subject: [PATCH 016/129] Fix InternalsVisibleTo of NuGet.LibraryModel for unsigned builds (#3723) --- src/NuGet.Core/NuGet.LibraryModel/AssemblyInfo.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/NuGet.Core/NuGet.LibraryModel/AssemblyInfo.cs b/src/NuGet.Core/NuGet.LibraryModel/AssemblyInfo.cs index 3e0348b4036..c37029445a7 100644 --- a/src/NuGet.Core/NuGet.LibraryModel/AssemblyInfo.cs +++ b/src/NuGet.Core/NuGet.LibraryModel/AssemblyInfo.cs @@ -3,5 +3,10 @@ using System.Runtime.CompilerServices; +#if SIGNED_BUILD [assembly: InternalsVisibleTo("NuGet.ProjectModel.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("NuGet.Commands.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +#else +[assembly: InternalsVisibleTo("NuGet.ProjectModel.Test")] +[assembly: InternalsVisibleTo("NuGet.Commands.Test")] +#endif From dd072de70169fcf48420f3cb51c1f38c9332b199 Mon Sep 17 00:00:00 2001 From: Heng Liu <45407901+heng-liu@users.noreply.github.com> Date: Fri, 23 Oct 2020 19:13:24 +0000 Subject: [PATCH 017/129] Fix and enable two flaky signing tests (#3721) --- .../Commands/InstallCommandTests.cs | 4 +++- .../SignatureTrustAndValidityVerificationProviderTests.cs | 4 ++-- test/TestUtilities/Test.Utility/Signing/OcspResponder.cs | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/InstallCommandTests.cs b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/InstallCommandTests.cs index 819b6dddccf..e43f4896e52 100644 --- a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/InstallCommandTests.cs +++ b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/InstallCommandTests.cs @@ -195,10 +195,12 @@ public async Task Install_TamperedAndRevokedCertificateSignaturePackage_FailsAsy var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, context.WorkingDirectory); SignedArchiveTestUtility.TamperWithPackage(signedPackagePath); + + await certificateAuthority.OcspResponder.WaitForResponseExpirationAsync(bcCertificate); certificateAuthority.Revoke( bcCertificate, RevocationReason.KeyCompromise, - DateTimeOffset.UtcNow); + DateTimeOffset.UtcNow.AddSeconds(-1)); var args = new string[] { diff --git a/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/SignatureTrustAndValidityVerificationProviderTests.cs b/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/SignatureTrustAndValidityVerificationProviderTests.cs index d97bf0f9c01..561f467ff61 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/SignatureTrustAndValidityVerificationProviderTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/SignatureTrustAndValidityVerificationProviderTests.cs @@ -130,7 +130,7 @@ public async Task VerifySignaturesAsync_ValidCertificateAndTimestampWithDifferen } } - [PlatformFact(Platform.Windows, Platform.Darwin)] // https://github.com/NuGet/Home/issues/9771 + [CIOnlyFact] public async Task VerifySignaturesAsync_ExpiredCertificateAndTimestamp_SuccessAsync() { var ca = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); @@ -181,7 +181,7 @@ public async Task VerifySignaturesAsync_ExpiredCertificateAndTimestamp_SuccessAs } } - [PlatformFact(Platform.Windows)] // https://github.com/NuGet/Home/issues/9763 + [CIOnlyFact] public async Task VerifySignaturesAsync_ExpiredCertificateAndTimestampWithTooLargeRange_FailsAsync() { var testServer = await _testFixture.GetSigningTestServerAsync(); diff --git a/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs b/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs index 016a256e04c..4be11ca636c 100644 --- a/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs +++ b/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs @@ -89,7 +89,9 @@ public override void Respond(HttpListenerContext context) var certificateId = request.GetCertID(); var certificateStatus = CertificateAuthority.GetStatus(certificateId); var thisUpdate = _options.ThisUpdate ?? now; - var nextUpdate = _options.NextUpdate ?? now.AddSeconds(1); + //On Windows, if the current time is equal (to the second) to a notAfter time (or nextUpdate time), it's considered valid. + //But OpenSSL considers it already expired (that the expiry happened when the clock changed to this second) + var nextUpdate = _options.NextUpdate ?? now.AddSeconds(2); _responses.AddOrUpdate(certificateId.SerialNumber.ToString(), nextUpdate, (key, currentNextUpdate) => { From b7839e8f519153f7c1accdf7e828a5fbbd5e5fd1 Mon Sep 17 00:00:00 2001 From: Andy Zivkovic Date: Tue, 27 Oct 2020 17:52:48 -0700 Subject: [PATCH 018/129] Only run E2E tests when VSIX installed successfully (#3737) --- build/templates/End_To_End_Tests_On_Windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/templates/End_To_End_Tests_On_Windows.yml b/build/templates/End_To_End_Tests_On_Windows.yml index 00bade86dca..3df93e290a0 100644 --- a/build/templates/End_To_End_Tests_On_Windows.yml +++ b/build/templates/End_To_End_Tests_On_Windows.yml @@ -67,7 +67,7 @@ steps: inputs: scriptName: "$(System.DefaultWorkingDirectory)\\artifacts\\EndToEnd\\scripts\\RunFunctionalTests.ps1" arguments: "-PMCCommand $(EndToEndTestCommandToRunPart) -PMCLaunchWaitTimeInSecs 30 -EachTestTimoutInSecs 600 -NuGetDropPath $(System.DefaultWorkingDirectory)\\artifacts -FuncTestRoot $(System.DefaultWorkingDirectory)\\artifacts -RunCounter $(Build.BuildNumber) -VSVersion 16.0" - condition: "eq(variables['IsOfficialBuild'], 'true')" + condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" - task: PowerShell@1 displayName: "RunFunctionalTests.ps1 (continue on error)" @@ -76,7 +76,7 @@ steps: inputs: scriptName: "$(System.DefaultWorkingDirectory)\\artifacts\\EndToEnd\\scripts\\RunFunctionalTests.ps1" arguments: "-PMCCommand $(EndToEndTestCommandToRunPart) -PMCLaunchWaitTimeInSecs 30 -EachTestTimoutInSecs 600 -NuGetDropPath $(System.DefaultWorkingDirectory)\\artifacts -FuncTestRoot $(System.DefaultWorkingDirectory)\\artifacts -RunCounter $(Build.BuildNumber) -VSVersion 16.0" - condition: "not(eq(variables['IsOfficialBuild'], 'true'))" + condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" - task: PublishTestResults@2 displayName: "Publish Test Results" From b1d6a4f285a83bbead39fedd60f63a5fdf20461c Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Wed, 28 Oct 2020 12:52:15 -0700 Subject: [PATCH 019/129] skip RestoreNetCore_MultipleProjects_SameToolDifferentVersionsAsync test (#3740) --- .../NuGet.CommandLine.Test/RestoreNETCoreTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs index 6d4268dcf0a..52246314d48 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs @@ -1740,7 +1740,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( } } - [Fact] + [Fact(Skip = "https://github.com/NuGet/Home/issues/10075")] public async Task RestoreNetCore_MultipleProjects_SameToolDifferentVersionsAsync() { // Arrange From 14b9a0e7b98d08114980c981eb2f88d04a5762fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srdjan=20Jov=C4=8Di=C4=87?= Date: Thu, 29 Oct 2020 09:21:44 -0700 Subject: [PATCH 020/129] Asynchronize access to IVsHierarchy. (#3701) * Asynchronize access to IVsHierarchy. * Reverting changes to VsTemplateWizard.cs * Reverting changes to VsFrameworkCompatibilityTests.cs * Fixing build break. * Fixing public API in InternalAPITestHook. * ProjectType: Using HashSet instead of arrays. * LegacyPackageReferenceRestoreUtilityTests: Avoid duplicate calls. * Fix CpsPackageReferenceProjectProvider.cs after mismerge on rebase. * Remove unused GetAllEnvDTEProjects method. * Ensure OnEnvDTEProjectAdded/Renamed is executed in entirety before continuing. * Fix whitespace. Co-authored-by: Srdjan Jovcic --- .../NuGetPowerShellBaseCommand.cs | 6 +- .../Handlers/ProjectRetargetingHandler.cs | 10 +- .../IDE/VSSolutionManager.cs | 42 ++++---- .../VsCoreProjectSystemReferenceReader.cs | 2 +- ...VsManagedLanguagesProjectSystemServices.cs | 40 ++++---- .../ProjectSystems/CpsProjectSystem.cs | 26 +++-- .../ProjectSystems/VsMSBuildProjectSystem.cs | 5 +- .../Projects/CpsPackageReferenceProject.cs | 2 +- .../Projects/LegacyPackageReferenceProject.cs | 29 +++--- .../Projects/MSBuildNuGetProjectProvider.cs | 2 +- .../Projects/VsProjectAdapter.cs | 53 +++++----- .../Projects/VsProjectAdapterProvider.cs | 2 +- .../Utility/EnvDTEProjectUtility.cs | 91 +++++++++-------- .../Utility/EnvDTESolutionUtility.cs | 16 +-- .../Utility/NuGetProjectUpgradeUtility.cs | 10 +- .../Utility/ProjectRetargetingUtility.cs | 4 +- .../Utility/RuntimeHelpers.cs | 14 +-- .../SolutionRestoreJob.cs | 18 +++- src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs | 21 ++-- .../IDE/EnvDteProjectExtensions.cs | 42 ++++---- .../IDE/VsHierarchyItem.cs | 91 +++++++++-------- .../IDE/VsHierarchyUtility.cs | 67 ++++++------- .../IVsProjectAdapter.cs | 6 +- .../NuGet.VisualStudio.Common/ProjectType.cs | 91 +++++++++++++++++ .../SupportedProjectTypes.cs | 92 ------------------ .../Extensibility/VsPackageInstaller.cs | 2 +- .../Extensibility/VsPathContextProvider.cs | 10 +- test/EndToEnd/API.Test.dll | Bin 0 -> 92160 bytes .../LegacyPackageReferenceProjectTests.cs | 22 ++--- ...gacyPackageReferenceRestoreUtilityTests.cs | 42 ++++---- .../ProjectSystems/TestVSProjectAdapter.cs | 17 +--- .../API.Test/InternalAPITestHook.cs | 11 ++- 32 files changed, 433 insertions(+), 453 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/ProjectType.cs delete mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/SupportedProjectTypes.cs create mode 100644 test/EndToEnd/API.Test.dll diff --git a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs index 73bf87ce40e..0b5917d81d5 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs @@ -793,7 +793,7 @@ public void WriteProjectNotFoundError(string projectName, bool terminating) { var notFoundException = new ItemNotFoundException( - String.Format( + string.Format( CultureInfo.CurrentCulture, Resources.Cmdlet_ProjectNotFound, projectName)); @@ -831,7 +831,7 @@ public void ThrowNoCompatibleProjectsTerminatingError() [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Justification = "This exception is passed to PowerShell. We really don't care about the type of exception here.")] protected void WriteError(string message) { - if (!String.IsNullOrEmpty(message)) + if (!string.IsNullOrEmpty(message)) { WriteError(new Exception(message)); } @@ -1043,7 +1043,7 @@ public void ExecutePSScriptInternal(string path) if (path != null) { string command = "& " + PathUtility.EscapePSPath(path) + " $__rootPath $__toolsPath $__package $__project"; - LogCore(MessageLevel.Info, String.Format(CultureInfo.CurrentCulture, Resources.Cmdlet_ExecutingScript, path)); + LogCore(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Cmdlet_ExecutingScript, path)); InvokeCommand.InvokeScript(command, false, PipelineResultTypes.Error, null, null); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Handlers/ProjectRetargetingHandler.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Handlers/ProjectRetargetingHandler.cs index 556caa2f2c8..465e16168a3 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Handlers/ProjectRetargetingHandler.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Handlers/ProjectRetargetingHandler.cs @@ -149,8 +149,8 @@ private async System.Threading.Tasks.Task ShowWarningsForPackageReinstallationAs var packageReferencesToBeReinstalled = ProjectRetargetingUtility.GetPackageReferencesMarkedForReinstallation(nuGetProject); if (packageReferencesToBeReinstalled.Count > 0) { - Debug.Assert(ProjectRetargetingUtility.IsNuGetInUse(project)); - var projectHierarchy = project.ToVsHierarchy(); + Debug.Assert(await ProjectRetargetingUtility.IsNuGetInUseAsync(project)); + var projectHierarchy = await project.ToVsHierarchyAsync(); ShowRetargetingErrorTask(packageReferencesToBeReinstalled.Select(p => p.PackageIdentity.Id), projectHierarchy, TaskErrorCategory.Warning, TaskPriority.Normal); } } @@ -275,9 +275,9 @@ int IVsTrackBatchRetargetingEvents.OnBatchRetargetingEnd() if (packagesToBeReinstalled.Count > 0) { // By asserting that NuGet is in use, we are also asserting that NuGet.VisualStudio.dll is already loaded - // Hence, it is okay to call project.ToVsHierarchy() - Debug.Assert(ProjectRetargetingUtility.IsNuGetInUse(project)); - var projectHierarchy = project.ToVsHierarchy(); + // Hence, it is okay to call project.ToVsHierarchyAsync() + Debug.Assert(await ProjectRetargetingUtility.IsNuGetInUseAsync(project)); + var projectHierarchy = await project.ToVsHierarchyAsync(); ShowRetargetingErrorTask(packagesToBeReinstalled.Select(p => p.Id), projectHierarchy, TaskErrorCategory.Error, TaskPriority.High); } // NuGet/Home#4833 Baseline diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs index bf80343f4b8..991de3adb07 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs @@ -366,9 +366,16 @@ public async Task DoesNuGetSupportsAnyProjectAsync() // first check with DTE, and if we find any supported project, then return immediately. var dte = await _asyncServiceProvider.GetDTEAsync(); - var isSupported = EnvDTESolutionUtility.GetAllEnvDTEProjects(dte) - .Where(EnvDTEProjectUtility.IsSupported) - .Any(); + var isSupported = false; + + foreach (Project project in await EnvDTESolutionUtility.GetAllEnvDTEProjectsAsync(dte)) + { + if (await EnvDTEProjectUtility.IsSupportedAsync(project)) + { + isSupported = true; + break; + } + } return isSupported; } @@ -540,15 +547,13 @@ private void SolutionSaveAs_AfterExecute(string Guid, int ID, object CustomIn, o private void OnEnvDTEProjectRenamed(Project envDTEProject, string oldName) { - NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async () => + NuGetUIThreadHelper.JoinableTaskFactory.Run(async () => { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - if (!string.IsNullOrEmpty(oldName) && await IsSolutionOpenAsync() && _solutionOpenedRaised) { await EnsureNuGetAndVsProjectAdapterCacheAsync(); - if (EnvDTEProjectUtility.IsSupported(envDTEProject)) + if (await EnvDTEProjectUtility.IsSupportedAsync(envDTEProject)) { RemoveVsProjectAdapterFromCache(oldName); @@ -565,11 +570,11 @@ private void OnEnvDTEProjectRenamed(Project envDTEProject, string oldName) AfterNuGetProjectRenamed?.Invoke(this, new NuGetProjectEventArgs(nuGetProject)); } - else if (EnvDTEProjectUtility.IsSolutionFolder(envDTEProject)) + else if (await EnvDTEProjectUtility.IsSolutionFolderAsync(envDTEProject)) { // In the case where a solution directory was changed, project FullNames are unchanged. // We only need to invalidate the projects under the current tree so as to sync the CustomUniqueNames. - foreach (var item in EnvDTEProjectUtility.GetSupportedChildProjects(envDTEProject)) + foreach (var item in await EnvDTEProjectUtility.GetSupportedChildProjectsAsync(envDTEProject)) { RemoveVsProjectAdapterFromCache(item.FullName); @@ -596,12 +601,10 @@ private void OnEnvDTEProjectRemoved(EnvDTE.Project envDTEProject) private void OnEnvDTEProjectAdded(Project envDTEProject) { - NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async () => + NuGetUIThreadHelper.JoinableTaskFactory.Run(async () => { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - if (await IsSolutionOpenAsync() - && EnvDTEProjectUtility.IsSupported(envDTEProject) + && await EnvDTEProjectUtility.IsSupportedAsync(envDTEProject) && !EnvDTEProjectUtility.IsParentProjectExplicitlyUnsupported(envDTEProject) && _solutionOpenedRaised) { @@ -659,9 +662,14 @@ await _initLock.ExecuteNuGetOperationAsync(async () => { var dte = await _asyncServiceProvider.GetDTEAsync(); - var supportedProjects = EnvDTESolutionUtility - .GetAllEnvDTEProjects(dte) - .Where(EnvDTEProjectUtility.IsSupported); + var supportedProjects = new List(); + foreach (Project project in await EnvDTESolutionUtility.GetAllEnvDTEProjectsAsync(dte)) + { + if (await EnvDTEProjectUtility.IsSupportedAsync(project)) + { + supportedProjects.Add(project); + } + } foreach (var project in supportedProjects) { @@ -697,7 +705,7 @@ await _initLock.ExecuteNuGetOperationAsync(async () => private async Task AddVsProjectAdapterToCacheAsync(IVsProjectAdapter vsProjectAdapter) { - if (!vsProjectAdapter.IsSupported) + if (!await vsProjectAdapter.IsSupportedAsync()) { return; } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsCoreProjectSystemReferenceReader.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsCoreProjectSystemReferenceReader.cs index 7891c679019..ba2304328c8 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsCoreProjectSystemReferenceReader.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsCoreProjectSystemReferenceReader.cs @@ -74,7 +74,7 @@ public async Task> GetProjectReferencesAsyn continue; } - if (EnvDTEProjectUtility.HasUnsupportedProjectCapability(reference3.SourceProject)) + if (await EnvDTEProjectUtility.HasUnsupportedProjectCapabilityAsync(reference3.SourceProject)) { // Skip this shared project continue; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsManagedLanguagesProjectSystemServices.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsManagedLanguagesProjectSystemServices.cs index d76bb1a2a35..3c8a7be3f81 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsManagedLanguagesProjectSystemServices.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/VsManagedLanguagesProjectSystemServices.cs @@ -31,7 +31,7 @@ internal class VsManagedLanguagesProjectSystemServices , IProjectSystemReferencesReader , IProjectSystemReferencesService { - private static readonly Array _referenceMetadata; + private static readonly Array ReferenceMetadata; private readonly IVsProjectAdapter _vsProjectAdapter; private readonly IVsProjectThreadingService _threadingService; @@ -59,13 +59,13 @@ internal class VsManagedLanguagesProjectSystemServices static VsManagedLanguagesProjectSystemServices() { - _referenceMetadata = Array.CreateInstance(typeof(string), 6); - _referenceMetadata.SetValue(ProjectItemProperties.IncludeAssets, 0); - _referenceMetadata.SetValue(ProjectItemProperties.ExcludeAssets, 1); - _referenceMetadata.SetValue(ProjectItemProperties.PrivateAssets, 2); - _referenceMetadata.SetValue(ProjectItemProperties.NoWarn, 3); - _referenceMetadata.SetValue(ProjectItemProperties.GeneratePathProperty, 4); - _referenceMetadata.SetValue(ProjectItemProperties.Aliases, 5); + ReferenceMetadata = Array.CreateInstance(typeof(string), 6); + ReferenceMetadata.SetValue(ProjectItemProperties.IncludeAssets, 0); + ReferenceMetadata.SetValue(ProjectItemProperties.ExcludeAssets, 1); + ReferenceMetadata.SetValue(ProjectItemProperties.PrivateAssets, 2); + ReferenceMetadata.SetValue(ProjectItemProperties.NoWarn, 3); + ReferenceMetadata.SetValue(ProjectItemProperties.GeneratePathProperty, 4); + ReferenceMetadata.SetValue(ProjectItemProperties.Aliases, 5); } public VsManagedLanguagesProjectSystemServices( @@ -108,7 +108,7 @@ public async Task> GetPackageReferencesAsync( { if (AsVSProject4.PackageReferences.TryGetReference( installedPackage, - _referenceMetadata, + ReferenceMetadata, out var version, out var metadataElements, out var metadataValues)) @@ -139,23 +139,23 @@ public async Task> GetProjectReferencesAsyn return new ProjectRestoreReference[] { }; } - var references = AsVSProject4.References - .Cast() - .Where(r => r.SourceProject != null && EnvDTEProjectUtility.IsSupported(r.SourceProject)) - .Select(reference => + var references = new List(); + foreach (Reference6 r in AsVSProject4.References.Cast()) + { + if (r.SourceProject != null && await EnvDTEProjectUtility.IsSupportedAsync(r.SourceProject)) { Array metadataElements; Array metadataValues; - reference.GetMetadata(_referenceMetadata, out metadataElements, out metadataValues); + r.GetMetadata(ReferenceMetadata, out metadataElements, out metadataValues); - return new ProjectReference( - uniqueName: reference.SourceProject.FullName, + references.Add(ToProjectRestoreReference(new ProjectReference( + uniqueName: r.SourceProject.FullName, metadataElements: metadataElements, - metadataValues: metadataValues); - }) - .Select(ToProjectRestoreReference); + metadataValues: metadataValues))); + } + } - return references.ToList(); + return references; } private static ProjectRestoreReference ToProjectRestoreReference(ProjectReference item) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/CpsProjectSystem.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/CpsProjectSystem.cs index a39ef70a992..780370169d6 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/CpsProjectSystem.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/CpsProjectSystem.cs @@ -31,13 +31,11 @@ public override void AddImport(string targetFullPath, ImportLocation location) } NuGetUIThreadHelper.JoinableTaskFactory.Run(async delegate - { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - - var root = VsProjectAdapter.ProjectDirectory; - var relativeTargetPath = PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(root), targetFullPath); - await AddImportStatementAsync(location, relativeTargetPath); - }); + { + var root = await VsProjectAdapter.GetProjectDirectoryAsync(); + var relativeTargetPath = PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(root), targetFullPath); + await AddImportStatementAsync(location, relativeTargetPath); + }); } [MethodImpl(MethodImplOptions.NoInlining)] @@ -62,14 +60,12 @@ public override void RemoveImport(string targetFullPath) } NuGetUIThreadHelper.JoinableTaskFactory.Run(async delegate - { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - - var root = VsProjectAdapter.ProjectDirectory; - // For VS 2012 or above, the operation has to be done inside the Writer lock - var relativeTargetPath = PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(root), targetFullPath); - await RemoveImportStatementAsync(relativeTargetPath); - }); + { + var root = await VsProjectAdapter.GetProjectDirectoryAsync(); + // For VS 2012 or above, the operation has to be done inside the Writer lock + var relativeTargetPath = PathUtility.GetRelativePath(PathUtility.EnsureTrailingSlash(root), targetFullPath); + await RemoveImportStatementAsync(relativeTargetPath); + }); } // IMPORTANT: The NoInlining is required to prevent CLR from loading VisualStudio12.dll assembly while running diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/VsMSBuildProjectSystem.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/VsMSBuildProjectSystem.cs index 5a204e7e8eb..c06f0e1b979 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/VsMSBuildProjectSystem.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/VsMSBuildProjectSystem.cs @@ -72,8 +72,7 @@ public string ProjectFullPath { NuGetUIThreadHelper.JoinableTaskFactory.Run(async delegate { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - _projectFullPath = VsProjectAdapter.ProjectDirectory; + _projectFullPath = await VsProjectAdapter.GetProjectDirectoryAsync(); }); } @@ -465,7 +464,7 @@ public virtual bool FileExistsInProject(string path) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - var containsFile = await EnvDTEProjectUtility.ContainsFile(VsProjectAdapter.Project, path); + var containsFile = await EnvDTEProjectUtility.ContainsFileAsync(VsProjectAdapter.Project, path); return containsFile; }); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProject.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProject.cs index a09de37482a..10b437b0ee8 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProject.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProject.cs @@ -207,7 +207,7 @@ private void IgnoreUnsupportProjectReference(PackageSpec project) foreach (var projectReference in frameworkInfo.ProjectReferences) { - if (SupportedProjectTypes.IsSupportedProjectExtension(projectReference.ProjectPath)) + if (ProjectType.IsSupportedProjectExtension(projectReference.ProjectPath)) { projectReferences.Add(projectReference); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProject.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProject.cs index 53c3edeeee8..63a4b9d2b6c 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProject.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProject.cs @@ -82,8 +82,7 @@ public override async Task GetAssetsFilePathAsync() public override async Task GetCacheFilePathAsync() { - await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - return NoOpRestoreUtilities.GetProjectCacheFilePath(cacheRoot: GetMSBuildProjectExtensionsPath()); + return NoOpRestoreUtilities.GetProjectCacheFilePath(cacheRoot: await GetMSBuildProjectExtensionsPathAsync()); } public override async Task GetAssetsFilePathOrNullAsync() @@ -93,10 +92,7 @@ public override async Task GetAssetsFilePathOrNullAsync() private async Task GetAssetsFilePathAsync(bool shouldThrow) { - await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - - var msbuildProjectExtensionsPath = GetMSBuildProjectExtensionsPath(shouldThrow); - + var msbuildProjectExtensionsPath = await GetMSBuildProjectExtensionsPathAsync(shouldThrow); if (msbuildProjectExtensionsPath == null) { return null; @@ -204,9 +200,9 @@ public override async Task AddFileToProjectAsync(string filePath) { await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - EnvDTEProjectUtility.EnsureCheckedOutIfExists(_vsProjectAdapter.Project, _vsProjectAdapter.ProjectDirectory, filePath); + EnvDTEProjectUtility.EnsureCheckedOutIfExists(_vsProjectAdapter.Project, await _vsProjectAdapter.GetProjectDirectoryAsync(), filePath); - var isFileExistsInProject = await EnvDTEProjectUtility.ContainsFile(_vsProjectAdapter.Project, filePath); + var isFileExistsInProject = await EnvDTEProjectUtility.ContainsFileAsync(_vsProjectAdapter.Project, filePath); if (!isFileExistsInProject) { @@ -221,18 +217,19 @@ private async Task AddProjectItemAsync(string filePath) var folderPath = Path.GetDirectoryName(filePath); var fullPath = filePath; - if (filePath.Contains(_vsProjectAdapter.ProjectDirectory)) + string projectDirectory = await _vsProjectAdapter.GetProjectDirectoryAsync(); + if (filePath.Contains(projectDirectory)) { // folderPath should always be relative to ProjectDirectory so if filePath already contains // ProjectDirectory then get a relative path and construct folderPath to get the appropriate // ProjectItems from dte where you have to add this file. - var relativeLockFilePath = FileSystemUtility.GetRelativePath(_vsProjectAdapter.ProjectDirectory, filePath); + var relativeLockFilePath = FileSystemUtility.GetRelativePath(projectDirectory, filePath); folderPath = Path.GetDirectoryName(relativeLockFilePath); } else { // get the fullPath wrt ProjectDirectory - fullPath = FileSystemUtility.GetFullPath(_vsProjectAdapter.ProjectDirectory, filePath); + fullPath = FileSystemUtility.GetFullPath(projectDirectory, filePath); } var container = await EnvDTEProjectUtility.GetProjectItemsAsync(_vsProjectAdapter.Project, folderPath, createIfNotExists: true); @@ -250,11 +247,11 @@ public override async Task UninstallPackageAsync( #endregion - private string GetMSBuildProjectExtensionsPath(bool shouldThrow = true) + private async Task GetMSBuildProjectExtensionsPathAsync(bool shouldThrow = true) { - ThreadHelper.ThrowIfNotOnUIThread(); + await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - var msbuildProjectExtensionsPath = _vsProjectAdapter.MSBuildProjectExtensionsPath; + var msbuildProjectExtensionsPath = await _vsProjectAdapter.GetMSBuildProjectExtensionsPathAsync(); if (string.IsNullOrEmpty(msbuildProjectExtensionsPath)) { @@ -263,7 +260,7 @@ private string GetMSBuildProjectExtensionsPath(bool shouldThrow = true) throw new InvalidDataException(string.Format( Strings.MSBuildPropertyNotFound, ProjectBuildProperties.MSBuildProjectExtensionsPath, - _vsProjectAdapter.ProjectDirectory)); + await _vsProjectAdapter.GetProjectDirectoryAsync())); } return null; @@ -437,7 +434,7 @@ private async Task GetPackageSpecAsync(ISettings settings) RestoreMetadata = new ProjectRestoreMetadata { ProjectStyle = ProjectStyle.PackageReference, - OutputPath = GetMSBuildProjectExtensionsPath(), + OutputPath = await GetMSBuildProjectExtensionsPathAsync(), ProjectPath = _projectFullPath, ProjectName = projectName, ProjectUniqueName = _projectFullPath, diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs index 293fd485094..9e5f18a0149 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs @@ -69,7 +69,7 @@ public async Task TryCreateNuGetProjectAsync( var folderNuGetProjectFullPath = context.PackagesPathFactory(); // Project folder path is the packages config folder path - var packagesConfigFolderPath = vsProjectAdapter.ProjectDirectory; + var packagesConfigFolderPath = await vsProjectAdapter.GetProjectDirectoryAsync(); return new VsMSBuildNuGetProject( vsProjectAdapter, diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs index bee0a4c3834..9e1dab3778a 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs @@ -35,19 +35,16 @@ internal class VsProjectAdapter : IVsProjectAdapter #region Properties - public string MSBuildProjectExtensionsPath + public async Task GetMSBuildProjectExtensionsPathAsync() { - get - { - var msbuildProjectExtensionsPath = BuildProperties.GetPropertyValue(ProjectBuildProperties.MSBuildProjectExtensionsPath); - - if (string.IsNullOrEmpty(msbuildProjectExtensionsPath)) - { - return null; - } + var msbuildProjectExtensionsPath = BuildProperties.GetPropertyValue(ProjectBuildProperties.MSBuildProjectExtensionsPath); - return Path.Combine(ProjectDirectory, msbuildProjectExtensionsPath); + if (string.IsNullOrEmpty(msbuildProjectExtensionsPath)) + { + return null; } + + return Path.Combine(await GetProjectDirectoryAsync(), msbuildProjectExtensionsPath); } public string RestorePackagesPath @@ -101,18 +98,15 @@ public string RestoreFallbackFolders public string FullName => ProjectNames.FullName; - public string ProjectDirectory + public async Task GetProjectDirectoryAsync() { - get + if (!IsDeferred) { - if (!IsDeferred) - { - return Project.GetFullPath(); - } - else - { - return Path.GetDirectoryName(FullProjectPath); - } + return await Project.GetFullPathAsync(); + } + else + { + return Path.GetDirectoryName(FullProjectPath); } } @@ -126,17 +120,14 @@ public bool IsDeferred } } - public bool IsSupported + public async Task IsSupportedAsync() { - get + if (!IsDeferred) { - if (!IsDeferred) - { - return EnvDTEProjectUtility.IsSupported(Project); - } - - return VsHierarchyUtility.IsSupported(VsHierarchy, _projectTypeGuid); + return await EnvDTEProjectUtility.IsSupportedAsync(Project); } + + return await VsHierarchyUtility.IsSupportedAsync(VsHierarchy, _projectTypeGuid); } public string PackageTargetFallback @@ -246,7 +237,7 @@ public async Task GetProjectTypeGuidsAsync() { if (!IsDeferred) { - return Project.GetProjectTypeGuids(); + return await Project.GetProjectTypeGuidsAsync(); } else { @@ -284,7 +275,7 @@ public async Task> GetReferencedProjectsAsync() if (!IsDeferred) { if (Project.Kind != null - && SupportedProjectTypes.IsSupportedForAddingReferences(Project.Kind)) + && ProjectType.IsSupportedForAddingReferences(Project.Kind)) { return EnvDTEProjectUtility.GetReferencedProjects(Project).Select(p => p.UniqueName); } @@ -294,7 +285,7 @@ public async Task> GetReferencedProjectsAsync() else { var projectTypeGuids = await GetProjectTypeGuidsAsync(); - if (projectTypeGuids.All(SupportedProjectTypes.IsSupportedForAddingReferences)) + if (projectTypeGuids.All(ProjectType.IsSupportedForAddingReferences)) { return await _workspaceService.GetProjectReferencesAsync(FullProjectPath); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs index 6b27a0624c2..3bfcfd1978d 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs @@ -68,7 +68,7 @@ public async Task CreateAdapterForFullyLoadedProjectAsync(Env // switch to main thread and use services we know must be done on main thread. await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - var vsHierarchyItem = VsHierarchyItem.FromDteProject(dteProject); + var vsHierarchyItem = await VsHierarchyItem.FromDteProjectAsync(dteProject); Func loadDteProject = _ => dteProject; var buildStorageProperty = vsHierarchyItem.VsHierarchy as IVsBuildPropertyStorage; diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs index 967aafdf68b..9ee8f5907b3 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs @@ -45,17 +45,14 @@ public static class EnvDTEProjectUtility #region Get Project Information - internal static bool IsSolutionFolder(EnvDTE.Project envDTEProject) + internal static async Task IsSolutionFolderAsync(EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); - + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); return envDTEProject.Kind != null && envDTEProject.Kind.Equals(VsProjectTypes.VsProjectItemKindSolutionFolder, StringComparison.OrdinalIgnoreCase); } - public static async Task ContainsFile(EnvDTE.Project envDTEProject, string path) + public static async Task ContainsFileAsync(EnvDTE.Project envDTEProject, string path) { - ThreadHelper.ThrowIfNotOnUIThread(); - if (string.Equals(envDTEProject.Kind, VsProjectTypes.WixProjectTypeGuid, StringComparison.OrdinalIgnoreCase) || string.Equals(envDTEProject.Kind, VsProjectTypes.NemerleProjectTypeGuid, StringComparison.OrdinalIgnoreCase) @@ -73,7 +70,10 @@ public static async Task ContainsFile(EnvDTE.Project envDTEProject, string var item = await GetProjectItemAsync(envDTEProject, path); return item != null; } - var vsProject = (IVsProject)envDTEProject.ToVsHierarchy(); + + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + var vsProject = (IVsProject)(await envDTEProject.ToVsHierarchyAsync()); if (vsProject == null) { return false; @@ -82,7 +82,7 @@ public static async Task ContainsFile(EnvDTE.Project envDTEProject, string int pFound; uint itemId; - if (IsProjectCapabilityCompliant(envDTEProject)) + if (await IsProjectCapabilityCompliantAsync(envDTEProject)) { // REVIEW: We want to revisit this after RTM - the code in this if statement should be applied to every project type. // We're checking for VSDOCUMENTPRIORITY.DP_Standard here to see if the file is included in the project. @@ -99,7 +99,7 @@ public static async Task ContainsFile(EnvDTE.Project envDTEProject, string // Get the ProjectItems for a folder path public static async Task GetProjectItemsAsync(EnvDTE.Project envDTEProject, string folderPath, bool createIfNotExists) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (string.IsNullOrEmpty(folderPath)) { @@ -113,7 +113,7 @@ public static async Task ContainsFile(EnvDTE.Project envDTEProject, string // Both types have the ProjectItems property that we want to access. object cursor = envDTEProject; - var fullPath = envDTEProject.GetFullPath(); + var fullPath = await envDTEProject.GetFullPathAsync(); var folderRelativePath = string.Empty; foreach (var part in pathParts) @@ -204,7 +204,7 @@ private static async Task IncludeExistingFolderToProjectAsync(EnvDTE.Proje // Execute command to include the existing folder into project. Must do this on UI thread. await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - var projectHierarchy = (IVsUIHierarchy)envDTEProject.ToVsHierarchy(); + var projectHierarchy = (IVsUIHierarchy)(await envDTEProject.ToVsHierarchyAsync()); uint itemId; var hr = projectHierarchy.ParseCanonicalName(folderRelativePath, out itemId); @@ -373,48 +373,45 @@ internal static References GetReferences(EnvDTE.Project project) return references; } - public static bool IsSupported(EnvDTE.Project envDTEProject) + public static async Task IsSupportedAsync(EnvDTE.Project envDTEProject) { Assumes.Present(envDTEProject); - ThreadHelper.ThrowIfNotOnUIThread(); - if (SupportsProjectKPackageManager(envDTEProject)) { return true; } - if (IsProjectCapabilityCompliant(envDTEProject)) + if (await IsProjectCapabilityCompliantAsync(envDTEProject)) { return true; } - return envDTEProject.Kind != null && SupportedProjectTypes.IsSupported(envDTEProject.Kind) && !HasUnsupportedProjectCapability(envDTEProject); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + return envDTEProject.Kind != null && ProjectType.IsSupported(envDTEProject.Kind) && !await HasUnsupportedProjectCapabilityAsync(envDTEProject); } - private static bool IsProjectCapabilityCompliant(EnvDTE.Project envDTEProject) + private static async Task IsProjectCapabilityCompliantAsync(EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); - Debug.Assert(envDTEProject != null); - - var hierarchy = envDTEProject.ToVsHierarchy(); - - return VsHierarchyUtility.IsProjectCapabilityCompliant(hierarchy); + var hierarchy = await envDTEProject.ToVsHierarchyAsync(); + return await VsHierarchyUtility.IsProjectCapabilityCompliantAsync(hierarchy); } public async static Task GetNuGetProjectAsync(EnvDTE.Project project, ISolutionManager solutionManager) { - ThreadHelper.ThrowIfNotOnUIThread(); - Debug.Assert(project != null); Debug.Assert(solutionManager != null); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + var nuGetProject = await solutionManager.GetNuGetProjectAsync(project.Name); if (nuGetProject == null) { nuGetProject = await solutionManager.GetNuGetProjectAsync(project.UniqueName); } + return nuGetProject; } @@ -432,15 +429,14 @@ internal static AssemblyReferences GetAssemblyReferences(EnvDTE.Project project) /// Recursively retrieves all supported child projects of a virtual folder. /// /// The root container project - internal static IEnumerable GetSupportedChildProjects(EnvDTE.Project envDTEProject) + internal static async Task> GetSupportedChildProjectsAsync(EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); - - if (!IsSolutionFolder(envDTEProject)) + if (!await IsSolutionFolderAsync(envDTEProject)) { - yield break; + return Array.Empty(); } + var supportedChildProjects = new List(); var containerProjects = new Queue(); containerProjects.Enqueue(envDTEProject); @@ -453,21 +449,23 @@ internal static AssemblyReferences GetAssemblyReferences(EnvDTE.Project project) if (nestedProject == null) { } - else if (IsSupported(nestedProject)) + else if (await IsSupportedAsync(nestedProject)) { - yield return nestedProject; + supportedChildProjects.Add(nestedProject); } - else if (IsSolutionFolder(nestedProject)) + else if (await IsSolutionFolderAsync(nestedProject)) { containerProjects.Enqueue(nestedProject); } } } + + return supportedChildProjects; } - internal static HashSet GetAssemblyClosure(EnvDTE.Project envDTEProject, IDictionary> visitedProjects) + internal static async Task> GetAssemblyClosureAsync(EnvDTE.Project envDTEProject, IDictionary> visitedProjects) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); HashSet assemblies; if (visitedProjects.TryGetValue(envDTEProject.UniqueName, out assemblies)) @@ -478,24 +476,24 @@ internal static HashSet GetAssemblyClosure(EnvDTE.Project envDTEProject, assemblies = new HashSet(PathComparer.Default); visitedProjects.Add(envDTEProject.UniqueName, assemblies); - var localProjectAssemblies = GetLocalProjectAssemblies(envDTEProject); + var localProjectAssemblies = await GetLocalProjectAssembliesAsync(envDTEProject); CollectionsUtility.AddRange(assemblies, localProjectAssemblies); var referencedProjects = GetReferencedProjects(envDTEProject); foreach (var project in referencedProjects) { - var assemblyClosure = GetAssemblyClosure(project, visitedProjects); + var assemblyClosure = await GetAssemblyClosureAsync(project, visitedProjects); CollectionsUtility.AddRange(assemblies, assemblyClosure); } return assemblies; } - private static HashSet GetLocalProjectAssemblies(EnvDTE.Project envDTEProject) + private static async Task> GetLocalProjectAssembliesAsync(EnvDTE.Project envDTEProject) { if (envDTEProject.IsWebSite()) { - var websiteLocalAssemblies = GetWebsiteLocalAssemblies(envDTEProject); + var websiteLocalAssemblies = await GetWebsiteLocalAssembliesAsync(envDTEProject); return websiteLocalAssemblies; } @@ -531,7 +529,7 @@ private static HashSet GetLocalProjectAssemblies(EnvDTE.Project envDTEPr return assemblies; } - private static HashSet GetWebsiteLocalAssemblies(EnvDTE.Project envDTEProject) + private static async Task> GetWebsiteLocalAssembliesAsync(EnvDTE.Project envDTEProject) { var assemblies = new HashSet(PathComparer.Default); var references = GetAssemblyReferences(envDTEProject); @@ -550,7 +548,7 @@ private static HashSet GetWebsiteLocalAssemblies(EnvDTE.Project envDTEPr // For website projects, we always add .refresh files that point to the corresponding binaries in packages. In the event of bin deployed assemblies that are also GACed, // the ReferenceKind is not AssemblyReferenceBin. Consequently, we work around this by looking for any additional assembly declarations specified via .refresh files. - var envDTEProjectPath = envDTEProject.GetFullPath(); + var envDTEProjectPath = await envDTEProject.GetFullPathAsync(); CollectionsUtility.AddRange(assemblies, RefreshFileUtility.ResolveRefreshPaths(envDTEProjectPath)); return assemblies; @@ -636,7 +634,7 @@ public static bool IsExplicitlyUnsupported(EnvDTE.Project envDTEProject) { ThreadHelper.ThrowIfNotOnUIThread(); - return envDTEProject.Kind == null || SupportedProjectTypes.IsUnsupported(envDTEProject.Kind); + return envDTEProject.Kind == null || ProjectType.IsUnsupported(envDTEProject.Kind); } public static bool IsParentProjectExplicitlyUnsupported(EnvDTE.Project envDTEProject) @@ -710,9 +708,9 @@ public static async Task HasBuildIntegratedConfig(EnvDTE.Project project) { var projectNameConfig = ProjectJsonPathUtilities.GetProjectConfigWithProjectName(project.Name); - var containsProjectJson = await ContainsFile(project, projectNameConfig); + var containsProjectJson = await ContainsFileAsync(project, projectNameConfig); - var containsProjectNameJson = await ContainsFile( + var containsProjectNameJson = await ContainsFileAsync( project, ProjectJsonPathUtilities.ProjectConfigFileName); @@ -722,10 +720,9 @@ public static async Task HasBuildIntegratedConfig(EnvDTE.Project project) /// /// Check if the project has an unsupported project capability, such as, "SharedAssetsProject" /// - public static bool HasUnsupportedProjectCapability(EnvDTE.Project envDTEProject) + public static async Task HasUnsupportedProjectCapabilityAsync(EnvDTE.Project envDTEProject) { - var hier = envDTEProject.ToVsHierarchy(); - + var hier = await envDTEProject.ToVsHierarchyAsync(); return VsHierarchyUtility.HasUnsupportedProjectCapability(hier); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTESolutionUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTESolutionUtility.cs index 09f647f4508..3335de5ba0d 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTESolutionUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTESolutionUtility.cs @@ -6,25 +6,11 @@ using System.Linq; using System.Threading.Tasks; using NuGet.VisualStudio; -using Task = System.Threading.Tasks.Task; namespace NuGet.PackageManagement.VisualStudio { public static class EnvDTESolutionUtility { - /// - /// Get the list of all supported projects in the current solution. This method - /// recursively iterates through all projects. - /// - public static IEnumerable GetAllEnvDTEProjects(EnvDTE.DTE dte) - { - return NuGetUIThreadHelper.JoinableTaskFactory.Run(async delegate - { - var result = await GetAllEnvDTEProjectsAsync(dte); - return result; - }); - } - public static async Task> GetAllEnvDTEProjectsAsync(EnvDTE.DTE dte) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); @@ -50,7 +36,7 @@ public static class EnvDTESolutionUtility { var envDTEProject = envDTEProjects.Pop(); - if (EnvDTEProjectUtility.IsSupported(envDTEProject)) + if (await EnvDTEProjectUtility.IsSupportedAsync(envDTEProject)) { resultantEnvDTEProjects.Add(envDTEProject); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/NuGetProjectUpgradeUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/NuGetProjectUpgradeUtility.cs index 3f830e44866..d86d29db30e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/NuGetProjectUpgradeUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/NuGetProjectUpgradeUtility.cs @@ -75,12 +75,12 @@ public static async Task IsNuGetProjectUpgradeableAsync(NuGetProject nuGet envDTEProject = vsmsBuildNuGetProjectSystem.VsProjectAdapter.Project; } - if (!EnvDTEProjectUtility.IsSupported(envDTEProject)) + if (!await EnvDTEProjectUtility.IsSupportedAsync(envDTEProject)) { return false; } - return IsProjectPackageReferenceCompatible(envDTEProject); + return await IsProjectPackageReferenceCompatibleAsync(envDTEProject); } private static async Task GetNuGetProject(Project envDTEProject) @@ -92,9 +92,9 @@ private static async Task GetNuGetProject(Project envDTEProject) return nuGetProject; } - private static bool IsProjectPackageReferenceCompatible(Project project) + private static async Task IsProjectPackageReferenceCompatibleAsync(Project project) { - var projectGuids = project.GetProjectTypeGuids(); + var projectGuids = await project.GetProjectTypeGuidsAsync(); if (projectGuids.Any(t => UnupgradeableProjectTypes.Contains(t))) { @@ -103,7 +103,7 @@ private static bool IsProjectPackageReferenceCompatible(Project project) // Project is supported language, and not an unsupported type return UpgradeableProjectTypes.Contains(project.Kind) && - projectGuids.All(projectTypeGuid => !SupportedProjectTypes.IsUnsupported(projectTypeGuid)); + projectGuids.All(projectTypeGuid => !ProjectType.IsUnsupported(projectTypeGuid)); } public static bool IsPackagesConfigSelected(IVsMonitorSelection vsMonitorSelection) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/ProjectRetargetingUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/ProjectRetargetingUtility.cs index d182851621e..e09cdb6a7f5 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/ProjectRetargetingUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/ProjectRetargetingUtility.cs @@ -256,9 +256,9 @@ public static bool IsProjectRetargetable(NuGetProject project) /// Determines if NuGet is used in the project. Currently, it is determined by checking if packages.config is part of the project /// /// The project which is checked to see if NuGet is used in it - public static bool IsNuGetInUse(Project project) + public static async Task IsNuGetInUseAsync(Project project) { - return EnvDTEProjectUtility.IsSupported(project) && File.Exists(project.GetPackagesConfigFullPath()); + return await EnvDTEProjectUtility.IsSupportedAsync(project) && File.Exists(await project.GetPackagesConfigFullPathAsync()); } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/RuntimeHelpers.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/RuntimeHelpers.cs index 63ad27d139f..190da2053c0 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/RuntimeHelpers.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/RuntimeHelpers.cs @@ -31,7 +31,7 @@ public static async Task AddBindingRedirectsAsync( await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Keep track of visited projects - if (SupportsBindingRedirects(vsProjectAdapter.Project)) + if (await SupportsBindingRedirectsAsync(vsProjectAdapter.Project)) { // Get the dependentEnvDTEProjectsDictionary once here, so that, it is not called for every single project var dependentProjectsDictionary = await vsSolutionManager.GetDependentProjectsDictionaryAsync(); @@ -45,10 +45,10 @@ await AddBindingRedirectsAsync(vsSolutionManager, vsProjectAdapter, domain, } } - private static bool SupportsBindingRedirects(EnvDTE.Project Project) + private static async Task SupportsBindingRedirectsAsync(EnvDTE.Project Project) { - return (Project.Kind != null && SupportedProjectTypes.IsSupportedForBindingRedirects(Project.Kind)) - && !Project.IsWindowsStoreApp(); + return (Project.Kind != null && ProjectType.IsSupportedForBindingRedirects(Project.Kind)) + && !await Project.IsWindowsStoreAppAsync(); } private static Task AddBindingRedirectsAsync( @@ -87,7 +87,7 @@ private static async Task AddBindingRedirectsAsync(VSSolutionManager vsSolutionM return; } - if (SupportsBindingRedirects(vsProjectAdapter.Project)) + if (await SupportsBindingRedirectsAsync(vsProjectAdapter.Project)) { await AddBindingRedirectsAsync(vsSolutionManager, vsProjectAdapter, domain, projectAssembliesCache, frameworkMultiTargeting, nuGetProjectContext); } @@ -142,7 +142,7 @@ public static async Task> AddBindingRedirectsAsync( return redirects; } - IEnumerable assemblies = EnvDTEProjectUtility.GetAssemblyClosure(vsProjectAdapter.Project, projectAssembliesCache); + IEnumerable assemblies = await EnvDTEProjectUtility.GetAssemblyClosureAsync(vsProjectAdapter.Project, projectAssembliesCache); redirects = BindingRedirectResolver.GetBindingRedirects(assemblies, domain); if (frameworkMultiTargeting != null) @@ -152,7 +152,7 @@ public static async Task> AddBindingRedirectsAsync( } // Create a binding redirect manager over the configuration - var manager = new BindingRedirectManager(vsProjectAdapter.Project.GetConfigurationFile(), msBuildNuGetProjectSystem); + var manager = new BindingRedirectManager(await vsProjectAdapter.Project.GetConfigurationFileAsync(), msBuildNuGetProjectSystem); // Add the redirects manager.AddBindingRedirects(redirects); diff --git a/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs b/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs index c07ca193ed4..c97ffa554a8 100644 --- a/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs +++ b/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs @@ -722,10 +722,20 @@ private async Task CheckPackagesConfigAsync() var dte = await _asyncServiceProvider.GetDTEAsync(); var projects = dte.Solution.Projects; - return projects - .OfType() - .Select(p => new ProjectInfo(p.GetFullPath(), p.Name)) - .Any(p => p.CheckPackagesConfig()); + + var succeeded = false; + + foreach (var p in projects.OfType()) + { + var pi = new ProjectInfo(await p.GetFullPathAsync(), p.Name); + if (pi.CheckPackagesConfig()) + { + succeeded = true; + break; + } + } + + return succeeded; }); } diff --git a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs index 213ab598e44..a1dc084a0a4 100644 --- a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs +++ b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs @@ -427,7 +427,7 @@ private async Task CreateNewWindowFrameAsync(Project project) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - var vsProject = project.ToVsHierarchy(); + var vsProject = await project.ToVsHierarchyAsync(); var documentName = project.FullName; // Find existing hierarchy and item id of the document window if it's @@ -639,7 +639,7 @@ private void ShowManageLibraryPackageDialog(object sender, EventArgs e) && !project.IsUnloaded() && - EnvDTEProjectUtility.IsSupported(project)) + await EnvDTEProjectUtility.IsSupportedAsync(project)) { var windowFrame = await FindExistingWindowFrameAsync(project); if (windowFrame == null) @@ -907,7 +907,7 @@ private void BeforeQueryStatusForUpgradeNuGetProject(object sender, EventArgs ar } command.Visible = GetIsSolutionOpen() && await IsPackagesConfigBasedProjectAsync(); - command.Enabled = !isConsoleBusy && IsSolutionExistsAndNotDebuggingAndNotBuilding() && HasActiveLoadedSupportedProject; + command.Enabled = !isConsoleBusy && IsSolutionExistsAndNotDebuggingAndNotBuilding() && await HasActiveLoadedSupportedProjectAsync(); }); } @@ -932,7 +932,7 @@ private void BeforeQueryStatusForUpgradePackagesConfig(object sender, EventArgs } command.Visible = GetIsSolutionOpen() && IsPackagesConfigSelected(); - command.Enabled = !isConsoleBusy && IsSolutionExistsAndNotDebuggingAndNotBuilding() && HasActiveLoadedSupportedProject; + command.Enabled = !isConsoleBusy && IsSolutionExistsAndNotDebuggingAndNotBuilding() && await HasActiveLoadedSupportedProjectAsync(); }); } @@ -1003,7 +1003,7 @@ private void BeforeQueryStatusForAddPackageDialog(object sender, EventArgs args) command.Enabled = IsSolutionExistsAndNotDebuggingAndNotBuilding() && !isConsoleBusy && - HasActiveLoadedSupportedProject; + await HasActiveLoadedSupportedProjectAsync(); }); } @@ -1081,14 +1081,11 @@ private void ShowOptionPageSafe(Type optionPageType) /// Gets whether the current IDE has an active, supported and non-unloaded project, which is a precondition for /// showing the Add Library Package Reference dialog /// - private bool HasActiveLoadedSupportedProject + private async Task HasActiveLoadedSupportedProjectAsync() { - get - { - var project = VsMonitorSelection.GetActiveProject(); - return project != null && !project.IsUnloaded() - && EnvDTEProjectUtility.IsSupported(project); - } + var project = VsMonitorSelection.GetActiveProject(); + return project != null && !project.IsUnloaded() + && await EnvDTEProjectUtility.IsSupportedAsync(project); } private bool ShouldMEFBeInitialized() diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/EnvDteProjectExtensions.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/EnvDteProjectExtensions.cs index 6c54f3e7e47..86d4b806bca 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/EnvDteProjectExtensions.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/EnvDteProjectExtensions.cs @@ -23,14 +23,14 @@ namespace NuGet.VisualStudio { public static class EnvDteProjectExtensions { - public static IVsHierarchy ToVsHierarchy(this EnvDTE.Project project) + public static async Task ToVsHierarchyAsync(this EnvDTE.Project project) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsHierarchy hierarchy; // Get the vs solution - var solution = ServiceLocator.GetInstance(); + var solution = await ServiceLocator.GetInstanceAsync(); int hr = solution.GetProjectOfUniqueName(project.GetUniqueName(), out hierarchy); if (hr != VSConstants.S_OK) @@ -41,14 +41,14 @@ public static IVsHierarchy ToVsHierarchy(this EnvDTE.Project project) return hierarchy; } - public static string[] GetProjectTypeGuids(this EnvDTE.Project project) + public static async Task GetProjectTypeGuidsAsync(this EnvDTE.Project project) { Verify.ArgumentIsNotNull(project, nameof(project)); - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Get the vs hierarchy as an IVsAggregatableProject to get the project type guids - IVsHierarchy hierarchy = ToVsHierarchy(project); + IVsHierarchy hierarchy = await ToVsHierarchyAsync(project); string[] projectTypeGuids = VsHierarchyUtility.GetProjectTypeGuids(hierarchy, project.Kind); return projectTypeGuids; @@ -105,9 +105,9 @@ public static string GetFullProjectPath(this EnvDTE.Project envDTEProject) /// /// The project. /// The full path of the project directory. - public static string GetFullPath(this EnvDTE.Project envDTEProject) + public static async Task GetFullPathAsync(this EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); Debug.Assert(envDTEProject != null); if (IsUnloaded(envDTEProject)) @@ -125,7 +125,7 @@ public static string GetFullPath(this EnvDTE.Project envDTEProject) // until we can find one containing the full path. // For website projects, always read FullPath from properties list - if (IsWebProject(envDTEProject)) + if (await IsWebProjectAsync(envDTEProject)) { // FullPath var fullProjectPath = GetPropertyValue(envDTEProject, FullPath); @@ -203,12 +203,12 @@ private static T GetPropertyValue(this EnvDTE.Project envDTEProject, string p /// Returns the full path of the packages config file associated with the project. /// /// The project. - public static string GetPackagesConfigFullPath(this EnvDTE.Project envDTEProject) + public static async Task GetPackagesConfigFullPathAsync(this EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); Debug.Assert(envDTEProject != null); - var projectDirectory = GetFullPath(envDTEProject); + var projectDirectory = await GetFullPathAsync(envDTEProject); var packagesConfigFullPath = Path.Combine( projectDirectory ?? string.Empty, @@ -324,11 +324,11 @@ public static string GetTargetFrameworkString(this EnvDTE.Project envDTEProject) } // TODO: Return null for library projects - public static string GetConfigurationFile(this EnvDTE.Project envDTEProject) + public static async Task GetConfigurationFileAsync(this EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - return IsWebProject(envDTEProject) ? WebConfig : AppConfig; + return await IsWebProjectAsync(envDTEProject) ? WebConfig : AppConfig; } private class PathComparer : IEqualityComparer @@ -412,10 +412,10 @@ private static bool IsXnaWindowsPhoneProject(this EnvDTE.Project envDTEProject) "Windows Phone OS 7.1".Equals(GetPropertyValue(envDTEProject, xnaPropertyValue), StringComparison.OrdinalIgnoreCase); } - private static bool IsWebProject(this EnvDTE.Project envDTEProject) + private static async Task IsWebProjectAsync(this EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); - string[] types = envDTEProject.GetProjectTypeGuids(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + string[] types = await envDTEProject.GetProjectTypeGuidsAsync(); return types.Contains(VsProjectTypes.WebSiteProjectTypeGuid, StringComparer.OrdinalIgnoreCase) || types.Contains(VsProjectTypes.WebApplicationProjectTypeGuid, StringComparer.OrdinalIgnoreCase); } @@ -427,10 +427,10 @@ public static bool IsWebSite(this EnvDTE.Project envDTEProject) return envDTEProject.Kind != null && envDTEProject.Kind.Equals(VsProjectTypes.WebSiteProjectTypeGuid, StringComparison.OrdinalIgnoreCase); } - public static bool IsWindowsStoreApp(this EnvDTE.Project envDTEProject) + public static async Task IsWindowsStoreAppAsync(this EnvDTE.Project envDTEProject) { - ThreadHelper.ThrowIfNotOnUIThread(); - string[] types = envDTEProject.GetProjectTypeGuids(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + string[] types = await envDTEProject.GetProjectTypeGuidsAsync(); return types.Contains(VsProjectTypes.WindowsStoreProjectTypeGuid, StringComparer.OrdinalIgnoreCase); } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyItem.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyItem.cs index ab07f9f812c..9928a3e3f02 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyItem.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyItem.cs @@ -2,8 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Threading.Tasks; using Microsoft; using Microsoft.VisualStudio; +using Microsoft.VisualStudio.PlatformUI; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -17,7 +19,7 @@ public sealed class VsHierarchyItem : IEquatable private readonly uint _vsitemid; private readonly IVsHierarchy _hierarchy; - internal delegate int ProcessItemDelegate(VsHierarchyItem item, object callerObject, out object newCallerObject); + internal delegate Task<(int processReturn, object newCallerObject)> ProcessItemDelegateAsync(VsHierarchyItem item, object callerObject); public IVsHierarchy VsHierarchy => _hierarchy; @@ -32,11 +34,10 @@ private VsHierarchyItem(IVsHierarchy hierarchy) { } - public static VsHierarchyItem FromDteProject(EnvDTE.Project project) + public static async Task FromDteProjectAsync(EnvDTE.Project project) { - ThreadHelper.ThrowIfNotOnUIThread(); Assumes.Present(project); - return new VsHierarchyItem(project.ToVsHierarchy()); + return new VsHierarchyItem(await project.ToVsHierarchyAsync()); } public static VsHierarchyItem FromVsHierarchy(IVsHierarchy project) @@ -59,51 +60,49 @@ public bool TryGetProjectId(out Guid projectId) internal uint VsItemID => _vsitemid; - internal bool IsExpandable() + internal async Task IsExpandableAsync() { - ThreadHelper.ThrowIfNotOnUIThread(); - var o = GetProperty(__VSHPROPID.VSHPROPID_Expandable); + var o = await GetPropertyAsync(__VSHPROPID.VSHPROPID_Expandable); if (o is bool) { return (bool)o; } + return (o is int) && (int)o != 0; } - private object GetProperty(__VSHPROPID propid) + private async Task GetPropertyAsync(__VSHPROPID propid) { - ThreadHelper.ThrowIfNotOnUIThread(); - if (TryGetProperty((int)propid, out var value)) - { - return value; - } - - return null; + (bool _, object value) = await TryGetPropertyAsync((int)propid); + return value; } - private bool TryGetProperty(int propid, out object value) + private async Task<(bool found, object value)> TryGetPropertyAsync(int propid) { - ThreadHelper.ThrowIfNotOnUIThread(); - - value = null; try { if (_hierarchy != null) { - _hierarchy.GetProperty(_vsitemid, propid, out value); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + _hierarchy.GetProperty(_vsitemid, propid, out object value); + return (true, value); } - - return true; } - catch + catch (Exception e) { - return false; + if (e.IsCritical()) + { + throw; + } + + // Ignore. } + + return (false, null); } - internal int WalkDepthFirst(bool fVisible, ProcessItemDelegate processCallback, object callerObject) + internal async Task WalkDepthFirstAsync(bool fVisible, ProcessItemDelegateAsync processCallbackAsync, object callerObject) { - ThreadHelper.ThrowIfNotOnUIThread(); // // TODO Need to see what to do if this is a sub project // @@ -111,13 +110,12 @@ internal int WalkDepthFirst(bool fVisible, ProcessItemDelegate processCallback, // Guid nodeGuid; // if (hier.GetGuidProperty(_vsitemid, (int)__VSHPROPID.VSHPROPID_TypeGuid, out nodeGuid) != 0) - if (processCallback == null) + if (processCallbackAsync == null) { return 0; } - object newCallerObject; - int processReturn = processCallback(this, callerObject, out newCallerObject); + (int processReturn, object newCallerObject) = await processCallbackAsync(this, callerObject); if (processReturn != 0) { // Callback says to skip (1) or stop (-1) @@ -132,44 +130,43 @@ internal int WalkDepthFirst(bool fVisible, ProcessItemDelegate processCallback, } // Walk children if there are any - if (IsExpandable()) + if (await IsExpandableAsync()) { - VsHierarchyItem child = GetFirstChild(fVisible); + VsHierarchyItem child = await GetFirstChildAsync(fVisible); while (child != null) { - object isNonMemberItemValue = child.GetProperty(__VSHPROPID.VSHPROPID_IsNonMemberItem); + object isNonMemberItemValue = await child.GetPropertyAsync(__VSHPROPID.VSHPROPID_IsNonMemberItem); // Some project systems (e.g. F#) don't support querying for the VSHPROPID_IsNonMemberItem property. // In that case, we treat this child as belonging to the project bool isMemberOfProject = isNonMemberItemValue == null || (bool)isNonMemberItemValue == false; if (isMemberOfProject) { - int returnVal = child.WalkDepthFirst(fVisible, processCallback, newCallerObject); + int returnVal = await child.WalkDepthFirstAsync(fVisible, processCallbackAsync, newCallerObject); if (returnVal == -1) { return returnVal; } } - child = child.GetNextSibling(fVisible); + child = await child.GetNextSiblingAsync(fVisible); } } return 0; } - internal VsHierarchyItem GetNextSibling(bool fVisible) + internal async Task GetNextSiblingAsync(bool fVisible) { - ThreadHelper.ThrowIfNotOnUIThread(); - uint childId = GetNextSiblingId(fVisible); + uint childId = await GetNextSiblingIdAsync(fVisible); if (childId != VSConstants.VSITEMID_NIL) { return new VsHierarchyItem(_hierarchy, childId); } + return null; } - internal uint GetNextSiblingId(bool fVisible) + internal async Task GetNextSiblingIdAsync(bool fVisible) { - ThreadHelper.ThrowIfNotOnUIThread(); - object o = GetProperty(fVisible ? __VSHPROPID.VSHPROPID_NextVisibleSibling : __VSHPROPID.VSHPROPID_NextSibling); + object o = await GetPropertyAsync(fVisible ? __VSHPROPID.VSHPROPID_NextVisibleSibling : __VSHPROPID.VSHPROPID_NextSibling); if (o is int) { @@ -179,33 +176,35 @@ internal uint GetNextSiblingId(bool fVisible) { return (uint)o; } + return VSConstants.VSITEMID_NIL; } - internal VsHierarchyItem GetFirstChild(bool fVisible) + internal async Task GetFirstChildAsync(bool fVisible) { - ThreadHelper.ThrowIfNotOnUIThread(); - uint childId = GetFirstChildId(fVisible); + uint childId = await GetFirstChildIdAsync(fVisible); if (childId != VSConstants.VSITEMID_NIL) { return new VsHierarchyItem(_hierarchy, childId); } + return null; } - internal uint GetFirstChildId(bool fVisible) + internal async Task GetFirstChildIdAsync(bool fVisible) { - ThreadHelper.ThrowIfNotOnUIThread(); - object o = GetProperty(fVisible ? __VSHPROPID.VSHPROPID_FirstVisibleChild : __VSHPROPID.VSHPROPID_FirstChild); + object o = await GetPropertyAsync(fVisible ? __VSHPROPID.VSHPROPID_FirstVisibleChild : __VSHPROPID.VSHPROPID_FirstChild); if (o is int) { return unchecked((uint)((int)o)); } + if (o is uint) { return (uint)o; } + return VSConstants.VSITEMID_NIL; } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs index bcf516bfb76..05469d04e65 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IDE/VsHierarchyUtility.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -31,25 +32,23 @@ public static string GetProjectPath(IVsHierarchy project) return projectPath; } - public static bool IsSupported(IVsHierarchy hierarchy, string projectTypeGuid) + public static async Task IsSupportedAsync(IVsHierarchy hierarchy, string projectTypeGuid) { - ThreadHelper.ThrowIfNotOnUIThread(); - - if (IsProjectCapabilityCompliant(hierarchy)) + if (await IsProjectCapabilityCompliantAsync(hierarchy)) { return true; } - return !string.IsNullOrEmpty(projectTypeGuid) && SupportedProjectTypes.IsSupported(projectTypeGuid) && !HasUnsupportedProjectCapability(hierarchy); + return !string.IsNullOrEmpty(projectTypeGuid) && ProjectType.IsSupported(projectTypeGuid) && !HasUnsupportedProjectCapability(hierarchy); } /// Check if this project appears to support NuGet. /// IVsHierarchy representing the project in the solution. /// True if NuGet should enable this project, false if NuGet should ignore the project. /// The project may be packages.config or PackageReference. This method does not tell you which. - public static bool IsProjectCapabilityCompliant(IVsHierarchy hierarchy) + public static async Task IsProjectCapabilityCompliantAsync(IVsHierarchy hierarchy) { - ThreadHelper.ThrowIfNotOnUIThread(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // NOTE: (AssemblyReferences + DeclaredSourceItems + UserSourceItems) exists solely for compatibility reasons // with existing custom CPS-based projects that existed before "PackageReferences" capability was introduced. @@ -126,7 +125,7 @@ public static async TaskExpandedNodes GetAllExpandedNodesAsync() foreach (var project in projects.Cast()) { var expandedNodes = - GetExpandedProjectHierarchyItems(project); + await GetExpandedProjectHierarchyItemsAsync(project); Debug.Assert(!results.ContainsKey(project.GetUniqueName())); results[project.GetUniqueName()] = new HashSet(expandedNodes); @@ -150,52 +149,49 @@ public static async Task CollapseAllNodesAsync(IDictionary GetExpandedProjectHierarchyItems(EnvDTE.Project project) + private static async Task> GetExpandedProjectHierarchyItemsAsync(EnvDTE.Project project) { - ThreadHelper.ThrowIfNotOnUIThread(); - - var projectHierarchyItem = VsHierarchyItem.FromDteProject(project); + var projectHierarchyItem = await VsHierarchyItem.FromDteProjectAsync(project); var solutionExplorerWindow = GetSolutionExplorerHierarchyWindow(); if (solutionExplorerWindow == null) { // If the solution explorer is collapsed since opening VS, this value is null. In such a case, simply exit early. - return new VsHierarchyItem[0]; + return Array.Empty(); } var expandedItems = new List(); + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + // processCallback return values: // 0 continue, // 1 don't recurse into, // -1 stop - projectHierarchyItem.WalkDepthFirst( + await projectHierarchyItem.WalkDepthFirstAsync( fVisible: true, - processCallback: - (VsHierarchyItem vsItem, object callerObject, out object newCallerObject) => + processCallbackAsync: + async (VsHierarchyItem vsItem, object callerObject) => { - newCallerObject = null; - if (IsVsHierarchyItemExpanded(vsItem, solutionExplorerWindow)) + if (await IsVsHierarchyItemExpandedAsync(vsItem, solutionExplorerWindow)) { expandedItems.Add(vsItem); } - return 0; + return (0, null); }, callerObject: null); return expandedItems; } - private static void CollapseProjectHierarchyItems(EnvDTE.Project project, ISet ignoredHierarcyItems) + private static async Task CollapseProjectHierarchyItemsAsync(EnvDTE.Project project, ISet ignoredHierarcyItems) { - ThreadHelper.ThrowIfNotOnUIThread(); - - var projectHierarchyItem = VsHierarchyItem.FromDteProject(project); + var projectHierarchyItem = await VsHierarchyItem.FromDteProjectAsync(project); var solutionExplorerWindow = GetSolutionExplorerHierarchyWindow(); if (solutionExplorerWindow == null) @@ -208,39 +204,35 @@ private static void CollapseProjectHierarchyItems(EnvDTE.Project project, ISet + processCallbackAsync: + async (VsHierarchyItem currentHierarchyItem, object callerObject) => { - newCallerObject = null; if (!ignoredHierarcyItems.Contains(currentHierarchyItem)) { - CollapseVsHierarchyItem(currentHierarchyItem, solutionExplorerWindow); + await CollapseVsHierarchyItemAsync(currentHierarchyItem, solutionExplorerWindow); } - return 0; + return (0, null); }, callerObject: null); } - private static void CollapseVsHierarchyItem(VsHierarchyItem vsHierarchyItem, IVsUIHierarchyWindow vsHierarchyWindow) + private static async Task CollapseVsHierarchyItemAsync(VsHierarchyItem vsHierarchyItem, IVsUIHierarchyWindow vsHierarchyWindow) { - ThreadHelper.ThrowIfNotOnUIThread(); - if (vsHierarchyItem == null || vsHierarchyWindow == null) { return; } + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); vsHierarchyWindow.ExpandItem(AsVsUIHierarchy(vsHierarchyItem), vsHierarchyItem.VsItemID, EXPANDFLAGS.EXPF_CollapseFolder); } - private static bool IsVsHierarchyItemExpanded(VsHierarchyItem hierarchyItem, IVsUIHierarchyWindow uiWindow) + private static async Task IsVsHierarchyItemExpandedAsync(VsHierarchyItem hierarchyItem, IVsUIHierarchyWindow uiWindow) { - ThreadHelper.ThrowIfNotOnUIThread(); - - if (!hierarchyItem.IsExpandable()) + if (!await hierarchyItem.IsExpandableAsync()) { return false; } @@ -248,6 +240,7 @@ private static bool IsVsHierarchyItemExpanded(VsHierarchyItem hierarchyItem, IVs const uint expandedStateMask = (uint)__VSHIERARCHYITEMSTATE.HIS_Expanded; uint itemState; + await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); uiWindow.GetItemState(AsVsUIHierarchy(hierarchyItem), hierarchyItem.VsItemID, expandedStateMask, out itemState); return ((__VSHIERARCHYITEMSTATE)itemState == __VSHIERARCHYITEMSTATE.HIS_Expanded); } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs index 407e19ed476..9eeaece3a92 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs @@ -24,7 +24,7 @@ public interface IVsProjectAdapter /// /// MSBuildProjectExtensionsPath project property (e.g. c:\projFoo\obj) /// - string MSBuildProjectExtensionsPath { get; } + Task GetMSBuildProjectExtensionsPathAsync(); IProjectBuildProperties BuildProperties { get; } @@ -36,7 +36,7 @@ public interface IVsProjectAdapter bool IsDeferred { get; } - bool IsSupported { get; } + Task IsSupportedAsync(); /// /// Comma or Semicolon separated list of NU* diagnostic codes e.g. NU1000,NU1001 @@ -58,7 +58,7 @@ public interface IVsProjectAdapter /// /// Full path to a parent directory containing project file. /// - string ProjectDirectory { get; } + Task GetProjectDirectoryAsync(); string ProjectName { get; } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/ProjectType.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/ProjectType.cs new file mode 100644 index 00000000000..666b0ac8ca7 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/ProjectType.cs @@ -0,0 +1,91 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace NuGet.VisualStudio +{ + public static class ProjectType + { + private static readonly HashSet Supported = new HashSet(StringComparer.OrdinalIgnoreCase) + { + VsProjectTypes.WebSiteProjectTypeGuid, + VsProjectTypes.CsharpProjectTypeGuid, + VsProjectTypes.VbProjectTypeGuid, + VsProjectTypes.CppProjectTypeGuid, + VsProjectTypes.JsProjectTypeGuid, + VsProjectTypes.FsharpProjectTypeGuid, + VsProjectTypes.NemerleProjectTypeGuid, + VsProjectTypes.WixProjectTypeGuid, + VsProjectTypes.SynergexProjectTypeGuid, + VsProjectTypes.NomadForVisualStudioProjectTypeGuid, + VsProjectTypes.TDSProjectTypeGuid, + VsProjectTypes.DxJsProjectTypeGuid, + VsProjectTypes.DeploymentProjectTypeGuid, + VsProjectTypes.CosmosProjectTypeGuid, + VsProjectTypes.ManagementPackProjectTypeGuid, + }; + + private static readonly HashSet Unsupported = new HashSet(StringComparer.OrdinalIgnoreCase) + { + VsProjectTypes.LightSwitchProjectTypeGuid, + VsProjectTypes.InstallShieldLimitedEditionTypeGuid + }; + + // List of project types that cannot have binding redirects added + private static readonly HashSet UnsupportedProjectTypesForBindingRedirects = new HashSet(StringComparer.OrdinalIgnoreCase) + { + VsProjectTypes.WixProjectTypeGuid, + VsProjectTypes.JsProjectTypeGuid, + VsProjectTypes.NemerleProjectTypeGuid, + VsProjectTypes.CppProjectTypeGuid, + VsProjectTypes.SynergexProjectTypeGuid, + VsProjectTypes.NomadForVisualStudioProjectTypeGuid, + VsProjectTypes.DxJsProjectTypeGuid, + VsProjectTypes.CosmosProjectTypeGuid, + }; + + // List of project types that cannot have references added to them + private static readonly HashSet UnsupportedProjectTypesForAddingReferences = new HashSet(StringComparer.OrdinalIgnoreCase) + { + VsProjectTypes.WixProjectTypeGuid, + VsProjectTypes.CppProjectTypeGuid, + }; + + private static readonly HashSet UnsupportedProjectExtension = new HashSet(StringComparer.OrdinalIgnoreCase) + { + ".metaproj", + ".shproj", + ".vcxitems", + ".sqlproj" + }; + + public static bool IsSupported(string projectKind) + { + return Supported.Contains(projectKind); + } + + public static bool IsUnsupported(string projectKind) + { + return Unsupported.Contains(projectKind); + } + + public static bool IsSupportedForBindingRedirects(string projectKind) + { + return !UnsupportedProjectTypesForBindingRedirects.Contains(projectKind, StringComparer.OrdinalIgnoreCase); + } + + public static bool IsSupportedForAddingReferences(string projectKind) + { + return !UnsupportedProjectTypesForAddingReferences.Contains(projectKind, StringComparer.OrdinalIgnoreCase); + } + + public static bool IsSupportedProjectExtension(string projectPath) + { + return !UnsupportedProjectExtension.Contains(Path.GetExtension(projectPath)); + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/SupportedProjectTypes.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/SupportedProjectTypes.cs deleted file mode 100644 index 316051b4058..00000000000 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/SupportedProjectTypes.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using NuGet.VisualStudio; - -namespace NuGet.VisualStudio -{ - public static class SupportedProjectTypes - { - private static readonly HashSet _supportedProjectTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - VsProjectTypes.WebSiteProjectTypeGuid, - VsProjectTypes.CsharpProjectTypeGuid, - VsProjectTypes.VbProjectTypeGuid, - VsProjectTypes.CppProjectTypeGuid, - VsProjectTypes.JsProjectTypeGuid, - VsProjectTypes.FsharpProjectTypeGuid, - VsProjectTypes.NemerleProjectTypeGuid, - VsProjectTypes.WixProjectTypeGuid, - VsProjectTypes.SynergexProjectTypeGuid, - VsProjectTypes.NomadForVisualStudioProjectTypeGuid, - VsProjectTypes.TDSProjectTypeGuid, - VsProjectTypes.DxJsProjectTypeGuid, - VsProjectTypes.DeploymentProjectTypeGuid, - VsProjectTypes.CosmosProjectTypeGuid, - VsProjectTypes.ManagementPackProjectTypeGuid, - }; - - private static readonly HashSet _unsupportedProjectTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - VsProjectTypes.LightSwitchProjectTypeGuid, - VsProjectTypes.InstallShieldLimitedEditionTypeGuid - }; - - // List of project types that cannot have binding redirects added - private static readonly string[] _unsupportedProjectTypesForBindingRedirects = - { - VsProjectTypes.WixProjectTypeGuid, - VsProjectTypes.JsProjectTypeGuid, - VsProjectTypes.NemerleProjectTypeGuid, - VsProjectTypes.CppProjectTypeGuid, - VsProjectTypes.SynergexProjectTypeGuid, - VsProjectTypes.NomadForVisualStudioProjectTypeGuid, - VsProjectTypes.DxJsProjectTypeGuid, - VsProjectTypes.CosmosProjectTypeGuid, - }; - - // List of project types that cannot have references added to them - private static readonly string[] _unsupportedProjectTypesForAddingReferences = - { - VsProjectTypes.WixProjectTypeGuid, - VsProjectTypes.CppProjectTypeGuid, - }; - - private static readonly HashSet _unsupportedProjectExtension = new HashSet(StringComparer.OrdinalIgnoreCase) - { - ".metaproj", - ".shproj", - ".vcxitems", - ".sqlproj" - }; - - public static bool IsSupported(string projectKind) - { - return _supportedProjectTypes.Contains(projectKind); - } - - public static bool IsUnsupported(string projectKind) - { - return _unsupportedProjectTypes.Contains(projectKind); - } - - public static bool IsSupportedForBindingRedirects(string projectKind) - { - return !_unsupportedProjectTypesForBindingRedirects.Contains(projectKind, StringComparer.OrdinalIgnoreCase); - } - - public static bool IsSupportedForAddingReferences(string projectKind) - { - return !_unsupportedProjectTypesForAddingReferences.Contains(projectKind, StringComparer.OrdinalIgnoreCase); - } - - public static bool IsSupportedProjectExtension(string projectPath) - { - return !_unsupportedProjectExtension.Contains(Path.GetExtension(projectPath)); - } - } -} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPackageInstaller.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPackageInstaller.cs index 71d85450d4c..dbe5a9ed0f9 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPackageInstaller.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPackageInstaller.cs @@ -70,7 +70,7 @@ private void RunJTFWithCorrectContext(Project project, Func asyncTask) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - IVsHierarchy vsHierarchy = project.ToVsHierarchy(); + IVsHierarchy vsHierarchy = await project.ToVsHierarchyAsync(); if (vsHierarchy != null && VsHierarchyUtility.IsCPSCapabilityCompliant(vsHierarchy)) { diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPathContextProvider.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPathContextProvider.cs index b40d8df646d..f58b38498c4 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPathContextProvider.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/VsPathContextProvider.cs @@ -325,7 +325,15 @@ private async Task GetPathContextFromPackagesConfigAsync( private async Task> GetProjectsInSolutionAsync(DTE dte) { IEnumerable allProjects = await EnvDTESolutionUtility.GetAllEnvDTEProjectsAsync(dte); - IEnumerable supportedProjects = allProjects.Where(EnvDTEProjectUtility.IsSupported); + var supportedProjects = new List(); + foreach (Project project in allProjects) + { + if (await EnvDTEProjectUtility.IsSupportedAsync(project)) + { + supportedProjects.Add(project); + } + } + return supportedProjects; } diff --git a/test/EndToEnd/API.Test.dll b/test/EndToEnd/API.Test.dll new file mode 100644 index 0000000000000000000000000000000000000000..0750fcd34ed5c6fe236ae85113e118f22da804a5 GIT binary patch literal 92160 zcmdRX2YeLO7WdiN%_i9t60%7k36KO5mTVHL5K*6~z!L>Uu^?hW5mAuU1ZuDS z(reQsoETCJDHs%#!DtU;qwVck%R9t;+f7LfuyRgxOzT@SEMz(CDNvmtZN}AwiOdP zC5C3jX<0ZwTpJe1ith(al#$pPNkMviP=0!18x}JpWaVch{(*AP%@f-KAbVzhreWXM zTR`6f)pd_=%*ju$%>Y;oP&O1N`&ggd2ZMY{{-u)J=k?vfH&5F-?pHuXY>l^MG7FrEw_( z==`v=c=zJ0cz;VVwOIy-fTLTZa{ymNd^)ls9T^3K0%(BFO=w3mniGm)3XW(a4;Ra_ zSyg(F$tMR7pXRWlW~^8-_$G{w8Ovg>V=O4ukY#*f&|U+AXkDIIpc9|LGhF<)?Q&!o?ThIou;hXl3PWW{@# zK9en0cdMgfw}ZU35u-fa>mD$~^oyP{V0(dWW^O|8(Rot38dADA|5c`ET*>I>KvS@z zrVLDt8R@4VHsp2Bw>v=|geTiR%9CftxynR5G7=z+EiuHV*E5=`O8>h>(SeUHf`> z=_VZlg-UeLcKX19$cN41!*y!v{|%Yl&>?%ZHO#Mwdip_+8GkmGo)9KDjEF+9%F_x( z4%e}36+1);<{(STL7z)ot$A2VOCw%YGif}82>BrKs7m4SGb-vD$V0vP2sD=y8g#6LQ ztZ;35*qx4Ruwv^xoGHDky|@LX4)P!@zv({kMZ%T?i$dX`(}&i^CPN<9towm$+6U#t z6e_40B2g|e?+ICWPeP(+KDCa>}4uZq> zVBSi#XI(qa+f7U7_Xm-V4$P>b*6<@9Syc-$ZsW~90QO0grnAq*VR-jI;s(&`ZXi7; z9*UX;oom%B(4r^gH$CdM3ELdD2`&v`b;tA)cd!i#!Bgw0a$h(phCv+9>Twz@4pbGT zUr|*YnjPDZi2adV5jy~Bb$a4JWKbEA^u#n2p%=RiZX`HY4}#tz>V3@B8#j7usn?6m z5{{w&Vte4t8v*i43Hf8_2jK*|B?25nuS!x; zk0scJNh#@qF@!jRK@XKZpt5l1d+21Xu^fg*36m-U`9j-j~gI17c@yt z*c`EGPm{VUsQUw-?s1?)+p#f1+X+B7 z1_yK#FuHGdBiMi%pSIVj%|wKl4t~OfnBVlV(WNoj9aPY@8?$Bt(1nf+T?E?r2?C`r z`9CxK$I?%Gk)Cz$*h@m5QDJ*F$7}A(_I|r^i@B|a9ckTNMGyUWb19vR<#h5 zz$h{OFX^i)>i^QGALE&dr!#9N0L2&_P)xum_QlDkdn@35y5CCaCZ-eJ7}fbr-}rQ6 zq*6BqF?17vZVWEyCSY{WiMFHxXq=0|*b-)`g{5?qO#cbVwP;^|%KlzuTMh!lxvz;? z$ic7(g>ysB(a0ri6WO=|GGgElqk?3Ot9%t?XnZVHk>;RBhr%{fZ(8Xiu{hYX!(m&= zH-S7O*35{KEIG~p2SiN{suLK^ac_;VWKXmiYfpaD58CF~d~zbn>4fT1#*mEj1H_P`At6?9Sf=BEHYZo+025@Im|-Nxy;g> z70lqN^OzSp%b7Kk0XoW62Z7jPpN_Gx1N!otelM;&FP85v91jynzWYGoz>W(*226NoK! zeZzZ#eZgN3erbH4o#{lNq$xvX6*ZkiVfTVXV#`p(9wZZ(rjt=loI=X5O>E*+l&fW9 zp#f{N-RfeJZ1C>IdQ1N?-0GOUK)d<$eu&X=dLIg{;cTio3hY%a#B?&Bfyh77to)YqG?{|VGss{Pp~h@0HTYQHh?u*h z(c2wiHE*+X)%j~%$VN=^n|hkIX}@@m@-63iWzh|W2&XXfwZij3ug-kHu`!G?di#9vIu%;Z8_Wuw*O)c44#s0% zgz*Hter?u}bhh2>VIBa|*FSQo7F`$pgBabO>K-P!hHOFo6-NJ=AavdV9Tab5)=U73 z;UFj`5W}RAoRir8;pFe<^0$}$K%nF_FnKiQxO^It$2&Cf1c8sKqfo?l~0UGUK z)=4|CBkwqd=>M%KW3aCszd-=n(aNmQ!Ay>Junz6O9152Z@Y-Sai(6C1Fe3wNNyG^S zlsU+(nE;qEd4ich>|FMN+uh(j2ywpPb@Lip)k2Ktwq)$Kp{^0W_M(fjp_s{_ivV=h zt1bejp`NaFZFS|PbP>}**FUIhq)%6Y(bZjb5r8gCkg$tDTU`&e)s>&pMN9`>+fvsy zK3$mCXcs0w*hK)kFquLZfwsCHZmSFJ^9BGh9dwPNu2DW+m|ds~QxS9#fG$j~&_$rF zu1DJHg5jPnVmj#Bj=Fa6=_)t6`lv1f(1pnpx(FCu=$9NPeUR(i6pu)s>9G~)HX`#g zpvKNdqGvpHAMifg68MkjH2F~+FzUFE!LXu8jAMu-1w>*-hDZY5=7{q>*TT`1IbLO24*C@Z zZG{ZOmXL4S58JG7oYP@GnE-D8DNfS%F_gWFX|K*{=u2$xKbQrbZJFV2ky$fQXy_K& zPy(*ky>`O>{HER9cA~u$0L5%4Az!n?HtQRgbZF=9UA6O{ls(DU&Rr?rawakhI?&2? z!Vt8RD6|tx1RP2r*-jI0tfu)*lZ`Bm_r7GaoTgP8@L>C6h9Y0R35f-Fp*kVU}A`bVGErUN0N%5r9-()3Htu{%-r zOe6a|_DdWlP<9iuLgy%E&8&k^tP2oIAa((#NpHQ_nKEYiWE@W}+#fK*EdaA-)X4cF)$j2H7`2S^9aK#tY&es!ig(Tr)OH>#FZ$T`&1P>!z{^G zYj`Ql@lP|0@IWlK0F{lmaHwBJzN?WymUQ`D%wxL?1htk1O+p)Mq2ib5E2X}Zeq*pn{Gzdatq5z znn)1!x3Yd!oBHZtC>q0Z8VC9|qHk}5uIv_w-O;8dITk0;28_6*A6Bu|mUA1kLg!Xy z&8&kBSYu%Wfn*F!)3tvazwSYKi+%FeP=e*$!>rJ`n^`mKAP?&+mU#7HS8f^?5S^h zfw38aM*BRKl0Aj8G1)RUYuMILDa~>|V^-*V!mOEfkiC=2CJ?)qZLM$m7iAA^BfEq< zG8u>nZNaQ}FmWIGOSn~F?MP-xH{w}fP+mj-*%xiIY^*9FJif5vR(xkO z5#u?0A@2PG8HxKL2G4$D4zYAkaM&!;T>? z8y(9gD$8nS)>?@E6tD_iK1f;zNtnf}&@u-r1bQ6P#6zgov(}9j1!-2FR--0rNK{9D zS`4EhA{$FPMaOVAfR3ckE4hn5`$DOJrvmNmUl04Is{Ny&_ixxwHrS8J%Gi&IG1Q&* zV^;wCXIVB;u%DUFe)4(t&rbtTRTr#|hZ8v1iikO9-dJL6R~7oGBWZM$MyKjMYhhrX z;9t6&u|i5Zv-ewI_fvZ@`+4^6>c%^0;+?7S=JR|Fcs3sJYrscqz{zK2I2h0{IL*>W zDBZ2@X)$bJ;_~)6P+-}_W?Rk7d^VF6!q(A5H|Ch*LU`GQS>iF&JD8Zz37BSWj1`1w zr)rEkN*Xl;sx?0xdz_*+_WdKO^w<+5V#jlRbJ;a|i{7CxTpYmbf9e~|7Jth(Nc|lNUKF=0L;u3RbX@sxXAfLhcX_tmE}kLO zh#a8t#O}z8=PrL~ZZln-Y#7_v1DLUm4U!q#a0t5kmC$S1#A0|e^M#YF-tcz2I<_Y8 zCDX)9@NMJk*of+L-Ns*0O8g6T)h_;J;&%$7_7&E8lc2UI>Zl-nq?eozbQ0`R6k*N;`wQ_<^=Mg-yh73{T@3J)9=yA;iwNSI*M5IduBdIk+ogF z$GQ$jF>RaikoRt3lL#!gguTtPiRS9kr!-r=HwJx$fTI*2VuZ}XZW zc&OI0**Ly|laZfMn=Oq?(QrOA$14B^mv|e%yzSVqDayc<415_943DK4Y@&)28^M6~ z8{i#3ut@=fO1ule!8(pMFr~;yeuN?;p=2BQOg!RXwF}`@Bm_JZKa$oPHo~VaMavTZ zCe<`jSvIr8`>Z&K6}CyS@e4siR(=*=`moJf(i)>P z@gay?ExrqylbMooyo+Q?t)Cc9W@?`8W%(jv-Z{e+}NjV`9__e{*Hw7*k=?_v)wRQ4-c%v z1;$a7{= zf@L#v4rMuNs%!#Tm=V(%Y-NcW0yQl^-Hl{fr)V!s;$KIK;O}0zD$ux&>xhX5IzHkt z3%dWucu)l5aU?T3Xf_HO5A?cZJcva+nEB#C)?_?-I7a}qY^GhuL$x6uN0BzEj`6@0 zos0*uj0baHJe1jsM}iV8o0&6*<*1`oHi2Y3lqG5i)U>wo=z!krczE}ISVi)i&Nuf{ z^Vwg%u^7X=?eF11Y#{9_1yuX=M9R;*ckfIDDmxDxaYeS%09Gsy;P!@1<&jG;>H=o+Un zW2}xxLAwU#GQ{euG!9i_(KVR)x&~R3UBhk$#QU#s;%nHeWAqyo+%c+Z&?im@RZ0*0 z#6GI$MAbtq`vmjW!hd36&@rlt!ZA!6x*E4ohPiuN$f9L4GrQGArh-}GJJ8SDf$QF4 z)<&HrCOd(dt#!7eWg96^$HIy4+4l7A>9PNqw)epNV%nbWoI%>8kJ8b0%<%Bh({QnbxvevFF+bYFUF@0 zSmH~$d@9~X9}MY3dL@*2zZ8l*R*Jw!1#b1u&k#5dyW)UzlF}M~7(Q*AZM3TrOqb!r zf7yi0?wPS)P(WOJCVi9XoJko;-(<{bm8|Lw)yJ$_WY0asoHO#!$uq^YBMT&Ex+M+&_UWh=Ne#BLL8eECj zl#8OVR=D$u*zZVVxCM)}kY1VW06;CxKgP%yUeqTiC8I|>8CAtSJZTmH1m2B`B=F@_q@Y`VH*S8Xq&B}wlC^Q4f;?^vbSj8?17D}EsKc>{k*;2D zJ3~d=%mPs}Om%+F&x@r)p={ja|Ek#ZSO%rmwArU@#Kimou6@uM>f!9RXIW{2GifYsCUw%d`hhg1V*tR}BmdolIG}gZ_#q&d1hN}ei9pfF6HNaszj(y7| z(C40AZq|J}`4Hr5n9+NeqM$+EU%fX43M`vg1euvH$Yf0hIqF;i5H7otnY|Ke<0lw< zC5dh@tggVV%1raB@L8PRevjiaspM6_>4QBZs_{_3&Q%m=*_WwQRbjI#kq4=&i+7r= ziSJKAmn)r$b3Acoxm8}vX4Z)P&5<#j9Yvh0m7eM8MXkYDcLo7sSW$FgQof<0WjvA8 z+Ya?xTcg!?*zG=!&g7m*c16|MS=J$N^=w?RPGcREp}=9zN35?!L)=(z&RG`OaF%rw zGoI65hk~9{AE2Rr6?!e3Sge@Le4!?*ca}x}U{Hk;1#ng(N-y33Fun!qSxA&}Fx`j} z?484ED z=VXJ=?_frs--3er{6O_N77qA`SooZo&*x&bA-yy4v&q}6!fh~+Naavz%HzghO~y$^?vn=Uf<-t#!zzvJDu<$TYq z(D{~GGwX2geGnXH0P||LCu0_6Txw*TNf|#I8UHmheo`5%gN%b!1_AS|wIntX`+?N^ zO|vQMawDsevVJGG<=`Hk?P*n6tb?rSDvN-5?(MY)eJ;NVFH0n!od?NmIUys%V%E$$ z$T&o05NIo74rN^HlaWp?%gJC?=!BUyvko$5s0;#aWh5x$2A_;9a#;@EQ>Tmwvu4&o z#-S>MKwB9{QpU|b8QsWbIeE+qom^(ktb+{9Z-@^8BO~>6m}etFIRazqD9E$yN6{NF zru=7-m>o82Pe~CNUQaUP@LG?84lj&aY}T-!$M7N+!;6`3c#+i`UVJkooalqDsz)2; zD7f1}Re+<7r$C+3z@rWHS!lRI2QaZb+F;&VxTALqtjsv>s(?J_2}-bRX3k?QN4+XS zdOYAf&U%|^a$}$}q8^75sFiIu23=8k8w0e`zYoN$ENE1xdjqfkqTlB?t@6dZfKj%b zD6>MRJF{liA?6r+h&h4IV~#h!q)B7`ENp8N^GOYu-MyIq@#_KR5gH|634ECum%!&x z&?OLq76GZ%kQ0j~keM&!Wc8LnU&zxCO<%}WL4KO^3aC>W((vs12-Scfqf-&f9>?4l za%F}*4f($)!Lpe-FR~nUw8~b%ex6nK3rG`{=pkHSQ&nb{`I3?ta+VW)N$5SsR%KC7 zw9=|OlG~R`&gNZFdFx~u{cqO8?cuy}f6_1JvR~Zc>lelB36|4?S)o(JteJJ_7nr}$ zF9>wrFD5`2=6lQqufe$gtzS?A`o#uj>=&=2p#1_9Ao|4zFwwG!MZaL?>lb8A_KOLe z3i`p#1?(4i#oC(+Q~~4ZwUOD2%0#JN~bQ*u1Po zK7{xaW(@I1DCh!=X#)1owrrvhUuM4elFy5;Wq%B)Hpk?N8rTsJ6!Ek}Z_8AL3dX!< zT%e~Nsrsbt-g^mWp4a)iN*@PAj#YaJv<4&5sTi%%-6ff`sck%6`*(h7t|>Y>|HPc z8ctIU#IkoW_w_Di_IlS(lwjG+oF7?^I$C8bVE=%s1omi%T!k6l${jVdYFKjjqOTxz zKzpm4e?N<(BhfwWAH>#XZ13^KwhyCeIpxd>o!-ovS%=ty7O^GJb!?k8w!gxj|1GwZ zfY=6b1F4?>4Y0-*3X-uU7O`dKi!E9IJhrL;v9;Q0U~C;8!Tnfqd^%wBBq?1iyq z=KRiPM;)!Q6|h@T%G%zU9CtGB-SZZ$Zk`ffE;0roF=PT|wQ z{mTN?z;{S2n^?}N%zdFzW^ez3lRt)rnUltH)X^%NfNxSy?qA00{>3yP-NEUMuL0b@ zv}gk^)^SfPw=m3ole%euyM@8iB{qPWg9m1q)R}Tm>%O{nJx&OlaNvel*R)Xy>?R}J z?qu>NMP)@z)78)UnXy4SP3U%~13Ep11zOLb{PVzV@E4z9RCF>Au&?Y69AbyQg2yWV z)j%x!CiB+9oxS@FWkwi>L7sz0CX5X;2gji799m@)C{Ex6G&LP7W7Lr8 z*T-##YzMSAWZRrCK(63;{tx4T9*#J4M+^S9`I8b52OQNJFJUb(aain&1F?t$GhZCY z`sZ;_1&9M~q}kJt+ELeCx-jupo~#NrXORs zjY9|Y--tsl*=;Cz(U9)k%WfKL@GxK?#e4gj$ zW1pu#ErO5v%F!5cu#|_i*0NdblUJM=0pC>PjzB-%P_6pac=B~+eNdCCcfH}=4_tA5 z=l27&AHx;>5U1aN$9}TGe%xOh`!Qh~`%m=jCkpm6^Vv^6&;A$&a=e93@OeUu`epb6 z+=GV_4SxGotA5Ge*8WueU$h^G6oSbF_T%i+vww4*0g?^&S1{wo6lv%{RwgECv58VA^577!C!IpC zZw*gilSLHXLP&WeOVXfS<@m&h;+A;+1&fr{^C(}e5 z(hHrzEJvLo$cUnxL@)Lb>|XGj3dQwSJgouUL>iiqfP(erNiy~$%ENr#5O#(wP_k^M z-e(J2lSK)3Cjpj45HRJdbo>aRfCQ{aY{L;jUZ{z>ltxsL9}{f(KEeV|vMTWp9W89T z`?Ut&%6r%l7~_q7#gpMPd_PdzoodLcmNwk&leMkNO8KOCvTp$T-k;+e>>BI*TnCew zFW7v44tLeK!+TSkNGv`#XlCvkfXa;b@pJ%U5##`5rcHv$ENi=>#*tBnj&nWU12Gxt zwEq6P_l%u!FwfZeI$K75x70IsqAZ&s<)bHkrA>85{n57cS3vNFni*{Rm0VX;-YD~) z!(;lFb8+2;{?waIcK@X#e;al0j@ob8CQnHFMvV7}RMAshk~ z7+3yx!+D2^<3}z(JT^4VOm}u7d(sic0h$&Z>ozYCtx0ax049l2qIBzT5{RU=$_#%n|$}# zv^&GunHXQ16@X}i~{?Zo1|zL~ji)Ef6@m{I#rO27xK$eb}OM;*6{kncUfu|(P? zWkVBaA$}bX^lDGkv>uy}d!5(!im2u4=&k z0~(0s&|~f!ddln#y*(%aUwk5Sc4s;2XqByiJrPyDF6!IaacG%lgq_J`Od84)`4!rX zi?oXp%bgu_Ul%paaCdflQi5eOb0)DIb+pP>z}^j23G_&GC--$l<&JtyRw{LK^3kL| zdG3lTxiRO$4gcv=Fpdqg*@$sZ8VCPj^DQNy9lO2$FAMqN>P;Yi+> zZuqzN`vHf$KX!v3g__BB#KuFnb2y4M`hHqSo`$)&bAzu*;JXhA#Y6GqifXJv<&?%= z>E1B0=1-uMITUEmLRxG!E6{udfCPqVB!)?n@0qj0{NaF^ViljZD>vW?@)bEpB8!)E zy=4VnXFiPe#j341sn&=nHbnT~5Htx)W0ATn%O-%kd_3IE&ZxVK3!6&fFC!?G=1_C?UPX`uxw({Cz<*BBw3Svl0S46 zcjlssj%6M@j9Zd2-cHQ}sBhx3km$*(qm|NT)~D5KK86TPzsdNq!m^u?nz5>Hl<-p| za%62hm`+!ksEV>|70nxky7M;n#7F5-Q&pSoqKdhT;7hn9j3z(JRQsdaa7%yO4KqJh zF02qb19d>B$Mz()2JfZ}gKH4eD{&oxD-W)MX~}=QAE-m!FkBTVx8IBKUOWmM_V|e3 zacI@wi68k8zXi-VryP%h&MB8^{P?;HzRg1=;>XMvKeD!qUo)x@KFw^KK=XX039K;@ z$02MpjbS=BKN7%*kRoeiEqv-Os@kTgqf(*{(WYHV*XpFw6_w{WS|4p#?bm#eD2&I#nlhgrz90npDfxbYnu3JI(>__z|K`1Yt`A%Uqq;+#k-W1nRc;LpTimeAtW zC^pSQQXInuAOdOlG7~he038{(c_V`|IWkmsa%2#~${gZzENwBq_@V^0G(Y6uh<89I zw?fHr@fNz?B=&pwrTw_TN-UU6yBHTiSq~iU{t(+`Xn=2RNRMx)f4@so_md1#IV^UA zLO)$r{O^&5hP~54XtuQSOtB32Kn*5EHdX*mZPT1R=_?5Ri=*} z%Fcop3G}c0m>aJ#`oX`7%MUqck=tuY2;Bui!)Xa#qe4rFs4{ov)I+9#Og_G3l3!GGRKpDLYy9(Mp{gjZJw!N>m*pxx;UQ<3SNg2+)^XA5KLorL{VAOg_@k*FQR-lLN+^=kRQ&qT?EoCip2(!L2&{aX!?y8w-!Z z7~fdnFOd1h0vX_mmCVrJFF+1QSp0!Vp4aJEAQFyX<{Jyj31K=GE+xNZGjlFtIqGPY zt$=+Ys`#_{VcyG_vA|zM`vu;?nB>W!O3QREC$HBI{#m|jv>m%^JBY+6VdfhMrX4{u z5H2G>zIj9DT+DLR(JGq&2Lk`1U~(WNo7KfYxP%f+a!2swzW> zz7tMhWeuN-9d;mw4Ll~=_{cwI@F_`L-j3J%tVQjNdfs)7Q}r6PDb4DavyLw=RhC30w%ZVW8)igfrN!u0mGlmS5Ji#xCPN4yu)zzre5-* zyIsc&VZIW%cDHLa%u^u7vWY}@W7b-T<-x3v%8BlF2!uJ;kRKmcB6F^0IclnG0thqy zrdKk^$wqYuvS}|SlCb_PDEr2i=%j1|<-~A?(*E^mGjD5Ka42#;ReNTnp|@VAX24Al zK_s_Z%zbZ?7(3jzqpzg^Z3aF~MA_G8Hf~`M#r`_?o>*l>jpgdYWbkz&>45eo68{;* zG4M6^T~dL@c8qsOFg67aK)i22!`wM`v+f(nhh_E_W^}}jDCoZPdi4_S9^fTn;X!7; zNtUc|=Q_@w_^=XCpVsn)KjJrznr{Y>n1N0ZI~0lT`SBM*vo>yF9A()gh|L5pxq;V) zL>(ebE3nIqfxz9scR+V|$M&uVI-7UHaxDCZV=(yWR>=Mv>k!#69PVPqb!Zg|x(?l- zE-Hn5d;*6`j0a{u7m>ByI&?d#tk{iUb?!isn?+V74uh?U!l;Y7~YMx z{EZlr4KZBHj4@n;g2wPBjp0DZw`^h&LuS4hlC@n7??sgryO}Y>jH@wZRr?s;kGlBY zh#?EU7(SppHd*nlB~rUwgU5QeqCzVaSD7l}I4qRFah!>(O4Ybt?8TK;UBs0rFRtp1 zsH0{?)db^_wsGx>s*||RL|jYY!}f6A3>30lU42G`Y7t~hmi5XAd#h*|IFB2 zuRJzcEt`O4KZMlorxDa*6(fkL)kIMFHG;Q$5oA>t5hTispxPaEw82qrtg*dq1iPa0 zmYU=}9>?bHxI*w(`xy2^T^v{EF~na!2M&D_WAkw|@NdMBY>44=%oxKbP|z5z(ijFI z-?E8C44L_2NY-{Sd^8>mX%rblR<)1eGpLKlfn>oK!)KMpCaYx=NL=SdODQ#4 zPk7N{RTt4B%8Qm-7wwLv**c&%;kM*I8aHCGbztU;8(EWE2lFZU zzffiIH_zkF%Uaaw^%WLvwybG3m&H0AN+}qdBH)!lsanHN!jvY=>fr=VoK0_&UdH03nf$!s1KFvR_1M$F&(+tVOZNOwv5MF+?gy zyUq<>*I||EIvsvqfGA_M{%&~U2v}Y`bQ`ydCc9NNKB}U`9FX~FOojOk1pRzzxcR{X z4O>*BjrOVAqsHY?N8PP~Ozyr0^G@Zj@g%oo$$6zO`oI+QQwMqbzWNpFe!w*xc-Yk8 zTd>zrj}W4-z5#!@eRWS90j_2r*`Pi$>02nD|sK8zePClJhp1ZKiW!ip7nqp0FuV)HFyX zy3NPIGR7*_5%gZm10UuN{V$kY#sSfDm z!1JDEV2J2*j7K{ecWASGfvW;EosB#62*K=#arX)IyW?)NzQH6PI@{;W=;TjP(9X6- zhugmRqz*OcY0P{*jeK5Di`@g-Au)qj;5uX(m18iB!G!!)l%%u3y!eAA<5M z{BWuI;aezh*_C zCxra~VGgEzo(eH@{=;(ARM`ZQld7^r4S}kHwU2|{9RVHCzTcJb>^|v?&dvjZf;nGs z^oRKW1dXoUTMB>N-y9^-?kafJT{}nxyMJQ_yMIQmcHggoJi@Yxfzix-vxTxjlFk;t zlG(DEIlr)MGff6nX;m`JGy`3`cd9-)!c+Zw{t2DOl}p1)wXYRAQuggl`@V(`dAR%y z<7(DMQepdz-;B~@vflw>_igbHBcP-1ZrQ|O>&?vfDjeA$=vxg+j~wn2R8lhqcrSbD z3-GDxG+Hkqrz@Mc_*|1L+HjoN7q%lJ%_`@}7!&=VZ9^O$^lTsoHZb$qK(=-^s3aB8 z#)ee&X4!zpTo@}6s7cwdUl%rz3O3|0gAM%Q9*x5~&jw;(12dluWNT-GN>TxBY)Dma zmJN7f1RHXpCS}6`UD!Y>*pSZ*Ht4SiaXdWa*+2|zVCJ)dZ0&4NNh+X?4XNtCYy<9u z1rK{*1ApemwP9CGxcu=O{WHIA@fj{j|Lnpt^1`x0X0S|uD~Fan>{&((EMw-gjBM>J zQ%NeIjb*87*D`OMH!tpdoWmx;!z0+mpJ{RJ8V$Sn<1PA^dQ(60+-}+;1B~g(494gW zywI3OJY$G~G0c3%kgc6DDoF*jF(y@=3{!G%an!M0+jFhj!%y>l_V9y!{R_7IQU6Y- zVKTs;Ud&*Re$-EU@MO?T!^FTIWwQJg+ zjU(EHrxCEL8cKY2@kMC;lcM;%iNy)DYepA#kr#FiUs_xP*k?kk#w0%HugMxqAxQ-rHKd64_prM1eWKEjPMmh|enZEO}&q1Dz z`o5FqHXb(TQ0&-6ZaNd+MWv%|&q*@qeB1}2uJ1qh95)*ID8Q440p5Og;vf>^pM@>e z-hJ-M%FG4u-@s5QLIsK|aW&(DwSu!-`59%*tb+Rt{#{O4j2u2!T98NA}F(a`7mhh=5PlLcYkOb2IQhRGPdp6USACk%OSA0QnqZE8?O|nW^Ozz(}&;OuSg#5KcS#f zb{xd|M~1L|Rt0_10~S@wmwiu(RmiXO`)2gd zcdPb*2hM9?njdF6sf6`2`jO_lntlU{WIIH&w`@6-QP_a!6v>=HOxF))+D9X@jYfH6 z4Y}^np72a2qj^isgo2UMS~IM6q?|K|>AtnY@S|jtY8MS0DL0`eSN1Bu9{ps`A(R$X z$-g7MMe;i2qYtB4 z11_SJmkuUn2!C*6A#f|J*A6FC3Y*}bFwm6>o$f-{D0I6k^IC;^xzP0r9W}!6-JsCAxF1?R%s@9P?iRP5H^K&y&uja{ zoj|eNBtclT7Sr|^*sw~16?yWCLOtYmg+5lO1SbZ>ZB(dC)+k>NB#psbaGyetC{!*F zD1;kc;QGmf%6Bh%$QY@XhZKiDm<1>%k1F)7LUDOap*46SF-Gd-359Axga+dMdbV?x zLW6K>!?qZiL*#iMG*n(vO0HvL&?7b|^cW&DMn=gy3f+XoXbk@H`g;oHYRh(%4-~@G z0^Dx$u|h3addFZ5`%Iyw-3U#`Gbgs?QI#@FzEQ|{qEWubikK%3mc}vo4YwZ@cc?a%+>rc$1`Pa=vt zOo9YRQfBltw!ZL9Ojeq5X=N);D=g;DpkWT_!fn@+cJs!RR$|`h3X3ihADKh>dOv{ zP-uhN&^<6xp*5JYR7z!FtU}o;r8Y25q5IWmBLm|V z8m%(74(y`Po@&GRz-|g*Q-yZ!5}2e=gW9l9U@wJ^RP9p&lNCB$aR&zWRp=$PZ(3kK zh2GPa%?uo<&`9l(M+Igo^p>{sxWFuhN)&1d%u(oK_4TsAQ9j(+fw>Bup&HH)9HY>D zwc(1u@d|yR&;TUAA@hVS`<1-p}PZ%6}nQP2LnqL3Muq>V3|ViD)fBdRE2Ks zNhxmx&QRz~h29CArBH=ZeiArWp{Eu1Mc{mehAQscz(oo@RZJ;A1uj+SQ-xXsmn*cp zQd-tk3e8q1Y+b9+Ql*SoHz;(iLb=w>3gxT5?$#=WepbFB>kfqmD6Yi1OQCHQ>TTVl z&^(1It@{<)TcK*}!N6`UPRUNi0olED0@7ovb}Ak$TlJqbT;KpK$Mn%Y|PqOXQD0hi{*5^6jjHDS5F z?wG)EdAa-Rfg)KEeoo6fTSan$)nKu{N3ci=tn?suRZ9Ov`2=v4^dhgRnHFQ&)SH^} zh6%;wol{IXO~6J6I_>EFyyFHg1a=!uZ|Os6U&8jVTv~O2%2}rA>5%r7oQ?FVK$9!E zNL~uE<~m``>w%R>3#=QEjt$-b35zP$P+I&x*gHOb9n!Nh*0-x~Tk}+kGD44ah5aV; zC16M8yoPjU?gpeo^4>+dD8D0DSK2>BOJ?`~3S6dbJ7i5k`TCsik^YkVGt#Z|T9NLM zpV1>AeY3GRUO;MN<+P3pU)SRBq`rjhtt;}Ugntfe;yr(g;krqj}aGxGUvLs`$Pv&+gcjPjWC09W9N@v;-VMIbX^yK8+ zacJR$yj_qUoIeR^es|Iwr0J&ad!c4OVa-3oq`5wm>4n)$J-hZrc|h)gNGErj>1$6T z%3EcRLrU#oS*o_Yq$yh!kcte-Ss7_YTAAyY>6h~qc#Rz62ih2rxoXR<+FK^(ux3-z z+bKWa2j0SLT6#(b<2WpfHnxpgdz$Sdq}exTVF${ks4;!U^uumB^q!G+MERLLIQq^- zTq<;Q6j&Fcd{K~NWID!UksPAs^bpIB>)4r&F_mg9N5QjU%B)bkDm6NupRa`{&uE}0 zO;1RTGJm}%;fO9Im>%WlWlcb=bk0tzvY2`rZ}Ua-9<<7|ZB-UqSefgmycRVBa@*3I zsCoWLY4qfzM<~JAxLdc*r8Q{JPw|F@HJ$|160f!N&*sv5k{?Q1_g7lwadC$EGW;}n zS7kBvTJnO=Z-15Mhx8e)=TrTGyp;JzHEl;(K+-cf=R~qNnvTig$l9%2S0jtOO9sD* z^w%L7NRR2y`E96_?M{3C}H`+n(sh=E>g@_ z=|3U;HS?_Q0l6pVH7EZq-P$^6HVEl`#Y|JMin196*~xK~@`Ow%gTv|Yvg+D)WLb5_Q_KHmQ~^$)GM-qCfq+0G* zXrXLZioK0|uFwj3ari4G1Efccd@JOqp&ypi$V?YHpz7C>T3O>lgQ{~&>*X64!k4^ix%3X@jhCp_UQVfHt_$g5kBLTgo1I^NZSdtR7mr zwVdffcMjdM^dIts3tcvJXz8|iv)53LE!ehnJIOLoMy&rBK>Zb3-sA21NdLg_dKdyDy+uT-?=) z3*os4znPt)xX~^&pl})}mngJCaz;?*Iu|##n7H3u+?d|fP>UC8DCOKJHOzLQx}w7Y ztx{-(SVN8}9W9@`xC4rs0o4v9-wIhfh`5;wEtfLIU2P!s%V>GjrQA4lDJYLc2&u16 z@foG#WP=NBh+a~<02Jm)jLLPN5Z2thi%c+(C-F)5RSygficEaZ8IR zvtmo5eXimrDzscyD(*}d_ZgxxL+*E>XNy8*GbCfA(f({vLD@{1s?Z9ltc{k=k~J80ZljUv|9Y;eAb!4+9P5yO-Hg>q2=IQ#+x_4lKOm(3-z4j?vAPI$*_IRxx`&l{GKpF4!oRrZbEiN=NM(Cs@Wg#e6y13K( zOv+d!*SXN8eez_HtXAkzsf#X1TP!~*v`{`PI;$>Og+A<=Cnv~_ zE<_J5l{;K$Y%CAIig>?5#=aBr2%p-GUrv-v17+L;znm!fF7yQaa-x*D&>ban%1)C0 zF7$B8TtE#98JWwZS)t|fYk^(1Ox77n_0q{={ymm9u=vC>0|h1Ap9+b9m;H_mBCZV%S*0_+T z{o*9z}lEYDhdS+_|Kg^bKQq@R!S4ykh~Cs=)hcgS!bZncbZaqoo|q^*`EZE$D0xK)aK zxeacUi+e(G{kCVzjP}(sNFmeC)v~ohi{&bes@2lc2Di+`{g{^5Yqea_26vN-6UBYq z2KTdz+dbpQvelBi1GO)fqqBZ2yHolqWVGKUwJz@2w4S~0k|W#TnqAy&&~TTmQ^?qG zmps#k@^zPTt<@KlWusHp-X$@GJbi-|!VD<&plooVn*$5d?via?=xcc5E*a}WZv{y? z!G&%Y;`VT%_W~n;o9aR%t$*~oTMl-ii9te#D`d3aEprumH&8YL_r)@E4BPo`ptQUa z(BTRh$~7|A#gTH2Odgw}Tq9EyGL-kobQed;dt~lEQtvLRBjq~jHzh^6PO23$ln==u7e~s6ByVbp@*(N2kfD57%3K^NAC@Kir6?bk zr3x9!N90TwN6JTJ*a0cZM`XA{hVoGv<>E;BsLVYuMfs>4t&pKyFAEe}EGt3*Sudw4 zWJb<dii?!*oAsod4OuC3H~jXtAh*D*2^##nuF1?UXFF4gyQaZp?u6X z>qQPSd@o|Gte4R)GzVjBy_}?w*UobkGUEaIrjyT%hxJmgkfD4`8WdVAHE9dd9+T!a zxRYEy`sFbhJtHOMF&V3nk@C1qRA{jjLdxTEP8-}xmyc2&mmV`yQXZEQg^ZLZq@Rl; zXizDSzQhr2=@+qlQ$WT5lwF)hk zZDGUHa%3A^v&%;*Ps^`!Qc|9lR)vg|XCxy*++x`sQl63V3VFE63Yn-pBd;HslJbna zsgR+3R^E4U)b}jDn@v$Zi!Wmd8OrA*&&84QIXQK1it;%*T_HpHyqxdiNcp@(k4{lO zFGUI&$`_>E#gXy_i5`=pd_js7GL$b$xr-y^ixNFHMfsu>DP$;Ll5!VE%9jKieEc&# z@+Il5kfHpS#9SOH|0SdB6y?8UdxZ?;%QD`@k@97^e}0PcWm&6`p?pQ2P-w9%LR4On z>;VrdEO*6TI-#fN)cLMIqLN_k!SElo*zU8)r_Qr?h33Q@}BUT??&KHQr!)8(U- zH)ZvSDJgHtT?$c3n!F`1y0{O^19;cyWfv+NF#ynwCn;a%+AR*~wL$JMP@vZ^Qr_$0 z`VAim=usEfv;GiJrY|%47S`_yTsMVGt2amw7sr-ukY`R#wQPetr;wq1TV8i@qvDc(1zmVeQhqI)e3W0ydp^o<e~?W+${*yan^Q7>kZTk&GJlj+E{-yPl)1O0D1Vfr6*81R zNsEgkg};wKf6C`u0_3tH;(B4 zn?M;-F8E(*{usLzthSUAXCaUfl9!OCxq1zjGJ~omfOm4J(WGa<3JdSFu*P3zODvhD z^(+UpZC*;5c)qE&cT7|5!3iJYYvBzCYClFTHIi2+Wm;m&Of7j*HTug&n(^Ti=n0l< z*M&7~!!}AUng%LZ(^x{9MM#5Um$AmwH)y;}tWA6w1rv)uOFz*b*h?kv?&}+@4+`r; z+C$Q$QhUDXIezS2=v^MRE4`#Q{SB*1vK*8w^%ZMOy@#dVplqQUzr;ssmMqt?Z2IIf zm9R=Za9sg;nObrP##&H_#m;pYQ;si7{9|pQ_Rmw)KbHFKE!ASu3$;G3xOTy{E3S#ScEhzhu1UD|z_ll?y>ab>YhPUZ;o2WxpX@JN z1op=_SNr3;hW&98aRBNM#5E1qLAVaaH67O>xMtuw6xU2#hv7OL*DPGKaUFqc4z2{Q zBXJ#ts}WZduDQ78;W`@EF}RM!bsVnaaoM<!GjEnFkVfFA*Xr|ROHH@a zbeyKUX}XW5(=700-=O1~yPcluU7$5bS;QU| z__;hF%YYq#FJ*QZz6Hu#<1S@cUSUJpEiMx^8K)hSn$w>Z-ODjWjVfA_^Jj!r=jJZD31*t72JE^ zv{27LcEe1hV;hb_I=FNIzVSG2*cL+i6GLT6-!Je>^qEktTYjzn)6ikTF(sk2g~4~r zGSij?rw-3cdnoX2S>Lpt!LJ+Y)0QJfh4N(JfYOm^PX>BcjY558)fl8NlYt&qdlr>wU=9$oFtr@K~qqSzdX@78+q20rKXnCsAOjVkx zN;6$+rfbb~t(mPgv$bZn)*KcbiuNx4=H-FQgKw8y6uvF^QJ(>F zPf*I&g&ztoXm~8#GdOMNOX0aHXRgYbt8$vPrdey6wdTd(ocPJ=oM8Z(%}1n_s!$6vMmp!t@<3FU9s9) zh3_b?wZAP?RA=K|4n=*Zf&5j?{jOJSkNZ~?720rF4a=tKV96aQZH*&SysxsYrjS^mA^R~3?HiAp>d zGR;D!X;(?A?e=vmUM}8YKe^`3;wp9BibW+=s@hOfvcrA~n3arK$(Z%(UsrdPG{9e> z?&Z?%<_+0^S+q)U#oOnL!-z9h^vVWwGX>+?s7ma1JVt}1xkc1_((30d7Al)S3! z2>f%&O)TMZ`>glPlC<4XwWKttp7k#){UqaesC}r*4)x9ziimPvQRWsG+pt2LLF!6H%Jw{Ywhj!iM26!S^R5~`(Z)`EW4dzWLWT7eVp!%RcA zs0?^2)nTST%=81C<6h>umw5(NPt{$Hp!(A4yByc3KVCCfc8xj}n1cUjfv=V=wO!rt zv$Cb?g@Ip`J;3^NT)nG)efe>P&d84|Nq?YxsqLPXca<+y|6|>s0={U~m&=kuz!`2o*U$Q>&UuHA%My!@Q!Hm=ugT(7kH56g-w9=9hisHjMB9S?II4|5%F z!dxQ991!yG2m_gijQ__+NT_|v$S zSoo@qbU1A%$=u5=ewzEvX@z>qX@$nM`SEJgLU3Kk@Z)bcb@Q>DYGCs)oAmc*}htvy| zGj$=g2IWaJCe5)&89s{G|5JCAV^1*V1Y=Gx=5fY6&h)1kK80AX{}jibW6U{VuJoT{ zjIdFA*=$sPo9#j+<+s@=UoYcp7+(YYpZaSU-^Tb(#&-h$q`#B#A;yG&`ISG!n4^q2 z3QSetC}U1A<^(W3ffI~5#h6pTj0H|H<{V?r0rSU!bBwXsxoq}z%IQE2!=3Dh*gwkt z3HDF1e~x`y0i~*8zmxqC`$yS7!TwCalo(w;Q}Ag}o?^^7_Jw0ge0I5T5Z>k>K3-t{ zcDa`^HH_(Ge+c+@mk%*M#F(S(PXq7sPBZ=lV`hNai#ZPG#h7#K3+I%$(<_{umy^rP zejD(QdfOP^$(RuPN7=F222fRMnu!em=OC%*`G%2-ixL=_5@>2u|Es^A73=f_;ZZ06>?qJ z?___da7z66qM<_K9AeB-_NRd_t(j*03C7F-v!!N+F{c=Fj(t%yC8lab5tqM+`Lo{! z{OOuD#&qfe7=MZ}v%vh>#j}hNrBmXCi$y8%_m+N5 zcviOo(+8h0Lx4ZAdPu@O2YrG5(Ens@~r-6^JnP&Vf zV`j=Ic9wln&NXGfjr}3^C)uAapAuhPGhI&nXBi_rL_g%267Q`U@(_L!@a1bKCA@e_ zd~)sNV#3b=esS##!(z#lsJ}!kA^Z^FPh2v@@GRgTUNXz@%12*{=&Zm2X7VmlkCs3-&ReSY4*i3f`{0jUN$BEZQb-TN-LH#p8Xm2ytG~kb~pJsR#@Z;-e85S2!iTBrwi-^Vx_#-|q!)<_X_O&rQ1o%6? zA%%H}H(0C)uB7e}?^8_S<|!In6#DwV>klrWR*&$8cE$MozAKhv{6 z!@f7b^z6^F-&W7`?287bXMcu$ZzI#QKg)hw6VtOVnwg&c8TP$6{<*U{ERxtedIevF z=u|FI@4)=*Vf9hYI_t<7^e`ot=TZ!FcUt(WvpR|A8{x$o1_Ns!l1@#3x3bcaT z3yv3jrQp$m?-%@};LU>f3JM)-9UB}w9M?M{j&aAQ9A9#L#c|T{w~pr=KXv@l@t&j5 zS?Rpcx!UP-wmP>tuXT<%6V8u2|G@bt&OdiPE(^}k&I+x4>R*RJ2XJcSn*1`4kz{8Zte6`m?ADEdgz_ln%bZN*!PuPOOb$(fS3 zOIDV4mToV-u5`3CS$b>fROx3+UnqU0^aA(A?!E4N-QRKB7A#oMzF_NuTNnIbL2=o} zvXQd8%l@Y9-^+T+cb0#%{B(JV=UUG(&q>dto?m*FRE$+TRDrKBE!?v3(87Bb&MbUs zp{vqY`O(V1to(818Qa|sXThf5H%6xfdfE5wbf;y8aX9d==)ky91!0J91u?et`}zj*NYzkZV-P5xIvr++=y=ktcL#+ zz)j+(fSbfD;AZg>;AXs`z81T}{{r|j@dn_Jh_?WL1Yb-Yl*J zyjg4k+$;J3_lli>uM*b+zDn!`ycPGiSHm9xyiMEyc$Dq1sl%x7*fY58VZLpC|$x5pKW{Q3m)1u@LYLViDjQ#RY(G z6jgwu!V5SmE&{w?Tnu=>SOYjF)&q`-TEKA;02~($fX74&;4yI-;G4uIz&D9DzzNX> zIDzj_tVN%>5^z#%0h|(jfKy^8;Bm1V@VK}d@By(G@B#5rzz4-J;DaIz_>kBK_>i~( z@Pvo~o)BYzZx$)QH;V&+KPGMl{4sGD@L@3t_^>zv*axlrIC}NJibcvr%7`+id_wt> z@>Q(5f2sUhDN!rbT6IJ{rk+xtR-aSfQ~kDmwga}?Y@fG%#rBW3-`Fm*PuTCZpR)hG zeOJL}3(ge$tYE3*Qb&j5V~#f*mpfl|E^>X+^=a3aTo1aw<$A(ZT)3pLrSM?UokcGf zy;F35@n04Hp!n%xXUXc4mXhrykCi@A+Ux%31#d0be0(-S0Imz z;A-GjLc*&s?pzGF8g32TTDVK#*1@fZ^TE|ZmY1S+>frov0l0d&2DnDJCb(v}7K|FL zaF@Y-1a1S|Mz~FImt&M@gTviF*u-Md3D*VJ4c7yA1>9!1Ubrjau7cYFw-s(1+;+G= zxE*ji;rihQ;C8|7hT8*oHQY6D*TP)~w-@euxR1gO!VSR%G1?Bpg&^%P#wHD;?Fif` zB(V>Yh(HoIKoU1X3QO)cyc>u`RIZ?=gE*1cl=SqePGm+JRS7wF*ydbnJttI(gu zebj0_yh4B0=+9O96Sji$S*!Ddwc>uTPJF^a`K=TGLR}6ulwlvjDu0> ze|G5nI&^+rdbmpu_vqmsJ-k^DZ`Q**#B;d)WJg;*ffIQ<+VZ(74`vy=a4xz>oI`7r zDjxA!#UTpR5{zRW;7*8ZZ9Bz9_MM{9{)o8V{sggkxD{~q&b7*BJO|*0;G%Gc;BIpkD4&757x35Mo&fv|+&?<~ z%CF$w2d>D~s$ArHS=72Zm92PQ4|mX2qa1a)#NPmZ7Vbs3*Wum)zMycw;w`LE))yv~ z_QG406xWhCXdWwIhddUW2PCuTWdc zUlv=+5f66+?lW+I0o-@+d>QTyxc5PKk>^ge1^ehNo(gpg@C4uq&zIF_JbmIPcq$b; zMQz2c%2gHLR*%Dd5%3J$&*6Rz7g&foF5IpL@%$ePcZ$#A`PX=U3(vpD^JjSeJD#@6 z?dtN%onj5#<(22uod_R>`(ov<)yFIQ#1AWfro2=+r6`NGtIHPMsx-rGg$uz=!2JQ- zm*Ktz_YB<2aPPrYET+CFwnjpUcrrecs@)w)jt8Utsqt_mUfaJr|6BP zv_yQYwgrS6v_vAF=uK(+H#H6p`hnP#l+W#BTC6`F9ZyB#vG(LdEVL;+I2ZuIPAwMP zuNhH2@n~2}m;?=VqC0k=YoNP@ShW(XK|tHIg9F;3R8J(TZ5lR^6kX5J?coEFq{*`T zfEG(7iB8569g|(5rFQr4))Gk+iJ}>~DKt3P6-kaogA<+6U^1B(8Sqmna!DKVV*LT8 zrNS|^D;Auuc#<-w01ak(2KrO+gx1%;ClU+C4^pY~CNk6b>nV5Cw3`}cAeg){DTPa7 zfNF<56fs*znjizZo5R62F!@9^h(%{R|mGtf5a91QmtsG2DaN{r~2|d72$9Naw88-t@-`&h(`sSSk?V+J#sZy)K`ZW`BO zA+7r+Xf>CSdG*9Y<4Kld*eXa_j9lp(jn}Bl(I|P(cr>~Vic1-D9BXHjPPHePh|%|} zDb~+O763z?Q7ve81tJJYf}EVqRQ_gS+8K>!RGQf`dQR&}ETqi<8i?h+eLOWbo}y%V zQ<;eZEtJQpBKwW6cUYogBD7estE>rf{|2DJYmRtOFYQh zfSBG`G8K$Q`?7Qa_+1cr{un*QmS75MG$&n0FcsP-t%R;vVAdT=jwehTLXrcrGogWn zQ6wE{wQM@7KX^cEH#?4w%xCEIDA+TDsWgB(KBLST6(#{B$?|m{iX>CX-k2^sJ;~O{ zXaZ%tG8xZ_KpxqY-G{W$cuMPyMN<8tL}ZNB1Kc-_aa}{>i3AKM+l?*S0WHcF-JfNA zO*`!eo-I9|`K+%=SPz2S_QpWa;1>gaF}OQ59K9kq<{u<>WHAZICj^ejRk3EGPU>S! zfQu_OM3PtRoBp?iVJJA^wb!qwy=l&g||vXdbTE4#iou2qWMzv(F`?=9!1!Ztd_Kc(+)MDfNH%GKYFcI1p z(F`ni@t$Z9Mk-&O`hp1znt5Yn#f-eNLYrDxYIA!OM43@QQyYNY6z3GAbQGf50v_Y^ z=oycNhWw(p8|6poG4fDodjb;#Eu4kyggNMsq$r+-I6T^U2qOB4!mV0rUp&m3p(SME{bRv|gt-ewQb=mzC{6o87%H7Y78Jt~rR~>Jcx(

kYu)U_b#gTyfZ3@kf~)l2Uv49>Jxf6)9nqlF-Dz?G+5lQ1cp4VFc&yNO2*QXCYP@{n;Le2&Ou>g5lnKzAICOys~TqLC-`T%A|hgzDl zx<^I;Ac9I8)+DT3mn2pNxpf6)o>iS$O+=Fl<8j_rXyW`nK&l|p>tPI7z>pTQ3Q;Vp zv!&+1VI;^#=qyMuh=ve&BmsyDn+4F9m}WI(w7F-IgE!WkCfeUjifUPGnlS;y$YPp# znPV%WjCSve@E8gVNsqZ%7NI6Le+y6UvRRq2^@t7gvP({W5j-e2FHm;`AeTIS3=!Fj zEt4N&s5E%wEK^O2Kr2Y#A|zcrGua_9Kt+*Oq}N;;m`Oo^2H;L7m(13ft?}?Uc0U9t zFqh?Dpz4Pu6@%mfNe{VOCHg0l(1_aJ?Sz-VWo1koJAz3KQ_$`GIAq8SnV5M7!@*S0 zg3?QA#_Tsp_9wA55{(R_mLZXf?APMsseUbFWSW`UCTp+IVp<}CsDlw$+=2MkU?euM z53ATPS4_+=4KBF8mdcE|Vs2|;bC6e@dU0vtIS|*o>P}jE(GHBvZNAPY(En2?882%k zDFkfn@JYn^ESa^e#vE0qI{$o%((x2X5+kHn!a7vYSYyU#_dQCVJCusK7F*;~RA`EI zgF!E@b(6 zooI;-dG}3dQ-^k~H-$lvUl2@!{az-?)59p9wq`j#OF1cq_GCF`z71B6^jY^<8Do`m z_D(2AXAL`?54JP)e1`MwEpnXRHoEaJ_To5dzP&wby1d(aOfYw?B@2_?2dSJApFQ+s z@YY_I!Djcg3_f3P%f!ycvPMQCfO>GmfJblcN-`|AjYH*dCWXnBEK6qemUS}+b1|6N^Amga zX)$A>85UHaU9nUos#|0llcQP+9C;UKS1cJE(YD7j=tvSxF4w&oBug}z33u+(LO0Sj zDg+m~8O#hRasVxI1vXhQ^$c&iaS$R5-H4Nco`@C&4ovn3V_}|J&xy>;*XJhGO;Y}Z zo%_S6RsJ~Ryel_1s+3_l*-D6DI4m2yI~EoRZGZfLmIMf#BbF2+|fW;CMX69^B`=}WzR&!0G~pR1Vb7IIc&J%IiN2C$)aC@p9jUk zrd+lY!T_O;#wiihNFEmfp9b^L&3FrP+bnI*AZ zs-vbiVCTqa=RWKgXku`D3==?et5=>!bjIU1Ml{S7!csP(LmQ36bU2T(w{DgS+V_?F zrnI?}9E&Gu4^>#^fCteZ7`JmAy<)#MFfpcWhCYG{6{QgELFpJS5%nNFoYZHBw8ud6 z2V=fQFyls{Qly03KN%nl6mZxK=xu6JS;Lm$lr~qG29s*uO*a{2`UvM@38DhJjJJLGLJTbwD7&QX5-1e9z=qq+>^k9oD>bqRXO7{GPQJsTG=O%P&Y%eLL#SL5I`cON6C4C*g76fK}C|O zE@V9lk&tTWjYOLQ#`1xxW8K6RT{u`B9n}&Y7(Tf(vUD->`UeMDw&rA77)KhSJ(<+@ z4@W1Abzpl6KaD($gF9-tG4#CzFY-`|a3+dIoJ?q&Hl9iZG3ZHymfQk^Gake-y2(lw zj7&i;&QjP+lu@RENXnXGjsj&;Kr9$Wahz+>piHdPNm7su&X84qN*km3#`x&IOyoc? zF{-6{(B-s)@x+ap2sA|JI9?UlpFtUnHb=r?Oa{z4cOOb=F;dVB%BUBaFMXh#8`&G9 zp3QsV!RWkHSzB6jnRIDMK6A~=o&?Z~GNx!Ul*lCNBin*$iUlRxo(r*4iv|xdl*}YC zY67hckKzwMJ))K;Q;)sOeseM{Pf(PhmLTo`N<3p3}Bd~3qlw}9|uNwyN*FXL(^CbT9Y65bx+^Lue1$#WPBhPTUQ zWR%{i5U5lw)v7iejh?qwLhnvoCmLh~vt>wcdxoXDTLvUL`@$HA9V5{ZkMnZ?Q@wt4 zX$&$n{l;8{hG|T_W0E^9dSba!Vr3`3<{lUm>m7*aDF&=B8jYadtLCd7`a9VR6v61- za%D=#tF`Upu;nsRpUyHNwn7pU=F&`bU~*s$vzGTqXmOW4nrB&M{UrerLe9lb0B!k5QfP`iWAQMA<$jr(}oWW43Eklp2vp%QI-noQ%$l9pM*{_td zDr3PYvNuemx|xxrO=ci_vxK(0Gf@_J!>0Pd!OVLudInfonACDZAnT1)^v?azA{nCx zq)e&b1``qNO$!VJVk>4;T7m|0(MekhV}_&{Wlo+sG&i4l6j{$#x1JUqww6)!M>TD1 z9uE2|w`}m@Rw7wQqkC+L#BLG;@y*&HEFBZ_#2|&`Dc-|9MAOg%5xgNI?eCnIS}@m4 z4Gwb45)G!?#)^hV6tp@m7IKglvCEZ;rTnsJwfgXij!1bMlUF@xX=FBtQZ@St^L zK&@!$ln}f7H)~Ps6w!JHhbwwucfTP>6QSp;hm9Qvsh&t~)m8-Y2CSAaBSWmjKxYc7 zkKstj2R!CPF?W$qCCj|4L{?mXZ3!bIza6tB9-`^Fxqm>gxlS`)pfb;sYAx?%Z8-1i z52rgI!$5;m=weO?kKir!aB@D4~1yqhf}$D46reL z$X%9NT`0Qf=R{M3)4I-#&$PFxm}Z>8+F0A^YfMZ}X%>^DrZy6p2k1Fdza$Ud{rlnv zw_;)&97QTvUcAC8cczje!i(`P4R#!>lMvn^)b|6kP~2ulBNGj>rfDqhGbNK4#F9MP zB`NM|70Gk%x@~{cxhH72ALQqRAx0yL@+U$gvDzZ98B$tm~uAP2DSX+ zf-v4F;KZt`3eLRK0pvH7#fYn#-n@M;8(`joMFVsPE<1tuL^VK=p zf5Qq8Q&_3}!?Z}Fad*3fc&AE-;}S(e$BI*zJI+F=6Xm?@jR83KHE;7}JiRVbqi8eM z;G`=VDnyf5^hz4WP&*6_w3{Mm9b&4RY)r#)S+vEp{V=b!7=Mt^905dpY_J!z?no#C z5#T9njW@7^*fPUuZ6cZ4o-l$`Q81twx%X%UekT*J>C{(fDIG#pbSNRYq9a8T@fa;6 zSo(Yrq#3G7i}~#%W{3^9B}}EGMSw|wjL0(c3NfEt^mi?+^7(%m8}-wjj2Qmv&0AeTo5f`@Z+!cJMzv^0YV z$(g*+P1o*-b}-+o1eh#Zu7X(fnD%QkW!X!1C=Y-QJl<8i+w@gnN^gZAp?o=rMH%EBsB+ z9qduuz21-e+cDh3_Tqka0{6K!_?>|FImq0u=U2qFrOx`{>>m(B0ge<5iA^5*f0s2v}ab!q*s95t9 zqw)&G!+66_a7Bn-Y_t~E3m!p~Ci@RN*}oZmPDhms8Xo3sE{HH0<#S%NwmTi zhVuzU5yc%y89_>5D!Y-EL`WRAa4GRiMN3mUw>T<`u7mhF z#Yz zWKcQ6IY{L)OTQq7JPu|gwKTVcgZKnMowx;Gb+`;t>Hzg9IL3r1rf@ePl)jYUelF=4 z>O!qbd=n^d6rV2`0DK6sUPystkJ4-8a?|y6zpmk6zWo#_j6|(Mrp{lL9y{W&@!I7gj8*u&Vmb+sl65gBtgqA zZgk4SP$f!F4Sf)0P2fuxy8&Z04M7l}jrgudExzj^Dm$T?`#7&LeE(w)sD{y*YVm!G z2<5Q!642$#LpTrNYZ>@}OMPyqFie^u*&xzWH>c7`MH1V$p%i4isB9#6th=~eVbGBk zCYzjX47{-3gppm8jM^d4Qr*#{t8%Hypcu4f_iv_LsTIlQQ<+FjsYP;AXXhnW=f+#P zld(w1QuOB1W%HqyH)zjqxW#g5`uo5+jxUu+?W6CJ;Ojt;nz)oqi|okM&eZ;fvD8qb z>~xS%MK;DORtshMYSdf~K1NHCgvY@-j5b#=1oxaAJ>)7{vN?VASFdfn^tv|$OoC$f zDvGNBUU?;f?gFo>xZMtbp2^S1$GxCaot2)5;z@6`d+|juAgX}qC4|c>D5^pfc!g*3 z2})9)-sQxj8XR2Cf@+(~rGhUIHoH?*Z3Rx7ioa!wOHd}|>Erk^nF zgNjYb5a;sZdsD>5=2W;I$2cbss5G<*1R}+vsGQ|7riHMiaP+uxgP2+jd4QOjOu|q( zwF=xx($rqi5*IW{2v7PU#JSwX&=o_Jg=oiWG$8&v3se`L)TR?M8A?kn_f=VmTkxm` z5hXRnX9A=>B)Ge{I%Qz8Rpm&kt1iF0xH6?AKQn59Nk|-)i6v!J)jXR3vFQ!OuZsms)ICj>lsJ2F8I{6y{e3FVWL73IzXU4IQVE^?Z}BJxin zIrTe8)QO&UH_3JK%TR{NXAr!zm^n$92|maEJ&>~}|IfdeaQMeNVCuR;OI{p1>d7YAz)=3c$ zdk&Rk7N_KH9<+pW+)Vm-dj+oz$dGvf>Lz@T|W79Hw1|X6x2=j((Qr)Ro!kk z6xnSNjTvq)z+!MB~LsZs{6RHzxYmv?gfX~vvp_(=y;;#tK_U6cSc9+5xEk!Kh_ z!|>A#Kh5x2C(~BD8F$w1RI1$;=~cT?DMXSMJjW!@G5i9^pD7VGPx^IF`c3p5Db?#SXtI{2?_%=1*aF-{ zhCnS(-^7XU=9s$~{v5-flS3qrS3ES!p%LSj9Nj2_AUVE3lVwm^XlX!+ggM^B9PeRx zn&D}N?_>BrhVN(ieuf`p_(8Hrx696&epvP;&moR_n8{8ue3IdB8d}fBCH+m0)8Q(g ze4u>tq4LSEqF;L^A8~mVz`#IIh$^a6RqFR;nDP|CfIMLI{#RMgCm+dSahh1@gr_T< zPM6!l|4B>alev*+ERkoZmD2C9{~q~AXgc7Te5Z;6lZ;9$Iaxn#Vem93DsXvip2=6y z(>Pd&URvc|=3L;awwCHFEcVxF-s1vb7XBD ze4VE#K)M(6ph^=3o+4mSk<&d)R4BRxMjDd<8F!)6m0gVIpuEq+(pk#z9F2s>fukXU zVk?qWs7zccrj1X3lHn&AKEv=ChM#8mX@<`-e3s$o7-mJZR64CU zYq~U(aoVLfdb-q%HAM(QeYAXm8NP5qmTb~xQcbe>m1U(ae;1P(n>Gk)U;eP zdU<+@)J)aTOw7%etbhuTrPHlqy2{8@Cby)n%F4RR!la62{fPRQkP~;~Sjg8y98w z&ajbVp4`GF7s@RYBA#Kkb6HZ2S{f=!qplosJ?TcunMNB7%y_DvGR0WW>w`60<81k+ zEZpSWv{y1n_p11UGA6$^7uHw~EUQXLZ^{6adD2^9++8jVGOogE>@}4Ya@`M+1xL^# z>cdt=Im~($@ub@w(5u2S_gwl(EBz#?pBve2M0TpH(plh=dcY&(kSBc`N>A(0y|lVJ z&XVv9(M0)q9WK)cWitWBY??shfnBp9-q=yS&~1q}TFH~X!)PcfPgVonVTP!I?#Ssz z$1L(Zb|Eq5v7cJ@E|cXPo_A&OybHReR4vUU-snl+t@i*H4_B79_;ltQ&E#n!wHTqh zX{5HA>d#r_`#C2ypsTD3>oc{gDtoL>-;>?d?jb=B=_elEF}p0 zw23`y;c(W(K4-x`XJTKlU|%q?vli^EiG9g}eaXbWV!^&*VqddhUo)|9Sg>!nzH#&3 z-Afy0Kk0h-^1)lnpDnt~<^OKW?uVMTHM$Ba=|EfmhP@p>B948?BGsYN4y@dbvOBP1 zQXOua!&9d^3K2~E2sh0ny!nQxEwmF%%T9{=CV7vQ5JulabIToFTJ)4!(A93$;UYu% zZA$StK@Wft?->#1-^hE1y!YUxX=|0@umuFl*9lcXULhBS*I_mXMPl!syf>Mi)a8$0z z`^kF{p{wpuP=#o@}yDJ$rmX&3ol(l-a_)$kXJ|E)#MFfY2>ahaA7#J zxmK2`v=NRKwZ3XLR@CwUMQ*(7=O=UkQt6RC?Z;Q+@C9k*X+-9!pI202sjkN|f5?I; zCG5hqfcH>~=xByEQ_Iv6{DvXtK)fBa8@fys(L)xG_eZg~*HN^yuYULlQytyCNaqBs6D$46JLQ%r zo+yZF6hXz${%~rT^U_Qbzgr)1^lZxTNp#ACgN@a0mo*+^5?2Hh8yf%H4VDPe@g9Eb ziKhJc!_<|gXQkM1A!gJLGzY@g#!b8gPv2xDMQJt`dC@)~gJ6ri1w0x;^d^XdJ4{nN zlbEEjW_gBaI|&7JW1E1VZX9IDJb;zNPa%#f;Z}L?smwEmV-wD$ii)au!o}FtN~b+x zPx|&MPLob^22>E^Fu`-ENUs8hRwI_qMloW)X%In3IuY@q0`Vi=ON#|q7>bmJWeuje z_@$`H7j0{xA!|q+@Iixcm7Pv#T?!pf;%}LP6WalG(Vj$bY+F2L-ZSFcOi2ZFPNElE z6;V~Yt$V<{nYUiQ8@BO4Lv3?y08HEq%}D+8>-6gELQ3T|W4ug#fg&o+_xilJMvg01 z@`{)!Qbd8gb}8^1#kJpiz?+w_*4rM9dilC*(o3%>CJty}yn{84Ut(#Gc_X+ij}1R)mKUzMG?Q+?+Jm|c>JgMj%NaIud zW+r&e1Ls=n@{?QM(lisa&dVQfLDSot^d_}Qjc-<;hd;jo&-Vi|2~g|xiddb$K=PIO z4Dop@Yur%CkT>I<7HF)6xBeQVyehOV|L2oMhaxu4pGLlSsxz{FiNMS^fVZU-v1xu5 z^8HA9YkeT+OV%b2h~*=SXqunLJm37{&##IPsDknFp7VVrlJvjclD+X(t|2w46Vo!OQpxh*@iB=Lck)eJRpRh#%@{RYb#ivd#W1m6;G<#1)$q(R!Ygc|Hk~ zNe+$teUkqU6`u3?I%;Bk9#S+bB51j@&~jlCoocH5<`g3X6BSA}%{m(tOu%%=Gvg zzi3y)hV!I1?%f#ml^16+93ZY717c9-5p~wplnf6@?)T;a?cAV<=JV8K&MnqV0idBD zAjW+6V$JmUm73h)Fpm&)Gn`2U;pYsZze_6U_6Jz4c`j<{U%M7fitwLDOu3&_+=AF`f)G<8<*G)hCfbZzOQ&G@%6l68VqA*O!6o_e$;7G_yf%zmp;#| zi#X_CUHzbOiCJXLDJZf2Vb7mCZ0T-kX!bQ=uL(T; z^}g0FaQ8Pib#&Bq1$r7gb;_2G`p$-q`W9bPeV`kZO~@Tp^EDu+&L+RVrKJHAcjDO` z(&|FNpyu-rx3(hpu;15GH$392Z)j<44zxBm4u?i0WoLVPcY9-Ni_c%*TJLLU>2CJ5 zHu;-<{?5ksra*UnOM6F`q-^hLs&8%Zcl(+;+FN`LJ>8wY)|NoCucf=8%kTHs_XKG1 zLb(ST+WqbRmS$gbV>ikfXl?SfqwK!M)}FfVy5_oOzaMQul#Lzjoy~QvjlQ0yX4Ip( zxy9Gg+|uIf_BZzQ^fWj3v^I4}N`FhBp|PvG-PhdS(L_8Od>tL_0biZJsiC{QuB)Z1 z9&>);S%*C8x_i2jXAgv0=lAmS+zCd#`D4V;Q zeH|_SE?-Y~dsk0qv%j;uqfy_UvwktC_PpP$q1n7D23)Q_+Wez$XyI=_UC!UppdFvS z$e0$zH)=X2poDzQmG)H?FDFwAu}O(9OpZv!JM!3T5wPv${=zk;`zGxbw} z%Tu-t!S5&lA`>F`M$t1|QA~J%z&dI%o72E4?s;%3LuRZMLt?IooE!EH* zFr#b7!o%YBTQY_CBEeqDdhXwG3!M=7K3$?K8l^A%3btgL#vhi`)BSc8*p$s>@}GfG znDG)JCbPLoJB!XT2TydH;jW&E4ELFZ>?B z^!IK1zrK%yFI*DBLDyCE+t)bc!r$fW%X4pPSL+{)3sUSBbR*8V_}YuRXLJXR{^)nh z(SHz27o3xPdk~)nKrDAG#64_(n2y^}rp)c_xtxwMP3Br`1MVO~2IAjwom->y@Vo>AEi`B8|pk@S%CBO@4yWF^4u+(iu7XaPQZ+$sEm*x)5#LUUUzY^ld-i<|SR8pI>&n dp<4g__g^7_F$FCn#L12S70mye=l|~#_`jwGSlj>r literal 0 HcmV?d00001 diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceProjectTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceProjectTests.cs index 97b1cfc87a0..e513ee87d6b 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceProjectTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceProjectTests.cs @@ -53,8 +53,8 @@ public async Task GetAssetsFilePathAsync_WithValidMSBuildProjectExtensionsPath_S Directory.CreateDirectory(testMSBuildProjectExtensionsPath); var projectAdapter = Mock.Of(); Mock.Get(projectAdapter) - .SetupGet(x => x.MSBuildProjectExtensionsPath) - .Returns(testMSBuildProjectExtensionsPath); + .Setup(x => x.GetMSBuildProjectExtensionsPathAsync()) + .Returns(Task.FromResult(testMSBuildProjectExtensionsPath)); var testProject = new LegacyPackageReferenceProject( projectAdapter, @@ -72,7 +72,7 @@ public async Task GetAssetsFilePathAsync_WithValidMSBuildProjectExtensionsPath_S // Verify Mock.Get(projectAdapter) - .VerifyGet(x => x.MSBuildProjectExtensionsPath, Times.AtLeastOnce); + .Verify(x => x.GetMSBuildProjectExtensionsPathAsync(), Times.AtLeastOnce); } } @@ -107,8 +107,8 @@ public async Task GetCacheFilePathAsync_WithValidMSBuildProjectExtensionsPath_Su Directory.CreateDirectory(testMSBuildProjectExtensionsPath); var projectAdapter = Mock.Of(); Mock.Get(projectAdapter) - .SetupGet(x => x.MSBuildProjectExtensionsPath) - .Returns(testMSBuildProjectExtensionsPath); + .Setup(x => x.GetMSBuildProjectExtensionsPathAsync()) + .Returns(Task.FromResult(testMSBuildProjectExtensionsPath)); Mock.Get(projectAdapter) .SetupGet(x => x.FullProjectPath) @@ -130,7 +130,7 @@ public async Task GetCacheFilePathAsync_WithValidMSBuildProjectExtensionsPath_Su // Verify Mock.Get(projectAdapter) - .VerifyGet(x => x.MSBuildProjectExtensionsPath, Times.AtLeastOnce); + .Verify(x => x.GetMSBuildProjectExtensionsPathAsync(), Times.AtLeastOnce); } } @@ -165,8 +165,8 @@ public async Task GetCacheFilePathAsync_SwitchesToMainThread_Succeeds() Directory.CreateDirectory(testMSBuildProjectExtensionsPath); var projectAdapter = Mock.Of(); Mock.Get(projectAdapter) - .SetupGet(x => x.MSBuildProjectExtensionsPath) - .Returns(testMSBuildProjectExtensionsPath); + .Setup(x => x.GetMSBuildProjectExtensionsPathAsync()) + .Returns(Task.FromResult(testMSBuildProjectExtensionsPath)); Mock.Get(projectAdapter) .SetupGet(x => x.FullProjectPath) @@ -186,7 +186,7 @@ public async Task GetCacheFilePathAsync_SwitchesToMainThread_Succeeds() // Verify Mock.Get(projectAdapter) - .VerifyGet(x => x.MSBuildProjectExtensionsPath, Times.AtLeastOnce); + .Verify(x => x.GetMSBuildProjectExtensionsPathAsync(), Times.AtLeastOnce); } } @@ -1203,8 +1203,8 @@ private static IVsProjectAdapter CreateProjectAdapter(string fullPath) var testMSBuildProjectExtensionsPath = Path.Combine(fullPath, "obj"); Directory.CreateDirectory(testMSBuildProjectExtensionsPath); projectAdapter - .Setup(x => x.MSBuildProjectExtensionsPath) - .Returns(testMSBuildProjectExtensionsPath); + .Setup(x => x.GetMSBuildProjectExtensionsPathAsync()) + .Returns(Task.FromResult(testMSBuildProjectExtensionsPath)); return projectAdapter.Object; } diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceRestoreUtilityTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceRestoreUtilityTests.cs index 656a4bdfa95..c996583fb0d 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceRestoreUtilityTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/LegacyPackageReferenceRestoreUtilityTests.cs @@ -361,8 +361,9 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_ReadLoc Assert.True(File.Exists(projectLockFilePath)); // delete existing restore output files - File.Delete(Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json")); - File.Delete(Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); + string msBuildProjectExtensionsPath = await vsProjectAdapter.GetMSBuildProjectExtensionsPathAsync(); + File.Delete(Path.Combine(msBuildProjectExtensionsPath, "project.assets.json")); + File.Delete(Path.Combine(msBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); // add a new package var newPackageContext = new SimpleTestPackageContext("packageA", "1.0.1"); @@ -390,7 +391,7 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_ReadLoc Assert.False(restoreSummary.NoOpRestore); } - var lockFilePath = Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json"); + var lockFilePath = Path.Combine(msBuildProjectExtensionsPath, "project.assets.json"); Assert.True(File.Exists(lockFilePath)); var lockFile = new LockFileFormat().Read(lockFilePath); @@ -490,9 +491,11 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_UpdateL Assert.False(restoreSummary.NoOpRestore); } + string msBuildProjectExtensionsPath = await vsProjectAdapter.GetMSBuildProjectExtensionsPathAsync(); + // Initial asserts Assert.True(File.Exists(projectLockFilePath)); - var assetsFilePath = Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json"); + var assetsFilePath = Path.Combine(msBuildProjectExtensionsPath, "project.assets.json"); Assert.True(File.Exists(assetsFilePath)); // Assert that there is no warning logged into assets file @@ -500,7 +503,7 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_UpdateL Assert.False(assetsFile.LogMessages.Any()); // delete existing restore output files - File.Delete(Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json")); + File.Delete(Path.Combine(msBuildProjectExtensionsPath, "project.assets.json")); // install a new package projectServices.SetupInstalledPackages( @@ -867,8 +870,9 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_Package Assert.True(File.Exists(projectLockFilePath)); // delete existing restore output files - File.Delete(Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json")); - File.Delete(Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); + string msBuildProjectExtensionsPath = await vsProjectAdapter.GetMSBuildProjectExtensionsPathAsync(); + File.Delete(Path.Combine(msBuildProjectExtensionsPath, "project.assets.json")); + File.Delete(Path.Combine(msBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); // clean packages folder Directory.Delete(testSolutionManager.GlobalPackagesFolder, true); @@ -1001,7 +1005,7 @@ public async Task LegacyPackageReference_Restore_PackageShaValidationFailed_Logs Assert.True(File.Exists(projectLockFilePath)); // delete existing restore output files - File.Delete(Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json")); + File.Delete(Path.Combine(await vsProjectAdapter.GetMSBuildProjectExtensionsPathAsync(), "project.assets.json")); // clean packages folder Directory.Delete(testSolutionManager.GlobalPackagesFolder, true); @@ -1153,7 +1157,7 @@ public async Task TestPacMan_InstallPackageAsync_LegacyPackageRefProjects_Dualit sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); // Assert - var lockFilePath = Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, "project.assets.json"); + var lockFilePath = Path.Combine(await vsProjectAdapterA.GetMSBuildProjectExtensionsPathAsync(), "project.assets.json"); Assert.True(File.Exists(lockFilePath)); } @@ -1225,7 +1229,7 @@ public async Task TestPacMan_InstallPackageAsync_LegacyPackageRefProjects_develo sourceRepositoryProvider.GetRepositories(), sourceRepositoryProvider.GetRepositories(), CancellationToken.None); // Assert - var assetsFilePath = Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, "project.assets.json"); + var assetsFilePath = Path.Combine(await vsProjectAdapterA.GetMSBuildProjectExtensionsPathAsync(), "project.assets.json"); Assert.True(File.Exists(assetsFilePath)); var assetsFile = new LockFileFormat().Read(assetsFilePath); @@ -1346,7 +1350,7 @@ await nuGetPackageManager.ExecuteNuGetProjectActionsAsync( CancellationToken.None); // Assert - var assetsFilePath = Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, "project.assets.json"); + var assetsFilePath = Path.Combine(await vsProjectAdapterA.GetMSBuildProjectExtensionsPathAsync(), "project.assets.json"); Assert.True(File.Exists(assetsFilePath)); var assetsFile = new LockFileFormat().Read(assetsFilePath); @@ -1827,7 +1831,9 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_Package Assert.True(File.Exists(projectLockFilePath)); - var lockFilePath = Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, "project.assets.json"); + string msBuildProjectExtensionsPathA = await vsProjectAdapterA.GetMSBuildProjectExtensionsPathAsync(); + + var lockFilePath = Path.Combine(msBuildProjectExtensionsPathA, "project.assets.json"); Assert.True(File.Exists(lockFilePath)); var lockFile = new LockFileFormat().Read(lockFilePath); @@ -1835,8 +1841,8 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_Package Assert.Equal("1.0.0", resolvedVersion.ToNormalizedString()); // delete existing restore output files - File.Delete(Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, "project.assets.json")); - File.Delete(Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); + File.Delete(Path.Combine(msBuildProjectExtensionsPathA, "project.assets.json")); + File.Delete(Path.Combine(msBuildProjectExtensionsPathA, NoOpRestoreUtilities.NoOpCacheFileName)); //clear packageA 1.0.0 from global packages folder var packageAPath = Path.Combine(testSolutionManager.GlobalPackagesFolder, "packagea", "1.0.0"); @@ -2008,8 +2014,8 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_Package Assert.Equal(PackageDependencyType.Project, lockFile.Targets[0].Dependencies[1].Type); // Act - File.Delete(Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); - File.Delete(Path.Combine(vsProjectAdapterB.MSBuildProjectExtensionsPath, NoOpRestoreUtilities.NoOpCacheFileName)); + File.Delete(Path.Combine(await vsProjectAdapterA.GetMSBuildProjectExtensionsPathAsync(), NoOpRestoreUtilities.NoOpCacheFileName)); + File.Delete(Path.Combine(await vsProjectAdapterB.GetMSBuildProjectExtensionsPathAsync(), NoOpRestoreUtilities.NoOpCacheFileName)); restoreSummaries = await DependencyGraphRestoreUtility.RestoreAsync( testSolutionManager, @@ -2156,7 +2162,7 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_Restore_BuildTr Assert.False(restoreSummary.NoOpRestore); } - var assetsFilePath = Path.Combine(vsProjectAdapterA.MSBuildProjectExtensionsPath, "project.assets.json"); + var assetsFilePath = Path.Combine(await vsProjectAdapterA.GetMSBuildProjectExtensionsPathAsync(), "project.assets.json"); Assert.True(File.Exists(assetsFilePath)); var assetsFile = new LockFileFormat().Read(assetsFilePath); @@ -2276,7 +2282,7 @@ public async Task DependencyGraphRestoreUtility_LegacyPackageRef_CPVM_Restore() Assert.False(restoreSummary.NoOpRestore); } - var assetsFilePath = Path.Combine(vsProjectAdapter.MSBuildProjectExtensionsPath, "project.assets.json"); + var assetsFilePath = Path.Combine(await vsProjectAdapter.GetMSBuildProjectExtensionsPathAsync(), "project.assets.json"); Assert.True(File.Exists(assetsFilePath)); var assetsFile = new LockFileFormat().Read(assetsFilePath); diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs index 24378be42e3..0aa78e06ef0 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/TestVSProjectAdapter.cs @@ -54,12 +54,9 @@ public string AssetTargetFallback } } - public string MSBuildProjectExtensionsPath + public async Task GetMSBuildProjectExtensionsPathAsync() { - get - { - return Path.Combine(ProjectDirectory, "obj"); - } + return Path.Combine(await GetProjectDirectoryAsync(), "obj"); } public IProjectBuildProperties BuildProperties { get; } = Mock.Of(); @@ -72,7 +69,7 @@ public string MSBuildProjectExtensionsPath public bool IsDeferred => false; - public bool IsSupported => true; + public Task IsSupportedAsync() => Task.FromResult(true); public string NoWarn { @@ -100,13 +97,7 @@ public string ProjectId } } - public string ProjectDirectory - { - get - { - return Path.GetDirectoryName(FullProjectPath); - } - } + public Task GetProjectDirectoryAsync() => Task.FromResult(Path.GetDirectoryName(FullProjectPath)); public string ProjectName => ProjectNames.ShortName; diff --git a/test/TestExtensions/API.Test/InternalAPITestHook.cs b/test/TestExtensions/API.Test/InternalAPITestHook.cs index 251013bc27d..1c2f4b5eef7 100644 --- a/test/TestExtensions/API.Test/InternalAPITestHook.cs +++ b/test/TestExtensions/API.Test/InternalAPITestHook.cs @@ -156,10 +156,13 @@ public static bool BatchEventsApi(string id, string version) }); } - public static async Task MigrateJsonProject(string projectName) + public static IVsProjectJsonToPackageReferenceMigrateResult MigrateJsonProject(string projectName) { - var migrator = ServiceLocator.GetComponent(); - return (IVsProjectJsonToPackageReferenceMigrateResult)await migrator.MigrateProjectJsonToPackageReferenceAsync(projectName); + return ThreadHelper.JoinableTaskFactory.Run(async () => + { + var migrator = ServiceLocator.GetComponent(); + return (IVsProjectJsonToPackageReferenceMigrateResult)await migrator.MigrateProjectJsonToPackageReferenceAsync(projectName); + }); } public static bool IsFileExistsInProject(string projectUniqueName, string filePath) @@ -178,7 +181,7 @@ public static bool IsFileExistsInProject(string projectUniqueName, string filePa if (!string.IsNullOrEmpty(solutionProjectPath) && PathUtility.GetStringComparerBasedOnOS().Equals(solutionProjectPath, projectUniqueName)) { - return await EnvDTEProjectUtility.ContainsFile(project, filePath); + return await EnvDTEProjectUtility.ContainsFileAsync(project, filePath); } } From 974240454b21791a171157e471671a462429db66 Mon Sep 17 00:00:00 2001 From: Andy Zivkovic Date: Thu, 29 Oct 2020 13:06:48 -0700 Subject: [PATCH 021/129] Publish "nightly" nupkgs to dnceng public feed (#3742) --- build/templates/Build_and_UnitTest.yml | 13 ++-- scripts/cibuild/PublishArtifactsFromVsts.ps1 | 72 -------------------- 2 files changed, 7 insertions(+), 78 deletions(-) delete mode 100644 scripts/cibuild/PublishArtifactsFromVsts.ps1 diff --git a/build/templates/Build_and_UnitTest.yml b/build/templates/Build_and_UnitTest.yml index 7532a868393..3acac96e3de 100644 --- a/build/templates/Build_and_UnitTest.yml +++ b/build/templates/Build_and_UnitTest.yml @@ -413,13 +413,14 @@ steps: TargetFolder: "$(CIRoot)\\PLOC\\$(Build.SourceBranchName)\\$(Build.BuildNumber)" condition: " and(succeeded(),eq(variables['BuildRTM'], 'false'), eq(variables['IsOfficialBuild'], 'true')) " -- task: PowerShell@1 - displayName: "Publish Artifacts to MyGet" - continueOnError: "true" +- task: NuGetCommand@2 + displayName: Publish public Nuget packages to nuget-build inputs: - scriptName: "$(Build.Repository.LocalPath)\\scripts\\cibuild\\PublishArtifactsFromVsts.ps1" - arguments: "-NuGetBuildFeedUrl $(NuGetBuildFeed) -NuGetBuildSymbolsFeedUrl $(NuGetBuildSymbolsFeed) -DotnetCoreFeedUrl $(DotnetCoreBuildFeed) -DotnetCoreSymbolsFeedUrl $(DotnetCoreSymbolsFeed) -NuGetBuildFeedApiKey $(NuGetBuildApiKey) -DotnetCoreFeedApiKey $(DotnetCoreFeedApiKey)" - failOnStandardError: "true" + command: push + packagesToPush: 'artifacts\nupkgs\*.nupkg;!artifacts\nupkgs\*.symbols.nupkg' + nuGetFeedType: external + allowPackageConflicts: true + publishFeedCredentials : nuget-build-dnceng-public-feed condition: " and(succeeded(),eq(variables['PublishArtifactsToMyGet'], 'true'), eq(variables['BuildRTM'], 'false')) " - task: MSBuild@1 diff --git a/scripts/cibuild/PublishArtifactsFromVsts.ps1 b/scripts/cibuild/PublishArtifactsFromVsts.ps1 deleted file mode 100644 index 19b8b961bda..00000000000 --- a/scripts/cibuild/PublishArtifactsFromVsts.ps1 +++ /dev/null @@ -1,72 +0,0 @@ -<# -.SYNOPSIS -Sets build variables during a VSTS build dynamically. - -.DESCRIPTION -This script is used to publish all offical nupkgs (from dev and release-* branches) to -myget feeds. - -#> - -param -( - [Parameter(Mandatory=$True)] - [string]$NuGetBuildFeedUrl, - - [Parameter(Mandatory=$True)] - [string]$NuGetBuildSymbolsFeedUrl, - - [Parameter(Mandatory=$True)] - [string]$DotnetCoreFeedUrl, - - [Parameter(Mandatory=$True)] - [string]$DotnetCoreSymbolsFeedUrl, - - [Parameter(Mandatory=$True)] - [string]$NuGetBuildFeedApiKey, - - [Parameter(Mandatory=$True)] - [string]$DotnetCoreFeedApiKey -) - -function Push-ToMyGet { - [CmdletBinding(SupportsShouldProcess=$True)] - param( - [parameter(ValueFromPipeline=$True, Mandatory=$True, Position=0)] - [string[]] $NupkgFiles, - [string] $ApiKey, - [string] $BuildFeed, - [string] $SymbolSource - ) - Process { - $NupkgFiles | %{ - $Feed = Switch -Wildcard ($_) { - "*.symbols.nupkg" { $SymbolSource } - Default { $BuildFeed } - } - $opts = 'nuget', 'push', $_, '-k', $ApiKey, '-s', $Feed - if ($VerbosePreference) { - $opts += '-verbosity', 'detailed' - } - - if ($pscmdlet.ShouldProcess($_, "push to '${Feed}'")) { - Write-Output "dotnet $opts" - & dotnet $opts - if (-not $?) { - Write-Error "Failed to push a package '$_' to myget feed '${Feed}'. Exit code: ${LASTEXITCODE}" - } - } - } - } -} - -$NupkgsDir = Join-Path $env:BUILD_REPOSITORY_LOCALPATH artifacts\nupkgs - -if(Test-Path $NupkgsDir) -{ - # Push all nupkgs to the nuget-build feed on myget. - Get-Item "$NupkgsDir\*.nupkg" -Exclude "Test.*.nupkg", "*.symbols.nupkg" | Push-ToMyGet -ApiKey $NuGetBuildFeedApiKey -BuildFeed $NuGetBuildFeedUrl -SymbolSource $NuGetBuildSymbolsFeedUrl - # We push NuGet.Build.Tasks.Pack nupkg to dotnet-core feed as per the request of the CLI team. - Get-Item "$NupkgsDir\NuGet.Build.Tasks.Pack*.nupkg" -Exclude "*.symbols.nupkg" | Push-ToMyGet -ApiKey $DotnetCoreFeedApiKey -BuildFeed $DotnetCoreFeedUrl -SymbolSource $DotnetCoreSymbolsFeedUrl -} - From f6e407e853e7646d8a5905041bed06da5a835fa3 Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Thu, 29 Oct 2020 18:02:02 -0700 Subject: [PATCH 022/129] Implement Blame Collector to help detect and fix hangs in test code (#3741) --- build/build.proj | 4 ++-- build/vsts_build.yaml | 40 ++++++++++++++++++++++++++++++++-------- build/xunit.runsettings | 10 ++++++++++ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/build/build.proj b/build/build.proj index 2e995c74373..b12388909c2 100644 --- a/build/build.proj +++ b/build/build.proj @@ -385,8 +385,8 @@ @(TestAssemblyPath->WithMetadataValue("IsCore", "true")) $(CoreInputTestAssemblies.Replace(';', ' ')) - --TestAdapterPath:$(XunitXmlLoggerDirectory) --logger:"xunit;LogFileName=$(TestResultsFileName)-vsts.$(TestResultOutputFormat)" --logger:"console;verbosity=detailed" --settings:$(MSBuildThisFileDirectory)xunit.runsettings - $(DotnetExePath) vstest $(CoreInputTestAssembliesSpaced) $(VsTestLogger) + --test-adapter-path:$(XunitXmlLoggerDirectory) --logger:"xunit;LogFileName=$(TestResultsFileName)-vsts.$(TestResultOutputFormat)" --logger:"console;verbosity=detailed" --settings:$(MSBuildThisFileDirectory)xunit.runsettings + $(DotnetExePath) test $(CoreInputTestAssembliesSpaced) $(VsTestLogger) diff --git a/build/vsts_build.yaml b/build/vsts_build.yaml index 8717fb91656..c3293c681c9 100644 --- a/build/vsts_build.yaml +++ b/build/vsts_build.yaml @@ -202,7 +202,7 @@ jobs: msbuildVersion: "16.0" configuration: "$(BuildConfiguration)" msbuildArguments: "/t:CoreFuncTests /p:BuildRTM=false /p:BuildNumber=$(BuildNumber) /p:TestResultOutputFormat=xml /p:SkipDesktopAssemblies=$(SkipDesktopAssemblies) /p:SkipCoreAssemblies=$(SkipCoreAssemblies)" - condition: "eq(variables['IsOfficialBuild'], 'true')" + condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" - task: MSBuild@1 displayName: "Run Functional Tests (stop on error)" @@ -212,7 +212,7 @@ jobs: msbuildVersion: "16.0" configuration: "$(BuildConfiguration)" msbuildArguments: "/t:CoreFuncTests /p:BuildRTM=false /p:BuildNumber=$(BuildNumber) /p:TestResultOutputFormat=xml /p:SkipDesktopAssemblies=$(SkipDesktopAssemblies) /p:SkipCoreAssemblies=$(SkipCoreAssemblies)" - condition: "not(eq(variables['IsOfficialBuild'], 'true'))" + condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" - task: PublishTestResults@2 displayName: "Publish Test Results" @@ -225,6 +225,14 @@ jobs: testRunTitle: "NuGet.Client Functional Tests On Windows" condition: "succeededOrFailed()" + - task: PublishBuildArtifacts@1 + displayName: "Publish Test Hang Dump" + inputs: + PathtoPublish: "$(Build.Repository.LocalPath)/build/TestResults" + ArtifactName: "$(Agent.JobName)" + ArtifactType: "Container" + condition: "or(failed(), canceled())" + - task: PowerShell@1 displayName: "Initialize Git Commit Status on GitHub" inputs: @@ -281,7 +289,7 @@ jobs: scriptPath: "scripts/funcTests/runFuncTests.sh" disableAutoCwd: "true" cwd: "$(Build.Repository.LocalPath)" - condition: "eq(variables['IsOfficialBuild'], 'true')" + condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" - task: ShellScript@2 displayName: "Run Tests (stop on error)" @@ -290,7 +298,7 @@ jobs: scriptPath: "scripts/funcTests/runFuncTests.sh" disableAutoCwd: "true" cwd: "$(Build.Repository.LocalPath)" - condition: "not(eq(variables['IsOfficialBuild'], 'true'))" + condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" - task: PublishTestResults@2 displayName: "Publish Test Results" @@ -302,6 +310,14 @@ jobs: mergeTestResults: "true" condition: "succeededOrFailed()" + - task: PublishBuildArtifacts@1 + displayName: "Publish Test Hang Dump" + inputs: + PathtoPublish: "$(Build.Repository.LocalPath)/build/TestResults" + ArtifactName: "$(Agent.JobName)" + ArtifactType: "Container" + condition: "or(failed(), canceled())" + - task: PowerShell@2 displayName: "Initialize Git Commit Status on GitHub" inputs: @@ -364,7 +380,7 @@ jobs: scriptPath: "scripts/funcTests/runFuncTests.sh" disableAutoCwd: "true" cwd: "$(Build.Repository.LocalPath)" - condition: "eq(variables['IsOfficialBuild'], 'true')" + condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" - task: ShellScript@2 displayName: "Run Tests (stop on error)" @@ -373,7 +389,7 @@ jobs: scriptPath: "scripts/funcTests/runFuncTests.sh" disableAutoCwd: "true" cwd: "$(Build.Repository.LocalPath)" - condition: "not(eq(variables['IsOfficialBuild'], 'true'))" + condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" - task: PublishTestResults@2 displayName: "Publish Test Results" @@ -385,6 +401,14 @@ jobs: testRunTitle: "NuGet.Client Tests On Mac" condition: "succeededOrFailed()" + - task: PublishBuildArtifacts@1 + displayName: "Publish Test Hang Dump" + inputs: + PathtoPublish: "$(Build.Repository.LocalPath)/build/TestResults" + ArtifactName: "$(Agent.JobName)" + ArtifactType: "Container" + condition: "or(failed(), canceled())" + - task: PowerShell@2 displayName: "Initialize Git Commit Status on GitHub" inputs: @@ -536,7 +560,7 @@ jobs: msbuildVersion: "16.0" configuration: "$(BuildConfiguration)" msbuildArguments: "/t:ApexTestsStandalone /p:TestResultOutputFormat=xml /p:BuildNumber=$(BuildNumber)" - condition: "eq(variables['IsOfficialBuild'], 'true')" + condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" - task: MSBuild@1 displayName: "Run Apex Tests (stop on error)" @@ -547,7 +571,7 @@ jobs: msbuildVersion: "16.0" configuration: "$(BuildConfiguration)" msbuildArguments: "/t:ApexTestsStandalone /p:TestResultOutputFormat=xml /p:BuildNumber=$(BuildNumber)" - condition: "not(eq(variables['IsOfficialBuild'], 'true'))" + condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" - task: PublishTestResults@2 displayName: "Publish Test Results" diff --git a/build/xunit.runsettings b/build/xunit.runsettings index c278c777d33..1a14af04649 100644 --- a/build/xunit.runsettings +++ b/build/xunit.runsettings @@ -3,4 +3,14 @@ verbose FrameworkCore10 + + + + + + %AGENT_TEMPDIRECTORY% + + + + From d96176a80daeb3ce71eb97f93a3b65d932a10a73 Mon Sep 17 00:00:00 2001 From: Epsitha Ananth <47157394+epananth@users.noreply.github.com> Date: Thu, 29 Oct 2020 18:05:05 -0700 Subject: [PATCH 023/129] Use V3 for DncEng BAR publishing (#3731) --- NuGet.Config | 1 + build/bootstrap.proj | 4 ++-- build/common.project.props | 5 ++--- build/publish.proj | 9 +++++---- build/templates/Build_and_UnitTest.yml | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/NuGet.Config b/NuGet.Config index ca8ad37e600..9b282747ae4 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -7,6 +7,7 @@ + diff --git a/build/bootstrap.proj b/build/bootstrap.proj index 414eec18779..7f0683f8326 100644 --- a/build/bootstrap.proj +++ b/build/bootstrap.proj @@ -14,8 +14,8 @@ - - + + diff --git a/build/common.project.props b/build/common.project.props index 03c93ae6519..bb3512cff27 100644 --- a/build/common.project.props +++ b/build/common.project.props @@ -49,8 +49,8 @@ $(NuGetBuildLocalizationRepository)localize $(ArtifactsDirectory)LocalizedFiles $(SolutionPackagesFolder)microbuild.core\0.2.0\build\ - $(SolutionPackagesFolder)microsoft.dotnet.build.tasks.feed\5.0.0-beta.20224.2\tools\netcoreapp2.1\Microsoft.DotNet.Build.Tasks.Feed.dll - $(SolutionPackagesFolder)microsoft.dotnet.maestro.tasks\1.1.0-beta.20352.2\tools\netcoreapp3.1\Microsoft.DotNet.Maestro.Tasks.dll + $(SolutionPackagesFolder)microsoft.dotnet.build.tasks.feed\6.0.0-beta.20528.5\tools\netcoreapp2.1\Microsoft.DotNet.Build.Tasks.Feed.dll + $(SolutionPackagesFolder)microsoft.dotnet.maestro.tasks\1.1.0-beta.20528.3\tools\netcoreapp3.1\Microsoft.DotNet.Maestro.Tasks.dll $(NoWarn);NU5105;NU5048 @@ -143,7 +143,6 @@ $(SemanticVersion)$(PreReleaseInformationVersion) - $(SemanticVersion)$(PreReleaseInformationVersion)+$(BUILD_SOURCEVERSION) diff --git a/build/publish.proj b/build/publish.proj index f934605eb64..2ca29b67891 100644 --- a/build/publish.proj +++ b/build/publish.proj @@ -51,22 +51,23 @@ - + AssetManifestPath="$(AssetManifestPath)" + PublishingVersion="3" /> + ManifestsPath="$(ArtifactsLogDir)AssetManifest\" + AssetVersion="$(Version)" /> diff --git a/build/templates/Build_and_UnitTest.yml b/build/templates/Build_and_UnitTest.yml index 3acac96e3de..543557abd05 100644 --- a/build/templates/Build_and_UnitTest.yml +++ b/build/templates/Build_and_UnitTest.yml @@ -493,7 +493,7 @@ steps: - task: CmdLine@2 displayName: "Publish to the .NET Core build asset registry (BAR)" inputs: - script: dotnet msbuild $(Build.Repository.LocalPath)\build\publish.proj /t:PublishToBuildAssetRegistry /p:NuGetClientNupkgsDirectoryPath=$(Build.Repository.LocalPath)\artifacts\$(NupkgOutputDir) /p:BUILD_BUILDNUMBER=$(Build.BuildNumber) /p:BUILD_SOURCEBRANCH=$(Build.SourceBranchName) /p:BUILD_SOURCEVERSION=$(Build.SourceVersion) /p:BUILD_REPOSITORY_URI=$(Build.Repository.Uri) /p:ArtifactsLogDir=$(Build.Repository.LocalPath)\artifacts\manifests\ /p:MaestroApiEndpoint=$(MaestroApiEndpoint) /p:MaestroAccessToken=$(MaestroAccessToken) + script: dotnet msbuild $(Build.Repository.LocalPath)\build\publish.proj /t:PublishToBuildAssetRegistry /p:NuGetClientNupkgsDirectoryPath=$(Build.Repository.LocalPath)\artifacts\$(NupkgOutputDir) /p:BUILD_BUILDNUMBER=$(Build.BuildNumber) /p:BUILD_SOURCEBRANCH=$(Build.SourceBranchName) /p:BUILD_SOURCEVERSION=$(Build.SourceVersion) /p:BUILD_REPOSITORY_URI=$(Build.Repository.Uri) /p:BUILD_REPOSITORY_NAME=$(Build.Repository.Name) /p:ArtifactsLogDir=$(Build.Repository.LocalPath)\artifacts\manifests\ /p:MaestroApiEndpoint=$(MaestroApiEndpoint) /p:MaestroAccessToken=$(MaestroAccessToken) workingDirectory: cli failOnStderr: true env: From d760325dafeaed35f0b6eb32fc3a3be3400021d3 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 30 Oct 2020 10:41:35 -0700 Subject: [PATCH 024/129] Move the format check to allow running the unit tests regardless of the format check status (#3745) --- build/templates/Build_and_UnitTest.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build/templates/Build_and_UnitTest.yml b/build/templates/Build_and_UnitTest.yml index 543557abd05..bfadb0f3f20 100644 --- a/build/templates/Build_and_UnitTest.yml +++ b/build/templates/Build_and_UnitTest.yml @@ -87,14 +87,6 @@ steps: dotnet tool restore condition: "and(not(eq(variables['IsOfficialBuild'], 'true')), eq(variables['BuildRTM'], 'true'))" #skip this task for nonRTM in private build -- task: PowerShell@1 - displayName: "Check source file format" - inputs: - scriptType: "inlineScript" - inlineScript: | - dotnet format --check --exclude submodules --verbosity diagnostic - condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')), eq(variables['BuildRTM'], 'true'))" #skip this task for nonRTM in private build - - task: MSBuild@1 displayName: "Restore for VS2019" inputs: @@ -186,6 +178,14 @@ steps: publishRunAttachments: "false" condition: "and(succeededOrFailed(),eq(variables['BuildRTM'], 'true'))" +- task: PowerShell@1 + displayName: "Check source file format" + inputs: + scriptType: "inlineScript" + inlineScript: | + dotnet format --check --exclude submodules --verbosity diagnostic + condition: "and(succeededOrFailed(), not(eq(variables['IsOfficialBuild'], 'true')), eq(variables['BuildRTM'], 'true'))" #skip this task for nonRTM in private build + - task: PowerShell@1 displayName: "Initialize Git Commit Status on GitHub" inputs: From 82d33c6a7c9002cf88106cc36f6fde72dd9e35ea Mon Sep 17 00:00:00 2001 From: Damon Tivel Date: Fri, 30 Oct 2020 13:27:02 -0700 Subject: [PATCH 025/129] PM UI: batch project selection updates in solution PM UI (#3746) Resolve https://github.com/NuGet/Home/issues/10112 --- .../PackageSolutionDetailControlModel.cs | 86 ++++++++++++++++--- 1 file changed, 72 insertions(+), 14 deletions(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs index a042b31a60b..41bd2e41811 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Models/PackageSolutionDetailControlModel.cs @@ -32,6 +32,7 @@ internal class PackageSolutionDetailControlModel : DetailControlModel // Indicates whether the SelectCheckBoxState is being updated in code. True means the state is being updated by code, while false means the state is changed by user clicking the checkbox. private bool _updatingSelectCheckBoxState; private bool? _selectCheckBoxState; + private bool _isInBatchUpdate; private List _projects; // List of projects in the solution private PackageSolutionDetailControlModel( @@ -387,11 +388,21 @@ public bool CanUninstall } private void Project_SelectedChanged(object sender, EventArgs e) + { + if (_isInBatchUpdate) + { + return; + } + + UpdateSelectAllAfterProjectSelectionChanged(); + } + + private void UpdateSelectAllAfterProjectSelectionChanged() { UpdateSelectCheckBoxState(); NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(() => CreateVersionsAndUpdateInstallUninstallAsync()) - .PostOnFailure(nameof(PackageSolutionDetailControlModel), nameof(Project_SelectedChanged)); + .PostOnFailure(nameof(PackageSolutionDetailControlModel), nameof(UpdateSelectAllAfterProjectSelectionChanged)); } private async Task CreateVersionsAndUpdateInstallUninstallAsync() @@ -465,11 +476,7 @@ internal async Task SelectAllProjectsAsync(bool select, CancellationToken cancel return; } - foreach (var project in Projects) - { - project.IsSelected = select; - } - await CreateVersionsAndUpdateInstallUninstallAsync(); + await BatchUpdateIsSelectedAsync(select); } [SuppressMessage("Microsoft.VisualStudio.Threading.Analyzers", "VSTHRD100", Justification = "NuGet/Home#4833 Baseline")] @@ -505,10 +512,7 @@ private void AutoSelectProjects() if (_filter == ItemFilter.Consolidate || _filter == ItemFilter.UpdatesAvailable) { - foreach (var project in _projects) - { - project.IsSelected = project.InstalledVersion != null; - } + BatchUpdateIsSelectedBasedOnInstalledVersion(); } } @@ -521,10 +525,7 @@ public override void OnFilterChanged(ItemFilter? previousFilter, ItemFilter curr if ((previousFilter == ItemFilter.Consolidate || previousFilter == ItemFilter.UpdatesAvailable) && (_filter == ItemFilter.All || _filter == ItemFilter.Installed)) { - foreach (var project in _projects) - { - project.IsSelected = false; - } + BatchUnselectAllProjects(); } } @@ -563,5 +564,62 @@ public override IEnumerable GetSelectedProjects(UserAction return selectedProjects; } + + private void BatchUnselectAllProjects() + { + _isInBatchUpdate = true; + + try + { + foreach (PackageInstallationInfo project in Projects) + { + project.IsSelected = false; + } + + UpdateSelectCheckBoxState(); + UpdateSelectAllAfterProjectSelectionChanged(); + } + finally + { + _isInBatchUpdate = false; + } + } + + private void BatchUpdateIsSelectedBasedOnInstalledVersion() + { + _isInBatchUpdate = true; + + try + { + foreach (PackageInstallationInfo project in Projects) + { + project.IsSelected = project.InstalledVersion != null; + } + } + finally + { + _isInBatchUpdate = false; + } + } + + private async ValueTask BatchUpdateIsSelectedAsync(bool isSelected) + { + _isInBatchUpdate = true; + + try + { + foreach (PackageInstallationInfo project in Projects) + { + project.IsSelected = isSelected; + } + + UpdateSelectCheckBoxState(); + await CreateVersionsAndUpdateInstallUninstallAsync(); + } + finally + { + _isInBatchUpdate = false; + } + } } } From 53ba5449ca3fb329eccfa0866c073f7986742b02 Mon Sep 17 00:00:00 2001 From: Fernando Aguilar Date: Fri, 30 Oct 2020 14:16:34 -0700 Subject: [PATCH 026/129] Localized help for `get-help nuget` in Package Manger Console (#3733) Fixes https://github.com/NuGet/Home/issues/4604 --- .../NuGet.VisualStudio.Client.csproj | 4 +-- .../NuGetConsole.Host.PowerShell.csproj | 31 +++++++++++++++++-- ....help.txt => about_NuGet.Cmdlets.help.txt} | 0 3 files changed, 30 insertions(+), 5 deletions(-) rename src/NuGet.Clients/NuGetConsole.Host.PowerShell/Scripts/{about_NuGet.PackageManagement.PowerShellCmdlets.help.txt => about_NuGet.Cmdlets.help.txt} (100%) diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Client/NuGet.VisualStudio.Client.csproj b/src/NuGet.Clients/NuGet.VisualStudio.Client/NuGet.VisualStudio.Client.csproj index 9d655160584..64c6fd058ff 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Client/NuGet.VisualStudio.Client.csproj +++ b/src/NuGet.Clients/NuGet.VisualStudio.Client/NuGet.VisualStudio.Client.csproj @@ -55,8 +55,8 @@ - - Modules\NuGet\about_NuGet.PackageManagement.PowerShellCmdlets.help.txt + + Modules\NuGet\about_NuGet.Cmdlets.help.txt true diff --git a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/NuGetConsole.Host.PowerShell.csproj b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/NuGetConsole.Host.PowerShell.csproj index ee43bcfe423..f1bc5aeccb3 100644 --- a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/NuGetConsole.Host.PowerShell.csproj +++ b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/NuGetConsole.Host.PowerShell.csproj @@ -137,7 +137,9 @@ - + + PreserveNewest + @@ -179,12 +181,35 @@ + + + + + + + + + + + + + + + + + <_AllLocalizedXmlFiles Include="$(OutputPath)Scripts\**\NuGet.PackageManagement.PowerShellCmdlets.dll-Help.xml" /> - + <_XmlLocFiles Include="@(_AllLocalizedXmlFiles)"> Modules\NuGet\$([MSBuild]::MakeRelative($(OutputPath)Scripts, %(_AllLocalizedXmlFiles.Identity))) - + + + <_TxtLocFiles Include="$(LocalizationRootDirectory)\%(VSLanguage.Identity)\15\about_NuGet.Cmdlets.help.txt"> + Modules\NuGet\%(VSLanguage.Locale)\about_NuGet.Cmdlets.help.txt + + + diff --git a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/Scripts/about_NuGet.PackageManagement.PowerShellCmdlets.help.txt b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/Scripts/about_NuGet.Cmdlets.help.txt similarity index 100% rename from src/NuGet.Clients/NuGetConsole.Host.PowerShell/Scripts/about_NuGet.PackageManagement.PowerShellCmdlets.help.txt rename to src/NuGet.Clients/NuGetConsole.Host.PowerShell/Scripts/about_NuGet.Cmdlets.help.txt From dbb712e06668153b763180aa3923bda9b26d8fde Mon Sep 17 00:00:00 2001 From: Andy Zivkovic Date: Fri, 30 Oct 2020 18:07:28 -0700 Subject: [PATCH 027/129] Use myget-legacy AzDO feed instead of myget.org (#3748) --- NuGet.Config | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/NuGet.Config b/NuGet.Config index 9b282747ae4..cf76eadf108 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -2,15 +2,13 @@ - + + + + - - - - - From 4f7628ca571118969a3920485a5ee881ea5f6e5c Mon Sep 17 00:00:00 2001 From: Damon Tivel Date: Tue, 3 Nov 2020 11:23:23 -0800 Subject: [PATCH 028/129] VS OE: defer assembly loads (#3751) Progress on https://github.com/NuGet/Home/issues/9919 --- .../NuGet.Tools/NuGet.Tools.csproj | 1 + .../NuGetBrokeredServiceFactory.cs | 150 ++++++++++++++++++ src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs | 36 +---- .../NuGetBrokeredServiceFactory.cs | 33 ---- .../Extensibility/NuGetProjectService.cs | 2 +- .../NuGetServiceMessagePackRpcDescriptor.cs | 62 ++++---- 6 files changed, 186 insertions(+), 98 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.Tools/NuGetBrokeredServiceFactory.cs delete mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetBrokeredServiceFactory.cs diff --git a/src/NuGet.Clients/NuGet.Tools/NuGet.Tools.csproj b/src/NuGet.Clients/NuGet.Tools/NuGet.Tools.csproj index 1fec6ed00f7..57cb1023fb6 100644 --- a/src/NuGet.Clients/NuGet.Tools/NuGet.Tools.csproj +++ b/src/NuGet.Clients/NuGet.Tools/NuGet.Tools.csproj @@ -39,6 +39,7 @@ + diff --git a/src/NuGet.Clients/NuGet.Tools/NuGetBrokeredServiceFactory.cs b/src/NuGet.Clients/NuGet.Tools/NuGetBrokeredServiceFactory.cs new file mode 100644 index 00000000000..ff00b597b9a --- /dev/null +++ b/src/NuGet.Clients/NuGet.Tools/NuGetBrokeredServiceFactory.cs @@ -0,0 +1,150 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft; +using Microsoft.ServiceHub.Framework; +using Microsoft.ServiceHub.Framework.Services; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Threading; +using NuGet.PackageManagement.VisualStudio; +using NuGet.VisualStudio; +using NuGet.VisualStudio.Implementation.Extensibility; +using NuGet.VisualStudio.Internal.Contracts; +using ContractsNuGetServices = NuGet.VisualStudio.Contracts.NuGetServices; +using IBrokeredServiceContainer = Microsoft.VisualStudio.Shell.ServiceBroker.IBrokeredServiceContainer; +using ISettings = NuGet.Configuration.ISettings; +using SVsBrokeredServiceContainer = Microsoft.VisualStudio.Shell.ServiceBroker.SVsBrokeredServiceContainer; +using Task = System.Threading.Tasks.Task; + +namespace NuGetVSExtension +{ + // The disposables live for the duration of the process. +#pragma warning disable CA1001 // Types that own disposable fields should be disposable + internal sealed class NuGetBrokeredServiceFactory +#pragma warning restore CA1001 // Types that own disposable fields should be disposable + { + private readonly AsyncLazyInitializer _lazyInitializer; + private AsyncLazy _lazySettings; + private AsyncLazy _lazySolutionManager; + private INuGetProjectManagerServiceState _projectManagerServiceSharedState; + private ISharedServiceState _sharedServiceState; + + private NuGetBrokeredServiceFactory() + { + _lazyInitializer = new AsyncLazyInitializer(InitializeAsync, ThreadHelper.JoinableTaskFactory); + } + + internal static async ValueTask ProfferServicesAsync(IAsyncServiceProvider serviceProvider) + { + Assumes.NotNull(serviceProvider); + + IBrokeredServiceContainer brokeredServiceContainer = await serviceProvider.GetServiceAsync(); + + var factory = new NuGetBrokeredServiceFactory(); + + // This service descriptor reference will cause NuGet.VisualStudio.Contracts.dll to load. + brokeredServiceContainer.Proffer(ContractsNuGetServices.NuGetProjectServiceV1, factory.CreateNuGetProjectServiceV1); + + // These service descriptor references will cause NuGet.VisualStudio.Internal.Contracts.dll to load. + brokeredServiceContainer.Proffer(NuGetServices.SourceProviderService, factory.CreateSourceProviderServiceAsync); + brokeredServiceContainer.Proffer(NuGetServices.SolutionManagerService, factory.CreateSolutionManagerServiceAsync); + brokeredServiceContainer.Proffer(NuGetServices.ProjectManagerService, factory.CreateProjectManagerServiceAsync); + brokeredServiceContainer.Proffer(NuGetServices.ProjectUpgraderService, factory.CreateProjectUpgraderServiceAsync); + } + + private ValueTask CreateSourceProviderServiceAsync( + ServiceMoniker moniker, + ServiceActivationOptions options, + IServiceBroker serviceBroker, + AuthorizationServiceClient authorizationServiceClient, + CancellationToken cancellationToken) + { +#pragma warning disable CA2000 // Dispose objects before losing scope + return new ValueTask(new NuGetSourcesService(options, serviceBroker, authorizationServiceClient)); +#pragma warning restore CA2000 // Dispose objects before losing scope + } + + private async ValueTask CreateSolutionManagerServiceAsync( + ServiceMoniker moniker, + ServiceActivationOptions options, + IServiceBroker serviceBroker, + AuthorizationServiceClient authorizationServiceClient, + CancellationToken cancellationToken) + { + NuGetSolutionManagerService service = await NuGetSolutionManagerService.CreateAsync( + options, + serviceBroker, + authorizationServiceClient, + cancellationToken); + + return service; + } + + private async ValueTask CreateProjectManagerServiceAsync( + ServiceMoniker moniker, + ServiceActivationOptions options, + IServiceBroker serviceBroker, + AuthorizationServiceClient authorizationServiceClient, + CancellationToken cancellationToken) + { + await _lazyInitializer.InitializeAsync(cancellationToken); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var service = new NuGetProjectManagerService( + options, + serviceBroker, + authorizationServiceClient, + _projectManagerServiceSharedState, + _sharedServiceState); +#pragma warning restore CA2000 // Dispose objects before losing scope + + return service; + } + + private async ValueTask CreateProjectUpgraderServiceAsync( + ServiceMoniker moniker, + ServiceActivationOptions options, + IServiceBroker serviceBroker, + AuthorizationServiceClient authorizationServiceClient, + CancellationToken cancellationToken) + { + await _lazyInitializer.InitializeAsync(cancellationToken); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var service = new NuGetProjectUpgraderService( + options, + serviceBroker, + authorizationServiceClient, + _sharedServiceState); +#pragma warning restore CA2000 // Dispose objects before losing scope + + return service; + } + + private async ValueTask CreateNuGetProjectServiceV1( + ServiceMoniker moniker, + ServiceActivationOptions options, + IServiceBroker serviceBroker, + CancellationToken cancellationToken) + { + await _lazyInitializer.InitializeAsync(cancellationToken); + + IVsSolutionManager solutionManager = await _lazySolutionManager.GetValueAsync(cancellationToken); + ISettings settings = await _lazySettings.GetValueAsync(cancellationToken); + + return new NuGetProjectService(solutionManager, settings); + } + + private Task InitializeAsync() + { + _lazySettings = new AsyncLazy(ServiceLocator.GetInstanceAsync, ThreadHelper.JoinableTaskFactory); + _lazySolutionManager = new AsyncLazy(ServiceLocator.GetInstanceAsync, ThreadHelper.JoinableTaskFactory); + _projectManagerServiceSharedState = new NuGetProjectManagerServiceState(); + _sharedServiceState = new SharedServiceState(); + + return Task.CompletedTask; + } + } +} diff --git a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs index a1dc084a0a4..a4611010b2d 100644 --- a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs +++ b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs @@ -26,18 +26,15 @@ using NuGet.ProjectManagement; using NuGet.VisualStudio; using NuGet.VisualStudio.Common; -using NuGet.VisualStudio.Implementation.Extensibility; using NuGet.VisualStudio.Internal.Contracts; using NuGet.VisualStudio.Telemetry; using NuGetConsole; using NuGetConsole.Implementation; using ContractsNuGetServices = NuGet.VisualStudio.Contracts.NuGetServices; -using IBrokeredServiceContainer = Microsoft.VisualStudio.Shell.ServiceBroker.IBrokeredServiceContainer; using ISettings = NuGet.Configuration.ISettings; using ProvideBrokeredServiceAttribute = Microsoft.VisualStudio.Shell.ServiceBroker.ProvideBrokeredServiceAttribute; using Resx = NuGet.PackageManagement.UI.Resources; using ServiceAudience = Microsoft.VisualStudio.Shell.ServiceBroker.ServiceAudience; -using SVsBrokeredServiceContainer = Microsoft.VisualStudio.Shell.ServiceBroker.SVsBrokeredServiceContainer; using Task = System.Threading.Tasks.Task; using UI = NuGet.PackageManagement.UI; @@ -137,8 +134,6 @@ public NuGetPackage() private IDisposable ProjectUpgradeHandler { get; set; } - private INuGetProjectManagerServiceState _projectManagerServiceState; - [Import] private Lazy ServiceBrokerProvider { get; set; } @@ -181,27 +176,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke }, ThreadHelper.JoinableTaskFactory); - var brokeredServiceContainer = await this.GetServiceAsync(); - var lazySolutionManager = new AsyncLazy(() => ServiceLocator.GetInstanceAsync(), ThreadHelper.JoinableTaskFactory); - var lazySettings = new AsyncLazy(() => ServiceLocator.GetInstanceAsync(), ThreadHelper.JoinableTaskFactory); - var nuGetBrokeredServiceFactory = new NuGetBrokeredServiceFactory(lazySolutionManager, lazySettings); - brokeredServiceContainer.Proffer(ContractsNuGetServices.NuGetProjectServiceV1, nuGetBrokeredServiceFactory.CreateNuGetProjectServiceV1); - - var state = new SharedServiceState(); - _projectManagerServiceState = new NuGetProjectManagerServiceState(); - - brokeredServiceContainer.Proffer( - NuGetServices.SourceProviderService, - (mk, options, sb, ac, ct) => new ValueTask(new NuGetSourcesService(options, sb, ac))); - brokeredServiceContainer.Proffer( - NuGetServices.SolutionManagerService, - (mk, options, sb, ac, ct) => ToValueTaskOfObject(NuGetSolutionManagerService.CreateAsync(options, sb, ac, ct))); - brokeredServiceContainer.Proffer( - NuGetServices.ProjectManagerService, - (mk, options, sb, ac, ct) => new ValueTask(new NuGetProjectManagerService(options, sb, ac, _projectManagerServiceState, state))); - brokeredServiceContainer.Proffer( - NuGetServices.ProjectUpgraderService, - (mk, options, sb, ac, ct) => new ValueTask(new NuGetProjectUpgraderService(options, sb, ac, state))); + await NuGetBrokeredServiceFactory.ProfferServicesAsync(this); } /// @@ -1120,8 +1095,6 @@ private void OnBeginShutDown() { _dteEvents.OnBeginShutdown -= OnBeginShutDown; _dteEvents = null; - - _projectManagerServiceState?.Dispose(); } #region IVsPersistSolutionOpts @@ -1165,12 +1138,5 @@ public int WriteUserOptions(IStream _, string __) } #endregion IVsPersistSolutionOpts - - private static async ValueTask ToValueTaskOfObject(ValueTask valueTask) - { - T value = await valueTask; - - return (object)value; - } } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetBrokeredServiceFactory.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetBrokeredServiceFactory.cs deleted file mode 100644 index eda9aca671f..00000000000 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetBrokeredServiceFactory.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.ServiceHub.Framework; -using Microsoft.VisualStudio.Threading; -using NuGet.Configuration; -using NuGet.PackageManagement.VisualStudio; - -namespace NuGet.VisualStudio.Implementation.Extensibility -{ - public class NuGetBrokeredServiceFactory - { - private readonly AsyncLazy _solutionManager; - private readonly AsyncLazy _settings; - - public NuGetBrokeredServiceFactory(AsyncLazy solutionManager, AsyncLazy settings) - { - _solutionManager = solutionManager ?? throw new ArgumentNullException(nameof(solutionManager)); - _settings = settings ?? throw new ArgumentNullException(nameof(settings)); - } - - public async ValueTask CreateNuGetProjectServiceV1(ServiceMoniker moniker, ServiceActivationOptions options, IServiceBroker serviceBroker, CancellationToken cancellationToken) - { - var solutionManager = await _solutionManager.GetValueAsync(cancellationToken); - var settings = await _settings.GetValueAsync(cancellationToken); - - return new NuGetProjectService(solutionManager, settings); - } - } -} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetProjectService.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetProjectService.cs index c1b06ce9734..d994d7403f5 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetProjectService.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Extensibility/NuGetProjectService.cs @@ -19,7 +19,7 @@ namespace NuGet.VisualStudio.Implementation.Extensibility { - internal class NuGetProjectService : INuGetProjectService + public sealed class NuGetProjectService : INuGetProjectService { private readonly IVsSolutionManager _solutionManager; private readonly ISettings _settings; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs index f5c8dae57ea..01f712d10ba 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs @@ -15,34 +15,8 @@ namespace NuGet.VisualStudio.Internal.Contracts { internal class NuGetServiceMessagePackRpcDescriptor : ServiceJsonRpcDescriptor { - private static readonly MessagePackSerializerOptions MessagePackSerializerOptions; - - static NuGetServiceMessagePackRpcDescriptor() - { - var formatters = new IMessagePackFormatter[] - { - FloatRangeFormatter.Instance, - IPackageReferenceContextInfoFormatter.Instance, - IProjectContextInfoFormatter.Instance, - IProjectMetadataContextInfoFormatter.Instance, - NuGetFrameworkFormatter.Instance, - NuGetVersionFormatter.Instance, - PackageDependencyFormatter.Instance, - PackageDependencyInfoFormatter.Instance, - PackageIdentityFormatter.Instance, - PackageReferenceFormatter.Instance, - PackageSourceFormatter.Instance, - PackageSourceUpdateOptionsFormatter.Instance, - ProjectActionFormatter.Instance, - RemoteErrorFormatter.Instance, - VersionRangeFormatter.Instance - }; - var resolvers = new IFormatterResolver[] { MessagePackSerializerOptions.Standard.Resolver }; - - MessagePackSerializerOptions = MessagePackSerializerOptions.Standard - .WithSecurity(MessagePackSecurity.UntrustedData) - .WithResolver(CompositeResolver.Create(formatters, resolvers)); - } + private static readonly Lazy MessagePackSerializerOptions = + new Lazy(CreateMessagePackSerializerOptions); internal NuGetServiceMessagePackRpcDescriptor(ServiceMoniker serviceMoniker) : base(serviceMoniker, Formatters.MessagePack, MessageDelimiters.BigEndianInt32LengthHeader) @@ -66,7 +40,10 @@ protected override IJsonRpcMessageFormatter CreateFormatter() Assumes.True(Formatter == Formatters.MessagePack); MessagePackFormatter formatter = base.CreateFormatter() as MessagePackFormatter ?? new MessagePackFormatter(); - formatter.SetMessagePackSerializerOptions(MessagePackSerializerOptions); + MessagePackSerializerOptions options = MessagePackSerializerOptions.Value; + + formatter.SetMessagePackSerializerOptions(options); + return formatter; } @@ -74,5 +51,32 @@ protected override JsonRpc CreateJsonRpc(IJsonRpcMessageHandler handler) { return new NuGetJsonRpc(handler); } + + private static MessagePackSerializerOptions CreateMessagePackSerializerOptions() + { + var formatters = new IMessagePackFormatter[] + { + FloatRangeFormatter.Instance, + IPackageReferenceContextInfoFormatter.Instance, + IProjectContextInfoFormatter.Instance, + IProjectMetadataContextInfoFormatter.Instance, + NuGetFrameworkFormatter.Instance, + NuGetVersionFormatter.Instance, + PackageDependencyFormatter.Instance, + PackageDependencyInfoFormatter.Instance, + PackageIdentityFormatter.Instance, + PackageReferenceFormatter.Instance, + PackageSourceFormatter.Instance, + PackageSourceUpdateOptionsFormatter.Instance, + ProjectActionFormatter.Instance, + RemoteErrorFormatter.Instance, + VersionRangeFormatter.Instance + }; + var resolvers = new IFormatterResolver[] { MessagePack.MessagePackSerializerOptions.Standard.Resolver }; + + return MessagePack.MessagePackSerializerOptions.Standard + .WithSecurity(MessagePackSecurity.UntrustedData) + .WithResolver(CompositeResolver.Create(formatters, resolvers)); + } } } From db35904009e94c9a623201521d95ca1225a69f69 Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Wed, 4 Nov 2020 08:20:53 -0800 Subject: [PATCH 029/129] support logging in CommandRunner when tests are executed in parallel (#3732) --- .../Test.Utility/CommandRunner.cs | 56 +++++++++---------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/test/TestUtilities/Test.Utility/CommandRunner.cs b/test/TestUtilities/Test.Utility/CommandRunner.cs index 4b7dc6cee61..add0e54cc87 100644 --- a/test/TestUtilities/Test.Utility/CommandRunner.cs +++ b/test/TestUtilities/Test.Utility/CommandRunner.cs @@ -22,7 +22,6 @@ public static CommandRunnerResult Run( bool waitForExit, int timeOutInMilliseconds = 60000, Action inputAction = null, - bool shareProcessObject = false, IDictionary environmentVariables = null) { var psi = new ProcessStartInfo(Path.GetFullPath(process), arguments) @@ -60,27 +59,33 @@ public static CommandRunnerResult Run( Process p = null; - try + using (p = new Process()) { - p = new Process(); + p.OutputDataReceived += OutputHandler; + p.ErrorDataReceived += ErrorHandler; p.StartInfo = psi; p.Start(); - var outputTask = ConsumeStreamReaderAsync(p.StandardOutput, output); - var errorTask = ConsumeStreamReaderAsync(p.StandardError, errors); - inputAction?.Invoke(p.StandardInput); + p.BeginOutputReadLine(); + p.BeginErrorReadLine(); + if (waitForExit) { -#if DEBUG - var processExited = true; +#if DEBUG p.WaitForExit(); + var processExited = true; #else var processExited = p.WaitForExit(timeOutInMilliseconds); #endif - if (!processExited) + if (processExited) + { + p.WaitForExit(); + exitCode = p.ExitCode; + } + else { Kill(p); WaitForExit(p); @@ -89,34 +94,25 @@ public static CommandRunnerResult Run( throw new TimeoutException($"{processName} timed out: " + psi.Arguments); } - - if (processExited) - { - Task.WaitAll(outputTask, errorTask); - exitCode = p.ExitCode; - } } + + p.CancelOutputRead(); + p.CancelErrorRead(); } - finally + + void OutputHandler(object sendingProcess, DataReceivedEventArgs e) { - if (!shareProcessObject) - { - p.Dispose(); - } + if (!string.IsNullOrEmpty(e.Data)) + output.AppendLine(e.Data); } - return new CommandRunnerResult(p, exitCode, output.ToString(), errors.ToString()); - } - - private static async Task ConsumeStreamReaderAsync(StreamReader reader, StringBuilder lines) - { - await Task.Yield(); - - string line; - while ((line = await reader.ReadLineAsync()) != null) + void ErrorHandler(object sendingProcess, DataReceivedEventArgs e) { - lines.AppendLine(line); + if (!string.IsNullOrEmpty(e.Data)) + errors.AppendLine(e.Data); } + + return new CommandRunnerResult(p, exitCode, output.ToString(), errors.ToString()); } private static void Kill(Process process) From ff71fa18a7b175a7d70d3a77a2877b012ac35edb Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Wed, 4 Nov 2020 09:45:01 -0800 Subject: [PATCH 030/129] shared compilation of XmlUtility (#3728) --- NuGet.sln | 1 + build/Shared/XmlUtility.cs | 90 +++++++++++++++++++ .../Commands/DownloadCommandBase.cs | 2 +- ...uGet.PackageManagement.VisualStudio.csproj | 5 +- .../Utility/FrameworkAssemblyResolver.cs | 3 +- .../NuGet.SolutionRestoreManager.csproj | 1 + .../Utility/XmlUtility.cs | 68 -------------- .../VsTemplateWizard.cs | 5 +- .../NuGet.Build.Tasks/BuildTasksUtility.cs | 4 +- .../Utility/BuildAssetsUtils.cs | 2 +- .../NuGet.Common/Utility/XmlUtility.cs | 23 +++++ src/NuGet.Core/NuGet.Common/XmlUtility.cs | 43 --------- .../Settings/Items/CredentialsItem.cs | 1 + .../Settings/SettingSection.cs | 1 + .../Settings/SettingsFile.cs | 2 +- .../Settings/SettingsGroup.cs | 1 + .../Utility/FileSystemUtility.cs | 17 ++++ .../{XmlUtility.cs => XElementUtility.cs} | 67 -------------- .../FileModifiers/XmlTransformer.cs | 2 +- .../MSBuildNuGetProjectSystemUtility.cs | 19 ++++ .../Utility/XmlUtility.cs | 64 +++++-------- .../NuGet.Packaging/GlobalSuppressions.cs | 2 - .../PackageCreation/Authoring/Manifest.cs | 3 +- .../PackageCreation/Utility/XmlUtility.cs | 25 ++---- .../NuGet.Shared.Tests.csproj | 3 + .../XmlUtilityTests.cs | 33 +++++-- 26 files changed, 228 insertions(+), 259 deletions(-) create mode 100644 build/Shared/XmlUtility.cs delete mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Implementation/Utility/XmlUtility.cs create mode 100644 src/NuGet.Core/NuGet.Common/Utility/XmlUtility.cs delete mode 100644 src/NuGet.Core/NuGet.Common/XmlUtility.cs rename src/NuGet.Core/NuGet.Configuration/Utility/{XmlUtility.cs => XElementUtility.cs} (70%) rename test/NuGet.Core.Tests/{NuGet.Common.Test => NuGet.Shared.Tests}/XmlUtilityTests.cs (66%) diff --git a/NuGet.sln b/NuGet.sln index 8665974358a..4096c07d028 100644 --- a/NuGet.sln +++ b/NuGet.sln @@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{DE23D0 build\Shared\HashCodeCombiner.cs = build\Shared\HashCodeCombiner.cs build\Shared\TypeExtensions.cs = build\Shared\TypeExtensions.cs build\Shared\TypeInfo.cs = build\Shared\TypeInfo.cs + build\Shared\XmlUtility.cs = build\Shared\XmlUtility.cs EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D1549653-9631-4E16-9967-55427174A0DC}" diff --git a/build/Shared/XmlUtility.cs b/build/Shared/XmlUtility.cs new file mode 100644 index 00000000000..0f915af2225 --- /dev/null +++ b/build/Shared/XmlUtility.cs @@ -0,0 +1,90 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Xml; +using System.Xml.Linq; + +namespace NuGet.Shared +{ + internal static class XmlUtility + { + /// + /// Creates a new from a file. + /// + /// A URI string that references the file to load into a new . + /// An that contains the contents of the specified file. + internal static XDocument Load(string inputUri) + { + return Load(inputUri, LoadOptions.None); + } + + /// + /// Creates a new from a file. Optionally, whitespace can be preserved. + /// + /// A URI string that references the file to load into a new . + /// A set of . + /// An that contains the contents of the specified file. + internal static XDocument Load(string inputUri, LoadOptions options) + { + using (var reader = XmlReader.Create(inputUri, GetXmlReaderSettings(options))) + { + return XDocument.Load(reader, options); + } + } + + /// + /// Creates a new from a stream. + /// + /// The stream that contains the XML data. + /// An that contains the contents of the specified stream. + internal static XDocument Load(Stream input) + { + return Load(input, LoadOptions.None); + } + + /// + /// Creates a new System.Xml.Linq.XDocument from a stream. Optionally, whitespace can be preserved. + /// + /// The stream that contains the XML data. + /// A set of . + /// An that contains the contents of the specified stream. + internal static XDocument Load(Stream input, LoadOptions options) + { + using (var reader = XmlReader.Create(input, GetXmlReaderSettings(options))) + { + return XDocument.Load(reader, options); + } + } + + /// + /// Converts the name to a valid XML local name, if it is invalid. + /// + /// The name to be encoded. + /// The encoded name. + internal static string GetEncodedXMLName(string name) + { + try + { + return XmlConvert.VerifyName(name); + } + catch (XmlException) + { + return XmlConvert.EncodeLocalName(name); + } + } + + /// + /// Creates an instance of with safe settings + /// A set of . + /// + private static XmlReaderSettings GetXmlReaderSettings(LoadOptions options) + { + XmlReaderSettings rs = new XmlReaderSettings(); + if ((options & LoadOptions.PreserveWhitespace) == 0) + rs.IgnoreWhitespace = true; + rs.IgnoreProcessingInstructions = true; + return rs; + } + } +} diff --git a/src/NuGet.Clients/NuGet.CommandLine/Commands/DownloadCommandBase.cs b/src/NuGet.Clients/NuGet.CommandLine/Commands/DownloadCommandBase.cs index 3518305b5ba..be92b1d1f96 100644 --- a/src/NuGet.Clients/NuGet.CommandLine/Commands/DownloadCommandBase.cs +++ b/src/NuGet.Clients/NuGet.CommandLine/Commands/DownloadCommandBase.cs @@ -12,7 +12,7 @@ using NuGet.Configuration; using NuGet.Packaging; using NuGet.Protocol; -using XmlUtility = NuGet.Common.XmlUtility; +using XmlUtility = NuGet.Shared.XmlUtility; namespace NuGet.CommandLine { diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj index d3b3eabdf24..6dadf252745 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj @@ -1,4 +1,4 @@ - + @@ -309,6 +309,9 @@ EqualityUtility.cs + + XmlUtility.cs + diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/FrameworkAssemblyResolver.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/FrameworkAssemblyResolver.cs index 4b082a60c3d..c7ff58e4743 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/FrameworkAssemblyResolver.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/FrameworkAssemblyResolver.cs @@ -10,6 +10,7 @@ using System.Runtime.Versioning; using Microsoft.Build.Utilities; using NuGet.ProjectManagement; +using XmlUtility = NuGet.Shared.XmlUtility; namespace NuGet.PackageManagement.VisualStudio { @@ -192,7 +193,7 @@ private static List GetFrameworkAssemblies(string referenceAs using (var stream = File.OpenRead(FileSystemUtility.GetFullPath(referenceAssembliesPath, FrameworkListFileName))) { - var document = XmlUtility.LoadSafe(stream); + var document = XmlUtility.Load(stream); var root = document.Root; if (root.Name.LocalName.Equals("FileList", StringComparison.OrdinalIgnoreCase)) { diff --git a/src/NuGet.Clients/NuGet.SolutionRestoreManager/NuGet.SolutionRestoreManager.csproj b/src/NuGet.Clients/NuGet.SolutionRestoreManager/NuGet.SolutionRestoreManager.csproj index c9920f1c991..14d237df23c 100644 --- a/src/NuGet.Clients/NuGet.SolutionRestoreManager/NuGet.SolutionRestoreManager.csproj +++ b/src/NuGet.Clients/NuGet.SolutionRestoreManager/NuGet.SolutionRestoreManager.csproj @@ -27,6 +27,7 @@ + diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Utility/XmlUtility.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Utility/XmlUtility.cs deleted file mode 100644 index 07249484993..00000000000 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/Utility/XmlUtility.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using System.Xml; -using System.Xml.Linq; - -namespace NuGet.VisualStudio -{ - public static class XmlUtility - { - public static XDocument LoadSafe(string filePath) - { - var settings = CreateSafeSettings(); - using (var reader = XmlReader.Create(filePath, settings)) - { - return XDocument.Load(reader); - } - } - - public static XDocument LoadSafe(Stream input) - { - var settings = CreateSafeSettings(); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader); - } - - public static XDocument LoadSafe(Stream input, bool ignoreWhiteSpace) - { - var settings = CreateSafeSettings(ignoreWhiteSpace); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader); - } - - public static XDocument LoadSafe(Stream input, LoadOptions options) - { - var settings = CreateSafeSettings(); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader, options); - } - - private static XmlReaderSettings CreateSafeSettings(bool ignoreWhiteSpace = false) - { - var safeSettings = new XmlReaderSettings - { - XmlResolver = null, - DtdProcessing = DtdProcessing.Prohibit, - IgnoreWhitespace = ignoreWhiteSpace - }; - - return safeSettings; - } - - internal static bool TryParseDocument(string content, out XDocument document) - { - document = null; - try - { - document = XDocument.Parse(content); - return true; - } - catch (XmlException) - { - return false; - } - } - } -} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/VsTemplateWizard.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/VsTemplateWizard.cs index 3287496d46a..64c8ea15234 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/VsTemplateWizard.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/VsTemplateWizard.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Xml.Linq; @@ -23,6 +21,7 @@ using NuGet.Versioning; using NuGet.VisualStudio.Implementation.Resources; using Task = System.Threading.Tasks.Task; +using XmlUtility = NuGet.Shared.XmlUtility; namespace NuGet.VisualStudio { @@ -244,7 +243,7 @@ private RepositoryType GetRepositoryType(XElement packagesElement) internal virtual XDocument LoadDocument(string path) { - return XmlUtility.LoadSafe(path); + return XmlUtility.Load(path, LoadOptions.PreserveWhitespace); } private Task ProjectFinishedGeneratingAsync(Project project) diff --git a/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs b/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs index 218d17dc240..ffacb8aef38 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs @@ -29,7 +29,7 @@ using NuGet.PackageManagement; using NuGet.ProjectManagement; using NuGet.Shared; -using XmlUtility = NuGet.Common.XmlUtility; +using static NuGet.Shared.XmlUtility; #endif namespace NuGet.Build.Tasks @@ -621,7 +621,7 @@ internal static PackageSaveMode CalculateEffectivePackageSaveMode(ISettings sett { try { - XDocument xDocument = XmlUtility.Load(projectConfigFilePath); + XDocument xDocument = Load(projectConfigFilePath); var reader = new PackagesConfigReader(xDocument); return reader.GetPackages(allowDuplicatePackageIds); } diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/BuildAssetsUtils.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/BuildAssetsUtils.cs index 3e50b0a5ed5..9a048b3ff9e 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/BuildAssetsUtils.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/BuildAssetsUtils.cs @@ -16,7 +16,7 @@ using NuGet.ProjectModel; using NuGet.Repositories; using NuGet.Versioning; -using XmlUtility = NuGet.Common.XmlUtility; +using XmlUtility = NuGet.Shared.XmlUtility; namespace NuGet.Commands { diff --git a/src/NuGet.Core/NuGet.Common/Utility/XmlUtility.cs b/src/NuGet.Core/NuGet.Common/Utility/XmlUtility.cs new file mode 100644 index 00000000000..032005da74d --- /dev/null +++ b/src/NuGet.Core/NuGet.Common/Utility/XmlUtility.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Xml.Linq; +using static NuGet.Shared.XmlUtility; + +namespace NuGet.Common +{ + [Obsolete("This class is obsolete and will be removed in a future release.")] + public static class XmlUtility + { + /// + /// Creates a new System.Xml.Linq.XDocument from a file. + /// + /// A URI string that references the file to load into a new + /// An that contains the contents of the specified file. + public static XDocument Load(string filePath) + { + return Shared.XmlUtility.Load(filePath); + } + } +} diff --git a/src/NuGet.Core/NuGet.Common/XmlUtility.cs b/src/NuGet.Core/NuGet.Common/XmlUtility.cs deleted file mode 100644 index b97493ef811..00000000000 --- a/src/NuGet.Core/NuGet.Common/XmlUtility.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Xml; -using System.Xml.Linq; - -namespace NuGet.Common -{ - public static class XmlUtility - { - /// - /// Creates a new System.Xml.Linq.XDocument from a file. - /// - /// A URI string that references the file to load into a new - /// An that contains the contents of the specified file. - public static XDocument Load(string filePath) - { - if (string.IsNullOrEmpty(filePath)) - { - throw new ArgumentException(Strings.ArgumentNullOrEmpty, nameof(filePath)); - } - - using (var reader = XmlReader.Create(filePath, GetXmlReaderSettings())) - { - return XDocument.Load(reader); - } - } - - /// - /// Creates an instance of System.Xml.XmlReaderSettings with safe settings - /// - private static XmlReaderSettings GetXmlReaderSettings() - { - return new XmlReaderSettings() - { - IgnoreWhitespace = true, - IgnoreProcessingInstructions = true, - IgnoreComments = true - }; - } - } -} diff --git a/src/NuGet.Core/NuGet.Configuration/Settings/Items/CredentialsItem.cs b/src/NuGet.Core/NuGet.Configuration/Settings/Items/CredentialsItem.cs index c036d3621d1..9d349d64559 100644 --- a/src/NuGet.Core/NuGet.Configuration/Settings/Items/CredentialsItem.cs +++ b/src/NuGet.Core/NuGet.Configuration/Settings/Items/CredentialsItem.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Xml; using System.Xml.Linq; +using NuGet.Shared; namespace NuGet.Configuration { diff --git a/src/NuGet.Core/NuGet.Configuration/Settings/SettingSection.cs b/src/NuGet.Core/NuGet.Configuration/Settings/SettingSection.cs index 00a47648ff3..4f5c4082786 100644 --- a/src/NuGet.Core/NuGet.Configuration/Settings/SettingSection.cs +++ b/src/NuGet.Core/NuGet.Configuration/Settings/SettingSection.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Xml; using System.Xml.Linq; +using NuGet.Shared; namespace NuGet.Configuration { diff --git a/src/NuGet.Core/NuGet.Configuration/Settings/SettingsFile.cs b/src/NuGet.Core/NuGet.Configuration/Settings/SettingsFile.cs index bcc9cb1d977..c16e8b60248 100644 --- a/src/NuGet.Core/NuGet.Configuration/Settings/SettingsFile.cs +++ b/src/NuGet.Core/NuGet.Configuration/Settings/SettingsFile.cs @@ -111,7 +111,7 @@ public SettingsFile(string directoryPath, string fileName, bool isMachineWide, b XDocument config = null; ExecuteSynchronized(() => { - config = XmlUtility.GetOrCreateDocument(CreateDefaultConfig(), ConfigFilePath); + config = FileSystemUtility.GetOrCreateDocument(CreateDefaultConfig(), ConfigFilePath); }); _xDocument = config; diff --git a/src/NuGet.Core/NuGet.Configuration/Settings/SettingsGroup.cs b/src/NuGet.Core/NuGet.Configuration/Settings/SettingsGroup.cs index 38a85e52f33..9e3ec26536d 100644 --- a/src/NuGet.Core/NuGet.Configuration/Settings/SettingsGroup.cs +++ b/src/NuGet.Core/NuGet.Configuration/Settings/SettingsGroup.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using NuGet.Shared; namespace NuGet.Configuration { diff --git a/src/NuGet.Core/NuGet.Configuration/Utility/FileSystemUtility.cs b/src/NuGet.Core/NuGet.Configuration/Utility/FileSystemUtility.cs index 95e8d8ee1e0..8c9d9599eb3 100644 --- a/src/NuGet.Core/NuGet.Configuration/Utility/FileSystemUtility.cs +++ b/src/NuGet.Core/NuGet.Configuration/Utility/FileSystemUtility.cs @@ -5,11 +5,28 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Xml.Linq; +using NuGet.Shared; namespace NuGet.Configuration { internal static class FileSystemUtility { + internal static XDocument GetOrCreateDocument(XDocument content, string fullPath) + { + if (File.Exists(fullPath)) + { + try + { + return XmlUtility.Load(fullPath, LoadOptions.PreserveWhitespace); + } + catch (FileNotFoundException) { } + } + + AddFile(fullPath, content.Save); + return content; + } + internal static void AddFile(string fullPath, Action writeToStream) { Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); diff --git a/src/NuGet.Core/NuGet.Configuration/Utility/XmlUtility.cs b/src/NuGet.Core/NuGet.Configuration/Utility/XElementUtility.cs similarity index 70% rename from src/NuGet.Core/NuGet.Configuration/Utility/XmlUtility.cs rename to src/NuGet.Core/NuGet.Configuration/Utility/XElementUtility.cs index 7e19ccae809..bfd8b96f85a 100644 --- a/src/NuGet.Core/NuGet.Configuration/Utility/XmlUtility.cs +++ b/src/NuGet.Core/NuGet.Configuration/Utility/XElementUtility.cs @@ -9,73 +9,6 @@ namespace NuGet.Configuration { - internal static class XmlUtility - { - internal static XDocument GetOrCreateDocument(XDocument content, string fullPath) - { - if (File.Exists(fullPath)) - { - try - { - return GetDocument(fullPath); - } - catch (FileNotFoundException) - { - return CreateDocument(content, fullPath); - } - } - return CreateDocument(content, fullPath); - } - - internal static string GetEncodedXMLName(string name) - { - try - { - return XmlConvert.VerifyName(name); - } - catch (XmlException) - { - return XmlConvert.EncodeLocalName(name); - } - } - - private static XDocument CreateDocument(XDocument content, string fullPath) - { - // Add it to the file system - FileSystemUtility.AddFile(fullPath, content.Save); - return content; - } - - private static XDocument GetDocument(string fullPath) - { - using (Stream configStream = File.OpenRead(fullPath)) - { - return LoadSafe(configStream, LoadOptions.PreserveWhitespace); - } - } - - private static XDocument LoadSafe(Stream input, LoadOptions options) - { - var settings = CreateSafeSettings(); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader, options); - } - - private static XmlReaderSettings CreateSafeSettings(bool ignoreWhiteSpace = false) - { - var safeSettings = new XmlReaderSettings - { -#if !IS_CORECLR - XmlResolver = null, -#endif - DtdProcessing = DtdProcessing.Prohibit, - IgnoreWhitespace = ignoreWhiteSpace - }; - - return safeSettings; - } - } - internal static class XElementUtility { internal static string GetOptionalAttributeValue(XElement element, string localName) diff --git a/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XmlTransformer.cs b/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XmlTransformer.cs index 8e0b2a9e015..c87142e8434 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XmlTransformer.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XmlTransformer.cs @@ -71,7 +71,7 @@ public async Task TransformFileAsync( // Get the xml fragment var xmlFragment = await GetXmlAsync(streamTaskFactory, projectSystem, cancellationToken); - var transformDocument = XmlUtility.GetOrCreateDocument(xmlFragment.Name, targetPath, projectSystem); + var transformDocument = MSBuildNuGetProjectSystemUtility.GetOrCreateDocument(xmlFragment.Name, targetPath, projectSystem); // Do a merge transformDocument.Root.MergeWith(xmlFragment, _nodeActions); diff --git a/src/NuGet.Core/NuGet.PackageManagement/Utility/MSBuildNuGetProjectSystemUtility.cs b/src/NuGet.Core/NuGet.PackageManagement/Utility/MSBuildNuGetProjectSystemUtility.cs index 7020eeaa240..8d5458dff6e 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/Utility/MSBuildNuGetProjectSystemUtility.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/Utility/MSBuildNuGetProjectSystemUtility.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Xml.Linq; using NuGet.Common; using NuGet.Frameworks; using NuGet.PackageManagement; @@ -19,6 +20,24 @@ namespace NuGet.ProjectManagement { public static class MSBuildNuGetProjectSystemUtility { + internal static XDocument GetOrCreateDocument(XName rootName, string path, IMSBuildProjectSystem msBuildNuGetProjectSystem) + { + if (File.Exists(Path.Combine(msBuildNuGetProjectSystem.ProjectFullPath, path))) + { + try + { + return Shared.XmlUtility.Load(Path.Combine(msBuildNuGetProjectSystem.ProjectFullPath, path), LoadOptions.PreserveWhitespace); + } + catch (FileNotFoundException) { } + } + + var document = new XDocument(new XElement(rootName)); + // Add it to the project system + AddFile(msBuildNuGetProjectSystem, path, document.Save); + + return document; + } + public static FrameworkSpecificGroup GetMostCompatibleGroup(NuGetFramework projectTargetFramework, IEnumerable itemGroups) { diff --git a/src/NuGet.Core/NuGet.PackageManagement/Utility/XmlUtility.cs b/src/NuGet.Core/NuGet.PackageManagement/Utility/XmlUtility.cs index 56cd5842e80..bf774799bd7 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/Utility/XmlUtility.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/Utility/XmlUtility.cs @@ -1,70 +1,47 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; using System.Xml; using System.Xml.Linq; +using XmlUtility = NuGet.Shared.XmlUtility; namespace NuGet.ProjectManagement { public static class XmlUtility { + [Obsolete("This method is obsolete and will be removed in a future release.")] public static XDocument LoadSafe(string filePath) { - var settings = CreateSafeSettings(); - using (var reader = XmlReader.Create(filePath, settings)) - { - return XDocument.Load(reader); - } + return Shared.XmlUtility.Load(filePath); } + [Obsolete("This method is obsolete and will be removed in a future release.")] public static XDocument LoadSafe(Stream input) { - var settings = CreateSafeSettings(); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader); + return Shared.XmlUtility.Load(input); } + [Obsolete("This method is obsolete and will be removed in a future release.")] public static XDocument LoadSafe(Stream input, bool ignoreWhiteSpace) { - var settings = CreateSafeSettings(ignoreWhiteSpace); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader); - } + if (ignoreWhiteSpace) + return Shared.XmlUtility.Load(input); - public static XDocument LoadSafe(Stream input, LoadOptions options) - { - var settings = CreateSafeSettings(); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader, options); + return Shared.XmlUtility.Load(input, LoadOptions.PreserveWhitespace); } - private static XmlReaderSettings CreateSafeSettings(bool ignoreWhiteSpace = false) + [Obsolete("This method is obsolete and will be removed in a future release.")] + public static XDocument LoadSafe(Stream input, LoadOptions options) { - var safeSettings = new XmlReaderSettings - { - XmlResolver = null, - DtdProcessing = DtdProcessing.Prohibit, - IgnoreWhitespace = ignoreWhiteSpace - }; - - return safeSettings; + return Shared.XmlUtility.Load(input, options); } + [Obsolete("This method is obsolete and will be removed in a future release.")] public static XDocument GetOrCreateDocument(XName rootName, string path, IMSBuildProjectSystem msBuildNuGetProjectSystem) { - if (File.Exists(Path.Combine(msBuildNuGetProjectSystem.ProjectFullPath, path))) - { - try - { - return GetDocument(msBuildNuGetProjectSystem.ProjectFullPath, path); - } - catch (FileNotFoundException) - { - return CreateDocument(rootName, path, msBuildNuGetProjectSystem); - } - } - return CreateDocument(rootName, path, msBuildNuGetProjectSystem); + return MSBuildNuGetProjectSystemUtility.GetOrCreateDocument(rootName, path, msBuildNuGetProjectSystem); } public static XDocument GetOrCreateDocument(XName rootName, string root, string path, INuGetProjectContext nuGetProjectContext) @@ -73,16 +50,15 @@ public static XDocument GetOrCreateDocument(XName rootName, string root, string { try { - return GetDocument(root, path); - } - catch (FileNotFoundException) - { - return CreateDocument(rootName, root, path, nuGetProjectContext); + return Shared.XmlUtility.Load(Path.Combine(root, path), LoadOptions.PreserveWhitespace); } + catch (FileNotFoundException) { } } + return CreateDocument(rootName, root, path, nuGetProjectContext); } + [Obsolete("This method is obsolete and will be removed in a future release.")] public static XDocument CreateDocument(XName rootName, string path, IMSBuildProjectSystem msBuildNuGetProjectSystem) { var document = new XDocument(new XElement(rootName)); @@ -99,6 +75,7 @@ public static XDocument CreateDocument(XName rootName, string root, string path, return document; } + [Obsolete("This method is obsolete and will be removed in a future release.")] public static XDocument GetDocument(string root, string path) { var fullPath = Path.Combine(root, path); @@ -108,6 +85,7 @@ public static XDocument GetDocument(string root, string path) } } + [Obsolete("This method is obsolete and will be removed in a future release.")] public static bool TryParseDocument(string content, out XDocument document) { document = null; diff --git a/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs index 75988843f1f..8a27d889dc0 100644 --- a/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs @@ -246,8 +246,6 @@ [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'XElement XElementExtensions.Except(XElement source, XElement target)', validate parameter 'source' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.XElementExtensions.Except(System.Xml.Linq.XElement,System.Xml.Linq.XElement)~System.Xml.Linq.XElement")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'string XElementExtensions.GetOptionalAttributeValue(XElement element, string localName, string namespaceName = null)', validate parameter 'element' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.XElementExtensions.GetOptionalAttributeValue(System.Xml.Linq.XElement,System.String,System.String)~System.String")] [assembly: SuppressMessage("Build", "CA1308:In method 'GetXElementFromLicenseMetadata', replace the call to 'ToLowerInvariant' with 'ToUpperInvariant'.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.Xml.PackageMetadataXmlExtensions.GetXElementFromLicenseMetadata(System.Xml.Linq.XNamespace,NuGet.Packaging.LicenseMetadata)~System.Xml.Linq.XElement")] -[assembly: SuppressMessage("Build", "CA2000:Call System.IDisposable.Dispose on object created by 'XmlReader.Create(input, settings)' before all references to it are out of scope.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.XmlUtility.LoadSafe(System.IO.Stream)~System.Xml.Linq.XDocument")] -[assembly: SuppressMessage("Build", "CA2000:Call System.IDisposable.Dispose on object created by 'XmlReader.Create(input, settings)' before all references to it are out of scope.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.XmlUtility.LoadSafe(System.IO.Stream,System.Boolean)~System.Xml.Linq.XDocument")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'IEnumerable ZipArchiveExtensions.GetFiles(ZipArchive zipArchive)', validate parameter 'zipArchive' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.ZipArchiveExtensions.GetFiles(System.IO.Compression.ZipArchive)~System.Collections.Generic.IEnumerable{System.String}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'ZipArchiveEntry ZipArchiveExtensions.LookupEntry(ZipArchive zipArchive, string path)', validate parameter 'zipArchive' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.ZipArchiveExtensions.LookupEntry(System.IO.Compression.ZipArchive,System.String)~System.IO.Compression.ZipArchiveEntry")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'string ZipArchiveExtensions.SaveAsFile(ZipArchiveEntry entry, string fileFullPath, ILogger logger)', validate parameter 'entry' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Packaging.ZipArchiveExtensions.SaveAsFile(System.IO.Compression.ZipArchiveEntry,System.String,NuGet.Common.ILogger)~System.String")] diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/Manifest.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/Manifest.cs index 004386e9028..cc70500f0d3 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/Manifest.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/Manifest.cs @@ -12,6 +12,7 @@ using NuGet.Packaging.Core; using NuGet.Packaging.PackageCreation.Resources; using NuGet.Packaging.Xml; +using static NuGet.Shared.XmlUtility; namespace NuGet.Packaging { @@ -114,7 +115,7 @@ public static Manifest ReadFrom(Stream stream, Func propertyProv XDocument document; if (propertyProvider == null) { - document = XmlUtility.LoadSafe(stream, ignoreWhiteSpace: true); + document = Load(stream); } else { diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Utility/XmlUtility.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Utility/XmlUtility.cs index 864ada15351..23675a7cf69 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Utility/XmlUtility.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Utility/XmlUtility.cs @@ -1,38 +1,27 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; -using System.Xml; using System.Xml.Linq; +using XmlUtility = NuGet.Shared.XmlUtility; namespace NuGet.Packaging { + [Obsolete("This class is obsolete and will be removed in a future release.")] public static class XmlUtility { public static XDocument LoadSafe(Stream input) { - var settings = CreateSafeSettings(); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader); + return Shared.XmlUtility.Load(input); } public static XDocument LoadSafe(Stream input, bool ignoreWhiteSpace) { - var settings = CreateSafeSettings(ignoreWhiteSpace); - var reader = XmlReader.Create(input, settings); - return XDocument.Load(reader); - } - - private static XmlReaderSettings CreateSafeSettings(bool ignoreWhiteSpace = false) - { - var safeSettings = new XmlReaderSettings - { - DtdProcessing = DtdProcessing.Prohibit, - IgnoreWhitespace = ignoreWhiteSpace - }; + if (ignoreWhiteSpace) + return Shared.XmlUtility.Load(input); - return safeSettings; + return Shared.XmlUtility.Load(input, LoadOptions.PreserveWhitespace); } } } - diff --git a/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj b/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj index 841aab1d94e..de2a9e909d5 100644 --- a/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj +++ b/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj @@ -14,6 +14,9 @@ + + + diff --git a/test/NuGet.Core.Tests/NuGet.Common.Test/XmlUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Shared.Tests/XmlUtilityTests.cs similarity index 66% rename from test/NuGet.Core.Tests/NuGet.Common.Test/XmlUtilityTests.cs rename to test/NuGet.Core.Tests/NuGet.Shared.Tests/XmlUtilityTests.cs index b3b21ad3489..5e1d575e84f 100644 --- a/test/NuGet.Core.Tests/NuGet.Common.Test/XmlUtilityTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Shared.Tests/XmlUtilityTests.cs @@ -9,22 +9,22 @@ using NuGet.Test.Utility; using Xunit; -namespace NuGet.Common.Test +namespace NuGet.Shared.Test { public class XmlUtilityTests { [Fact] - public void Load_WhenFilePathIsNull_Throws() + public void Load_FilePathIsNull_Throws() { //Act - var exception = Assert.Throws(() => XmlUtility.Load(filePath: null)); + var exception = Assert.Throws(() => XmlUtility.Load(inputUri: null)); //Assert - Assert.Equal("filePath", exception.ParamName); + Assert.Equal("inputUri", exception.ParamName); } [Fact] - public void Load_WhenFileWithSecureXmlIsPassedAsArgument_Success() + public void Load_FileWithSecureXml_Success() { using (var root = TestDirectory.Create()) { @@ -50,7 +50,7 @@ public void Load_WhenFileWithSecureXmlIsPassedAsArgument_Success() } [Fact] - public void Load_WhenFileWithInSecureXmlIsPassedAsArgument_Throws() + public void Load_FileWithInSecureXml_Throws() { using (var root = TestDirectory.Create()) { @@ -74,5 +74,26 @@ public void Load_WhenFileWithInSecureXmlIsPassedAsArgument_Throws() Assert.Throws(() => XmlUtility.Load(path)); } } + + [Fact] + public void GetEncodedXMLName_ValidXmlElementNameMatchesInput_Success() + { + string validXml = "packageSources"; + + string encodedXml = XmlUtility.GetEncodedXMLName(validXml); + + Assert.Equal(validXml, encodedXml); + } + + [Fact] + public void GetEncodedXMLName_EncodesInValidXmlElementName_Success() + { + string invalidXml = "package Sources"; + + string encodedXml = XmlUtility.GetEncodedXMLName(invalidXml); + + Assert.NotEqual(invalidXml, encodedXml); + Assert.Equal(encodedXml, "package_x0020_Sources"); + } } } From e5382be081c7dc513acf6ad09cdedf818c3d6bf4 Mon Sep 17 00:00:00 2001 From: Marcin Krystianc Date: Wed, 4 Nov 2020 20:02:43 +0100 Subject: [PATCH 031/129] Adding support for pushing multiple packages (#3739) * support for pushing multiple packages * timeout for all packages * tests * update obsolete messages * reduce diff noise * Revert "reduce diff noise" * update call sites * addressing PR comments * formatting * add test for one or more pushed paths * reduce the diff noise * testing push by filename and by wildcard * Delete result.txt * revert change for NuGet.exe * test correct path * - Reverting NuGet.CommandLine tests - Adding NuGet.XPlat tests * - Reverting NuGet.CommandLine tests - Adding NuGet.XPlat tests --- .../NuGet.CommandLine/Commands/PushCommand.cs | 2 +- .../Commands/PushCommand.cs | 5 +- .../CommandRunners/PushRunner.cs | 36 +++++++++++- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 3 +- .../netcoreapp5.0/PublicAPI.Unshipped.txt | 1 + .../netstandard2.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net472/PublicAPI.Unshipped.txt | 1 + .../netcoreapp5.0/PublicAPI.Unshipped.txt | 1 + .../netstandard2.0/PublicAPI.Unshipped.txt | 1 + .../Resources/PackageUpdateResource.cs | 55 +++++++++++++------ .../NuGet.XPlat.FuncTest/XPlatPushTests.cs | 41 ++++++++++++++ .../NuGet.Commands.Test/PushCommandTests.cs | 15 +++-- .../Resources/PackageUpdateResourceTests.cs | 32 +++++------ 13 files changed, 149 insertions(+), 45 deletions(-) diff --git a/src/NuGet.Clients/NuGet.CommandLine/Commands/PushCommand.cs b/src/NuGet.Clients/NuGet.CommandLine/Commands/PushCommand.cs index c734c09e86d..1ce493590a6 100644 --- a/src/NuGet.Clients/NuGet.CommandLine/Commands/PushCommand.cs +++ b/src/NuGet.Clients/NuGet.CommandLine/Commands/PushCommand.cs @@ -62,7 +62,7 @@ public override async Task ExecuteCommandAsync() await PushRunner.Run( Settings, SourceProvider, - packagePath, + new[] { packagePath }, Source, apiKeyValue, SymbolSource, diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs index 2e5341b60ab..a5967f6ae37 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/PushCommand.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.CommandLineUtils; using NuGet.Commands; @@ -87,7 +88,7 @@ public static void Register(CommandLineApplication app, Func getLogger) throw new ArgumentException(Strings.Push_MissingArguments); } - string packagePath = arguments.Values[0]; + IList packagePaths = arguments.Values; string sourcePath = source.Value(); string apiKeyValue = apikey.Value(); string symbolSourcePath = symbolSource.Value(); @@ -113,7 +114,7 @@ public static void Register(CommandLineApplication app, Func getLogger) await PushRunner.Run( sourceProvider.Settings, sourceProvider, - packagePath, + packagePaths, sourcePath, apiKeyValue, symbolSourcePath, diff --git a/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs b/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs index 66808b5a318..b9f36a51a48 100644 --- a/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs +++ b/src/NuGet.Core/NuGet.Commands/CommandRunners/PushRunner.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Threading.Tasks; using NuGet.Common; using NuGet.Configuration; @@ -17,7 +18,7 @@ public static class PushRunner public static async Task Run( ISettings settings, IPackageSourceProvider sourceProvider, - string packagePath, + IList packagePaths, string source, string apiKey, string symbolSource, @@ -57,7 +58,7 @@ public static async Task Run( } await packageUpdateResource.Push( - packagePath, + packagePaths, symbolSource, timeoutSeconds, disableBuffering, @@ -68,5 +69,36 @@ await packageUpdateResource.Push( symbolPackageUpdateResource, logger); } + + [Obsolete("Use Run method which takes multiple package paths.")] + public static Task Run( + ISettings settings, + IPackageSourceProvider sourceProvider, + string packagePath, + string source, + string apiKey, + string symbolSource, + string symbolApiKey, + int timeoutSeconds, + bool disableBuffering, + bool noSymbols, + bool noServiceEndpoint, + bool skipDuplicate, + ILogger logger) + { + return Run(settings: settings, + sourceProvider: sourceProvider, + packagePaths: new[] { packagePath }, + source: source, + apiKey: apiKey, + symbolSource: symbolSource, + symbolApiKey: symbolApiKey, + timeoutSeconds: timeoutSeconds, + disableBuffering: disableBuffering, + noSymbols: noSymbols, + noServiceEndpoint: noServiceEndpoint, + skipDuplicate: skipDuplicate, + logger: logger); + } } } diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt index 48f39c597df..f139652d4be 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList NuGet.Commands.VerifyArgs.PackagePaths.set -> void -static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework \ No newline at end of file +static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework +static NuGet.Commands.PushRunner.Run(NuGet.Configuration.ISettings settings, NuGet.Configuration.IPackageSourceProvider sourceProvider, System.Collections.Generic.IList packagePaths, string source, string apiKey, string symbolSource, string symbolApiKey, int timeoutSeconds, bool disableBuffering, bool noSymbols, bool noServiceEndpoint, bool skipDuplicate, NuGet.Common.ILogger logger) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt index 7b35bec2079..f139652d4be 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList NuGet.Commands.VerifyArgs.PackagePaths.set -> void static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework +static NuGet.Commands.PushRunner.Run(NuGet.Configuration.ISettings settings, NuGet.Configuration.IPackageSourceProvider sourceProvider, System.Collections.Generic.IList packagePaths, string source, string apiKey, string symbolSource, string symbolApiKey, int timeoutSeconds, bool disableBuffering, bool noSymbols, bool noServiceEndpoint, bool skipDuplicate, NuGet.Common.ILogger logger) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 7b35bec2079..f139652d4be 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList NuGet.Commands.VerifyArgs.PackagePaths.set -> void static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework +static NuGet.Commands.PushRunner.Run(NuGet.Configuration.ISettings settings, NuGet.Configuration.IPackageSourceProvider sourceProvider, System.Collections.Generic.IList packagePaths, string source, string apiKey, string symbolSource, string symbolApiKey, int timeoutSeconds, bool disableBuffering, bool noSymbols, bool noServiceEndpoint, bool skipDuplicate, NuGet.Common.ILogger logger) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index d34e9d8eef0..d5fdde29f64 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -11,3 +11,4 @@ NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string const NuGet.Protocol.JsonProperties.Severity = "severity" -> string const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string +NuGet.Protocol.Core.Types.PackageUpdateResource.Push(System.Collections.Generic.IList packagePaths, string symbolSource, int timeoutInSecond, bool disableBuffering, System.Func getApiKey, System.Func getSymbolApiKey, bool noServiceEndpoint, bool skipDuplicate, NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, NuGet.Common.ILogger log) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt index d34e9d8eef0..d5fdde29f64 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt @@ -11,3 +11,4 @@ NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string const NuGet.Protocol.JsonProperties.Severity = "severity" -> string const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string +NuGet.Protocol.Core.Types.PackageUpdateResource.Push(System.Collections.Generic.IList packagePaths, string symbolSource, int timeoutInSecond, bool disableBuffering, System.Func getApiKey, System.Func getSymbolApiKey, bool noServiceEndpoint, bool skipDuplicate, NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, NuGet.Common.ILogger log) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index d34e9d8eef0..d5fdde29f64 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -11,3 +11,4 @@ NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string const NuGet.Protocol.JsonProperties.Severity = "severity" -> string const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string +NuGet.Protocol.Core.Types.PackageUpdateResource.Push(System.Collections.Generic.IList packagePaths, string symbolSource, int timeoutInSecond, bool disableBuffering, System.Func getApiKey, System.Func getSymbolApiKey, bool noServiceEndpoint, bool skipDuplicate, NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, NuGet.Common.ILogger log) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/Resources/PackageUpdateResource.cs b/src/NuGet.Core/NuGet.Protocol/Resources/PackageUpdateResource.cs index 9ca4abb3259..40c3bb9ff5c 100644 --- a/src/NuGet.Core/NuGet.Protocol/Resources/PackageUpdateResource.cs +++ b/src/NuGet.Core/NuGet.Protocol/Resources/PackageUpdateResource.cs @@ -54,7 +54,7 @@ public Uri SourceUri } public async Task Push( - string packagePath, + IList packagePaths, string symbolSource, // empty to not push symbols int timeoutInSecond, bool disableBuffering, @@ -74,31 +74,50 @@ public async Task Push( tokenSource.CancelAfter(requestTimeout); var apiKey = getApiKey(_source); - bool explicitSnupkgPush = true; - - if (!packagePath.EndsWith(NuGetConstants.SnupkgExtension, StringComparison.OrdinalIgnoreCase)) + foreach (var packagePath in packagePaths) { - await PushPackage(packagePath, _source, apiKey, noServiceEndpoint, skipDuplicate, - requestTimeout, log, tokenSource.Token); + bool explicitSnupkgPush = true; + if (!packagePath.EndsWith(NuGetConstants.SnupkgExtension, StringComparison.OrdinalIgnoreCase)) + { + await PushPackage(packagePath, _source, apiKey, noServiceEndpoint, skipDuplicate, + requestTimeout, log, tokenSource.Token); - //Since this was not a snupkg push (probably .nupkg), when we try pushing symbols later, don't error if there are no snupkg files found. - explicitSnupkgPush = false; - } + //Since this was not a snupkg push (probably .nupkg), when we try pushing symbols later, don't error if there are no snupkg files found. + explicitSnupkgPush = false; + } - // symbolSource is only set when: - // - The user specified it on the command line - // - The endpoint for main package supports pushing snupkgs - if (!string.IsNullOrEmpty(symbolSource)) - { - var symbolApiKey = getSymbolApiKey(symbolSource); + // symbolSource is only set when: + // - The user specified it on the command line + // - The endpoint for main package supports pushing snupkgs + if (!string.IsNullOrEmpty(symbolSource)) + { + var symbolApiKey = getSymbolApiKey(symbolSource); - await PushSymbols(packagePath, symbolSource, symbolApiKey, - noServiceEndpoint, skipDuplicate, symbolPackageUpdateResource, - requestTimeout, log, explicitSnupkgPush, tokenSource.Token); + await PushSymbols(packagePath, symbolSource, symbolApiKey, + noServiceEndpoint, skipDuplicate, symbolPackageUpdateResource, + requestTimeout, log, explicitSnupkgPush, tokenSource.Token); + } } } } + [Obsolete("Use Push method which takes multiple package paths.")] + public Task Push( + string packagePath, + string symbolSource, // empty to not push symbols + int timeoutInSecond, + bool disableBuffering, + Func getApiKey, + Func getSymbolApiKey, + bool noServiceEndpoint, + bool skipDuplicate, + SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, + ILogger log) + { + return Push(new[] { packagePath }, symbolSource, timeoutInSecond, disableBuffering, getApiKey, + getSymbolApiKey, noServiceEndpoint, skipDuplicate, symbolPackageUpdateResource, log); + } + [Obsolete("Consolidating to one PackageUpdateResource.Push method which has all parameters defined.")] public async Task Push( string packagePath, diff --git a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs index 54eb8219ff3..6c71c1d18cc 100644 --- a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatPushTests.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.Linq; using System.Threading.Tasks; using NuGet.Configuration; using NuGet.Test.Utility; @@ -147,6 +149,45 @@ public async Task PushToServerSucceeds_DeleteFirst(PackageSource packageSource) } } + // Tests pushing multiple packages (multiple paths) + [Fact] + public async Task PushMultiplePathsToFileSystemSource() + { + using (var packageDirectory = TestDirectory.Create()) + using (var source = TestDirectory.Create()) + { + // Arrange + var log = new TestCommandOutputLogger(); + var packageInfoCollection = new[] + { + await TestPackagesCore.GetRuntimePackageAsync(packageDirectory, "testPackageA", "1.1.0"), + await TestPackagesCore.GetRuntimePackageAsync(packageDirectory, "testPackageB", "1.1.0"), + }; + + var pushArgs = new List + { + "push", + packageInfoCollection[0].FullName, + packageInfoCollection[1].FullName, + "--source", + source, + }; + + // Act + var exitCode = CommandLine.XPlat.Program.MainInternal(pushArgs.ToArray(), log); + + // Assert + Assert.Equal(string.Empty, log.ShowErrors()); + Assert.Equal(0, exitCode); + + foreach (var packageInfo in packageInfoCollection) + { + Assert.Contains($"Pushing {packageInfo.Name}", log.ShowMessages()); + Assert.True(File.Exists(Path.Combine(source, packageInfo.Name))); + } + } + } + /// /// This is called when the package must be deleted before being pushed. It's ok if this /// fails, maybe the package was never pushed. diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/PushCommandTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/PushCommandTests.cs index 0e2357f1e5d..e08154980b2 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/PushCommandTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/PushCommandTests.cs @@ -33,13 +33,17 @@ public async Task PushCommand_AbsolutePathSourceAsync() new PackageSource(packagePushDest.FullName) }; - var packageInfo = await SimpleTestPackageUtility.CreateFullPackageAsync(workingDir, "test", "1.0.0"); + var packageInfoCollection = new[] + { + await SimpleTestPackageUtility.CreateFullPackageAsync(workingDir, "test1", "1.0.0"), + await SimpleTestPackageUtility.CreateFullPackageAsync(workingDir, "test2", "1.0.0") + }; // Act await PushRunner.Run( Settings.LoadDefaultSettings(null, null, null), new TestPackageSourceProvider(packageSources), - packageInfo.FullName, + new[] { packageInfoCollection[0].FullName, packageInfoCollection[1].FullName }, packagePushDest.FullName, null, // api key null, // symbols source @@ -52,8 +56,11 @@ await PushRunner.Run( new TestLogger()); // Assert - var destFile = Path.Combine(packagePushDest.FullName, packageInfo.Name); - Assert.Equal(true, File.Exists(destFile)); + foreach (var packageInfo in packageInfoCollection) + { + var destFile = Path.Combine(packagePushDest.FullName, packageInfo.Name); + Assert.True(File.Exists(destFile)); + } } } } diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Resources/PackageUpdateResourceTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Resources/PackageUpdateResourceTests.cs index ae052a39ad9..8109821e828 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Resources/PackageUpdateResourceTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Resources/PackageUpdateResourceTests.cs @@ -144,7 +144,7 @@ public async Task PackageUpdateResource_AllowsApiKeyWhenPushingAsync() // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, @@ -198,7 +198,7 @@ public async Task PackageUpdateResource_AllowsNoApiKeyWhenPushingAsync() // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, @@ -287,7 +287,7 @@ public async Task PackageUpdateResource_SourceAndSymbolNuGetOrgPushingAsync(stri // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: symbolSource, timeoutInSecond: 5, disableBuffering: false, @@ -353,7 +353,7 @@ public async Task PackageUpdateResource_NuGetOrgSourceOnlyPushingAsync() // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: symbolSource, timeoutInSecond: 5, disableBuffering: false, @@ -427,7 +427,7 @@ public async Task PackageUpdateResource_SymbolSourceOnlyPushingAsync() // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: symbolSource, timeoutInSecond: 5, disableBuffering: false, @@ -503,7 +503,7 @@ public async Task PackageUpdateResource_NoSymbolSourcePushingSymbolAsync(string // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, @@ -556,7 +556,7 @@ public async Task PackageUpdateResource_NoServiceEndpointOnCustomServerAsync() // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, @@ -606,7 +606,7 @@ public async Task PackageUpdateResource_NoServiceEndpointOnCustomServer_ShouldAd // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, @@ -669,7 +669,7 @@ public async Task PackageUpdateResource_PackageNotExistOnNuGetOrgPushingAsync() // Act await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, @@ -704,21 +704,20 @@ public async Task PackageUpdateResource_GetErrorFromCreateKeyPushingAsync() var apiKey = "serverapikey"; var packageInfo = await SimpleTestPackageUtility.CreateFullPackageAsync(workingDir, "test", "1.0.0"); - var symbolPackageInfo = await SimpleTestPackageUtility.CreateSymbolPackageAsync(workingDir, "test", "1.0.0"); + var symbolPackageInfo = + await SimpleTestPackageUtility.CreateSymbolPackageAsync(workingDir, "test", "1.0.0"); var responses = new Dictionary>> { { - "https://www.myget.org/api/v2/", - request => + "https://www.myget.org/api/v2/", request => { sourceRequest = request; return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)); } }, { - "https://nuget.smbsrc.net/api/v2/package/", - request => + "https://nuget.smbsrc.net/api/v2/package/", request => { symbolRequest = request; return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)); @@ -731,7 +730,6 @@ public async Task PackageUpdateResource_GetErrorFromCreateKeyPushingAsync() return Task.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError)); } } - }; var repo = StaticHttpHandler.CreateSource(source, Repository.Provider.GetCoreV3(), responses); @@ -741,7 +739,7 @@ public async Task PackageUpdateResource_GetErrorFromCreateKeyPushingAsync() // Act var ex = await Assert.ThrowsAsync( async () => await resource.Push( - packagePath: packageInfo.FullName, + packagePaths: new[] { packageInfo.FullName }, symbolSource: symbolSource, timeoutInSecond: 5, disableBuffering: false, @@ -808,7 +806,7 @@ public async Task PackageUpdateResource_RetryNuGetSymbolPushingAsync() // Act await resource.Push( - packagePath: symbolPackageInfo.FullName, + packagePaths: new[] { symbolPackageInfo.FullName }, symbolSource: null, timeoutInSecond: 5, disableBuffering: false, From 49a0be72b4aabcdf2e955b7960ab41d20710616c Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Wed, 4 Nov 2020 14:34:05 -0800 Subject: [PATCH 032/129] Remove dead code, ProjectK (xproj) code & LSL code (#3750) --- NuGet.sln | 1 - build/NuGet-WithApex.sln | 1 - .../Commands/ProjectFactory.cs | 1 - .../NuGet.CommandLine/GlobalSuppressions.cs | 1 - .../Cmdlets/InstallPackageCommand.cs | 4 - .../PackageActionBaseCommand.cs | 5 - .../GlobalSuppressions.cs | 4 - ...uGet.PackageManagement.VisualStudio.csproj | 10 - .../DeferredProjectCapabilities.cs | 15 -- .../DeferredProjectServicesProxy.cs | 95 -------- .../WorkspaceProjectBuildProperties.cs | 53 ----- .../WorkspaceProjectServices.cs | 129 ---------- .../MSBuildNuGetProjectSystemFactory.cs | 7 - .../CpsPackageReferenceProjectProvider.cs | 1 - .../Projects/IVsProjectAdapterProvider.cs | 7 - .../LegacyPackageReferenceProjectProvider.cs | 67 +----- .../Projects/MSBuildNuGetProjectProvider.cs | 14 +- .../Projects/ProjectJsonProjectProvider.cs | 14 +- .../Projects/ProjectKNuGetProject.cs | 220 ------------------ .../Projects/ProjectKNuGetProjectProvider.cs | 49 ---- .../Projects/VsProjectAdapter.cs | 44 +--- .../Projects/VsProjectAdapterProvider.cs | 11 - .../DeferredProjectWorkspaceService.cs | 120 ---------- .../Telemetry/NuGetProjectType.cs | 5 - .../Telemetry/VSTelemetryServiceUtility.cs | 6 - .../Utility/EnvDTEProjectUtility.cs | 54 ----- .../VSNuGetProjectFactory.cs | 191 --------------- .../NuGet.Tools/GlobalSuppressions.cs | 1 - src/NuGet.Clients/NuGet.Tools/Guids.cs | 1 - .../IVsProjectAdapter.cs | 2 - .../IDeferredProjectWorkspaceService.cs | 20 -- .../ProjectContextInfo.cs | 4 - .../Utils/InstalledPackageEnumerator.cs | 8 +- .../GlobalSuppressions.cs | 1 - .../Utility/MSBuildAPIUtility.cs | 1 - .../NuGet.Commands/GlobalSuppressions.cs | 2 - .../NuGet.Commands/MSBuildProjectFactory.cs | 2 - .../GlobalSuppressions.cs | 1 - .../GraphModel/GraphOperations.cs | 1 - .../NuGet.Frameworks/GlobalSuppressions.cs | 1 - .../NuGet.Frameworks/NuGetFramework.cs | 1 - .../InstallationCompatibility.cs | 9 - .../Projects/ProjectKNuGetProject.cs | 10 - .../PublicAPI.Shipped.txt | 2 - .../NuGet.Packaging/GlobalSuppressions.cs | 2 - .../NuGet.Packaging/PackageArchiveReader.cs | 1 - .../Authoring/PackageBuilder.cs | 1 - .../Rules/UnrecognizedScriptFileRule.cs | 1 - .../NuGet.Protocol/GlobalSuppressions.cs | 6 - .../LegacyFeedCapabilityResourceV2Feed.cs | 5 - .../RemoteV2FindPackageByIdResource.cs | 5 - .../Resources/ServiceIndexResourceV3.cs | 1 - ...PackageManagement.VisualStudio.Test.csproj | 1 - .../ProjectKNuGetProjectTests.cs | 200 ---------------- .../Telemetry/NuGetTelemetryServiceTests.cs | 1 - .../InstallationCompatibilityTests.cs | 145 ------------ .../TestProjectKNuGetProject.cs | 55 ----- 57 files changed, 24 insertions(+), 1596 deletions(-) delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectCapabilities.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectServicesProxy.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectBuildProperties.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectServices.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProject.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProjectProvider.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/DeferredProjectWorkspaceService.cs delete mode 100644 src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/VSNuGetProjectFactory.cs delete mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/Services/IDeferredProjectWorkspaceService.cs delete mode 100644 src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectKNuGetProject.cs delete mode 100644 test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/ProjectKNuGetProjectTests.cs delete mode 100644 test/NuGet.Core.Tests/NuGet.PackageManagement.Test/TestProjectKNuGetProject.cs diff --git a/NuGet.sln b/NuGet.sln index 4096c07d028..883cb141eb0 100644 --- a/NuGet.sln +++ b/NuGet.sln @@ -57,7 +57,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{96255044 test\EndToEnd\tests\OpenPackagePageTest.ps1 = test\EndToEnd\tests\OpenPackagePageTest.ps1 test\EndToEnd\tests\PackageRestoreTest.ps1 = test\EndToEnd\tests\PackageRestoreTest.ps1 test\EndToEnd\tests\PackTest.ps1 = test\EndToEnd\tests\PackTest.ps1 - test\EndToEnd\tests\ProjectKTest.ps1 = test\EndToEnd\tests\ProjectKTest.ps1 test\EndToEnd\tests\ProjectRetargeting.ps1 = test\EndToEnd\tests\ProjectRetargeting.ps1 test\EndToEnd\tests\ServicesTest.ps1 = test\EndToEnd\tests\ServicesTest.ps1 test\EndToEnd\tests\Settings.ps1 = test\EndToEnd\tests\Settings.ps1 diff --git a/build/NuGet-WithApex.sln b/build/NuGet-WithApex.sln index 1138c863422..c9912943c38 100644 --- a/build/NuGet-WithApex.sln +++ b/build/NuGet-WithApex.sln @@ -52,7 +52,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{96255044 ..\test\EndToEnd\tests\OpenPackagePageTest.ps1 = ..\test\EndToEnd\tests\OpenPackagePageTest.ps1 ..\test\EndToEnd\tests\PackageRestoreTest.ps1 = ..\test\EndToEnd\tests\PackageRestoreTest.ps1 ..\test\EndToEnd\tests\PackTest.ps1 = ..\test\EndToEnd\tests\PackTest.ps1 - ..\test\EndToEnd\tests\ProjectKTest.ps1 = ..\test\EndToEnd\tests\ProjectKTest.ps1 ..\test\EndToEnd\tests\ProjectRetargeting.ps1 = ..\test\EndToEnd\tests\ProjectRetargeting.ps1 ..\test\EndToEnd\tests\ServicesTest.ps1 = ..\test\EndToEnd\tests\ServicesTest.ps1 ..\test\EndToEnd\tests\Settings.ps1 = ..\test\EndToEnd\tests\Settings.ps1 diff --git a/src/NuGet.Clients/NuGet.CommandLine/Commands/ProjectFactory.cs b/src/NuGet.Clients/NuGet.CommandLine/Commands/ProjectFactory.cs index 371c8a2bd2d..a3acef87294 100644 --- a/src/NuGet.Clients/NuGet.CommandLine/Commands/ProjectFactory.cs +++ b/src/NuGet.Clients/NuGet.CommandLine/Commands/ProjectFactory.cs @@ -59,7 +59,6 @@ public class ProjectFactory : MSBuildUser, IProjectFactory, CoreV2.NuGet.IProper private const string ContentItemType = "Content"; private const string ProjectReferenceItemType = "ProjectReference"; private const string ReferenceOutputAssembly = "ReferenceOutputAssembly"; - private const string PackagesFolder = "packages"; private const string TransformFileExtension = ".transform"; [Import] diff --git a/src/NuGet.Clients/NuGet.CommandLine/GlobalSuppressions.cs b/src/NuGet.Clients/NuGet.CommandLine/GlobalSuppressions.cs index a9273c5f4b9..58d0ba8d527 100644 --- a/src/NuGet.Clients/NuGet.CommandLine/GlobalSuppressions.cs +++ b/src/NuGet.Clients/NuGet.CommandLine/GlobalSuppressions.cs @@ -10,7 +10,6 @@ [assembly: SuppressMessage("Build", "CA1802:Field 'UserAgent' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.CommandLine.CommandLineConstants.UserAgent")] [assembly: SuppressMessage("Build", "CA1802:Field 'CredentialProviderPattern' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.CommandLine.ExtensionLocator.CredentialProviderPattern")] -[assembly: SuppressMessage("Build", "CA1823:Unused field 'PackagesFolder'.", Justification = "", Scope = "member", Target = "~F:NuGet.CommandLine.ProjectFactory.PackagesFolder")] [assembly: SuppressMessage("Build", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "member", Target = "~F:NuGet.Common.MSBuildUser._frameworkAssembly")] [assembly: SuppressMessage("Build", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "member", Target = "~F:NuGet.Common.MSBuildUser._msbuildAssembly")] [assembly: SuppressMessage("Build", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "member", Target = "~F:NuGet.Common.MSBuildUser._msbuildDirectory")] diff --git a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/Cmdlets/InstallPackageCommand.cs b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/Cmdlets/InstallPackageCommand.cs index f23fac037d2..20f446ad75e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/Cmdlets/InstallPackageCommand.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/Cmdlets/InstallPackageCommand.cs @@ -240,10 +240,6 @@ private void ParseUserInputForId() Source = Path.GetDirectoryName(fullPath); } } - else - { - NormalizePackageId(Project); - } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/PackageActionBaseCommand.cs b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/PackageActionBaseCommand.cs index 7dcfd229725..3397eb83cf2 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/PackageActionBaseCommand.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/PackageActionBaseCommand.cs @@ -251,11 +251,6 @@ protected async Task InstallPackageByIdAsync(NuGetProject project, string packag /// protected void NormalizePackageId(NuGetProject project) { - if (!(project is ProjectKNuGetProjectBase)) - { - return; - } - var metadata = NuGetUIThreadHelper.JoinableTaskFactory.Run(() => GetPackagesFromRemoteSourceAsync(Id, includePrerelease: true)); if (!metadata.Any()) { diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/GlobalSuppressions.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/GlobalSuppressions.cs index 70b98ba648e..9d05662de21 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/GlobalSuppressions.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/GlobalSuppressions.cs @@ -61,7 +61,6 @@ [assembly: SuppressMessage("Build", "CA1801:Parameter shouldThrow of method GetSources is never used. Remove the parameter or use it in the method body.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.GetSources(NuGet.Configuration.ISettings,System.Boolean)~System.Collections.Generic.IList{NuGet.Configuration.PackageSource}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task LegacyPackageReferenceProject.InstallPackageAsync(string packageId, VersionRange range, INuGetProjectContext _, BuildIntegratedInstallationContext __, CancellationToken token)', validate parameter '__' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.InstallPackageAsync(System.String,NuGet.Versioning.VersionRange,NuGet.ProjectManagement.INuGetProjectContext,NuGet.ProjectManagement.BuildIntegratedInstallationContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task LegacyPackageReferenceProject.UninstallPackageAsync(PackageIdentity packageIdentity, INuGetProjectContext _, CancellationToken token)', validate parameter 'packageIdentity' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.UninstallPackageAsync(NuGet.Packaging.Core.PackageIdentity,NuGet.ProjectManagement.INuGetProjectContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'LegacyPackageReferenceProjectProvider.LegacyPackageReferenceProjectProvider(IAsyncServiceProvider vsServiceProvider, Lazy workspaceService, IVsProjectThreadingService threadingService)', validate parameter 'threadingService' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProjectProvider.#ctor(Microsoft.VisualStudio.Shell.IAsyncServiceProvider,System.Lazy{NuGet.VisualStudio.IDeferredProjectWorkspaceService},NuGet.PackageManagement.VisualStudio.IVsProjectThreadingService)")] [assembly: SuppressMessage("Build", "CA1822:Member CreateCoreProjectSystemServices does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProjectProvider.CreateCoreProjectSystemServices(NuGet.VisualStudio.IVsProjectAdapter,Microsoft.VisualStudio.ComponentModelHost.IComponentModel)~NuGet.ProjectManagement.INuGetProjectServices")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task LegacyPackageReferenceProjectProvider.TryCreateNuGetProjectAsync(IVsProjectAdapter vsProjectAdapter, ProjectProviderContext context, bool forceProjectType)', validate parameter 'vsProjectAdapter' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProjectProvider.TryCreateNuGetProjectAsync(NuGet.VisualStudio.IVsProjectAdapter,NuGet.PackageManagement.VisualStudio.ProjectProviderContext,System.Boolean)~System.Threading.Tasks.Task{NuGet.ProjectManagement.NuGetProject}")] [assembly: SuppressMessage("Build", "CA1031:Modify 'GetAssemblyReferences' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.MicrosoftBuildEvaluationProjectUtility.GetAssemblyReferences(Microsoft.Build.Evaluation.Project)~System.Collections.Generic.IEnumerable{System.Tuple{Microsoft.Build.Evaluation.ProjectItem,System.Reflection.AssemblyName}}")] @@ -88,9 +87,6 @@ [assembly: SuppressMessage("Build", "CA1031:Modify 'TryCreateNuGetProjectAsync' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.NuGetProjectFactory.TryCreateNuGetProjectAsync(NuGet.VisualStudio.IVsProjectAdapter,NuGet.PackageManagement.VisualStudio.ProjectProviderContext)~System.Threading.Tasks.Task{NuGet.ProjectManagement.NuGetProject}")] [assembly: SuppressMessage("Build", "CA1305:The behavior of 'string.Format(string, object)' could vary based on the current user's locale settings. Replace this call in 'ProjectJsonToPackageRefMigrator.MigrateAsync(BuildIntegratedNuGetProject)' with a call to 'string.Format(IFormatProvider, string, params object[])'.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectJsonToPackageRefMigrator.MigrateAsync(NuGet.ProjectManagement.Projects.BuildIntegratedNuGetProject)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task ProjectJsonToPackageRefMigrator.MigrateAsync(BuildIntegratedNuGetProject project)', validate parameter 'project' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectJsonToPackageRefMigrator.MigrateAsync(NuGet.ProjectManagement.Projects.BuildIntegratedNuGetProject)~System.Threading.Tasks.Task")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task ProjectKNuGetProject.InstallPackageAsync(PackageIdentity packageIdentity, DownloadResourceResult downloadResourceResult, INuGetProjectContext nuGetProjectContext, CancellationToken token)', validate parameter 'nuGetProjectContext' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectKNuGetProject.InstallPackageAsync(NuGet.Packaging.Core.PackageIdentity,NuGet.Protocol.Core.Types.DownloadResourceResult,NuGet.ProjectManagement.INuGetProjectContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task ProjectKNuGetProject.UninstallPackageAsync(PackageIdentity packageIdentity, INuGetProjectContext nuGetProjectContext, CancellationToken token)', validate parameter 'nuGetProjectContext' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectKNuGetProject.UninstallPackageAsync(NuGet.Packaging.Core.PackageIdentity,NuGet.ProjectManagement.INuGetProjectContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")] -[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task ProjectKNuGetProjectProvider.TryCreateNuGetProjectAsync(IVsProjectAdapter project, ProjectProviderContext context, bool forceProjectType)', validate parameter 'project' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectKNuGetProjectProvider.TryCreateNuGetProjectAsync(NuGet.VisualStudio.IVsProjectAdapter,NuGet.PackageManagement.VisualStudio.ProjectProviderContext,System.Boolean)~System.Threading.Tasks.Task{NuGet.ProjectManagement.NuGetProject}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'List ProjectRetargetingUtility.GetPackagesToBeReinstalled(NuGetFramework projectFramework, IEnumerable packageReferences)', validate parameter 'packageReferences' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectRetargetingUtility.GetPackagesToBeReinstalled(NuGet.Frameworks.NuGetFramework,System.Collections.Generic.IEnumerable{NuGet.Packaging.PackageReference})~System.Collections.Generic.List{NuGet.Packaging.Core.PackageIdentity}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task ProjectRetargetingUtility.MarkPackagesForReinstallation(NuGetProject project, IList packagesToBeReinstalled)', validate parameter 'project' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectRetargetingUtility.MarkPackagesForReinstallation(NuGet.ProjectManagement.NuGetProject,System.Collections.Generic.IList{NuGet.Packaging.Core.PackageIdentity})~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1031:Modify 'MarkPackagesForReinstallation' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.ProjectRetargetingUtility.MarkPackagesForReinstallation(NuGet.ProjectManagement.NuGetProject,System.Collections.Generic.IList{NuGet.Packaging.Core.PackageIdentity})~System.Threading.Tasks.Task")] diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj index 6dadf252745..7b776b79f5b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/NuGet.PackageManagement.VisualStudio.csproj @@ -84,15 +84,11 @@ - - - - @@ -121,7 +117,6 @@ - @@ -129,7 +124,6 @@ - @@ -152,7 +146,6 @@ - @@ -212,7 +205,6 @@ - @@ -220,8 +212,6 @@ - - diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectCapabilities.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectCapabilities.cs deleted file mode 100644 index c46b324f1f0..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectCapabilities.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using NuGet.ProjectManagement; - -namespace NuGet.PackageManagement.VisualStudio -{ - /// - /// Project system capabilities for deferred project. - /// - internal class DeferredProjectCapabilities : IProjectSystemCapabilities - { - public bool SupportsPackageReferences { get; set; } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectServicesProxy.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectServicesProxy.cs deleted file mode 100644 index f6e7efe9d36..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/DeferredProjectServicesProxy.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft; -using Microsoft.VisualStudio.ComponentModelHost; -using NuGet.ProjectManagement; -using NuGet.VisualStudio; - -namespace NuGet.PackageManagement.VisualStudio -{ - /// - /// Implementation of project services for a deferred project. - /// It delegates read-only service requests to . - /// Other service requests that are not supported in DPL mode will be delegated to a fallback - /// project services instance. - /// - internal class DeferredProjectServicesProxy : INuGetProjectServices - { - private readonly IVsProjectAdapter _vsProjectAdapter; - private readonly IComponentModel _componentModel; - private readonly IProjectSystemCapabilities _deferredProjectCapabilities; - private readonly WorkspaceProjectServices _deferredProjectServices; - private readonly Lazy _fallbackProjectServices; - private readonly IVsProjectThreadingService _threadingService; - - public DeferredProjectServicesProxy( - IVsProjectAdapter vsProjectAdapter, - IProjectSystemCapabilities deferredProjectCapabilities, - Func getFallbackProjectServices, - IComponentModel componentModel) - { - Assumes.Present(vsProjectAdapter); - Assumes.Present(deferredProjectCapabilities); - Assumes.Present(getFallbackProjectServices); - Assumes.Present(componentModel); - - _vsProjectAdapter = vsProjectAdapter; - _deferredProjectCapabilities = deferredProjectCapabilities; - _componentModel = componentModel; - - _threadingService = _componentModel.GetService(); - _fallbackProjectServices = new Lazy(getFallbackProjectServices); - _deferredProjectServices = new WorkspaceProjectServices(vsProjectAdapter, this); - } - - public IProjectBuildProperties BuildProperties => _vsProjectAdapter.BuildProperties; - - public IProjectSystemCapabilities Capabilities - { - get - { - return _threadingService.ExecuteSynchronously( - async () => - { - await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - - if (_vsProjectAdapter.IsDeferred) - { - return _deferredProjectCapabilities; - } - - return _fallbackProjectServices.Value.Capabilities; - }); - } - } - - public IProjectSystemReferencesReader ReferencesReader - { - get - { - return _threadingService.ExecuteSynchronously( - async () => - { - await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync(); - - if (_vsProjectAdapter.IsDeferred) - { - return _deferredProjectServices; - } - - return _fallbackProjectServices.Value.ReferencesReader; - }); - } - } - - public IProjectSystemService ProjectSystem => _fallbackProjectServices.Value.ProjectSystem; - - public IProjectSystemReferencesService References => _fallbackProjectServices.Value.References; - - public IProjectScriptHostService ScriptService => _fallbackProjectServices.Value.ScriptService; - - public T GetGlobalService() where T : class => _componentModel.GetService(); - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectBuildProperties.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectBuildProperties.cs deleted file mode 100644 index fc266001526..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectBuildProperties.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft; -using Microsoft.VisualStudio.Threading; -using Microsoft.VisualStudio.Workspace.Extensions.MSBuild; -using NuGet.ProjectManagement; -using NuGet.VisualStudio; - -namespace NuGet.PackageManagement.VisualStudio -{ - internal class WorkspaceProjectBuildProperties - : IProjectBuildProperties - { - private readonly AsyncLazy _buildProjectDataService; - - private readonly IDeferredProjectWorkspaceService _workspaceService; - private readonly IVsProjectThreadingService _threadingService; - private readonly string _fullProjectPath; - - public WorkspaceProjectBuildProperties( - string fullProjectPath, - IDeferredProjectWorkspaceService workspaceService, - IVsProjectThreadingService threadingService) - { - Assumes.Present(workspaceService); - Assumes.Present(threadingService); - - _workspaceService = workspaceService; - _threadingService = threadingService; - _fullProjectPath = fullProjectPath; - - _buildProjectDataService = new AsyncLazy( - () => workspaceService.GetMSBuildProjectDataServiceAsync(_fullProjectPath), - threadingService.JoinableTaskFactory); - } - - public string GetPropertyValue(string propertyName) - { - return _threadingService.ExecuteSynchronously(() => GetPropertyValueAsync(propertyName)); - } - - public async Task GetPropertyValueAsync(string propertyName) - { - Assumes.NotNullOrEmpty(propertyName); - - var dataService = await _buildProjectDataService.GetValueAsync(); - var propertyData = await dataService.GetProjectProperty(propertyName); - return propertyData.EvaluatedValue; - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectServices.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectServices.cs deleted file mode 100644 index a7d8f45b490..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectServices/WorkspaceProjectServices.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft; -using Microsoft.VisualStudio.Threading; -using Microsoft.VisualStudio.Workspace.Extensions.MSBuild; -using NuGet.Commands; -using NuGet.Frameworks; -using NuGet.LibraryModel; -using NuGet.ProjectManagement; -using NuGet.ProjectModel; -using NuGet.Versioning; -using NuGet.VisualStudio; - -namespace NuGet.PackageManagement.VisualStudio -{ - /// - /// Implementation of read-only project services available in DPL mode. - /// - internal class WorkspaceProjectServices - : IProjectSystemReferencesReader - { - private readonly IVsProjectAdapter _vsProjectAdapter; - private readonly IDeferredProjectWorkspaceService _workspaceService; - private readonly IVsProjectThreadingService _threadingService; - - private readonly AsyncLazy _buildProjectDataService; - private readonly string _fullProjectPath; - - private IMSBuildProjectDataService BuildProjectDataService => _threadingService.ExecuteSynchronously(_buildProjectDataService.GetValueAsync); - - public WorkspaceProjectServices( - IVsProjectAdapter vsProjectAdapter, - INuGetProjectServices projectServices) - { - Assumes.Present(vsProjectAdapter); - Assumes.Present(projectServices); - - _vsProjectAdapter = vsProjectAdapter; - _fullProjectPath = vsProjectAdapter.FullProjectPath; - - _workspaceService = projectServices.GetGlobalService(); - Assumes.Present(_workspaceService); - - _threadingService = projectServices.GetGlobalService(); - Assumes.Present(_threadingService); - - _buildProjectDataService = new AsyncLazy( - () => _workspaceService.GetMSBuildProjectDataServiceAsync(_fullProjectPath), - _threadingService.JoinableTaskFactory); - } - - public async Task> GetPackageReferencesAsync( - NuGetFramework targetFramework, - CancellationToken token) - { - var dataService = await _buildProjectDataService.GetValueAsync(token); - - var referenceItems = await dataService.GetProjectItems(ProjectItems.PackageReference, token); - - var packageReferences = referenceItems - .Select(ToPackageLibraryDependency) - .ToList(); - - return packageReferences; - } - - public async Task> GetProjectReferencesAsync( - Common.ILogger logger, - CancellationToken token) - { - var references = await _workspaceService.GetProjectReferencesAsync(_fullProjectPath); - - return references - .Select(reference => new ProjectRestoreReference - { - ProjectPath = reference, - ProjectUniqueName = reference - }) - .ToList(); - } - - private static LibraryDependency ToPackageLibraryDependency(MSBuildProjectItemData item) - { - var dependency = new LibraryDependency - { - LibraryRange = new LibraryRange( - name: item.EvaluatedInclude, - versionRange: GetVersionRange(item), - typeConstraint: LibraryDependencyTarget.Package) - }; - - MSBuildRestoreUtility.ApplyIncludeFlags( - dependency, - GetItemMetadataValueOrDefault(item, ProjectItemProperties.IncludeAssets), - GetItemMetadataValueOrDefault(item, ProjectItemProperties.ExcludeAssets), - GetItemMetadataValueOrDefault(item, ProjectItemProperties.PrivateAssets)); - - return dependency; - } - - private static VersionRange GetVersionRange(MSBuildProjectItemData item) - { - var versionRange = GetItemMetadataValueOrDefault(item, ProjectBuildProperties.Version); - - if (!string.IsNullOrEmpty(versionRange)) - { - return VersionRange.Parse(versionRange); - } - - return VersionRange.All; - } - - private static string GetItemMetadataValueOrDefault( - MSBuildProjectItemData item, string propertyName, string defaultValue = "") - { - if (item.Metadata.TryGetValue(propertyName, out var propertyValue)) - { - return propertyValue; - } - - return defaultValue; - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/MSBuildNuGetProjectSystemFactory.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/MSBuildNuGetProjectSystemFactory.cs index 1abea8df4d0..34689bc554b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/MSBuildNuGetProjectSystemFactory.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/ProjectSystems/MSBuildNuGetProjectSystemFactory.cs @@ -45,13 +45,6 @@ public async static Task CreateMSBuildNuGetProjectSystem Strings.DTE_ProjectUnsupported, vsProjectAdapter.ProjectName)); } - if (!vsProjectAdapter.IsDeferred - && EnvDTEProjectUtility.SupportsProjectKPackageManager(vsProjectAdapter.Project)) - { - throw new InvalidOperationException( - string.Format(CultureInfo.CurrentCulture, Strings.DTE_ProjectUnsupported, typeof(IMSBuildProjectSystem).FullName)); - } - var guids = await vsProjectAdapter.GetProjectTypeGuidsAsync(); if (guids.Contains(VsProjectTypes.CppProjectTypeGuid)) // Got a cpp project { diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs index 03a193ff2ca..5d537159a2a 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProjectProvider.cs @@ -23,7 +23,6 @@ namespace NuGet.PackageManagement.VisualStudio /// [Export(typeof(INuGetProjectProvider))] [Name(nameof(CpsPackageReferenceProjectProvider))] - [Microsoft.VisualStudio.Utilities.Order(After = nameof(ProjectKNuGetProjectProvider))] public class CpsPackageReferenceProjectProvider : INuGetProjectProvider { private static readonly string PackageReference = ProjectStyle.PackageReference.ToString(); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/IVsProjectAdapterProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/IVsProjectAdapterProvider.cs index 9480ef92ae2..448a087f65e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/IVsProjectAdapterProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/IVsProjectAdapterProvider.cs @@ -11,13 +11,6 @@ namespace NuGet.PackageManagement.VisualStudio /// public interface IVsProjectAdapterProvider { - /// - /// Check if given file path exists from AnyCode api in LSL mode. - /// - /// - /// true, if file path exists - Task EntityExistsAsync(string filePath); - /// /// Creates a project adapter for fully loaded project represented by DTE object. /// diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProjectProvider.cs index 9f8681ae6c5..ad8e4aa98de 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProjectProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProjectProvider.cs @@ -27,7 +27,6 @@ public sealed class LegacyPackageReferenceProjectProvider : INuGetProjectProvide { private static readonly string PackageReference = ProjectStyle.PackageReference.ToString(); - private readonly Lazy _workspaceService; private readonly IVsProjectThreadingService _threadingService; private readonly AsyncLazy _componentModel; @@ -35,23 +34,18 @@ public sealed class LegacyPackageReferenceProjectProvider : INuGetProjectProvide [ImportingConstructor] public LegacyPackageReferenceProjectProvider( - Lazy workspaceService, IVsProjectThreadingService threadingService) : this(AsyncServiceProvider.GlobalProvider, - workspaceService, threadingService) { } public LegacyPackageReferenceProjectProvider( IAsyncServiceProvider vsServiceProvider, - Lazy workspaceService, IVsProjectThreadingService threadingService) { Assumes.Present(vsServiceProvider); - Assumes.Present(workspaceService); Assumes.Present(threadingService); - _workspaceService = workspaceService; _threadingService = threadingService; _componentModel = new AsyncLazy( @@ -99,61 +93,24 @@ private async Task TryCreateProjectServicesAsync( var restoreProjectStyle = await vsProjectAdapter.BuildProperties.GetPropertyValueAsync( ProjectBuildProperties.RestoreProjectStyle); - if (vsProjectAdapter.IsDeferred) - { - if (!forceCreate && - !PackageReference.Equals(restoreProjectStyle, StringComparison.OrdinalIgnoreCase)) - { - if (!await ProjectHasPackageReferencesAsync(vsProjectAdapter)) - { - return null; - } - } - - return new DeferredProjectServicesProxy( - vsProjectAdapter, - new DeferredProjectCapabilities { SupportsPackageReferences = true }, - () => CreateCoreProjectSystemServices(vsProjectAdapter, componentModel), - componentModel); - } - else - { - var asVSProject4 = vsProjectAdapter.Project.Object as VSProject4; + var asVSProject4 = vsProjectAdapter.Project.Object as VSProject4; - // A legacy CSProj must cast to VSProject4 to manipulate package references - if (asVSProject4 == null) - { - return null; - } - - // For legacy csproj, either the RestoreProjectStyle must be set to PackageReference or - // project has atleast one package dependency defined as PackageReference - if (forceCreate - || PackageReference.Equals(restoreProjectStyle, StringComparison.OrdinalIgnoreCase) - || (asVSProject4.PackageReferences?.InstalledPackages?.Length ?? 0) > 0) - { - return CreateCoreProjectSystemServices(vsProjectAdapter, componentModel); - } + // A legacy CSProj must cast to VSProject4 to manipulate package references + if (asVSProject4 == null) + { + return null; } - return null; - } - - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - private async Task ProjectHasPackageReferencesAsync(IVsProjectAdapter vsProjectAdapter) - { - var buildProjectDataService = await _workspaceService.Value.GetMSBuildProjectDataServiceAsync( - vsProjectAdapter.FullProjectPath); - Assumes.Present(buildProjectDataService); - - var referenceItems = await buildProjectDataService.GetProjectItems( - ProjectItems.PackageReference, CancellationToken.None); - if (referenceItems == null || referenceItems.Count == 0) + // For legacy csproj, either the RestoreProjectStyle must be set to PackageReference or + // project has atleast one package dependency defined as PackageReference + if (forceCreate + || PackageReference.Equals(restoreProjectStyle, StringComparison.OrdinalIgnoreCase) + || (asVSProject4.PackageReferences?.InstalledPackages?.Length ?? 0) > 0) { - return false; + return CreateCoreProjectSystemServices(vsProjectAdapter, componentModel); } - return true; + return null; } private INuGetProjectServices CreateCoreProjectSystemServices( diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs index 9e5f18a0149..056042d4ac2 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/MSBuildNuGetProjectProvider.cs @@ -83,19 +83,7 @@ private async Task CreateProjectServicesAsync( IVsProjectAdapter vsProjectAdapter, VsMSBuildProjectSystem projectSystem) { var componentModel = await _componentModel.GetValueAsync(); - - if (vsProjectAdapter.IsDeferred) - { - return new DeferredProjectServicesProxy( - vsProjectAdapter, - new DeferredProjectCapabilities { SupportsPackageReferences = false }, - () => new VsMSBuildProjectSystemServices(vsProjectAdapter, projectSystem, componentModel), - componentModel); - } - else - { - return new VsMSBuildProjectSystemServices(vsProjectAdapter, projectSystem, componentModel); - } + return new VsMSBuildProjectSystemServices(vsProjectAdapter, projectSystem, componentModel); } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectJsonProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectJsonProjectProvider.cs index de1f8d1a9fc..06c09b2751b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectJsonProjectProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectJsonProjectProvider.cs @@ -110,19 +110,7 @@ public async Task TryCreateNuGetProjectAsync( private async Task CreateProjectServicesAsync(IVsProjectAdapter vsProjectAdapter) { var componentModel = await _componentModel.GetValueAsync(); - - if (vsProjectAdapter.IsDeferred) - { - return new DeferredProjectServicesProxy( - vsProjectAdapter, - new DeferredProjectCapabilities { SupportsPackageReferences = false }, - () => new VsCoreProjectSystemServices(vsProjectAdapter, componentModel), - componentModel); - } - else - { - return new VsCoreProjectSystemServices(vsProjectAdapter, componentModel); - } + return new VsCoreProjectSystemServices(vsProjectAdapter, componentModel); } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProject.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProject.cs deleted file mode 100644 index 6edf19af727..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProject.cs +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.ProjectSystem.Interop; -using NuGet.Frameworks; -using NuGet.Packaging; -using NuGet.Packaging.Core; -using NuGet.ProjectManagement; -using NuGet.ProjectManagement.Projects; -using NuGet.Protocol.Core.Types; -using NuGet.Versioning; -using NuGet.VisualStudio; - -namespace NuGet.PackageManagement.VisualStudio -{ - public class NuGetPackageMoniker : INuGetPackageMoniker - { - public string Id { get; set; } - - public string Version { get; set; } - } - - public class ProjectKNuGetProject : ProjectKNuGetProjectBase - { - private const string StateKey = "PackageUpgradeState"; - - private INuGetPackageManager _project; - - /// - /// When performing an update operation from the UI, this action is converted to two lower - /// level actions: uninstall then install. Unfortunately, this means that any state removed - /// during the uninstall that is not included in the install operation is lost. This - /// dictionary is used to maintain this state between uninstall and install operations. The - /// state is cleared during the and - /// steps. - /// - private readonly Dictionary _packageUpdateState - = new Dictionary(StringComparer.OrdinalIgnoreCase); - - public override Task PostProcessAsync(INuGetProjectContext nuGetProjectContext, CancellationToken token) - { - // Technically we only need to clear state during the PreProcessAsync step, but clearing - // here as well means we're not holding on to information that will never be used thus - // using less memory. - _packageUpdateState.Clear(); - - return base.PostProcessAsync(nuGetProjectContext, token); - } - - public override Task PreProcessAsync(INuGetProjectContext nuGetProjectContext, CancellationToken token) - { - _packageUpdateState.Clear(); - - return base.PreProcessAsync(nuGetProjectContext, token); - } - - public ProjectKNuGetProject(INuGetPackageManager project, string projectName, string uniqueName, string projectId) - { - _project = project; - InternalMetadata.Add(NuGetProjectMetadataKeys.Name, projectName); - InternalMetadata.Add(NuGetProjectMetadataKeys.UniqueName, uniqueName); - InternalMetadata.Add(NuGetProjectMetadataKeys.ProjectId, projectId); - - NuGetUIThreadHelper.JoinableTaskFactory.Run(async () => - { - var frameworks = await _project.GetSupportedFrameworksAsync(CancellationToken.None); - var supportedFrameworks = frameworks.Select(f => NuGetFramework.Parse(f.FullName)); - - InternalMetadata.Add(NuGetProjectMetadataKeys.SupportedFrameworks, supportedFrameworks); - }); - } - - public override async Task InstallPackageAsync( - PackageIdentity packageIdentity, - DownloadResourceResult downloadResourceResult, - INuGetProjectContext nuGetProjectContext, - CancellationToken token) - { - if (downloadResourceResult == null) - { - throw new ArgumentNullException(nameof(downloadResourceResult)); - } - - var packageStream = downloadResourceResult.PackageStream; - if (!packageStream.CanSeek) - { - throw new ArgumentException(Strings.PackageStreamShouldBeSeekable); - } - - // Uninstall the package if it is already installed. This should only happen when an - // update occurred from Install-Package PMC command, the Browse tab in the UI, or the - // Installed tab in the UI. An update from the Updates tab has an explicit Uninstall - // action before the install. - var installedPackages = await GetInstalledPackagesAsync(token); - var packageToReplace = installedPackages - .Where(pr => StringComparer.OrdinalIgnoreCase.Equals(pr.PackageIdentity.Id, packageIdentity.Id)) - .FirstOrDefault(); - - if (packageToReplace != null) - { - await UninstallPackageAsync(packageToReplace.PackageIdentity, nuGetProjectContext, token); - } - - nuGetProjectContext.Log(MessageLevel.Info, Strings.InstallingPackage, packageIdentity); - - // Get additional information from the package that the INuGetPackageManager can act on. - packageStream.Seek(0, SeekOrigin.Begin); - - IEnumerable supportedFrameworks; - IEnumerable packageTypes; - using (var packageReader = new PackageArchiveReader(packageStream, leaveStreamOpen: true)) - { - supportedFrameworks = packageReader.GetSupportedFrameworks(); - packageTypes = packageReader.GetPackageTypes(); - } - - var args = new Dictionary(); - - args["Frameworks"] = supportedFrameworks - .Where(f => f.IsSpecificFramework) - .ToArray(); - - args["PackageTypes"] = packageTypes - .ToArray(); - - object state; - if (_packageUpdateState.TryGetValue(packageIdentity.Id, out state)) - { - args[StateKey] = state; - } - - // Perform the actual installation by delegating to INuGetPackageManager. - await _project.InstallPackageAsync( - new NuGetPackageMoniker - { - Id = packageIdentity.Id, - Version = packageIdentity.Version.ToNormalizedString() - }, - args, - logger: null, - progress: null, - cancellationToken: token); - - return true; - } - - public override async Task UninstallPackageAsync(PackageIdentity packageIdentity, INuGetProjectContext nuGetProjectContext, CancellationToken token) - { - nuGetProjectContext.Log(MessageLevel.Info, Strings.UninstallingPackage, packageIdentity); - - var args = new Dictionary(); - - await _project.UninstallPackageAsync( - new NuGetPackageMoniker - { - Id = packageIdentity.Id, - Version = packageIdentity.Version.ToNormalizedString() - }, - args, - logger: null, - progress: null, - cancellationToken: token); - - // It's possible that the underlying project is trying to pass us back some state to be - // returned to it in a subsequent install of the same package identity. - object state; - if (args.TryGetValue(StateKey, out state)) - { - _packageUpdateState[packageIdentity.Id] = state; - } - - return true; - } - - public override async Task> GetInstalledPackagesAsync(CancellationToken token) - { - var result = new List(); - foreach (var item in await _project.GetInstalledPackagesAsync(token)) - { - PackageIdentity identity = null; - - var moniker = item as INuGetPackageMoniker; - if (moniker != null) - { - // As with build integrated projects (UWP project.json), treat the version as a - // version range and use the minimum version of that range. Eventually, this - // method should return VersionRange instances, not NuGetVersion so that the - // UI can express the full project.json intent. This improvement is tracked - // here: https://github.com/NuGet/Home/issues/3101 - var versionRange = VersionRange.Parse(moniker.Version); - var version = versionRange.MinVersion; - - identity = new PackageIdentity(moniker.Id, version); - } - else - { - // otherwise, item is the file name of the nupkg file - var fileName = item as string; - using (var packageReader = new PackageArchiveReader(fileName)) - { - identity = packageReader.GetIdentity(); - } - } - - result.Add(new PackageReference( - identity, - targetFramework: null)); - } - - return result; - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProjectProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProjectProvider.cs deleted file mode 100644 index cbf47b7672b..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/ProjectKNuGetProjectProvider.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel.Composition; -using System.Threading.Tasks; -using Microsoft; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Utilities; -using NuGet.ProjectManagement; -using NuGet.VisualStudio; - -namespace NuGet.PackageManagement.VisualStudio -{ - [Export(typeof(INuGetProjectProvider))] - [Name(nameof(ProjectKNuGetProjectProvider))] - public class ProjectKNuGetProjectProvider : INuGetProjectProvider - { - public RuntimeTypeHandle ProjectType => typeof(ProjectKNuGetProject).TypeHandle; - - public async Task TryCreateNuGetProjectAsync( - IVsProjectAdapter project, - ProjectProviderContext context, - bool forceProjectType) - { - Assumes.Present(project); - Assumes.Present(context); - - await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - - if (project.IsDeferred) - { - return null; - } - - var projectK = EnvDTEProjectUtility.GetProjectKPackageManager(project.Project); - if (projectK == null) - { - return null; - } - - return new ProjectKNuGetProject( - projectK, - project.ProjectName, - project.CustomUniqueName, - project.ProjectId); - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs index 9e1dab3778a..14d42300554 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapter.cs @@ -27,7 +27,6 @@ internal class VsProjectAdapter : IVsProjectAdapter private readonly VsHierarchyItem _vsHierarchyItem; private readonly Lazy _dteProject; - private readonly IDeferredProjectWorkspaceService _workspaceService; private readonly IVsProjectThreadingService _threadingService; private readonly string _projectTypeGuid; @@ -100,14 +99,7 @@ public string RestoreFallbackFolders public async Task GetProjectDirectoryAsync() { - if (!IsDeferred) - { - return await Project.GetFullPathAsync(); - } - else - { - return Path.GetDirectoryName(FullProjectPath); - } + return await Project.GetFullPathAsync(); } public string FullProjectPath { get; private set; } @@ -122,12 +114,7 @@ public bool IsDeferred public async Task IsSupportedAsync() { - if (!IsDeferred) - { - return await EnvDTEProjectUtility.IsSupportedAsync(Project); - } - - return await VsHierarchyUtility.IsSupportedAsync(VsHierarchy, _projectTypeGuid); + return await EnvDTEProjectUtility.IsSupportedAsync(Project); } public string PackageTargetFallback @@ -213,14 +200,12 @@ public VsProjectAdapter( string projectTypeGuid, Func loadDteProject, IProjectBuildProperties buildProperties, - IVsProjectThreadingService threadingService, - IDeferredProjectWorkspaceService workspaceService = null) + IVsProjectThreadingService threadingService) { Assumes.Present(vsHierarchyItem); _vsHierarchyItem = vsHierarchyItem; _dteProject = new Lazy(() => loadDteProject(_vsHierarchyItem.VsHierarchy)); - _workspaceService = workspaceService; _threadingService = threadingService; _projectTypeGuid = projectTypeGuid; @@ -270,28 +255,15 @@ public async Task GetDotNetFrameworkNameAsync() return null; } - public async Task> GetReferencedProjectsAsync() + public Task> GetReferencedProjectsAsync() { - if (!IsDeferred) + if (Project.Kind != null + && ProjectType.IsSupportedForAddingReferences(Project.Kind)) { - if (Project.Kind != null - && ProjectType.IsSupportedForAddingReferences(Project.Kind)) - { - return EnvDTEProjectUtility.GetReferencedProjects(Project).Select(p => p.UniqueName); - } - - return Enumerable.Empty(); + return System.Threading.Tasks.Task.FromResult(EnvDTEProjectUtility.GetReferencedProjects(Project).Select(p => p.UniqueName)); } - else - { - var projectTypeGuids = await GetProjectTypeGuidsAsync(); - if (projectTypeGuids.All(ProjectType.IsSupportedForAddingReferences)) - { - return await _workspaceService.GetProjectReferencesAsync(FullProjectPath); - } - return Enumerable.Empty(); - } + return System.Threading.Tasks.Task.FromResult(Enumerable.Empty()); } public async Task> GetRuntimeIdentifiersAsync() diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs index 3bfcfd1978d..6b821cf4ab4 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/VsProjectAdapterProvider.cs @@ -17,7 +17,6 @@ namespace NuGet.PackageManagement.VisualStudio internal class VsProjectAdapterProvider : IVsProjectAdapterProvider { private readonly IVsProjectThreadingService _threadingService; - private readonly AsyncLazy _workspaceService; private readonly AsyncLazy _vsSolution5; [ImportingConstructor] @@ -27,31 +26,21 @@ public VsProjectAdapterProvider( IVsProjectThreadingService threadingService) : this( threadingService, - new AsyncLazy(() => serviceProvider.GetServiceAsync(), threadingService.JoinableTaskFactory), new AsyncLazy(() => serviceProvider.GetServiceAsync(), threadingService.JoinableTaskFactory)) { } internal VsProjectAdapterProvider( IVsProjectThreadingService threadingService, - AsyncLazy workspaceService, AsyncLazy vsSolution5) { Assumes.Present(threadingService); - Assumes.Present(workspaceService); Assumes.Present(vsSolution5); _threadingService = threadingService; - _workspaceService = workspaceService; _vsSolution5 = vsSolution5; } - public async Task EntityExistsAsync(string filePath) - { - var workspaceService = await _workspaceService.GetValueAsync(); - return await workspaceService.EntityExistsAsync(filePath); - } - public IVsProjectAdapter CreateAdapterForFullyLoadedProject(EnvDTE.Project dteProject) { return _threadingService.ExecuteSynchronously( diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/DeferredProjectWorkspaceService.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/DeferredProjectWorkspaceService.cs deleted file mode 100644 index 4ced7a31657..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/DeferredProjectWorkspaceService.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.Linq; -using System.Threading.Tasks; -using Microsoft; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Threading; -using Microsoft.VisualStudio.Workspace; -using Microsoft.VisualStudio.Workspace.Extensions.MSBuild; -using Microsoft.VisualStudio.Workspace.Indexing; -using Microsoft.VisualStudio.Workspace.VSIntegration; -using NuGet.VisualStudio; - -namespace NuGet.PackageManagement.VisualStudio -{ - [Export(typeof(IDeferredProjectWorkspaceService))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal sealed class DeferredProjectWorkspaceService : IDeferredProjectWorkspaceService - { -#pragma warning disable CS0618 // Type or member is obsolete - private readonly AsyncLazy _solutionWorkspaceService; -#pragma warning restore CS0618 // Type or member is obsolete - -#pragma warning disable CS0618 // Type or member is obsolete - private IVsSolutionWorkspaceService SolutionWorkspaceService => NuGetUIThreadHelper.JoinableTaskFactory.Run(_solutionWorkspaceService.GetValueAsync); -#pragma warning restore CS0618 // Type or member is obsolete - - [ImportingConstructor] - public DeferredProjectWorkspaceService( - [Import(typeof(SVsServiceProvider))] - IServiceProvider serviceProvider) - { - if (serviceProvider == null) - { - throw new ArgumentNullException(nameof(serviceProvider)); - } - -#pragma warning disable CS0618 // Type or member is obsolete - _solutionWorkspaceService = new AsyncLazy( -#pragma warning restore CS0618 // Type or member is obsolete - async () => - { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); -#pragma warning disable CS0618 // Type or member is obsolete - return (IVsSolutionWorkspaceService)serviceProvider.GetService(typeof(SVsSolutionWorkspaceService)); -#pragma warning restore CS0618 // Type or member is obsolete - }, - NuGetUIThreadHelper.JoinableTaskFactory); - } - - public async Task EntityExistsAsync(string filePath) - { - var workspace = SolutionWorkspaceService.CurrentWorkspace; - var indexService = workspace.GetIndexWorkspaceService(); - var filePathExists = await indexService.EntityExists(filePath); - return filePathExists; - } - - public async Task> GetProjectReferencesAsync(string projectFilePath) - { - var workspace = SolutionWorkspaceService.CurrentWorkspace; - var indexService = workspace.GetIndexWorkspaceService(); - var fileReferenceResult = await indexService.GetFileReferencesAsync(projectFilePath, referenceTypes: (int)FileReferenceInfoType.ProjectReference); - return fileReferenceResult.Select(f => workspace.MakeRooted(f.Path)); - } - - public async Task GetMSBuildProjectDataServiceAsync( - string projectFilePath, string targetFramework) - { - Assumes.NotNullOrEmpty(projectFilePath); - - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - -#pragma warning disable CS0618 // Type or member is obsolete - var factory = SolutionWorkspaceService.GetService(); -#pragma warning restore CS0618 // Type or member is obsolete - Assumes.Present(factory); - - if (string.IsNullOrEmpty(targetFramework)) - { - return await factory.GetMSBuildProjectDataServiceAsync(projectFilePath); - } - else - { - var projectProperties = new Dictionary - { - { "TargetFramework", targetFramework } - }; - return await factory.GetMSBuildProjectDataServiceAsync( - projectFilePath, projectProperties: projectProperties); - } - } - - public async Task GetProjectTypeGuidAsync(string projectFilePath) - { - var workspace = SolutionWorkspaceService.CurrentWorkspace; - var solutionPath = SolutionWorkspaceService.SolutionFile; - var indexService = workspace.GetIndexWorkspaceService(); - var indexedSolutionProjectTypes = (await indexService.GetFileDataValuesAsync(solutionPath, - ProjectBaseTypesInSolution.TypeGuid, refreshOption: true)).FirstOrDefault(); - - if (indexedSolutionProjectTypes != null) - { - var relativeProjectPath = Common.PathUtility.GetRelativePath(solutionPath, projectFilePath); - - if (!string.IsNullOrEmpty(relativeProjectPath) - && indexedSolutionProjectTypes.Value.Types.TryGetValue(relativeProjectPath, out Guid projectTypeGuid)) - { - return projectTypeGuid.ToString("B"); - } - } - - return string.Empty; - } - } -} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/NuGetProjectType.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/NuGetProjectType.cs index 6c1c48ac8c2..f3d1a581343 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/NuGetProjectType.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/NuGetProjectType.cs @@ -28,11 +28,6 @@ public enum NuGetProjectType /// UwpProjectJson = 3, - /// - /// Corresponds to . - /// - XProjProjectJson = 4, - /// /// Corresponds to . /// diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/VSTelemetryServiceUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/VSTelemetryServiceUtility.cs index dd685b39893..2724a4d2025 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/VSTelemetryServiceUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Telemetry/VSTelemetryServiceUtility.cs @@ -90,7 +90,6 @@ public static async Task GetProjectTelemetryEventAsync(Nu projectType = NuGetProjectType.UnconfiguredNuGetType; } } -#if VS15 else if (nuGetProject is CpsPackageReferenceProject) { projectType = NuGetProjectType.CPSBasedPackageRefs; @@ -99,15 +98,10 @@ public static async Task GetProjectTelemetryEventAsync(Nu { projectType = NuGetProjectType.LegacyProjectSystemWithPackageRefs; } -#endif else if (nuGetProject is ProjectJsonNuGetProject) { projectType = NuGetProjectType.UwpProjectJson; } - else if (nuGetProject is ProjectKNuGetProjectBase) - { - projectType = NuGetProjectType.XProjProjectJson; - } var isUpgradable = await NuGetProjectUpgradeUtility.IsNuGetProjectUpgradeableAsync(nuGetProject); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs index 9ee8f5907b3..0f770176f1c 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Utility/EnvDTEProjectUtility.cs @@ -377,11 +377,6 @@ public static async Task IsSupportedAsync(EnvDTE.Project envDTEProject) { Assumes.Present(envDTEProject); - if (SupportsProjectKPackageManager(envDTEProject)) - { - return true; - } - if (await IsProjectCapabilityCompliantAsync(envDTEProject)) { return true; @@ -652,55 +647,6 @@ public static bool IsParentProjectExplicitlyUnsupported(EnvDTE.Project envDTEPro return IsExplicitlyUnsupported(parentEnvDTEProject); } - public static bool SupportsProjectKPackageManager(EnvDTE.Project envDTEProject) - { - ThreadHelper.ThrowIfNotOnUIThread(); - - var projectKProject = GetProjectKPackageManager(envDTEProject); - return projectKProject != null; - } - - public static INuGetPackageManager GetProjectKPackageManager(EnvDTE.Project project) - { - ThreadHelper.ThrowIfNotOnUIThread(); - - var vsProject = project as IVsProject; - if (vsProject == null) - { - return null; - } - - Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider = null; - vsProject.GetItemContext( - (uint)VSConstants.VSITEMID.Root, - out serviceProvider); - if (serviceProvider == null) - { - return null; - } - - using (var sp = new ServiceProvider(serviceProvider)) - { - var retValue = sp.GetService(typeof(INuGetPackageManager)); - if (retValue == null) - { - return null; - } - - if (!(retValue is INuGetPackageManager)) - { - // Workaround a bug in Dev14 prereleases where Lazy was returned. - var properties = retValue.GetType().GetProperties().Where(p => p.Name == "Value"); - if (properties.Count() == 1) - { - retValue = properties.First().GetValue(retValue); - } - } - - return retValue as INuGetPackageManager; - } - } - /// /// True if the project has a project.json file, indicating that it is build integrated /// diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/VSNuGetProjectFactory.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/VSNuGetProjectFactory.cs deleted file mode 100644 index db76bcb3202..00000000000 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/VSNuGetProjectFactory.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.ProjectSystem.Interop; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using NuGet.Common; -using NuGet.ProjectManagement; -using EnvDTEProject = EnvDTE.Project; -using IServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; - -namespace NuGet.PackageManagement.VisualStudio -{ - public class VSNuGetProjectFactory - { - private readonly Func _packagesPath; - - private EmptyNuGetProjectContext EmptyNuGetProjectContext { get; } - - // TODO: Add IDeleteOnRestartManager, VsPackageInstallerEvents and IVsFrameworkMultiTargeting to constructor - public VSNuGetProjectFactory(Func packagesPath) - { - if (packagesPath == null) - { - throw new ArgumentNullException(nameof(packagesPath)); - } - - _packagesPath = packagesPath; - EmptyNuGetProjectContext = new EmptyNuGetProjectContext(); - } - - public NuGetProject CreateNuGetProject(EnvDTEProject envDTEProject) - { - return CreateNuGetProject(envDTEProject, EmptyNuGetProjectContext); - } - - public NuGetProject CreateNuGetProject(EnvDTEProject envDTEProject, INuGetProjectContext nuGetProjectContext) - { - if (envDTEProject == null) - { - throw new ArgumentNullException(nameof(envDTEProject)); - } - - if (nuGetProjectContext == null) - { - throw new ArgumentNullException(nameof(nuGetProjectContext)); - } - - ThreadHelper.ThrowIfNotOnUIThread(); - - NuGetProject result = null; - - var projectK = GetProjectKProject(envDTEProject); - if (projectK != null) - { - result = new ProjectKNuGetProject( - projectK, - envDTEProject.Name, - EnvDTEProjectUtility.GetCustomUniqueName(envDTEProject), - VsHierarchyUtility.GetProjectId(envDTEProject)); - } - else if ((result = GetMSBuildShellOutNuGetProject(envDTEProject)) != null) - { - // Use the NuGetProject result initialized in the condition. - } - else - { - var msBuildNuGetProjectSystem = MSBuildNuGetProjectSystemFactory.CreateMSBuildNuGetProjectSystem( - envDTEProject, - nuGetProjectContext); - - var isWebSite = msBuildNuGetProjectSystem is WebSiteProjectSystem; - - // Web sites cannot have project.json - if (!isWebSite) - { - // Find the project file path - var projectFilePath = EnvDTEProjectUtility.GetFullProjectPath(envDTEProject); - - if (!string.IsNullOrEmpty(projectFilePath)) - { - var msbuildProjectFile = new FileInfo(projectFilePath); - var projectNameFromMSBuildPath = Path.GetFileNameWithoutExtension(msbuildProjectFile.Name); - - // Treat projects with project.json as build integrated projects - // Search for projectName.project.json first, then project.json - // If the name cannot be determined, search only for project.json - string projectJsonPath = null; - if (string.IsNullOrEmpty(projectNameFromMSBuildPath)) - { - projectJsonPath = Path.Combine(msbuildProjectFile.DirectoryName, - ProjectJsonPathUtilities.ProjectConfigFileName); - } - else - { - projectJsonPath = ProjectJsonPathUtilities.GetProjectConfigPath(msbuildProjectFile.DirectoryName, - projectNameFromMSBuildPath); - } - - if (File.Exists(projectJsonPath)) - { - result = new BuildIntegratedProjectSystem( - projectJsonPath, - msbuildProjectFile.FullName, - envDTEProject, - msBuildNuGetProjectSystem, - EnvDTEProjectUtility.GetCustomUniqueName(envDTEProject)); - } - } - } - - // Create a normal MSBuild project if no project.json was found - if (result == null) - { - var folderNuGetProjectFullPath = _packagesPath(); - - // Project folder path is the packages config folder path - var packagesConfigFolderPath = EnvDTEProjectUtility.GetFullPath(envDTEProject); - - result = new VSMSBuildNuGetProject( - envDTEProject, - msBuildNuGetProjectSystem, - folderNuGetProjectFullPath, - packagesConfigFolderPath); - } - } - - return result; - } - - public static MSBuildShellOutNuGetProject GetMSBuildShellOutNuGetProject(EnvDTEProject project) - { - try - { - return MSBuildShellOutNuGetProject.Create(project); - } - catch - { - // Ignore failures. If this method returns null, the problem falls into one of the other NuGet project - // types. - } - - return null; - } - - public static INuGetPackageManager GetProjectKProject(EnvDTEProject project) - { - ThreadHelper.ThrowIfNotOnUIThread(); - - var vsProject = VsHierarchyUtility.ToVsHierarchy(project) as IVsProject; - if (vsProject == null) - { - return null; - } - - IServiceProvider serviceProvider = null; - vsProject.GetItemContext( - (uint)VSConstants.VSITEMID.Root, - out serviceProvider); - if (serviceProvider == null) - { - return null; - } - - using (var sp = new ServiceProvider(serviceProvider)) - { - var retValue = sp.GetService(typeof(INuGetPackageManager)); - if (retValue == null) - { - return null; - } - - if (!(retValue is INuGetPackageManager)) - { - // Workaround a bug in Dev14 prereleases where Lazy was returned. - var properties = retValue.GetType().GetProperties().Where(p => p.Name == "Value"); - if (properties.Count() == 1) - { - retValue = properties.First().GetValue(retValue); - } - } - - return retValue as INuGetPackageManager; - } - } - } -} diff --git a/src/NuGet.Clients/NuGet.Tools/GlobalSuppressions.cs b/src/NuGet.Clients/NuGet.Tools/GlobalSuppressions.cs index 2ff599acdfc..8f088609b5a 100644 --- a/src/NuGet.Clients/NuGet.Tools/GlobalSuppressions.cs +++ b/src/NuGet.Clients/NuGet.Tools/GlobalSuppressions.cs @@ -9,7 +9,6 @@ using System.Diagnostics.CodeAnalysis; [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD011:Use AsyncLazy", Justification = "", Scope = "member", Target = "~M:NuGetVSExtension.ShowErrorsCommand.#ctor(System.IServiceProvider)")] -[assembly: SuppressMessage("Build", "CA1823:Unused field 'guidNuGetVSEventsPackagePkgString'.", Justification = "", Scope = "member", Target = "~F:NuGetVSExtension.GuidList.guidNuGetVSEventsPackagePkgString")] [assembly: SuppressMessage("Build", "CA1031:Modify 'Flush' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGetVSExtension.DataStreamFromComStream.Flush")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void FontAndColorsRegistrationAttribute.Register(RegistrationContext context)', validate parameter 'context' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGetVSExtension.FontAndColorsRegistrationAttribute.Register(Microsoft.VisualStudio.Shell.RegistrationAttribute.RegistrationContext)")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void FontAndColorsRegistrationAttribute.Unregister(RegistrationContext context)', validate parameter 'context' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGetVSExtension.FontAndColorsRegistrationAttribute.Unregister(Microsoft.VisualStudio.Shell.RegistrationAttribute.RegistrationContext)")] diff --git a/src/NuGet.Clients/NuGet.Tools/Guids.cs b/src/NuGet.Clients/NuGet.Tools/Guids.cs index dd6e4c2183e..e280c21ff9e 100644 --- a/src/NuGet.Clients/NuGet.Tools/Guids.cs +++ b/src/NuGet.Clients/NuGet.Tools/Guids.cs @@ -8,7 +8,6 @@ namespace NuGetVSExtension internal static class GuidList { public const string guidNuGetPkgString = "5fcc8577-4feb-4d04-ad72-d6c629b083cc"; - private const string guidNuGetVSEventsPackagePkgString = "38ebd926-b8b6-44e9-952d-1cfd38c84209"; private const string guidNuGetConsoleCmdSetString = "1E8A55F6-C18D-407F-91C8-94B02AE1CED6"; private const string guidNuGetDialogCmdSetString = "25fd982b-8cae-4cbd-a440-e03ffccde106"; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs index 9eeaece3a92..a635fa316bf 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs @@ -34,8 +34,6 @@ public interface IVsProjectAdapter string FullProjectPath { get; } - bool IsDeferred { get; } - Task IsSupportedAsync(); /// diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Services/IDeferredProjectWorkspaceService.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Services/IDeferredProjectWorkspaceService.cs deleted file mode 100644 index 9ab2a51ca2d..00000000000 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/Services/IDeferredProjectWorkspaceService.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.VisualStudio.Workspace.Extensions.MSBuild; - -namespace NuGet.VisualStudio -{ - public interface IDeferredProjectWorkspaceService - { - Task EntityExistsAsync(string filePath); - - Task> GetProjectReferencesAsync(string projectFilePath); - - Task GetMSBuildProjectDataServiceAsync(string projectFilePath, string targetFramework = null); - - Task GetProjectTypeGuidAsync(string projectFilePath); - } -} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs index 98b30add36c..53f2a6b5a0c 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs @@ -53,10 +53,6 @@ private static NuGetProjectKind GetProjectKind(NuGetProject nugetProject) { projectKind = NuGetProjectKind.PackagesConfig; } - else if (nugetProject is ProjectKNuGetProjectBase) - { - projectKind = NuGetProjectKind.ProjectK; - } return projectKind; } diff --git a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/Utils/InstalledPackageEnumerator.cs b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/Utils/InstalledPackageEnumerator.cs index 0c915c3e27c..87da36301ec 100644 --- a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/Utils/InstalledPackageEnumerator.cs +++ b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/Utils/InstalledPackageEnumerator.cs @@ -127,13 +127,9 @@ public async Task> EnumeratePackagesAsync( // if A -> B, we invoke B's init.ps1 before A's. var installedPackages = new List(); - var projects = (await _solutionManager.GetNuGetProjectsAsync()).ToList(); - - // Skip project K projects. - projects.RemoveAll(p => p is ProjectKNuGetProjectBase); - // Sort projects by type - var projectLookup = projects.ToLookup(p => p is BuildIntegratedNuGetProject); + var projectLookup = (await _solutionManager.GetNuGetProjectsAsync()) + .ToLookup(p => p is BuildIntegratedNuGetProject); // Each id/version should only be executed once var finishedPackages = new HashSet(); diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs index ad6a458dc55..28fbb94ce23 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/GlobalSuppressions.cs @@ -9,7 +9,6 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Build", "CA1802:Field '_useConsoleColor' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.CommandLine.XPlat.CommandOutputLogger._useConsoleColor")] -[assembly: SuppressMessage("Build", "CA1823:Unused field 'ASSETS_DIRECTORY_TAG'.", Justification = "", Scope = "member", Target = "~F:NuGet.CommandLine.XPlat.MSBuildAPIUtility.ASSETS_DIRECTORY_TAG")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void AddPackageReferenceCommand.Register(CommandLineApplication app, Func getLogger, Func getCommandRunner)', validate parameter 'app' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.AddPackageReferenceCommand.Register(Microsoft.Extensions.CommandLineUtils.CommandLineApplication,System.Func{NuGet.Common.ILogger},System.Func{NuGet.CommandLine.XPlat.IPackageReferenceCommandRunner})")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task AddPackageReferenceCommandRunner.ExecuteCommand(PackageReferenceArgs packageReferenceArgs, MSBuildAPIUtility msBuild)', validate parameter 'msBuild' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.AddPackageReferenceCommandRunner.ExecuteCommand(NuGet.CommandLine.XPlat.PackageReferenceArgs,NuGet.CommandLine.XPlat.MSBuildAPIUtility)~System.Threading.Tasks.Task{System.Int32}")] [assembly: SuppressMessage("Build", "CA1308:In method 'LogInternal', replace the call to 'ToLowerInvariant' with 'ToUpperInvariant'.", Justification = "", Scope = "member", Target = "~M:NuGet.CommandLine.XPlat.CommandOutputLogger.LogInternal(NuGet.Common.LogLevel,System.String)")] diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/MSBuildAPIUtility.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/MSBuildAPIUtility.cs index baae6f973e4..14bbeda7245 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/MSBuildAPIUtility.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/MSBuildAPIUtility.cs @@ -25,7 +25,6 @@ internal class MSBuildAPIUtility private const string VERSION_TAG = "Version"; private const string FRAMEWORK_TAG = "TargetFramework"; private const string FRAMEWORKS_TAG = "TargetFrameworks"; - private const string ASSETS_DIRECTORY_TAG = "MSBuildProjectExtensionsPath"; private const string RESTORE_STYLE_TAG = "RestoreProjectStyle"; private const string NUGET_STYLE_TAG = "NuGetProjectStyle"; private const string ASSETS_FILE_PATH_TAG = "ProjectAssetsFile"; diff --git a/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs index a36117eb9ac..8c1a889a1f6 100644 --- a/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Commands/GlobalSuppressions.cs @@ -24,8 +24,6 @@ [assembly: SuppressMessage("Build", "CA1802:Field 'LanguageCondition' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.BuildAssetsUtils.LanguageCondition")] [assembly: SuppressMessage("Build", "CA1802:Field 'NegativeLanguageCondition' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.BuildAssetsUtils.NegativeLanguageCondition")] [assembly: SuppressMessage("Build", "CA1802:Field 'TargetFrameworkCondition' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.BuildAssetsUtils.TargetFrameworkCondition")] -[assembly: SuppressMessage("Build", "CA1823:Unused field 'ReferenceFolder'.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.MSBuildProjectFactory.ReferenceFolder")] -[assembly: SuppressMessage("Build", "CA1823:Unused field 'ToolsFolder'.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.MSBuildProjectFactory.ToolsFolder")] [assembly: SuppressMessage("Build", "CA1823:Unused field 'FailureCode'.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.TrustedSignersCommandRunner.FailureCode")] [assembly: SuppressMessage("Build", "CA1802:Field 'RootDir' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Commands.VirtualFileProvider.RootDir")] [assembly: SuppressMessage("Build", "CA1303:Method 'IDisposable NoopChangeToken.RegisterChangeCallback(Action callback, object state)' passes a literal string as parameter 'message' of a call to 'NotSupportedException.NotSupportedException(string message)'. Retrieve the following string(s) from a resource table instead: \"Trigger does not support registering change notifications.\".", Justification = "", Scope = "member", Target = "~M:Microsoft.AspNet.FileProviders.NoopChangeToken.RegisterChangeCallback(System.Action{System.Object},System.Object)~System.IDisposable")] diff --git a/src/NuGet.Core/NuGet.Commands/MSBuildProjectFactory.cs b/src/NuGet.Core/NuGet.Commands/MSBuildProjectFactory.cs index 5a940bd97ce..312f6258315 100644 --- a/src/NuGet.Core/NuGet.Commands/MSBuildProjectFactory.cs +++ b/src/NuGet.Core/NuGet.Commands/MSBuildProjectFactory.cs @@ -21,8 +21,6 @@ public class MSBuildProjectFactory : IProjectFactory private ILogger _logger; // Packaging folders - private static readonly string ReferenceFolder = PackagingConstants.Folders.Lib; - private static readonly string ToolsFolder = PackagingConstants.Folders.Tools; private static readonly string SourcesFolder = PackagingConstants.Folders.Source; private MSBuildPackTargetArgs PackTargetArgs { get; set; } diff --git a/src/NuGet.Core/NuGet.DependencyResolver.Core/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.DependencyResolver.Core/GlobalSuppressions.cs index 80382f50725..54eef46e933 100644 --- a/src/NuGet.Core/NuGet.DependencyResolver.Core/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.DependencyResolver.Core/GlobalSuppressions.cs @@ -8,7 +8,6 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Build", "CA1823:Unused field 'LIGHT_UP_AND_RIGHT'.", Justification = "", Scope = "member", Target = "~F:NuGet.DependencyResolver.GraphOperations.LIGHT_UP_AND_RIGHT")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void AnalyzeResult.Combine(AnalyzeResult result)', validate parameter 'result' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.DependencyResolver.AnalyzeResult`1.Combine(NuGet.DependencyResolver.AnalyzeResult`1)")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void GraphOperations.Dump(GraphNode root, Action write)', validate parameter 'root' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.DependencyResolver.GraphOperations.Dump``1(NuGet.DependencyResolver.GraphNode{``0},System.Action{System.String})")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'string GraphOperations.GetId(GraphNode node)', validate parameter 'node' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.DependencyResolver.GraphOperations.GetId``1(NuGet.DependencyResolver.GraphNode{``0})~System.String")] diff --git a/src/NuGet.Core/NuGet.DependencyResolver.Core/GraphModel/GraphOperations.cs b/src/NuGet.Core/NuGet.DependencyResolver.Core/GraphModel/GraphOperations.cs index 6a644ac0da2..5ffd22aa191 100644 --- a/src/NuGet.Core/NuGet.DependencyResolver.Core/GraphModel/GraphOperations.cs +++ b/src/NuGet.Core/NuGet.DependencyResolver.Core/GraphModel/GraphOperations.cs @@ -889,7 +889,6 @@ private static bool WalkTreeRejectNodesOfRejectedNodes(bool state, GraphN // Box Drawing Unicode characters: // http://www.unicode.org/charts/PDF/U2500.pdf private const char LIGHT_HORIZONTAL = '\u2500'; - private const char LIGHT_UP_AND_RIGHT = '\u2514'; private const char LIGHT_VERTICAL_AND_RIGHT = '\u251C'; [Conditional("DEBUG")] diff --git a/src/NuGet.Core/NuGet.Frameworks/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Frameworks/GlobalSuppressions.cs index 272f66dc7ad..e3ee360a6c7 100644 --- a/src/NuGet.Core/NuGet.Frameworks/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Frameworks/GlobalSuppressions.cs @@ -8,7 +8,6 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Build", "CA1823:Unused field 'Portable'.", Justification = "", Scope = "member", Target = "~F:NuGet.Frameworks.NuGetFramework.Portable")] [assembly: SuppressMessage("Build", "CA1303:Method 'AssetTargetFallbackFramework.AssetTargetFallbackFramework(NuGetFramework framework, IList fallbackFrameworks)' passes a literal string as parameter 'message' of a call to 'ArgumentException.ArgumentException(string message, string paramName)'. Retrieve the following string(s) from a resource table instead: \"Empty fallbackFrameworks is invalid\".", Justification = "", Scope = "member", Target = "~M:NuGet.Frameworks.AssetTargetFallbackFramework.#ctor(NuGet.Frameworks.NuGetFramework,System.Collections.Generic.IReadOnlyList{NuGet.Frameworks.NuGetFramework})")] [assembly: SuppressMessage("Build", "CA1822:Member IsSpecialFrameworkCompatible does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.Frameworks.CompatibilityProvider.IsSpecialFrameworkCompatible(NuGet.Frameworks.NuGetFramework,NuGet.Frameworks.NuGetFramework)~System.Nullable{System.Boolean}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'CompatibilityTable.CompatibilityTable(IEnumerable frameworks, IFrameworkNameProvider mappings, IFrameworkCompatibilityProvider compat)', validate parameter 'compat' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Frameworks.CompatibilityTable.#ctor(System.Collections.Generic.IEnumerable{NuGet.Frameworks.NuGetFramework},NuGet.Frameworks.IFrameworkNameProvider,NuGet.Frameworks.IFrameworkCompatibilityProvider)")] diff --git a/src/NuGet.Core/NuGet.Frameworks/NuGetFramework.cs b/src/NuGet.Core/NuGet.Frameworks/NuGetFramework.cs index 6a5bf90370f..efc4187595a 100644 --- a/src/NuGet.Core/NuGet.Frameworks/NuGetFramework.cs +++ b/src/NuGet.Core/NuGet.Frameworks/NuGetFramework.cs @@ -24,7 +24,6 @@ partial class NuGetFramework : IEquatable private readonly string _frameworkProfile; private string _targetFrameworkMoniker; private string _targetPlatformMoniker; - private const string Portable = "portable"; private int? _hashCode; public NuGetFramework(NuGetFramework framework) diff --git a/src/NuGet.Core/NuGet.PackageManagement/InstallationCompatibility.cs b/src/NuGet.Core/NuGet.PackageManagement/InstallationCompatibility.cs index 0b687ac8072..87bf50c1831 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/InstallationCompatibility.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/InstallationCompatibility.cs @@ -13,7 +13,6 @@ using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.ProjectManagement; -using NuGet.ProjectManagement.Projects; using NuGet.Protocol.Core.Types; namespace NuGet.PackageManagement @@ -174,14 +173,6 @@ private static void EnsurePackageCompatibility( { // These types are always acceptable. } - else if (nuGetProject is ProjectKNuGetProjectBase && - packageType == PackageType.DotnetCliTool) - { - // ProjectKNuGetProjectBase projects are .NET Core (both "dotnet" and "dnx"). - // .NET CLI tools are support for "dotnet" projects. The projects eventually - // call into INuGetPackageManager, which is not implemented by NuGet. This code - // will make the decision of how to install the .NET CLI tool package. - } else { throw new PackagingException(string.Format( diff --git a/src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectKNuGetProject.cs b/src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectKNuGetProject.cs deleted file mode 100644 index 213e21b5301..00000000000 --- a/src/NuGet.Core/NuGet.PackageManagement/Projects/ProjectKNuGetProject.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - - -namespace NuGet.ProjectManagement.Projects -{ - public abstract class ProjectKNuGetProjectBase : NuGetProject, INuGetIntegratedProject - { - } -} diff --git a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt index 1c843254b01..42565e41c4e 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt @@ -616,8 +616,6 @@ NuGet.ProjectManagement.Projects.ProjectJsonNuGetProject.IsUAPFramework(NuGet.Fr NuGet.ProjectManagement.Projects.ProjectJsonNuGetProject.JsonConfigPath.get -> string NuGet.ProjectManagement.Projects.ProjectJsonNuGetProject.ProjectJsonNuGetProject(string jsonConfig, string msBuildProjectPath) -> void NuGet.ProjectManagement.Projects.ProjectJsonNuGetProject.RemoveDependencyAsync(string packageId, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task -NuGet.ProjectManagement.Projects.ProjectKNuGetProjectBase -NuGet.ProjectManagement.Projects.ProjectKNuGetProjectBase.ProjectKNuGetProjectBase() -> void NuGet.ProjectManagement.SourceControlManager NuGet.ProjectManagement.SourceControlManager.IsPackagesFolderBoundToSourceControl() -> bool NuGet.ProjectManagement.SourceControlManager.Settings.get -> NuGet.Configuration.ISettings diff --git a/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs index 8a27d889dc0..1eef70f5f08 100644 --- a/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Packaging/GlobalSuppressions.cs @@ -11,7 +11,6 @@ [assembly: SuppressMessage("Build", "CA1825:Avoid unnecessary zero-length array allocations. Use Array.Empty() instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Core.PackageDependencyInfo.EmptyDependencies")] [assembly: SuppressMessage("Build", "CA2211:Non-constant fields should not be visible", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Licenses.NuGetLicenseData.LicenseListVersion")] [assembly: SuppressMessage("Build", "CA1823:Unused field 'SchemaVersionAttributeName'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Manifest.SchemaVersionAttributeName")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_utf8Encoding'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.PackageArchiveReader._utf8Encoding")] [assembly: SuppressMessage("Build", "CA1823:Unused field 'DefaultContentType'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.PackageBuilder.DefaultContentType")] [assembly: SuppressMessage("Build", "CA2213:'PackagesConfigWriter' contains field '_stream' that is of IDisposable type 'Stream', but it is never disposed. Change the Dispose method on 'PackagesConfigWriter' to call Close or Dispose on this field.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.PackagesConfigWriter._stream")] [assembly: SuppressMessage("Build", "CA1802:Field 'SampleDescription' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Rules.DefaultManifestValuesRule.SampleDescription")] @@ -19,7 +18,6 @@ [assembly: SuppressMessage("Build", "CA1802:Field 'SampleManifestDependencyVersion' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Rules.DefaultManifestValuesRule.SampleManifestDependencyVersion")] [assembly: SuppressMessage("Build", "CA1802:Field 'SampleReleaseNotes' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Rules.DefaultManifestValuesRule.SampleReleaseNotes")] [assembly: SuppressMessage("Build", "CA1802:Field 'SampleTags' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Rules.DefaultManifestValuesRule.SampleTags")] -[assembly: SuppressMessage("Build", "CA1823:Unused field 'ToolsDirectory'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Rules.UnrecognizedScriptFileRule.ToolsDirectory")] [assembly: SuppressMessage("Build", "CA1823:Unused field '_rfc3161RequestTimeoutSeconds'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Signing.Rfc3161TimestampProvider._rfc3161RequestTimeoutSeconds")] [assembly: SuppressMessage("Build", "CA1823:Unused field '_millisecondsPerMicrosecond'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Signing.Rfc3161TimestampVerificationUtility._millisecondsPerMicrosecond")] [assembly: SuppressMessage("Build", "CA1823:Unused field 'INVALID_PROVIDER_TYPE_HRESULT'.", Justification = "", Scope = "member", Target = "~F:NuGet.Packaging.Signing.X509SignatureProvider.INVALID_PROVIDER_TYPE_HRESULT")] diff --git a/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs b/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs index e5cc924f42a..48570094b27 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs @@ -23,7 +23,6 @@ namespace NuGet.Packaging public class PackageArchiveReader : PackageReaderBase { private readonly ZipArchive _zipArchive; - private readonly Encoding _utf8Encoding = new UTF8Encoding(); private readonly SigningSpecifications _signingSpecifications = SigningSpecifications.V1; /// diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs index a9f46c75114..8e6c5bc3551 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs @@ -26,7 +26,6 @@ namespace NuGet.Packaging { public class PackageBuilder : IPackageMetadata { - private const string DefaultContentType = "application/octet"; private static readonly Uri DefaultUri = new Uri("http://defaultcontainer/"); internal const string ManifestRelationType = "manifest"; private readonly bool _includeEmptyDirectories; diff --git a/src/NuGet.Core/NuGet.Packaging/Rules/UnrecognizedScriptFileRule.cs b/src/NuGet.Core/NuGet.Packaging/Rules/UnrecognizedScriptFileRule.cs index 15d33e50599..a3649d6067f 100644 --- a/src/NuGet.Core/NuGet.Packaging/Rules/UnrecognizedScriptFileRule.cs +++ b/src/NuGet.Core/NuGet.Packaging/Rules/UnrecognizedScriptFileRule.cs @@ -13,7 +13,6 @@ namespace NuGet.Packaging.Rules internal class UnrecognizedScriptFileRule : IPackageRule { private const string ScriptExtension = ".ps1"; - private static readonly string ToolsDirectory = PackagingConstants.Folders.Tools; public string MessageFormat { get; } diff --git a/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs index 676db34931a..4767316a7b8 100644 --- a/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs @@ -9,13 +9,7 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Build", "CA1802:Field 'NuGetConfigurationKey' is declared as 'readonly' but is initialized with a constant value. Mark this field as 'const' instead.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.HttpRequestMessageExtensions.NuGetConfigurationKey")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_xnameEntityType'.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.LegacyFeedCapabilityResourceV2Feed._xnameEntityType")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_xnameProperty'.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.LegacyFeedCapabilityResourceV2Feed._xnameProperty")] [assembly: SuppressMessage("Build", "CA2213:'SymmetricHandshake' contains field '_timeoutCancellationTokenSource' that is of IDisposable type 'CancellationTokenSource', but it is never disposed. Change the Dispose method on 'SymmetricHandshake' to call Close or Dispose on this field.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.Plugins.SymmetricHandshake._timeoutCancellationTokenSource")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_unlistedPublishedTime'.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.RemoteV2FindPackageByIdResource._unlistedPublishedTime")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_xnameLink'.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.RemoteV2FindPackageByIdResource._xnameLink")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_xnamePublish'.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.RemoteV2FindPackageByIdResource._xnamePublish")] -[assembly: SuppressMessage("Build", "CA1823:Unused field '_emptyUris'.", Justification = "", Scope = "member", Target = "~F:NuGet.Protocol.ServiceIndexResourceV3._emptyUris")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task> AutoCompleteResourceV2FeedProvider.TryCreate(SourceRepository source, CancellationToken token)', validate parameter 'source' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.AutoCompleteResourceV2FeedProvider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Tuple{System.Boolean,NuGet.Protocol.Core.Types.INuGetResource}}")] [assembly: SuppressMessage("Build", "CA1308:In method 'IdStartsWith', replace the call to 'ToLowerInvariant' with 'ToUpperInvariant'.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.AutoCompleteResourceV3.IdStartsWith(System.String,System.Boolean,NuGet.Common.ILogger,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Collections.Generic.IEnumerable{System.String}}")] [assembly: SuppressMessage("Build", "CA1305:The behavior of 'bool.ToString()' could vary based on the current user's locale settings. Replace this call in 'AutoCompleteResourceV3.IdStartsWith(string, bool, ILogger, CancellationToken)' with a call to 'bool.ToString(IFormatProvider)'.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.AutoCompleteResourceV3.IdStartsWith(System.String,System.Boolean,NuGet.Common.ILogger,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Collections.Generic.IEnumerable{System.String}}")] diff --git a/src/NuGet.Core/NuGet.Protocol/LegacyFeed/LegacyFeedCapabilityResourceV2Feed.cs b/src/NuGet.Core/NuGet.Protocol/LegacyFeed/LegacyFeedCapabilityResourceV2Feed.cs index 3de98dbde20..45659534586 100644 --- a/src/NuGet.Core/NuGet.Protocol/LegacyFeed/LegacyFeedCapabilityResourceV2Feed.cs +++ b/src/NuGet.Core/NuGet.Protocol/LegacyFeed/LegacyFeedCapabilityResourceV2Feed.cs @@ -22,13 +22,8 @@ public class LegacyFeedCapabilityResourceV2Feed : LegacyFeedCapabilityResource private static readonly ConcurrentDictionary> CachedCapabilities = new ConcurrentDictionary>(); - private const string EdmNS = "http://schemas.microsoft.com/ado/2006/04/edm"; private const string MetadataUriFormat = "{0}/$metadata"; - private static readonly XName _xnameEntityType = XName.Get("EntityType", EdmNS); - private static readonly XName _xnameProperty = XName.Get("Property", EdmNS); - - private readonly string _metadataUri; private readonly V2FeedParser _feedParser; diff --git a/src/NuGet.Core/NuGet.Protocol/RemoteRepositories/RemoteV2FindPackageByIdResource.cs b/src/NuGet.Core/NuGet.Protocol/RemoteRepositories/RemoteV2FindPackageByIdResource.cs index a50f75ec672..483804018ce 100644 --- a/src/NuGet.Core/NuGet.Protocol/RemoteRepositories/RemoteV2FindPackageByIdResource.cs +++ b/src/NuGet.Core/NuGet.Protocol/RemoteRepositories/RemoteV2FindPackageByIdResource.cs @@ -28,14 +28,9 @@ public class RemoteV2FindPackageByIdResource : FindPackageByIdResource { private static readonly XName _xnameEntry = XName.Get("entry", "http://www.w3.org/2005/Atom"); private static readonly XName _xnameContent = XName.Get("content", "http://www.w3.org/2005/Atom"); - private static readonly XName _xnameLink = XName.Get("link", "http://www.w3.org/2005/Atom"); private static readonly XName _xnameProperties = XName.Get("properties", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"); private static readonly XName _xnameId = XName.Get("Id", "http://schemas.microsoft.com/ado/2007/08/dataservices"); private static readonly XName _xnameVersion = XName.Get("Version", "http://schemas.microsoft.com/ado/2007/08/dataservices"); - private static readonly XName _xnamePublish = XName.Get("Published", "http://schemas.microsoft.com/ado/2007/08/dataservices"); - - // An unlisted package's publish time must be 1900-01-01T00:00:00. - private static readonly DateTime _unlistedPublishedTime = new DateTime(1900, 1, 1, 0, 0, 0); private readonly string _baseUri; private readonly HttpSource _httpSource; diff --git a/src/NuGet.Core/NuGet.Protocol/Resources/ServiceIndexResourceV3.cs b/src/NuGet.Core/NuGet.Protocol/Resources/ServiceIndexResourceV3.cs index b0d70d61509..cc0a1c0e12b 100644 --- a/src/NuGet.Core/NuGet.Protocol/Resources/ServiceIndexResourceV3.cs +++ b/src/NuGet.Core/NuGet.Protocol/Resources/ServiceIndexResourceV3.cs @@ -20,7 +20,6 @@ public class ServiceIndexResourceV3 : INuGetResource private readonly IDictionary> _index; private readonly DateTime _requestTime; private static readonly IReadOnlyList _emptyEntries = new List(); - private static readonly IReadOnlyList _emptyUris = new List(); private static readonly SemanticVersion _defaultVersion = new SemanticVersion(0, 0, 0); public ServiceIndexResourceV3(JObject index, DateTime requestTime) diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj index c16e6325982..f77ca5d67b6 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/NuGet.PackageManagement.VisualStudio.Test.csproj @@ -34,7 +34,6 @@ - diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/ProjectKNuGetProjectTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/ProjectKNuGetProjectTests.cs deleted file mode 100644 index e6ee6e0bd82..00000000000 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/ProjectSystems/ProjectKNuGetProjectTests.cs +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.Versioning; -using System.Threading; -using System.Threading.Tasks; -using Microsoft; -using Microsoft.VisualStudio.ProjectSystem.Interop; -using Microsoft.VisualStudio.Threading; -using Moq; -using NuGet.Frameworks; -using NuGet.Packaging.Core; -using NuGet.ProjectManagement; -using NuGet.Protocol.Core.Types; -using NuGet.Test.Utility; -using NuGet.Versioning; -using NuGet.VisualStudio; -using Test.Utility.Threading; -using Xunit; - -namespace NuGet.PackageManagement.VisualStudio.Test -{ - [Collection(DispatcherThreadCollection.CollectionName)] - public class ProjectKNuGetProjectTests - { - private readonly JoinableTaskFactory _jtf; - - public ProjectKNuGetProjectTests(DispatcherThreadFixture fixture) - { - Assumes.Present(fixture); - - _jtf = fixture.JoinableTaskFactory; - - NuGetUIThreadHelper.SetCustomJoinableTaskFactory(_jtf); - } - - [Fact] - public async Task ProjectKNuGetProject_WithVersionRange_GetInstalledPackagesAsync() - { - // Arrange - using (var testDirectory = TestDirectory.Create()) - { - var tc = new TestContext(testDirectory); - - tc.PackageManager - .Setup(x => x.GetInstalledPackagesAsync(It.IsAny())) - .ReturnsAsync(new[] { new NuGetPackageMoniker { Id = "foo", Version = "1.0.0-*" } }); - - // Act - var actual = await tc.Target.GetInstalledPackagesAsync(CancellationToken.None); - - // Assert - Assert.Equal(1, actual.Count()); - var packageReference = actual.First(); - Assert.Equal("foo", packageReference.PackageIdentity.Id); - Assert.Equal(NuGetVersion.Parse("1.0.0-0"), packageReference.PackageIdentity.Version); - } - } - - [Fact] - public async Task ProjectKNuGetProject_WithPackageTypes_InstallPackageAsync() - { - // Arrange - using (var testDirectory = TestDirectory.Create()) - { - var tc = new TestContext(testDirectory); - using (var download = await tc.InitializePackageAsync()) - { - // Act - var result = await tc.Target.InstallPackageAsync( - tc.PackageIdentity, - download, - tc.ProjectContext.Object, - CancellationToken.None); - - // Assert - Assert.True(result); - tc.PackageManager.Verify( - x => x.InstallPackageAsync( - It.Is(y => - y.Id == tc.PackageIdentity.Id && - y.Version == tc.PackageIdentity.Version.ToNormalizedString()), - It.Is>(y => - y.ContainsKey("PackageTypes") && - Enumerable.SequenceEqual((IEnumerable)y["PackageTypes"], tc.PackageTypes)), - It.IsAny(), - It.IsAny>(), - It.IsAny()), - Times.Once); - } - } - } - - [Fact] - public async Task ProjectKNuGetProject_WithFrameworks_InstallPackageAsync() - { - // Arrange - using (var testDirectory = TestDirectory.Create()) - { - var tc = new TestContext(testDirectory); - using (var download = await tc.InitializePackageAsync()) - { - // Act - var result = await tc.Target.InstallPackageAsync( - tc.PackageIdentity, - download, - tc.ProjectContext.Object, - CancellationToken.None); - - // Assert - Assert.True(result); - tc.PackageManager.Verify( - x => x.InstallPackageAsync( - It.Is(y => - y.Id == tc.PackageIdentity.Id && - y.Version == tc.PackageIdentity.Version.ToNormalizedString()), - It.Is>(y => - y.ContainsKey("Frameworks") && - Enumerable.SequenceEqual( - (IEnumerable)y["Frameworks"], - new[] - { - NuGetFramework.Parse("net45"), - NuGetFramework.Parse("netstandard1.0") - })), - It.IsAny(), - It.IsAny>(), - It.IsAny()), - Times.Once); - } - } - } - - private class TestContext - { - public TestContext(TestDirectory testDirectory) - { - // Dependencies - TestDirectory = testDirectory; - PackageManager = new Mock(); - ProjectContext = new Mock(); - var projectName = "ProjectName"; - var uniqueName = "UniqueName"; - var projectId = string.Empty; - PackageIdentity = new PackageIdentity("PackageA", new NuGetVersion("1.0.0-beta")); - PackageTypes = new List - { - new PackageType("Foo", Version.Parse("1.0.0")), - new PackageType("Bar", Version.Parse("2.0")) - }; - SupportedFrameworks = new List - { - new NuGetFramework("net40"), - new NuGetFramework("netcoreapp1.0") - }; - - // Setup - PackageManager - .Setup(x => x.GetSupportedFrameworksAsync(It.IsAny())) - .Returns(() => Task.FromResult>( - SupportedFrameworks.Select(f => new FrameworkName(f.DotNetFrameworkName)).ToList())); - - PackageManager - .Setup(x => x.GetInstalledPackagesAsync(It.IsAny())) - .Returns(() => Task.FromResult>(new object[0])); - - Target = new ProjectKNuGetProject( - PackageManager.Object, - projectName, - uniqueName, - projectId); - } - - public TestDirectory TestDirectory { get; } - public Mock PackageManager { get; } - public Mock ProjectContext { get; } - public PackageIdentity PackageIdentity { get; } - public ProjectKNuGetProject Target { get; } - public List PackageTypes { get; } - public List SupportedFrameworks { get; } - - public async Task InitializePackageAsync() - { - var context = new SimpleTestPackageContext(PackageIdentity); - context.PackageTypes.Clear(); - context.PackageTypes.AddRange(PackageTypes); - - var package = await SimpleTestPackageUtility.CreateFullPackageAsync( - TestDirectory, - context); - - return new DownloadResourceResult(package.OpenRead(), TestDirectory.Path); - } - } - } -} diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/NuGetTelemetryServiceTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/NuGetTelemetryServiceTests.cs index f6624e68d97..ab9e5da25fe 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/NuGetTelemetryServiceTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Telemetry/NuGetTelemetryServiceTests.cs @@ -17,7 +17,6 @@ public class NuGetTelemetryServiceTests [InlineData(NuGetProjectType.Unknown)] [InlineData(NuGetProjectType.PackagesConfig)] [InlineData(NuGetProjectType.UwpProjectJson)] - [InlineData(NuGetProjectType.XProjProjectJson)] [InlineData(NuGetProjectType.CPSBasedPackageRefs)] [InlineData(NuGetProjectType.LegacyProjectSystemWithPackageRefs)] [InlineData(NuGetProjectType.UnconfiguredNuGetType)] diff --git a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/InstallationCompatibilityTests.cs b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/InstallationCompatibilityTests.cs index c86e901214c..4a335817c1e 100644 --- a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/InstallationCompatibilityTests.cs +++ b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/InstallationCompatibilityTests.cs @@ -108,89 +108,6 @@ public async Task EnsurePackageCompatibilityAsync_WithLowerMinClientVersion_Fail tc.NuspecReader.Verify(x => x.GetPackageTypes(), Times.Never); } - [Fact] - public async Task EnsurePackageCompatibility_WithValidProjectActions_Succeeds() - { - // Arrange - using (var userPackageFolder = TestDirectory.Create()) - { - var tc = new TestContext(userPackageFolder); - - await SimpleTestPackageUtility.CreateFolderFeedV3Async( - userPackageFolder, - PackageSaveMode.Defaultv3, - new[] - { - new SimpleTestPackageContext(tc.PackageIdentityA) - { - PackageTypes = { PackageType.DotnetCliTool } - }, - new SimpleTestPackageContext(tc.PackageIdentityB) // Not inspected, because this package is - // being uninstalled, not installed. - { - PackageTypes = { tc.InvalidPackageType } - }, - new SimpleTestPackageContext(tc.PackageIdentityC) - { - PackageTypes = { PackageType.Dependency } - }, - }); - - // Act & Assert - tc.Target.EnsurePackageCompatibility( - tc.ProjectKProject, - tc.NuGetPathContext.Object, - new NuGetProjectAction[] - { - NuGetProjectAction.CreateInstallProjectAction(tc.PackageIdentityA, tc.SourceRepository, tc.ProjectKProject), - NuGetProjectAction.CreateUninstallProjectAction(tc.PackageIdentityB, tc.ProjectKProject), - NuGetProjectAction.CreateInstallProjectAction(tc.PackageIdentityC, tc.SourceRepository, tc.ProjectKProject) - }, - tc.GetRestoreResult(new[] - { - tc.PackageIdentityA, - tc.PackageIdentityB, - tc.PackageIdentityC - })); - } - } - - [Fact] - public async Task EnsurePackageCompatibility_WithInvalidProjectActions_Fails() - { - // Arrange - using (var userPackageFolder = TestDirectory.Create()) - { - var tc = new TestContext(userPackageFolder); - - await SimpleTestPackageUtility.CreateFolderFeedV3Async( - userPackageFolder, - PackageSaveMode.Defaultv3, - new[] - { - new SimpleTestPackageContext(tc.PackageIdentityA) - { - PackageTypes = { tc.InvalidPackageType } - } - }); - - // Act & Assert - var ex = Assert.Throws(() => - tc.Target.EnsurePackageCompatibility( - tc.ProjectKProject, - tc.NuGetPathContext.Object, - new NuGetProjectAction[] - { - NuGetProjectAction.CreateInstallProjectAction(tc.PackageIdentityA, tc.SourceRepository, tc.ProjectKProject) - }, - tc.GetRestoreResult(new[] { tc.PackageIdentityA }))); - - Assert.Equal( - "Package 'PackageA 1.0.0' has a package type 'Invalid 1.2' that is not supported by project 'TestProjectKNuGetProject'.", - ex.Message); - } - } - [Fact] public async Task EnsurePackageCompatibilityAsync_WithNuGetProject_WithInvalidType_Fails() { @@ -266,66 +183,6 @@ public async Task EnsurePackageCompatibilityAsync_WithNuGetProject_WithDependenc await tc.VerifySuccessAsync(tc.NuGetProject); } - [Fact] - public async Task EnsurePackageCompatibilityAsync_WithProjectKProject_WithInvalidType_Fails() - { - // Arrange - var tc = new TestContext(); - tc.PackageTypes.Add(tc.InvalidPackageType); - - // Act & Assert - await tc.VerifyFailureAsync( - tc.ProjectKProject, - "Package 'PackageA 1.0.0' has a package type 'Invalid 1.2' that is not supported by project 'TestProjectKNuGetProject'."); - } - - [Fact] - public async Task EnsurePackageCompatibilityAsync_WithProjectKProject_WithMultipleTypes_Fails() - { - // Arrange - var tc = new TestContext(); - tc.PackageTypes.Add(PackageType.Legacy); - tc.PackageTypes.Add(PackageType.Dependency); - - // Act & Assert - await tc.VerifyFailureAsync( - tc.ProjectKProject, - "Package 'PackageA 1.0.0' has multiple package types, which is not supported."); - } - - [Fact] - public async Task EnsurePackageCompatibilityAsync_WithProjectKProject_WithDotnetCliToolType_Succeeds() - { - // Arrange - var tc = new TestContext(); - tc.PackageTypes.Add(PackageType.DotnetCliTool); - - // Act & Assert - await tc.VerifySuccessAsync(tc.ProjectKProject); - } - - [Fact] - public async Task EnsurePackageCompatibilityAsync_WithProjectKProject_WithLegacyType_Succeeds() - { - // Arrange - var tc = new TestContext(); - tc.PackageTypes.Add(PackageType.Legacy); - - // Act & Assert - await tc.VerifySuccessAsync(tc.ProjectKProject); - } - - [Fact] - public async Task EnsurePackageCompatibilityAsync_WithProjectKProject_WithDependency_Succeeds() - { - // Arrange - var tc = new TestContext(); - tc.PackageTypes.Add(PackageType.Dependency); - - // Act & Assert - await tc.VerifySuccessAsync(tc.ProjectKProject); - } - private class TestContext { public TestContext(string userPackageFolder = null) @@ -342,7 +199,6 @@ public TestContext(string userPackageFolder = null) InvalidPackageType = new PackageType("Invalid", new Version(1, 2)); NuGetProject = new TestNuGetProject(new List()); - ProjectKProject = new TestProjectKNuGetProject(); NuGetPathContext = new Mock(); @@ -397,7 +253,6 @@ public TestContext(string userPackageFolder = null) public List PackageTypes { get; } public NuGetVersion MinClientVersion { get; set; } public TestNuGetProject NuGetProject { get; } - public TestProjectKNuGetProject ProjectKProject { get; } public Mock NuGetPathContext { get; } public Mock PackageReader { get; } public Mock NuspecReader { get; } diff --git a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/TestProjectKNuGetProject.cs b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/TestProjectKNuGetProject.cs deleted file mode 100644 index 2550cba997a..00000000000 --- a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/TestProjectKNuGetProject.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using NuGet.Frameworks; -using NuGet.Packaging; -using NuGet.Packaging.Core; -using NuGet.ProjectManagement; -using NuGet.ProjectManagement.Projects; -using NuGet.Protocol.Core.Types; - -namespace NuGet.Test -{ - internal class TestProjectKNuGetProject : ProjectKNuGetProjectBase - { - public TestProjectKNuGetProject() - { - InternalMetadata.AddRange(CreateMetadata()); - } - - private static Dictionary CreateMetadata() - { - return new Dictionary - { - { NuGetProjectMetadataKeys.Name, nameof(TestProjectKNuGetProject) }, - { NuGetProjectMetadataKeys.TargetFramework, NuGetFramework.Parse("net45") }, - }; - } - - public override Task> GetInstalledPackagesAsync(CancellationToken token) - { - return Task.FromResult>(new PackageReference[0]); - } - - public override Task InstallPackageAsync( - PackageIdentity packageIdentity, - DownloadResourceResult downloadResourceResult, - INuGetProjectContext nuGetProjectContext, - CancellationToken token) - { - return Task.FromResult(true); - } - - public override Task UninstallPackageAsync( - PackageIdentity packageIdentity, - INuGetProjectContext nuGetProjectContext, - CancellationToken token) - { - throw new NotImplementedException(); - } - } -} From 8530a138791a66c4f6dde67357c5b024a3f91c57 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 5 Nov 2020 19:36:49 +0100 Subject: [PATCH 033/129] Don't wrap output when output has been redirected to a file. (#3743) This was introduced as a fix for https://github.com/NuGet/Home/issues/1893, which was previously fixed like I'm proposing here (https://github.com/NuGet/NuGet2/commit/98d15b3b5d18a3100136d8b9a5aaf857d7b8b5b4). I can't see a reason to wrap output when it has been redirected to a file, so I'm proposing to apply the original fix. --- src/NuGet.Clients/NuGet.CommandLine/Common/Console.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NuGet.Clients/NuGet.CommandLine/Common/Console.cs b/src/NuGet.Clients/NuGet.CommandLine/Common/Console.cs index f35ba2d5375..d6f61972008 100644 --- a/src/NuGet.Clients/NuGet.CommandLine/Common/Console.cs +++ b/src/NuGet.Clients/NuGet.CommandLine/Common/Console.cs @@ -77,7 +77,7 @@ public int WindowWidth { // This happens when redirecting output to a file, on // Linux and OS X (running with Mono). - return 80; + return int.MaxValue; } } catch (IOException) From 9157b098f4f65f82f301585b9ebbe1c052491130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 5 Nov 2020 11:39:39 -0800 Subject: [PATCH 034/129] bump preview version to preview.2 (#3753) --- build/config.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/config.props b/build/config.props index d788024fa93..99af188585a 100644 --- a/build/config.props +++ b/build/config.props @@ -19,7 +19,7 @@ - preview.1 + preview.2 false From f11b8166cd2bfcf4a26f40844adec6ad4530122b Mon Sep 17 00:00:00 2001 From: Andy Zivkovic Date: Mon, 9 Nov 2020 09:40:32 -0800 Subject: [PATCH 035/129] Use PublicApiAnalyzer with NuGet.VisualStudio.Internal.Contracts (#3708) --- .../INuGetProjectManagerService.cs | 2 - .../INuGetProjectManagerServiceState.cs | 2 - .../INuGetSolutionManagerService.cs | 2 - .../INuGetSourcesService.cs | 2 - .../IPackageReferenceContextInfo.cs | 2 - .../IProjectContextInfo.cs | 2 - .../IProjectMetadataContextInfo.cs | 2 - .../ImplicitProjectAction.cs | 2 +- ...Get.VisualStudio.Internal.Contracts.csproj | 3 + .../NuGetJsonRpc.cs | 8 +- .../NuGetProjectKind.cs | 2 - .../NuGetServiceMessagePackRpcDescriptor.cs | 2 - .../NuGetServices.cs | 2 - .../PackageReferenceContextInfo.cs | 2 - .../ProjectAction.cs | 4 +- .../ProjectContextInfo.cs | 2 - .../ProjectMetadataContextInfo.cs | 2 - .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 127 ++++++++++++++++++ .../Utility/RemoteError.cs | 14 +- .../Utility/RemoteErrorUtility.cs | 6 +- tools-local/ship-public-apis/Program.cs | 18 ++- 22 files changed, 161 insertions(+), 48 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Shipped.txt create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Unshipped.txt diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs index 3947e38d4de..6f239bf8c47 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerService.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using System.Collections.Generic; using System.Threading; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerServiceState.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerServiceState.cs index 67a2171e249..a02e29441e4 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerServiceState.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetProjectManagerServiceState.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using System.Collections.Generic; using Microsoft.VisualStudio.Threading; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSolutionManagerService.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSolutionManagerService.cs index c6b5612c1d6..0f1502148b7 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSolutionManagerService.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSolutionManagerService.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSourcesService.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSourcesService.cs index deafe73b1f4..a35ae46760d 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSourcesService.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/INuGetSourcesService.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using System.Collections.Generic; using System.Threading; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IPackageReferenceContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IPackageReferenceContextInfo.cs index ee125bacdf1..ca269381d95 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IPackageReferenceContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IPackageReferenceContextInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using NuGet.Frameworks; using NuGet.Packaging.Core; using NuGet.Versioning; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs index f0f1d03a1e3..c9e5e33246e 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectContextInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using NuGet.ProjectModel; namespace NuGet.VisualStudio.Internal.Contracts diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectMetadataContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectMetadataContextInfo.cs index 327d705aeeb..94ebeb9778c 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectMetadataContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/IProjectMetadataContextInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System.Collections.Generic; using NuGet.Frameworks; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ImplicitProjectAction.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ImplicitProjectAction.cs index 383c6ce85d1..78f1f40e369 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ImplicitProjectAction.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ImplicitProjectAction.cs @@ -28,7 +28,7 @@ public ImplicitProjectAction( ProjectActionType = projectActionType; } - public bool Equals(ImplicitProjectAction other) + public bool Equals(ImplicitProjectAction? other) { if (other == null) { diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGet.VisualStudio.Internal.Contracts.csproj b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGet.VisualStudio.Internal.Contracts.csproj index af33ef03e1c..3b993d7fa89 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGet.VisualStudio.Internal.Contracts.csproj +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGet.VisualStudio.Internal.Contracts.csproj @@ -10,6 +10,9 @@ true NuGet.VisualStudio.Internal.Contracts 8 + enable + + true diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs index 384dc05454c..d6d62659527 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetJsonRpc.cs @@ -15,16 +15,16 @@ internal NuGetJsonRpc(IJsonRpcMessageHandler messageHandler) { } - protected override Type GetErrorDetailsDataType(JsonRpcError error) + protected override Type? GetErrorDetailsDataType(JsonRpcError error) { - if (error is object - && error.Error is object - && (int)error.Error.Code == (int)RemoteErrorCode.RemoteError) + if ((int?)error?.Error?.Code == (int)RemoteErrorCode.RemoteError) { return typeof(RemoteError); } +#pragma warning disable CS8604 // Possible null reference argument. return base.GetErrorDetailsDataType(error); +#pragma warning restore CS8604 // Possible null reference argument. } } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetProjectKind.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetProjectKind.cs index c40ac13d7fe..0367aee99dc 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetProjectKind.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetProjectKind.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - namespace NuGet.VisualStudio.Internal.Contracts { public enum NuGetProjectKind diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs index 01f712d10ba..9abf2e68e5d 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using MessagePack; using MessagePack.Formatters; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServices.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServices.cs index 0745e9c0dcf..05b81e732c4 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServices.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServices.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using Microsoft.ServiceHub.Framework; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PackageReferenceContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PackageReferenceContextInfo.cs index 7479c4b516c..057596c496f 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PackageReferenceContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PackageReferenceContextInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using Microsoft; using NuGet.Frameworks; using NuGet.Packaging; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectAction.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectAction.cs index e5929fde71f..e6fa80c1f10 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectAction.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectAction.cs @@ -21,7 +21,7 @@ public ProjectAction( string projectId, PackageIdentity packageIdentity, NuGetProjectActionType projectActionType, - IReadOnlyList implicitActions) + IReadOnlyList? implicitActions) { if (string.IsNullOrEmpty(id)) { @@ -40,7 +40,7 @@ public ProjectAction( ImplicitActions = implicitActions ?? Array.Empty(); } - public bool Equals(ProjectAction other) + public bool Equals(ProjectAction? other) { if (other == null) { diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs index 53f2a6b5a0c..4932f7d2b5a 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectContextInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectMetadataContextInfo.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectMetadataContextInfo.cs index 987167ce089..f3257c6fcb8 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectMetadataContextInfo.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/ProjectMetadataContextInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Shipped.txt b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..7dc5c58110b --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Unshipped.txt b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..7aaabf4a274 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/PublicAPI.Unshipped.txt @@ -0,0 +1,127 @@ +#nullable enable +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.BeginOperationAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.EndOperationAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.ExecuteActionsAsync(System.Collections.Generic.IReadOnlyList! actions, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetInstallActionsAsync(System.Collections.Generic.IReadOnlyCollection! projectIds, NuGet.Packaging.Core.PackageIdentity! packageIdentity, NuGet.PackageManagement.VersionConstraints versionConstraints, bool includePrelease, NuGet.Resolver.DependencyBehavior dependencyBehavior, System.Collections.Generic.IReadOnlyList! packageSourceNames, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetInstalledPackagesAsync(System.Collections.Generic.IReadOnlyCollection! projectIds, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetInstalledPackagesDependencyInfoAsync(string! projectId, bool includeUnresolved, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetMetadataAsync(string! projectId, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetProjectAsync(string! projectId, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetProjectsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetProjectsWithDeprecatedDotnetFrameworkAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetUninstallActionsAsync(System.Collections.Generic.IReadOnlyCollection! projectIds, NuGet.Packaging.Core.PackageIdentity! packageIdentity, bool removeDependencies, bool forceRemove, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.GetUpdateActionsAsync(System.Collections.Generic.IReadOnlyCollection! projectIds, System.Collections.Generic.IReadOnlyCollection! packageIdentities, NuGet.PackageManagement.VersionConstraints versionConstraints, bool includePrelease, NuGet.Resolver.DependencyBehavior dependencyBehavior, System.Collections.Generic.IReadOnlyList! packageSourceNames, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerService.TryGetInstalledPackageFilePathAsync(string! projectId, NuGet.Packaging.Core.PackageIdentity! packageIdentity, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask<(bool, string?)> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.AsyncSemaphore.get -> Microsoft.VisualStudio.Threading.AsyncSemaphore! +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.PackageIdentity.get -> NuGet.Packaging.Core.PackageIdentity? +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.PackageIdentity.set -> void +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.Reset() -> void +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.ResolvedActions.get -> System.Collections.Generic.Dictionary! +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext? +NuGet.VisualStudio.Internal.Contracts.INuGetProjectManagerServiceState.SourceCacheContext.set -> void +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.BackupProjectAsync(string! projectId, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.GetUpgradeableProjectsAsync(System.Collections.Generic.IReadOnlyCollection! projectIds, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.InstallPackagesAsync(string! projectId, System.Collections.Generic.IReadOnlyList! packageIdentities, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.IsProjectUpgradeableAsync(string! projectId, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.SaveProjectAsync(string! projectId, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.UninstallPackagesAsync(string! projectId, System.Collections.Generic.IReadOnlyList! packageIdentities, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetProjectUpgraderService.UpgradeProjectToPackageReferenceAsync(string! projectId, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.AfterNuGetCacheUpdated -> System.EventHandler! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.AfterProjectRenamed -> System.EventHandler! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.GetSolutionDirectoryAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.ProjectAdded -> System.EventHandler! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.ProjectRemoved -> System.EventHandler! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.ProjectRenamed -> System.EventHandler! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService.ProjectUpdated -> System.EventHandler! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionService.RestoreSolutionAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +NuGet.VisualStudio.Internal.Contracts.INuGetSourcesService.GetPackageSourcesAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask!> +NuGet.VisualStudio.Internal.Contracts.INuGetSourcesService.SavePackageSourcesAsync(System.Collections.Generic.IReadOnlyList! sources, NuGet.Configuration.PackageSourceUpdateOptions! packageSourceUpdateOptions, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo.Framework.get -> NuGet.Frameworks.NuGetFramework! +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo.Identity.get -> NuGet.Packaging.Core.PackageIdentity! +NuGet.VisualStudio.Internal.Contracts.IProjectContextInfo.ProjectId.get -> string! +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo.SupportedFrameworks.get -> System.Collections.Generic.IReadOnlyCollection? +NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.Equals(NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction? other) -> bool +NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.Id.get -> string! +NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.ImplicitProjectAction(string! id, NuGet.Packaging.Core.PackageIdentity! packageIdentity, NuGet.PackageManagement.NuGetProjectActionType projectActionType) -> void +NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.PackageIdentity.get -> NuGet.Packaging.Core.PackageIdentity! +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.Framework.get -> NuGet.Frameworks.NuGetFramework! +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.Identity.get -> NuGet.Packaging.Core.PackageIdentity! +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.PackageReferenceContextInfo(NuGet.Packaging.Core.PackageIdentity! identity, NuGet.Frameworks.NuGetFramework! framework) -> void +NuGet.VisualStudio.Internal.Contracts.ProjectAction.Equals(NuGet.VisualStudio.Internal.Contracts.ProjectAction? other) -> bool +NuGet.VisualStudio.Internal.Contracts.ProjectAction.Id.get -> string! +NuGet.VisualStudio.Internal.Contracts.ProjectAction.ImplicitActions.get -> System.Collections.Generic.IReadOnlyList! +NuGet.VisualStudio.Internal.Contracts.ProjectAction.PackageIdentity.get -> NuGet.Packaging.Core.PackageIdentity! +NuGet.VisualStudio.Internal.Contracts.ProjectAction.ProjectAction(string! id, string! projectId, NuGet.Packaging.Core.PackageIdentity! packageIdentity, NuGet.PackageManagement.NuGetProjectActionType projectActionType, System.Collections.Generic.IReadOnlyList? implicitActions) -> void +NuGet.VisualStudio.Internal.Contracts.ProjectAction.ProjectId.get -> string! +NuGet.VisualStudio.Internal.Contracts.ProjectContextInfo.ProjectContextInfo(string! projectId, NuGet.ProjectModel.ProjectStyle projectStyle, NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind projectKind) -> void +NuGet.VisualStudio.Internal.Contracts.ProjectContextInfo.ProjectId.get -> string! +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.SupportedFrameworks.get -> System.Collections.Generic.IReadOnlyCollection? +NuGet.VisualStudio.Internal.Contracts.RemoteError +NuGet.VisualStudio.Internal.Contracts.RemoteError.ActivityLogMessage.get -> string? +NuGet.VisualStudio.Internal.Contracts.RemoteError.LogMessage.get -> NuGet.Common.ILogMessage! +NuGet.VisualStudio.Internal.Contracts.RemoteError.LogMessages.get -> System.Collections.Generic.IReadOnlyList? +NuGet.VisualStudio.Internal.Contracts.RemoteError.ProjectContextLogMessage.get -> string? +NuGet.VisualStudio.Internal.Contracts.RemoteError.RemoteError(string! typeName, NuGet.Common.ILogMessage! logMessage, System.Collections.Generic.IReadOnlyList? logMessages) -> void +NuGet.VisualStudio.Internal.Contracts.RemoteError.RemoteError(string! typeName, NuGet.Common.ILogMessage! logMessage, System.Collections.Generic.IReadOnlyList? logMessages, string? projectContextLogMessage, string? activityLogMessage) -> void +NuGet.VisualStudio.Internal.Contracts.RemoteError.TypeName.get -> string! +NuGet.VisualStudio.Internal.Contracts.RemoteErrorCode +NuGet.VisualStudio.Internal.Contracts.RemoteErrorCode.RemoteError = -31999 -> NuGet.VisualStudio.Internal.Contracts.RemoteErrorCode +NuGet.VisualStudio.Internal.Contracts.RemoteErrorUtility +override NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.Equals(object! obj) -> bool +override NuGet.VisualStudio.Internal.Contracts.ProjectAction.Equals(object! obj) -> bool +static NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.Create(NuGet.Packaging.Core.PackageIdentity! identity, NuGet.Frameworks.NuGetFramework! framework) -> NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo! +static NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.Create(NuGet.Packaging.PackageReference! packageReference) -> NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo! +static NuGet.VisualStudio.Internal.Contracts.ProjectContextInfo.CreateAsync(NuGet.ProjectManagement.NuGetProject! nugetProject, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask +static NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.Create(System.Collections.Generic.IReadOnlyDictionary! projectMetadata) -> NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo! +static NuGet.VisualStudio.Internal.Contracts.RemoteErrorUtility.ToRemoteError(System.Exception! exception) -> NuGet.VisualStudio.Internal.Contracts.RemoteError! +static readonly NuGet.VisualStudio.Internal.Contracts.NuGetServices.ProjectManagerService -> Microsoft.ServiceHub.Framework.ServiceRpcDescriptor! +static readonly NuGet.VisualStudio.Internal.Contracts.NuGetServices.ProjectUpgraderService -> Microsoft.ServiceHub.Framework.ServiceRpcDescriptor! +static readonly NuGet.VisualStudio.Internal.Contracts.NuGetServices.SolutionManagerService -> Microsoft.ServiceHub.Framework.ServiceRpcDescriptor! +static readonly NuGet.VisualStudio.Internal.Contracts.NuGetServices.SolutionService -> Microsoft.ServiceHub.Framework.ServiceRpcDescriptor! +static readonly NuGet.VisualStudio.Internal.Contracts.NuGetServices.SourceProviderService -> Microsoft.ServiceHub.Framework.ServiceRpcDescriptor! +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionManagerService +NuGet.VisualStudio.Internal.Contracts.INuGetSolutionService +NuGet.VisualStudio.Internal.Contracts.INuGetSourcesService +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo.AllowedVersions.get -> NuGet.Versioning.VersionRange? +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo.IsAutoReferenced.get -> bool +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo.IsDevelopmentDependency.get -> bool +NuGet.VisualStudio.Internal.Contracts.IPackageReferenceContextInfo.IsUserInstalled.get -> bool +NuGet.VisualStudio.Internal.Contracts.IProjectContextInfo +NuGet.VisualStudio.Internal.Contracts.IProjectContextInfo.ProjectKind.get -> NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.IProjectContextInfo.ProjectStyle.get -> NuGet.ProjectModel.ProjectStyle +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo.FullPath.get -> string? +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo.Name.get -> string? +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo.ProjectId.get -> string? +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo.TargetFramework.get -> NuGet.Frameworks.NuGetFramework? +NuGet.VisualStudio.Internal.Contracts.IProjectMetadataContextInfo.UniqueName.get -> string? +NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction +NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.ProjectActionType.get -> NuGet.PackageManagement.NuGetProjectActionType +NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind.PackageReference = 2 -> NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind.PackagesConfig = 1 -> NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind.ProjectK = 3 -> NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind.Unknown = 0 -> NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.NuGetServices +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.AllowedVersions.get -> NuGet.Versioning.VersionRange? +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.IsAutoReferenced.get -> bool +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.IsDevelopmentDependency.get -> bool +NuGet.VisualStudio.Internal.Contracts.PackageReferenceContextInfo.IsUserInstalled.get -> bool +NuGet.VisualStudio.Internal.Contracts.ProjectAction +NuGet.VisualStudio.Internal.Contracts.ProjectAction.ProjectActionType.get -> NuGet.PackageManagement.NuGetProjectActionType +NuGet.VisualStudio.Internal.Contracts.ProjectContextInfo +NuGet.VisualStudio.Internal.Contracts.ProjectContextInfo.ProjectKind.get -> NuGet.VisualStudio.Internal.Contracts.NuGetProjectKind +NuGet.VisualStudio.Internal.Contracts.ProjectContextInfo.ProjectStyle.get -> NuGet.ProjectModel.ProjectStyle +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.FullPath.get -> string? +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.Name.get -> string? +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.ProjectId.get -> string? +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.TargetFramework.get -> NuGet.Frameworks.NuGetFramework? +NuGet.VisualStudio.Internal.Contracts.ProjectMetadataContextInfo.UniqueName.get -> string? +override NuGet.VisualStudio.Internal.Contracts.ImplicitProjectAction.GetHashCode() -> int +override NuGet.VisualStudio.Internal.Contracts.ProjectAction.GetHashCode() -> int diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs index 7f046aa72f8..603af86b14f 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteError.cs @@ -10,12 +10,12 @@ namespace NuGet.VisualStudio.Internal.Contracts public sealed class RemoteError { public ILogMessage LogMessage { get; } - public IReadOnlyList LogMessages { get; } - public string ProjectContextLogMessage { get; } - public string ActivityLogMessage { get; } + public IReadOnlyList? LogMessages { get; } + public string? ProjectContextLogMessage { get; } + public string? ActivityLogMessage { get; } public string TypeName { get; } - public RemoteError(string typeName, ILogMessage logMessage, IReadOnlyList logMessages) + public RemoteError(string typeName, ILogMessage logMessage, IReadOnlyList? logMessages) { if (string.IsNullOrEmpty(typeName)) { @@ -30,9 +30,9 @@ public RemoteError(string typeName, ILogMessage logMessage, IReadOnlyList logMessages, - string projectContextLogMessage, - string activityLogMessage) + IReadOnlyList? logMessages, + string? projectContextLogMessage, + string? activityLogMessage) : this(typeName, logMessage, logMessages) { ProjectContextLogMessage = projectContextLogMessage; diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs index 50c97c7f5af..b2d7f0c6c87 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Utility/RemoteErrorUtility.cs @@ -25,7 +25,7 @@ public static RemoteError ToRemoteError(Exception exception) } ILogMessage logMessage; - IReadOnlyList logMessages = null; + IReadOnlyList? logMessages = null; string typeName = exception.GetType().FullName; if (exception is SignatureException signatureException) @@ -38,8 +38,8 @@ public static RemoteError ToRemoteError(Exception exception) } logMessage = new LogMessage(LogLevel.Error, ExceptionUtilities.DisplayMessage(exception, indent: false)); - string projectContextLogMessage = null; - string activityLogMessage = null; + string? projectContextLogMessage = null; + string? activityLogMessage = null; if (exception is NuGetResolverConstraintException || exception is PackageAlreadyInstalledException diff --git a/tools-local/ship-public-apis/Program.cs b/tools-local/ship-public-apis/Program.cs index 3143f2be4da..5e9bd627c75 100644 --- a/tools-local/ship-public-apis/Program.cs +++ b/tools-local/ship-public-apis/Program.cs @@ -80,7 +80,8 @@ static async Task MainAsync(DirectoryInfo path, bool resort) throw new FileNotFoundException($"Cannot migrate APIs from {unshippedTxtPath.FullName}. {shippedTxtPath} not found."); } - var lines = new List(); + var shippedLines = new List(); + var unshippedLines = new List(); int unshippedApiCount = 0; using (var stream = unshippedTxtPath.OpenText()) { @@ -89,8 +90,15 @@ static async Task MainAsync(DirectoryInfo path, bool resort) { if (!string.IsNullOrWhiteSpace(line)) { - lines.Add(line); - unshippedApiCount++; + if (line.StartsWith("#")) + { + unshippedLines.Add(line); + } + else + { + shippedLines.Add(line); + unshippedApiCount++; + } } } } @@ -109,8 +117,8 @@ static async Task MainAsync(DirectoryInfo path, bool resort) lines.Sort(StringComparer.Ordinal); - await File.WriteAllLinesAsync(shippedTxtPath, lines); - await File.WriteAllBytesAsync(unshippedTxtPath.FullName, Array.Empty()); + await File.WriteAllLinesAsync(shippedTxtPath, shippedLines); + await File.WriteAllLinesAsync(unshippedTxtPath.FullName, unshippedLines); Console.WriteLine($"{unshippedTxtPath.FullName}: Shipped {unshippedApiCount} APIs."); } From d723c73f5671fbf9c03b30485cfa47b55bb11607 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Mon, 9 Nov 2020 10:28:54 -0800 Subject: [PATCH 036/129] When restoring, resolve commandline passed sources against the current working directory (#3722) --- .../ExtensionMethods.cs | 13 ++++ .../IMSBuildProject.cs | 7 ++ .../MSBuildProjectInstance.cs | 12 ++++ .../MSBuildStaticGraphRestore.cs | 13 ++-- .../NuGet.Build.Tasks/BuildTasksUtility.cs | 59 ++++++++++++++-- .../GetRestoreSettingsTask.cs | 9 +++ .../NuGet.Build.Tasks/NuGet.RestoreEx.targets | 1 + .../NuGet.Build.Tasks/PublicAPI.Unshipped.txt | 6 +- .../NuGet.Build.Tasks/RestoreTaskEx.cs | 12 +++- .../RestoreNETCoreTest.cs | 5 +- .../MsbuildRestoreTaskTests.cs | 58 +++++++++++++++ .../BuildTasksUtilityTests.cs | 65 +++++++++++++++++ .../MSBuildStaticGraphRestoreTests.cs | 24 +++++-- .../MockMSBuildProject.cs | 25 +++++++ .../GetRestoreSettingTaskTests.cs | 70 +++++++++++++++++++ .../RestoreTaskExTests.cs | 8 ++- 16 files changed, 361 insertions(+), 26 deletions(-) create mode 100644 test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Console/ExtensionMethods.cs b/src/NuGet.Core/NuGet.Build.Tasks.Console/ExtensionMethods.cs index 861c49c51ec..b956b5f511e 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Console/ExtensionMethods.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks.Console/ExtensionMethods.cs @@ -37,6 +37,19 @@ public static string[] SplitPropertyValueOrNull(this IMSBuildItem item, string n return value == null ? null : MSBuildStringUtility.Split(value); } + /// + /// Splits the value of the specified property and returns an array if the property has a value, otherwise returns null. + /// + /// The to get the property value from. + /// The name of the property to get the value of and split. + /// A containing the split value of the property if the property had a value, otherwise null. + public static string[] SplitGlobalPropertyValueOrNull(this IMSBuildProject item, string name) + { + string value = item.GetGlobalProperty(name); + + return value == null ? null : MSBuildStringUtility.Split(value); + } + /// /// Determines if the specified value is equal to . /// diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Console/IMSBuildProject.cs b/src/NuGet.Core/NuGet.Build.Tasks.Console/IMSBuildProject.cs index 051c6735639..92ec7566d2e 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Console/IMSBuildProject.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks.Console/IMSBuildProject.cs @@ -21,6 +21,13 @@ internal interface IMSBuildProject : IMSBuildItem /// string FullPath { get; } + /// + /// Retrieve global property value and trim. + /// + /// + /// Trimmed global property value + string GetGlobalProperty(string property); + /// /// Gets items in the project with the specified name. /// diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildProjectInstance.cs b/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildProjectInstance.cs index 877e8710b0c..002ef7f1c63 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildProjectInstance.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildProjectInstance.cs @@ -50,5 +50,17 @@ public IEnumerable GetItems(string name) /// protected override string GetPropertyValue(string name) => _projectInstance.GetPropertyValue(name); + + public string GetGlobalProperty(string property) + { + string value = GetPropertyValue(property).Trim(); + + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + return value; + } } } diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildStaticGraphRestore.cs b/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildStaticGraphRestore.cs index 89b1c2a1a6e..509fbb8b2d6 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildStaticGraphRestore.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildStaticGraphRestore.cs @@ -247,7 +247,7 @@ internal static List GetPackageReferences(IMSBuildProject pro internal static string GetPackagesPath(IMSBuildProject project, ISettings settings) { return RestoreSettingsUtils.GetValue( - () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestorePackagesPathOverride")), + () => UriUtility.GetAbsolutePath(project.Directory, project.GetGlobalProperty("RestorePackagesPath")), () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestorePackagesPath")), () => SettingsUtility.GetGlobalPackagesFolder(settings)); } @@ -405,7 +405,7 @@ internal static NuGetVersion GetProjectVersion(IMSBuildItem project) internal static string GetRepositoryPath(IMSBuildProject project, ISettings settings) { return RestoreSettingsUtils.GetValue( - () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestoreRepositoryPathOverride")), + () => UriUtility.GetAbsolutePath(project.Directory, project.GetGlobalProperty("RestoreRepositoryPath")), () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestoreRepositoryPath")), () => SettingsUtility.GetRepositoryPath(settings), () => @@ -442,9 +442,10 @@ internal static string GetRestoreOutputPath(IMSBuildProject project) internal static List GetSources(IMSBuildProject project, IReadOnlyCollection innerNodes, ISettings settings) { return BuildTasksUtility.GetSources( + project.GetGlobalProperty("OriginalMSBuildStartupDirectory"), project.Directory, project.SplitPropertyValueOrNull("RestoreSources"), - project.SplitPropertyValueOrNull("RestoreSourcesOverride"), + project.SplitGlobalPropertyValueOrNull("RestoreSources"), innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectSources"))), settings) .Select(i => new PackageSource(i)) @@ -606,6 +607,8 @@ private DependencyGraphSpec GetDependencyGraphSpec(string entryProjectPath, IDic // Get the PackageSpecs in parallel because creating each one is relatively expensive so parallelism speeds things up Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, project => { + MSBuildLogger.LogMinimal($"For {project.OuterProject.FullPath}," + + $" the value of MSBuildStartupDirectory:{project.OuterProject.GetProperty("MSBuildStartupDirectory")}"); var packageSpec = GetPackageSpec(project.OuterProject, project); if (packageSpec != null) @@ -623,7 +626,6 @@ private DependencyGraphSpec GetDependencyGraphSpec(string entryProjectPath, IDic projectPathLookup.TryAdd(projectPath, projectPath); } - // TODO: Remove this lock once https://github.com/NuGet/Home/issues/9002 is fixed lock (dependencyGraphSpec) { dependencyGraphSpec.AddProject(packageSpec); @@ -765,9 +767,10 @@ private PackageSpec GetPackageSpec(IMSBuildProject project, IReadOnlyDictionary< CrossTargeting = (projectStyle == ProjectStyle.PackageReference || projectStyle == ProjectStyle.DotnetToolReference) && ( projectsByTargetFramework.Count > 1 || !string.IsNullOrWhiteSpace(project.GetProperty("TargetFrameworks"))), FallbackFolders = BuildTasksUtility.GetFallbackFolders( + project.GetProperty("MSBuildStartupDirectory"), project.Directory, project.SplitPropertyValueOrNull("RestoreFallbackFolders"), - project.SplitPropertyValueOrNull("RestoreFallbackFoldersOverride"), + project.SplitGlobalPropertyValueOrNull("RestoreFallbackFolders"), innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectFallbackFolders"))), innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectFallbackFoldersExcludes"))), settings), diff --git a/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs b/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs index ffacb8aef38..22b25bea9ce 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks/BuildTasksUtility.cs @@ -677,6 +677,7 @@ private static IEnumerable ProcessFailedEventsIntoRestoreLogs /// An containing fallback folders to exclude. /// An object containing settings for the project. /// A containing the package fallback folders for the project. + [Obsolete("This method calculates the source overrides incorrectly and will be removed in a future release")] public static string[] GetFallbackFolders(string projectDirectory, string[] fallbackFolders, string[] fallbackFoldersOverride, IEnumerable additionalProjectFallbackFolders, IEnumerable additionalProjectFallbackFoldersExcludes, ISettings settings) { // Fallback folders @@ -689,12 +690,12 @@ public static string[] GetFallbackFolders(string projectDirectory, string[] fall // Append additional fallback folders after removing excluded folders var filteredAdditionalProjectFallbackFolders = MSBuildRestoreUtility.AggregateSources( values: additionalProjectFallbackFolders, - excludeValues: additionalProjectFallbackFoldersExcludes) - .ToArray(); + excludeValues: additionalProjectFallbackFoldersExcludes); return AppendItems(projectDirectory, currentFallbackFolders, filteredAdditionalProjectFallbackFolders); } + [Obsolete("This method calculates the source overrides incorrectly and will be removed in a future release")] public static string[] GetSources(string projectDirectory, string[] sources, string[] sourcesOverride, IEnumerable additionalProjectSources, ISettings settings) { // Sources @@ -709,15 +710,61 @@ public static string[] GetSources(string projectDirectory, string[] sources, str var filteredAdditionalProjectSources = MSBuildRestoreUtility.AggregateSources( values: additionalProjectSources, excludeValues: Enumerable.Empty()) - .Select(MSBuildRestoreUtility.FixSourcePath) - .ToArray(); + .Select(MSBuildRestoreUtility.FixSourcePath); return AppendItems(projectDirectory, currentSources, filteredAdditionalProjectSources); } - private static string[] AppendItems(string projectDirectory, string[] current, string[] additional) + public static string[] GetSources(string startupDirectory, string projectDirectory, string[] sources, string[] sourcesOverride, IEnumerable additionalProjectSources, ISettings settings) { - if (additional == null || additional.Length == 0) + // Sources + var currentSources = RestoreSettingsUtils.GetValue( + () => sourcesOverride?.Select(MSBuildRestoreUtility.FixSourcePath).Select(e => UriUtility.GetAbsolutePath(startupDirectory, e)).ToArray(), + () => MSBuildRestoreUtility.ContainsClearKeyword(sources) ? Array.Empty() : null, + () => sources?.Select(MSBuildRestoreUtility.FixSourcePath).Select(e => UriUtility.GetAbsolutePath(projectDirectory, e)).ToArray(), + () => (PackageSourceProvider.LoadPackageSources(settings)).Where(e => e.IsEnabled).Select(e => e.Source).ToArray()); + + // Append additional sources + // Escape strings to avoid xplat path issues with msbuild. + var filteredAdditionalProjectSources = MSBuildRestoreUtility.AggregateSources( + values: additionalProjectSources, + excludeValues: Enumerable.Empty()) + .Select(MSBuildRestoreUtility.FixSourcePath); + + return AppendItems(projectDirectory, currentSources, filteredAdditionalProjectSources); + } + + /// + /// Gets the package fallback folders for a project. + /// + /// The start-up directory of the tool. + /// The full path to the directory of the project. + /// A containing the fallback folders for the project. + /// A containing overrides for the fallback folders for the project. + /// An containing additional fallback folders for the project. + /// An containing fallback folders to exclude. + /// An object containing settings for the project. + /// A containing the package fallback folders for the project. + public static string[] GetFallbackFolders(string startupDirectory, string projectDirectory, string[] fallbackFolders, string[] fallbackFoldersOverride, IEnumerable additionalProjectFallbackFolders, IEnumerable additionalProjectFallbackFoldersExcludes, ISettings settings) + { + // Fallback folders + var currentFallbackFolders = RestoreSettingsUtils.GetValue( + () => fallbackFoldersOverride?.Select(e => UriUtility.GetAbsolutePath(startupDirectory, e)).ToArray(), + () => MSBuildRestoreUtility.ContainsClearKeyword(fallbackFolders) ? Array.Empty() : null, + () => fallbackFolders?.Select(e => UriUtility.GetAbsolutePath(projectDirectory, e)).ToArray(), + () => SettingsUtility.GetFallbackPackageFolders(settings).ToArray()); + + // Append additional fallback folders after removing excluded folders + var filteredAdditionalProjectFallbackFolders = MSBuildRestoreUtility.AggregateSources( + values: additionalProjectFallbackFolders, + excludeValues: additionalProjectFallbackFoldersExcludes); + + return AppendItems(projectDirectory, currentFallbackFolders, filteredAdditionalProjectFallbackFolders); + } + + private static string[] AppendItems(string projectDirectory, string[] current, IEnumerable additional) + { + if (additional == null || !additional.Any()) { // noop return current; diff --git a/src/NuGet.Core/NuGet.Build.Tasks/GetRestoreSettingsTask.cs b/src/NuGet.Core/NuGet.Build.Tasks/GetRestoreSettingsTask.cs index e2f19028c61..967ef11cd29 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/GetRestoreSettingsTask.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks/GetRestoreSettingsTask.cs @@ -94,6 +94,13 @@ public class GetRestoreSettingsTask : Task public override bool Execute() { +#if DEBUG + var debugRestoreTask = Environment.GetEnvironmentVariable("DEBUG_RESTORE_TASK"); + if (!string.IsNullOrEmpty(debugRestoreTask) && debugRestoreTask.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + { + System.Diagnostics.Debugger.Launch(); + } +#endif var log = new MSBuildLogger(Log); // Log Inputs @@ -159,6 +166,7 @@ public override bool Execute() // Sources OutputSources = BuildTasksUtility.GetSources( + MSBuildStartupDirectory, Path.GetDirectoryName(ProjectUniqueName), RestoreSources, RestoreSourcesOverride, @@ -167,6 +175,7 @@ public override bool Execute() // Fallback folders OutputFallbackFolders = BuildTasksUtility.GetFallbackFolders( + MSBuildStartupDirectory, Path.GetDirectoryName(ProjectUniqueName), RestoreFallbackFolders, RestoreFallbackFoldersOverride, GetPropertyValues(RestoreSettingsPerFramework, "RestoreAdditionalProjectFallbackFolders"), diff --git a/src/NuGet.Core/NuGet.Build.Tasks/NuGet.RestoreEx.targets b/src/NuGet.Core/NuGet.Build.Tasks/NuGet.RestoreEx.targets index 38736953cbb..3e9eb9d4c20 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/NuGet.RestoreEx.targets +++ b/src/NuGet.Core/NuGet.Build.Tasks/NuGet.RestoreEx.targets @@ -31,6 +31,7 @@ Copyright (c) .NET Foundation. All rights reserved. RestorePackagesConfig="$(RestorePackagesConfig)" SolutionPath="$(SolutionPath)" ProcessFileName="$(NuGetConsoleProcessFileName)" + MSBuildStartupDirectory="$(MSBuildStartupDirectory)" /> diff --git a/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt index c9e8db685b1..b5b8ddb6851 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt @@ -1,4 +1,8 @@ NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetPlatform.get -> string NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetPlatform.set -> void +NuGet.Build.Tasks.RestoreTaskEx.MSBuildStartupDirectory.get -> string +NuGet.Build.Tasks.RestoreTaskEx.MSBuildStartupDirectory.set -> void NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.get -> string -NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.set -> void \ No newline at end of file +NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.set -> void +static NuGet.Build.Tasks.BuildTasksUtility.GetFallbackFolders(string startupDirectory, string projectDirectory, string[] fallbackFolders, string[] fallbackFoldersOverride, System.Collections.Generic.IEnumerable additionalProjectFallbackFolders, System.Collections.Generic.IEnumerable additionalProjectFallbackFoldersExcludes, NuGet.Configuration.ISettings settings) -> string[] +static NuGet.Build.Tasks.BuildTasksUtility.GetSources(string startupDirectory, string projectDirectory, string[] sources, string[] sourcesOverride, System.Collections.Generic.IEnumerable additionalProjectSources, NuGet.Configuration.ISettings settings) -> string[] \ No newline at end of file diff --git a/src/NuGet.Core/NuGet.Build.Tasks/RestoreTaskEx.cs b/src/NuGet.Core/NuGet.Build.Tasks/RestoreTaskEx.cs index 6f3c234806a..4109ae449df 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/RestoreTaskEx.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks/RestoreTaskEx.cs @@ -106,6 +106,11 @@ public sealed class RestoreTaskEx : Task, ICancelableTask, IDisposable /// public string ProcessFileName { get; set; } + /// + /// MSBuildStartupDirectory - Used to calculate relative paths + /// + public string MSBuildStartupDirectory { get; set; } + /// public void Cancel() => _cancellationTokenSource.Cancel(); @@ -206,9 +211,8 @@ internal IEnumerable GetCommandLineArguments() [nameof(Interactive)] = Interactive, [nameof(NoCache)] = NoCache, [nameof(Recursive)] = Recursive, - [nameof(RestorePackagesConfig)] = RestorePackagesConfig + [nameof(RestorePackagesConfig)] = RestorePackagesConfig, }; - // Semicolon delimited list of options yield return string.Join(";", options.Where(i => i.Value).Select(i => $"{i.Key}={i.Value}")); @@ -226,7 +230,9 @@ internal IEnumerable GetCommandLineArguments() : ProjectFullPath; // Semicolon delimited list of MSBuild global properties - yield return string.Join(";", GetGlobalProperties().Select(i => $"{i.Key}={i.Value}")); + var globalProperties = GetGlobalProperties().Select(i => $"{i.Key}={i.Value}").Concat(new string[] { $"OriginalMSBuildStartupDirectory={MSBuildStartupDirectory}" }); + + yield return string.Join(";", globalProperties); } /// diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs index 52246314d48..490d82ad4f8 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs @@ -5603,7 +5603,8 @@ public async Task RestoreNetCore_VerifySourcesResolvedAgainstWorkingDirAsync() solution.Projects.Add(projectA); solution.Create(pathContext.SolutionRoot); - var source = Path.Combine(pathContext.WorkingDirectory, "valid"); + var relativeSourceName = "valid"; + var source = Path.Combine(pathContext.WorkingDirectory, relativeSourceName); // X is only in the source await SimpleTestPackageUtility.CreateFolderFeedV3Async( @@ -5612,7 +5613,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( packageX); // Act - var r = Util.RestoreSolution(pathContext, 0, "-Source", source); + var r = Util.RestoreSolution(pathContext, 0, "-Source", relativeSourceName); // Assert r.Success.Should().BeTrue(); diff --git a/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs b/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs index 02b2fffa2d7..352b84930fd 100644 --- a/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs +++ b/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs @@ -635,5 +635,63 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( result.AllOutput.Should().Contain($"error : Invalid restore input. Missing required property 'OutputPath' for project type 'PackageReference'. Input files: {project.ProjectPath}."); } } + + [PlatformTheory(Platform.Windows)] + [InlineData(true)] + [InlineData(false)] + public async Task MsbuildRestore_WithRelativeSource_ResolvesAgainstCurrentWorkingDirectory(bool isStaticGraphRestore) + { + // Arrange + using (var pathContext = new SimpleTestPathContext()) + { + // Set up solution, project, and packages + var solution = new SimpleTestSolutionContext(pathContext.SolutionRoot); + + var net461 = NuGetFramework.Parse("net461"); + + var project = SimpleTestProjectContext.CreateLegacyPackageReference( + "a", + pathContext.SolutionRoot, + net461); + + var packageX = new SimpleTestPackageContext() + { + Id = "x", + Version = "1.0.0" + }; + + packageX.Files.Clear(); + project.AddPackageToAllFrameworks(packageX); + packageX.AddFile("lib/net461/a.dll"); + + solution.Projects.Add(project); + solution.Create(pathContext.SolutionRoot); + var relativePath = "relativeSource"; + var relativeSource = Path.Combine(pathContext.WorkingDirectory, relativePath); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + relativeSource, + packageX); + + var projectOutputPaths = new[] + { + project.AssetsFileOutputPath, + project.PropsOutput, + project.TargetsOutput, + project.CacheFileOutputPath, + }; + + // Restore the project with a PackageReference which generates assets + var result = _msbuildFixture.RunMsBuild(pathContext.WorkingDirectory, $"/t:restore {project.ProjectPath} /p:RestoreSources=\"{relativePath}\"" + + (isStaticGraphRestore ? " /p:RestoreUseStaticGraphEvaluation=true" : string.Empty), + ignoreExitCode: true); + result.Success.Should().BeTrue(because: result.AllOutput); + + foreach (var asset in projectOutputPaths) + { + new FileInfo(asset).Exists.Should().BeTrue(because: result.AllOutput); + } + } + } } } diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs new file mode 100644 index 00000000000..e61889f80f4 --- /dev/null +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using FluentAssertions; +using NuGet.Configuration; +using NuGet.Test.Utility; +using Xunit; + +namespace NuGet.Build.Tasks.Console.Test +{ + public class BuildTasksUtilityTests + { + [Fact] + public void GetSources_WithRestoreSourcesProperty_ResolvesAgainstProjectDirectory() + { + using (var testDir = TestDirectory.CreateInTemp()) + { + // Arrange + var startupDirectory = Path.Combine(testDir, "startup"); + var projectDirectory = Path.Combine(testDir, "project"); + var relativePath = "relativeSource"; + + // Act + var effectiveSources = BuildTasksUtility.GetSources( + startupDirectory: startupDirectory, + projectDirectory: projectDirectory, + sources: new string[] { relativePath }, + sourcesOverride: null, + additionalProjectSources: Array.Empty(), + settings: NullSettings.Instance + ); + + // Assert + effectiveSources.ShouldBeEquivalentTo(new[] { Path.Combine(projectDirectory, relativePath) }); + } + } + + [Fact] + public void GetSources_WithRestoreSourcesGlobal_Property_ResolvesAgainstWorkingDirectory() + { + using (var testDir = TestDirectory.CreateInTemp()) + { + // Arrange + var startupDirectory = Path.Combine(testDir, "startup"); + var projectDirectory = Path.Combine(testDir, "project"); + var relativePath = "relativeSource"; + + // Act + var effectiveSources = BuildTasksUtility.GetSources( + startupDirectory: startupDirectory, + projectDirectory: projectDirectory, + sources: new string[] { relativePath }, + sourcesOverride: new string[] { relativePath }, + additionalProjectSources: Array.Empty(), + settings: NullSettings.Instance + ); + + // Assert + effectiveSources.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); + } + } + } +} diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs index da325c0b7ab..2c413a4dc31 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs @@ -219,10 +219,14 @@ public void GetPackagesPath_WhenPathOrOverrideSpecified_PathIsCorrect(string pac { using (var testDirectory = TestDirectory.Create()) { - var project = new MockMSBuildProject(testDirectory, new Dictionary + var project = new MockMSBuildProject(testDirectory, + properties: new Dictionary { - ["RestorePackagesPathOverride"] = packagesPathOverride, ["RestorePackagesPath"] = packagesPath + }, + globalProperties: new Dictionary + { + ["RestorePackagesPath"] = packagesPathOverride, }); var settings = new MockSettings @@ -502,11 +506,15 @@ public void GetRepositoryPath_WhenPathSolutionOrOverrideSpecified_CorrectPathDet { using (var testDirectory = TestDirectory.Create()) { - var project = new MockMSBuildProject(testDirectory, new Dictionary + var project = new MockMSBuildProject(testDirectory, + properties: new Dictionary { ["RestoreRepositoryPath"] = restoreRepositoryPath, - ["RestoreRepositoryPathOverride"] = repositoryPathOverride, ["SolutionPath"] = solutionPath == null || solutionPath == "*Undefined*" ? solutionPath : UriUtility.GetAbsolutePath(testDirectory, solutionPath) + }, + globalProperties: new Dictionary + { + ["RestoreRepositoryPath"] = repositoryPathOverride, }); var settings = new MockSettings @@ -604,10 +612,14 @@ public void GetSources_WhenPerTargetFrameworkSources_CorrectSourcesDetected() [Fact] public void GetSources_WhenRestoreSourcesAndRestoreSourcesOverrideSpecified_CorrectSourcesDetected() { - var project = new MockMSBuildProject(new Dictionary + var project = new MockMSBuildProject( + properties: new Dictionary { ["RestoreSources"] = "https://source1;https://source2", - ["RestoreSourcesOverride"] = "https://source3" + }, + globalProperties: new Dictionary + { + ["RestoreSources"] = "https://source3" }); var settings = new MockSettings diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MockMSBuildProject.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MockMSBuildProject.cs index 877c4167541..c39b14e96c1 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MockMSBuildProject.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MockMSBuildProject.cs @@ -20,6 +20,11 @@ public MockMSBuildProject(TestDirectory directory, IDictionary p { } + public MockMSBuildProject(TestDirectory directory, IDictionary properties, IDictionary globalProperties) + : this(Path.Combine(directory, "ProjectA.csproj"), properties, new Dictionary>(), globalProperties) + { + } + public MockMSBuildProject(string fullPath) : this(fullPath, properties: null) { @@ -30,12 +35,22 @@ public MockMSBuildProject(IDictionary properties) { } + public MockMSBuildProject(IDictionary properties, IDictionary globalProperties) + : this("ProjectA", properties, new Dictionary>(), globalProperties) + { + } + public MockMSBuildProject(string fullPath, IDictionary properties) : this(fullPath, properties, items: null) { } public MockMSBuildProject(string fullPath, IDictionary properties, IDictionary> items) + : this(fullPath, properties, items, new Dictionary()) + { + } + + public MockMSBuildProject(string fullPath, IDictionary properties, IDictionary> items, IDictionary globalProperties) : base(Path.GetFileName(fullPath), properties ?? new Dictionary()) { Items = items ?? new Dictionary>(); @@ -43,6 +58,8 @@ public MockMSBuildProject(string fullPath, IDictionary propertie Directory = Path.GetDirectoryName(fullPath); FullPath = fullPath; + + GlobalProperties = globalProperties; } public string Directory { get; } @@ -51,9 +68,17 @@ public MockMSBuildProject(string fullPath, IDictionary propertie public IDictionary> Items { get; set; } + public IDictionary GlobalProperties { get; set; } + public IEnumerable GetItems(string name) { return Items.TryGetValue(name, out var items) ? items : null; } + + public string GetGlobalProperty(string property) + { + GlobalProperties.TryGetValue(property, out string value); + return value; + } } } diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs index 44ae978a223..e3298903d58 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs @@ -641,6 +641,76 @@ public void GetRestoreSettingsTask_WithRestoreRootDirectory_ProjectLevelConfigIs } } + [Fact] + public void GetRestoreSettingsTask_WithRestoreSourcesOverride_ResolvesAgainstWorkingDirectory() + { + using (var testDir = TestDirectory.CreateInTemp()) + { + // Arrange + var buildEngine = new TestBuildEngine(); + var testLogger = buildEngine.TestLogger; + + var settingsPerFramework = new List(); + var settings1 = new Mock(); + settings1.SetupGet(e => e.ItemSpec).Returns("a"); + settingsPerFramework.Add(settings1.Object); + var startupDirectory = Path.Combine(testDir, "innerPath"); + var relativePath = "relativeSource"; + + var task = new GetRestoreSettingsTask() + { + BuildEngine = buildEngine, + MSBuildStartupDirectory = startupDirectory, + ProjectUniqueName = Path.Combine(testDir, "a.csproj"), + RestoreSources = new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB") }, + RestoreSourcesOverride = new[] { relativePath }, + RestoreSettingsPerFramework = settingsPerFramework.ToArray() + }; + + // Act + var result = task.Execute(); + + // Assert + result.Should().BeTrue(); + task.OutputSources.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); + } + } + + [Fact] + public void GetRestoreSettingsTask_WithFallbackFoldersOverride_ResolvesAgainstWorkingDirectory() + { + using (var testDir = TestDirectory.CreateInTemp()) + { + // Arrange + var buildEngine = new TestBuildEngine(); + var testLogger = buildEngine.TestLogger; + + var settingsPerFramework = new List(); + var settings1 = new Mock(); + settings1.SetupGet(e => e.ItemSpec).Returns("a"); + settingsPerFramework.Add(settings1.Object); + var startupDirectory = Path.Combine(testDir, "innerPath"); + var relativePath = "relativeSource"; + + var task = new GetRestoreSettingsTask() + { + BuildEngine = buildEngine, + MSBuildStartupDirectory = startupDirectory, + ProjectUniqueName = Path.Combine(testDir, "a.csproj"), + RestoreFallbackFolders = new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB") }, + RestoreFallbackFoldersOverride = new[] { relativePath }, + RestoreSettingsPerFramework = settingsPerFramework.ToArray() + }; + + // Act + var result = task.Execute(); + + // Assert + result.Should().BeTrue(); + task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); + } + } + private static readonly string MachineWideSettingsConfig = @" "; diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/RestoreTaskExTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/RestoreTaskExTests.cs index 4ba1f524b64..b733ca0b568 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/RestoreTaskExTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/RestoreTaskExTests.cs @@ -52,10 +52,12 @@ public void GetCommandLineArguments_WhenOptionsSpecified_CorrectValuesReturned() NoCache = true, ProjectFullPath = projectPath, Recursive = true, - RestorePackagesConfig = true + RestorePackagesConfig = true, + MSBuildStartupDirectory = testDirectory, }) { - task.GetCommandLineArguments().ToList().Should().BeEquivalentTo( + var arguments = task.GetCommandLineArguments().ToList(); + arguments.Should().BeEquivalentTo( #if IS_CORECLR Path.ChangeExtension(typeof(RestoreTaskEx).Assembly.Location, ".Console.dll"), #endif @@ -66,7 +68,7 @@ public void GetCommandLineArguments_WhenOptionsSpecified_CorrectValuesReturned() Path.Combine(msbuildBinPath, "MSBuild.exe"), #endif projectPath, - "Property1=Value1;Property2= Value2 ;ExcludeRestorePackageImports=true"); + $"Property1=Value1;Property2= Value2 ;ExcludeRestorePackageImports=true;OriginalMSBuildStartupDirectory={testDirectory}"); } } } From 1343378a2d6fd3bde6f774745704d0c40375ee59 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Tue, 10 Nov 2020 16:41:26 -0800 Subject: [PATCH 037/129] Make the tests go through the no-op restore codepath (#3747) --- .../RestoreCommand/RestoreCommand.cs | 3 +- .../LibraryDependencyTypeFlag.cs | 5 +- .../RestoreCommandTests.cs | 72 +++++++++---------- .../UWPRestoreTests.cs | 21 ++++-- .../compiler/resources/uwpBlankAppV2.json | 2 +- .../CompatilibityCheckerTests.cs | 20 +++--- .../NuGet.Commands.Test/ContentFilesTests.cs | 48 ++++++------- .../DependencyTypeConstraintTests.cs | 12 ++-- .../NuGet.Commands.Test/IncludeTypeTests.cs | 12 ++-- .../MinClientVersionTests.cs | 2 +- .../PackagesWithResourcesTests.cs | 5 +- .../Project2ProjectInLockFileTests.cs | 18 ++--- .../ProjectResolutionTests.cs | 9 +-- .../FallbackFolderRestoreTests.cs | 10 +-- .../OriginalCaseGlobalPackageFolderTests.cs | 22 +++--- .../RestoreCommandTests.cs | 40 +++++------ .../NuGet.Commands.Test/RestoreSemVerTests.cs | 14 ++-- .../RuntimePackageTests.cs | 4 +- .../RuntimeTargetsTests.cs | 8 +-- .../Commands/ProjectJsonTestHelpers.cs | 39 ++++++++++ .../Commands/TestRestoreRequest.cs | 4 ++ 21 files changed, 208 insertions(+), 162 deletions(-) diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs index 571733f3229..2032212d1fc 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs @@ -621,8 +621,7 @@ private bool ValidatePackagesSha512(PackagesLockFile lockFile, LockFile assetsFi // DgSpec doesn't contain log messages, so skip no-op if there are any, as it's not taken into account in the hash if (_request.AllowNoOp && !_request.RestoreForceEvaluate && - File.Exists(_request.Project.RestoreMetadata.CacheFilePath) || - _request.AdditionalMessages?.Count > 0) + File.Exists(_request.Project.RestoreMetadata.CacheFilePath)) { cacheFile = FileUtility.SafeRead(_request.Project.RestoreMetadata.CacheFilePath, (stream, path) => CacheFileFormat.Read(stream, _logger, path)); diff --git a/src/NuGet.Core/NuGet.LibraryModel/LibraryDependencyTypeFlag.cs b/src/NuGet.Core/NuGet.LibraryModel/LibraryDependencyTypeFlag.cs index afe50ff88fa..0effda46be6 100644 --- a/src/NuGet.Core/NuGet.LibraryModel/LibraryDependencyTypeFlag.cs +++ b/src/NuGet.Core/NuGet.LibraryModel/LibraryDependencyTypeFlag.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using NuGet.Shared; namespace NuGet.LibraryModel { @@ -40,7 +41,9 @@ public override bool Equals(object obj) public override int GetHashCode() { - return StringComparer.Ordinal.GetHashCode(_value); + var combiner = new HashCodeCombiner(); + combiner.AddSequence(_value); + return combiner.CombinedHash; } public override string ToString() diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs index a0496becf86..4a5193c3dce 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs @@ -27,7 +27,7 @@ namespace NuGet.Commands.FuncTest { using static NuGet.Frameworks.FrameworkConstants; - using LocalPackageArchiveDownloader = NuGet.Protocol.LocalPackageArchiveDownloader; + using LocalPackageArchiveDownloader = Protocol.LocalPackageArchiveDownloader; public class RestoreCommandTests { @@ -47,7 +47,7 @@ public async Task RestoreCommand_LockFileHasOriginalPackageIdCaseAsync(string so using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfigWithNet46.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfigWithNet46.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "ENTITYFRAMEWORK", "6.1.3-BETA1"); var logger = new TestLogger(); @@ -146,7 +146,7 @@ public async Task RestoreCommand_CannotFindProjectReferenceWithDifferentNameCase { Directory.CreateDirectory(Path.Combine(projectDir, "TestProject")); var projectSpecPath = Path.Combine(projectDir, "TestProject", "project.json"); - var projectSpec = JsonPackageSpecReader.GetPackageSpec(BasicConfigWithNet46.ToString(), "TestProject", projectSpecPath); + var projectSpec = JsonPackageSpecReader.GetPackageSpec(BasicConfigWithNet46.ToString(), "TestProject", projectSpecPath).EnsureProjectJsonRestoreMetadata(); projectSpec.Dependencies = new List { new LibraryDependency() @@ -278,7 +278,7 @@ public async Task RestoreCommand_VerifyMinClientVersionV2SourceAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); // This package has a minclientversion of 9999 AddDependency(spec, "TestPackage.MinClientVersion", "1.0.0"); @@ -322,7 +322,7 @@ public async Task RestoreCommand_VerifyMinClientVersionV3SourceAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); // This package has a minclientversion of 9999 AddDependency(spec, "TestPackage.MinClientVersion", "1.0.0"); @@ -365,7 +365,7 @@ public async Task RestoreCommand_VerifyMinClientVersionLocalFolderAsync() { sources.Add(new PackageSource(sourceDir)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); // This package has a minclientversion of 9.9999.0 AddDependency(spec, "packageA", "1.0.0"); @@ -418,7 +418,7 @@ public async Task RestoreCommand_VerifyMinClientVersionAlreadyInstalledAsync() { sources.Add(new PackageSource(emptyDir)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); // This package has a minclientversion of 9.9999.0 AddDependency(spec, "packageA", "1.0.0"); @@ -507,7 +507,7 @@ public async Task RestoreCommand_FrameworkImportRulesAreAppliedAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -563,7 +563,7 @@ public async Task RestoreCommand_FrameworkImportArrayAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -621,7 +621,7 @@ public async Task RestoreCommand_FrameworkImportRulesAreApplied_NoopAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -679,7 +679,7 @@ public async Task RestoreCommand_LeftOverNupkg_OverwrittenAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); // Create left over nupkg to simulate a corrupted install @@ -740,7 +740,7 @@ public async Task RestoreCommand_FrameworkImport_WarnOnAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -792,7 +792,7 @@ public async Task RestoreCommand_FollowFallbackDependenciesAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -846,7 +846,7 @@ public async Task RestoreCommand_FrameworkImportValidateLockFileAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -891,7 +891,7 @@ public async Task RestoreCommand_DependenciesDifferOnCaseAsync() json["frameworks"] = frameworks; var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(json.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(json.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "nEwTonSoft.JSon", "6.0.8"); AddDependency(spec, "json-ld.net", "1.0.4"); @@ -946,7 +946,7 @@ public async Task RestoreCommand_DependenciesDifferOnCase_DowngradeAsync() json["frameworks"] = frameworks; var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(json.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(json.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "nEwTonSoft.JSon", "4.0.1"); AddDependency(spec, "dotNetRDF", "1.0.8.3533"); @@ -983,7 +983,7 @@ public async Task RestoreCommand_TestLockFileWrittenOnLockFileChangeAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NuGet.Versioning", "1.0.7"); @@ -1042,7 +1042,7 @@ public async Task RestoreCommand_NoopOnLockFileWriteIfFilesMatchAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NuGet.Versioning", "1.0.7"); @@ -1109,7 +1109,7 @@ public async Task RestoreCommand_NuGetVersioning107RuntimeAssembliesAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NuGet.Versioning", "1.0.7"); @@ -1153,7 +1153,7 @@ public async Task RestoreCommand_InstallPackageWithDependenciesAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "WebGrease", "1.6.0"); @@ -1219,7 +1219,7 @@ public async Task RestoreCommand_InstallPackageWithManyDependenciesAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) { @@ -1275,7 +1275,7 @@ public async Task RestoreCommand_InstallPackageWithReferenceDependenciesAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfigWithNet46.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfigWithNet46.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "Moon.Owin.Localization", "1.3.1"); @@ -1318,7 +1318,7 @@ public async Task RestoreCommand_RestoreWithNoChangesAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NuGet.Versioning", "1.0.7"); @@ -1360,7 +1360,7 @@ public async Task RestoreCommand_PackageIsAddedToPackageCacheAsync(string source using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NuGet.Versioning", "1.0.7"); @@ -1396,7 +1396,7 @@ public async Task RestoreCommand_PackagesAreExtractedToTheNormalizedPathAsync(st using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "owin", "1.0"); @@ -1430,7 +1430,7 @@ public async Task RestoreCommand_WarnWhenWeBumpYouUpAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "Newtonsoft.Json", "7.0.0"); // 7.0.0 does not exist so we'll bump up to 7.0.1 @@ -1468,7 +1468,7 @@ public async Task RestoreCommand_WarnWhenWeBumpYouUpOnSubsequentRestoresAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "Newtonsoft.Json", "7.0.0"); // 7.0.0 does not exist so we'll bump up to 7.0.1 @@ -1510,7 +1510,7 @@ public async Task RestoreCommand_JsonNet701RuntimeAssembliesAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "Newtonsoft.Json", "7.0.1"); @@ -1553,7 +1553,7 @@ public async Task RestoreCommand_NoCompatibleRuntimeAssembliesForProjectAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NuGet.Core", "2.8.3"); @@ -1604,7 +1604,7 @@ public async Task RestoreCommand_CorrectlyIdentifiesUnresolvedPackagesAsync() using (var sourceCacheContext = new SourceCacheContext()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(BasicConfig.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); AddDependency(spec, "NotARealPackage.ThisShouldNotExists.DontCreateIt.Seriously.JustDontDoIt.Please", "2.8.3"); @@ -1655,7 +1655,7 @@ public async Task RestoreCommand_PopulatesProjectFileDependencyGroupsCorrectlyAs using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(project, "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(project, "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -1702,7 +1702,7 @@ public async Task RestoreCommand_CanInstallPackageWithSatelliteAssembliesAsync() using (var projectDir = TestDirectory.Create()) { var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(project, "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(project, "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) @@ -1882,7 +1882,7 @@ public void RestoreCommand_PathTooLongException() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); string longPath = packagesDir + new string('_', 300); @@ -1933,7 +1933,7 @@ public async Task RestoreCommand_RestoreExactVersionWithFailingSourceAsync() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, cacheContext, logger) @@ -1976,7 +1976,7 @@ public async Task RestoreCommand_RestoreFloatingVersionWithFailingHttpSourceAsyn }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, cacheContext, logger) @@ -2016,7 +2016,7 @@ public async Task RestoreCommand_RestoreFloatingVersionWithFailingLocalSourceAsy }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/UWPRestoreTests.cs b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/UWPRestoreTests.cs index bc94aee21d8..1a43955c64f 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/UWPRestoreTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/UWPRestoreTests.cs @@ -91,7 +91,7 @@ public async Task UWPRestore_VerifySatellitePackagesAreCompatibleInPCL() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -197,7 +197,7 @@ public async Task UWPRestore_VerifySameResultWhenRestoringWithLocalPackages() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, cacheContext, logger); @@ -238,7 +238,7 @@ public async Task UWPRestore_SystemDependencyVersionConflict() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -290,7 +290,7 @@ public async Task UWPRestore_BlankUWPApp() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, cacheContext, logger); @@ -314,6 +314,7 @@ public async Task UWPRestore_BlankUWPApp() var lockFileJson = JObject.Parse(File.ReadAllText(request.LockFilePath)); RemovePackageFolders(lockFileJson); + RemoveRestoreSection(lockFileJson); // Assert Assert.True(result.Success); @@ -354,7 +355,7 @@ public async Task UWPRestore_BlankUWPAppV1() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -421,7 +422,7 @@ public async Task UWPRestore_ModernPCL() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -479,7 +480,7 @@ public async Task UWPRestore_UWPAppWithOffice365Packages() }"); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -509,5 +510,11 @@ private void RemovePackageFolders(JObject json) { json.Remove("packageFolders"); } + + private void RemoveRestoreSection(JObject json) + { + json.Remove("restore"); + json.Value("project").Remove("restore"); + } } } diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/compiler/resources/uwpBlankAppV2.json b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/compiler/resources/uwpBlankAppV2.json index 953f562a195..cc8b6ed1400 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/compiler/resources/uwpBlankAppV2.json +++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/compiler/resources/uwpBlankAppV2.json @@ -15725,4 +15725,4 @@ } } } -} \ No newline at end of file +} diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/CompatilibityCheckerTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/CompatilibityCheckerTests.cs index 9a7af4dcd17..1fc428d3563 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/CompatilibityCheckerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/CompatilibityCheckerTests.cs @@ -80,7 +80,7 @@ public async Task CompatilibityChecker_SingleFileVerifyCompatibilityAsync(string File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -151,7 +151,7 @@ public async Task CompatilibityChecker_PackageCompatibility_VerifyAvailableFrame File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -224,7 +224,7 @@ public async Task CompatilibityChecker_PackageCompatibility_VerifyNoAvailableFra File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -292,7 +292,7 @@ public async Task CompatilibityChecker_PackageCompatibility_VerifyAvailableFrame File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -362,7 +362,7 @@ public async Task CompatilibityChecker_PackageExcludeCompileRuntime_SuccessAsync File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -431,7 +431,7 @@ public async Task CompatilibityChecker_MissingRuntimeAssemblyCompileOnly_Success File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -499,7 +499,7 @@ public async Task CompatilibityChecker_MissingRuntimeAssembly_FailAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -570,7 +570,7 @@ public async Task CompatilibityChecker_MissingRuntimeAssembly_IgnoreAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -648,7 +648,7 @@ public async Task CompatilibityChecker_RuntimeFoundInAnotherPackage_SuccessAsync File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -727,7 +727,7 @@ public async Task CompatilibityChecker_RuntimeFoundInSamePackage_SuccessAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/ContentFilesTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/ContentFilesTests.cs index fe01df38619..3d07bd45b3a 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/ContentFilesTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/ContentFilesTests.cs @@ -71,7 +71,7 @@ public async Task ContentFiles_VerifyContentFilesAreAddedForNetstandard() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -140,7 +140,7 @@ public async Task ContentFiles_VerifyLockFileContainsCorrectPPOutputPath() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -209,7 +209,7 @@ public async Task ContentFiles_InvalidPPFileName() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -284,7 +284,7 @@ public async Task ContentFiles_VerifyNearestTFMPerLanguageNoCompatibleItems() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -380,7 +380,7 @@ public async Task ContentFiles_VerifyNearestTFMPerLanguageUap10() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -479,7 +479,7 @@ public async Task ContentFiles_VerifyNearestTFMPerLanguageNet45() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -575,7 +575,7 @@ public async Task ContentFiles_VerifyNearestTFMPerLanguage() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -668,7 +668,7 @@ public async Task ContentFiles_VerifyLockFileChange_Changed() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -744,7 +744,7 @@ public async Task ContentFiles_VerifyLockFileChange_NoChange() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -815,7 +815,7 @@ public async Task ContentFiles_IgnoreBadFolders() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -885,7 +885,7 @@ public async Task ContentFiles_NormalizeBuildActionNames() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -955,7 +955,7 @@ public async Task ContentFiles_InvalidBuildAction() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -1032,7 +1032,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingDirectoryAboveRoot() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1107,7 +1107,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingSupportExcludeDirSet() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1185,7 +1185,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingSupportExcludeDir() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1264,7 +1264,7 @@ public async Task ContentFiles_NuspecContentFilesRuleOrdering() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1344,7 +1344,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingSupportIncludeDir() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1425,7 +1425,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingIgnoreDirectoryUp() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1508,7 +1508,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingSupportExclude() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1591,7 +1591,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingSupportIncludeAll() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1668,7 +1668,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingIncludeExactRootFile() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1740,7 +1740,7 @@ public async Task ContentFiles_NuspecContentFilesGlobbingIncludeEmptyString() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -1795,7 +1795,7 @@ public async Task ContentFiles_DefaultActionsWithNoNuspecSettings() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); @@ -2009,7 +2009,7 @@ private async Task StandardSetup( } var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/DependencyTypeConstraintTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/DependencyTypeConstraintTests.cs index cd8485df0cb..47c2bb261de 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/DependencyTypeConstraintTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/DependencyTypeConstraintTests.cs @@ -54,7 +54,7 @@ public async Task DependencyTypeConstraint_RootProjectIsUsedOverPackageAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var project1PackagePath = await SimpleTestPackageUtility.CreateFullPackageAsync( packageSource.FullName, @@ -249,9 +249,9 @@ public async Task DependencyTypeConstraint_DefaultBehaviorWithNoTargetAsync() var specPath1 = Path.Combine(project1.FullName, "project.json"); var specPath2 = Path.Combine(packageAProject.FullName, "project.json"); var specPath3 = Path.Combine(packageAExternalProject.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); - var spec2 = JsonPackageSpecReader.GetPackageSpec(packageAProjectJson, "packageA", specPath2); - var spec3 = JsonPackageSpecReader.GetPackageSpec(packageAExternalProjectJson, "packageA", specPath3); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); + var spec2 = JsonPackageSpecReader.GetPackageSpec(packageAProjectJson, "packageA", specPath2).EnsureProjectJsonRestoreMetadata(); + var spec3 = JsonPackageSpecReader.GetPackageSpec(packageAExternalProjectJson, "packageA", specPath3).EnsureProjectJsonRestoreMetadata(); var packageAPath = await SimpleTestPackageUtility.CreateFullPackageAsync( packageSource.FullName, @@ -356,8 +356,8 @@ public async Task DependencyTypeConstraint_TargetPackageAsync() var specPath1 = Path.Combine(project1.FullName, "project.json"); var specPath2 = Path.Combine(packageAProject.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); - var spec2 = JsonPackageSpecReader.GetPackageSpec(packageAProjectJson, "packageA", specPath2); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); + var spec2 = JsonPackageSpecReader.GetPackageSpec(packageAProjectJson, "packageA", specPath2).EnsureProjectJsonRestoreMetadata(); var packageAPath = await SimpleTestPackageUtility.CreateFullPackageAsync( packageSource.FullName, diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/IncludeTypeTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/IncludeTypeTests.cs index 4c546a46a9b..2b24ab2acdb 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/IncludeTypeTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/IncludeTypeTests.cs @@ -1782,7 +1782,7 @@ private async Task ProjectToProjectSetupAsync( Directory.CreateDirectory(testProject2Dir); var specPath1 = Path.Combine(testProject1Dir, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(configJson1, "TestProject1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(configJson1, "TestProject1", specPath1).EnsureProjectJsonRestoreMetadata(); using (var writer = new StreamWriter(File.OpenWrite(specPath1))) { @@ -1790,7 +1790,7 @@ private async Task ProjectToProjectSetupAsync( } var specPath2 = Path.Combine(testProject2Dir, "project.json"); - var spec2 = JsonPackageSpecReader.GetPackageSpec(configJson2, "TestProject2", specPath2); + var spec2 = JsonPackageSpecReader.GetPackageSpec(configJson2, "TestProject2", specPath2).EnsureProjectJsonRestoreMetadata(); using (var writer = new StreamWriter(File.OpenWrite(specPath2))) { @@ -1853,21 +1853,21 @@ private async Task TriangleProjectSetupAsync( Directory.CreateDirectory(testProject3Dir); var specPath1 = Path.Combine(testProject1Dir, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(configJson1, "TestProject1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(configJson1, "TestProject1", specPath1).EnsureProjectJsonRestoreMetadata(); using (var writer = new StreamWriter(File.OpenWrite(specPath1))) { writer.WriteLine(configJson1); } var specPath2 = Path.Combine(testProject2Dir, "project.json"); - var spec2 = JsonPackageSpecReader.GetPackageSpec(configJson2, "TestProject2", specPath2); + var spec2 = JsonPackageSpecReader.GetPackageSpec(configJson2, "TestProject2", specPath2).EnsureProjectJsonRestoreMetadata(); using (var writer = new StreamWriter(File.OpenWrite(specPath2))) { writer.WriteLine(configJson2); } var specPath3 = Path.Combine(testProject3Dir, "project.json"); - var spec3 = JsonPackageSpecReader.GetPackageSpec(configJson3, "TestProject3", specPath3); + var spec3 = JsonPackageSpecReader.GetPackageSpec(configJson3, "TestProject3", specPath3).EnsureProjectJsonRestoreMetadata(); using (var writer = new StreamWriter(File.OpenWrite(specPath3))) { writer.WriteLine(configJson3); @@ -1919,7 +1919,7 @@ private async Task StandardSetupAsync( }; var specPath = Path.Combine(testProjectDir, "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson, "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson, "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger) { diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/MinClientVersionTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/MinClientVersionTests.cs index c0aac897d15..63b46d20904 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/MinClientVersionTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/MinClientVersionTests.cs @@ -50,7 +50,7 @@ public async Task MinClientVersion_DependencyVersionTooHighAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/PackagesWithResourcesTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/PackagesWithResourcesTests.cs index 48358dc9535..485b7db4f9e 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/PackagesWithResourcesTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/PackagesWithResourcesTests.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -12,10 +11,8 @@ using Newtonsoft.Json.Linq; using NuGet.Configuration; using NuGet.Frameworks; -using NuGet.LibraryModel; using NuGet.ProjectModel; using NuGet.Test.Utility; -using NuGet.Versioning; using Xunit; namespace NuGet.Commands.Test @@ -73,7 +70,7 @@ public async Task Resources_AppearInLockFileWithAppropriateLocaleValue() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/Project2ProjectInLockFileTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/Project2ProjectInLockFileTests.cs index 9214ea612ae..e168a06ccf1 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/Project2ProjectInLockFileTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/Project2ProjectInLockFileTests.cs @@ -95,9 +95,9 @@ public async Task Project2ProjectInLockFile_VerifySnapshotVersions() var specPath1 = Path.Combine(project1.FullName, "project.json"); var specPath2 = Path.Combine(project2.FullName, "project.json"); var specPath3 = Path.Combine(project3.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath1); - var spec2 = JsonPackageSpecReader.GetPackageSpec(project2Json, "project2", specPath2); - var spec3 = JsonPackageSpecReader.GetPackageSpec(project3Json, "project3", specPath3); + var spec1 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); + var spec2 = JsonPackageSpecReader.GetPackageSpec(project2Json, "project2", specPath2).EnsureProjectJsonRestoreMetadata(); + var spec3 = JsonPackageSpecReader.GetPackageSpec(project3Json, "project3", specPath3).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir, logger); @@ -199,8 +199,8 @@ public async Task Project2ProjectInLockFile_PackageReferenceConflict() var specPath1 = Path.Combine(project1.FullName, "project.json"); var specPath2 = Path.Combine(project2.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); - var spec2 = JsonPackageSpecReader.GetPackageSpec(project2Json, "project2", specPath2); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); + var spec2 = JsonPackageSpecReader.GetPackageSpec(project2Json, "project2", specPath2).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir, logger); @@ -262,7 +262,7 @@ public async Task Project2ProjectInLockFile_VerifyP2PWithNonProjectJsonReference File.WriteAllText(Path.Combine(project3.FullName, "project3.csproj"), string.Empty); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir, logger); @@ -369,9 +369,9 @@ public async Task Project2ProjectInLockFile_VerifyProjectsUnderProjectFileDepend var specPath1 = Path.Combine(project1.FullName, "project.json"); var specPath2 = Path.Combine(project2.FullName, "project.json"); var specPath3 = Path.Combine(project3.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath1); - var spec2 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project2", specPath2); - var spec3 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project3", specPath3); + var spec1 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); + var spec2 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project2", specPath2).EnsureProjectJsonRestoreMetadata(); + var spec3 = JsonPackageSpecReader.GetPackageSpec(projectJson, "project3", specPath3).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir, logger); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/ProjectResolutionTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/ProjectResolutionTests.cs index 41c004ae22b..489558300a0 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/ProjectResolutionTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/ProjectResolutionTests.cs @@ -7,14 +7,11 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; -using NuGet.LibraryModel; using NuGet.ProjectModel; using NuGet.Protocol.Core.Types; using NuGet.Test.Utility; -using NuGet.Versioning; using Xunit; namespace NuGet.Commands.Test @@ -428,7 +425,7 @@ public async Task ProjectResolution_ExternalReferenceWithNoProjectJson() File.WriteAllText(msbuidPath2, string.Empty); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger); @@ -609,8 +606,8 @@ public async Task ProjectResolution_MSBuildProjectDoesNotResolveByDirectory() var specPath1 = Path.Combine(project1.FullName, "project.json"); var specPath2 = Path.Combine(project2.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); - var spec2 = JsonPackageSpecReader.GetPackageSpec(project2Json, "project2", specPath2); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); + var spec2 = JsonPackageSpecReader.GetPackageSpec(project2Json, "project2", specPath2).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/FallbackFolderRestoreTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/FallbackFolderRestoreTests.cs index 10936587ce2..a3d991306b7 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/FallbackFolderRestoreTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/FallbackFolderRestoreTests.cs @@ -54,7 +54,7 @@ public async Task FallbackFolderRestore_AllPackagesFoundInFallbackAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest( @@ -151,7 +151,7 @@ public async Task FallbackFolderRestore_AllPackagesFoundInFallback_NuspecModeAsy File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest( @@ -240,7 +240,7 @@ public async Task FallbackFolderRestore_SinglePackageFoundInFallbackAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest( @@ -334,7 +334,7 @@ public async Task FallbackFolderRestore_NoPackagesFoundInFallbackAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest( @@ -419,7 +419,7 @@ public async Task FallbackFolderRestore_VerifyMissingFallbackFolderFailsAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest( diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/OriginalCaseGlobalPackageFolderTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/OriginalCaseGlobalPackageFolderTests.cs index 8b35b23b057..5b8d07511a3 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/OriginalCaseGlobalPackageFolderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommand/OriginalCaseGlobalPackageFolderTests.cs @@ -14,7 +14,6 @@ using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.ProjectModel; -using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.Test.Utility; using NuGet.Versioning; @@ -23,7 +22,7 @@ namespace NuGet.Commands.Test { - using LocalPackageArchiveDownloader = NuGet.Protocol.LocalPackageArchiveDownloader; + using LocalPackageArchiveDownloader = Protocol.LocalPackageArchiveDownloader; [Collection(nameof(NotThreadSafeResourceCollection))] public class OriginalCaseGlobalPackageFolderTests @@ -216,15 +215,18 @@ public void ConvertLockFileToOriginalCase_ConvertsPackagesPathsInLockFile() private static RestoreRequest GetRestoreRequest(string packagesDirectory, TestLogger logger, params string[] fallbackDirectories) { - return new TestRestoreRequest( - new PackageSpec(), - Enumerable.Empty(), - packagesDirectory, - fallbackDirectories, - logger) + using (var testDirectory = TestDirectory.Create()) { - IsLowercasePackagesDirectory = false - }; + return new TestRestoreRequest( + new PackageSpec() { FilePath = testDirectory.Path + "a.csproj" }.EnsureProjectJsonRestoreMetadata(), + Enumerable.Empty(), + packagesDirectory, + fallbackDirectories, + logger) + { + IsLowercasePackagesDirectory = false + }; + } } public static RestoreTargetGraph GetRestoreTargetGraph( diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs index 69e0d76d18a..2aa11e65aac 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests.cs @@ -71,7 +71,7 @@ public async Task RestoreCommand_VerifyRuntimeSpecificAssetsAreNotIncludedForCom File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -140,7 +140,7 @@ public async Task RestoreCommand_VerifyRuntimeSpecificAssetsAreNotIncludedForCom File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -210,7 +210,7 @@ public async Task RestoreCommand_CompileAssetsWithBothRefAndLib_VerifyRefWinsAsy File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -280,7 +280,7 @@ public async Task RestoreCommand_ObservesLowercaseFlagAsync(bool isLowercase) File.WriteAllText(Path.Combine(projectDir.FullName, "project.json"), projectJson); var specPath = Path.Combine(projectDir.FullName, "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest( @@ -358,7 +358,7 @@ public async Task RestoreCommand_WhenSwitchingBetweenLowercaseSettings_LockFileA File.WriteAllText(Path.Combine(projectDir.FullName, "project.json"), projectJson); var specPath = Path.Combine(projectDir.FullName, "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(projectJson, "project1", specPath).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var lockFilePath = Path.Combine(projectDir.FullName, "project.lock.json"); @@ -480,7 +480,7 @@ public async Task RestoreCommand_FileUriV3FolderAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -542,7 +542,7 @@ public async Task RestoreCommand_FileUriV2FolderAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -602,7 +602,7 @@ public async Task RestoreCommand_FindInV2FolderWithDifferentCasingAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -662,7 +662,7 @@ public async Task RestoreCommand_ReferenceWithSameNameDifferentCasingAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "PROJECT1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "PROJECT1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -729,7 +729,7 @@ public async Task RestoreCommand_ImportsWithHigherVersion_NoFallbackAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -799,7 +799,7 @@ public async Task RestoreCommand_ImportsWithHigherVersion_FallbackAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -869,7 +869,7 @@ public async Task RestoreCommand_ImportsWithHigherVersion_MultiFallbackAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -939,7 +939,7 @@ public async Task RestoreCommand_ImportsNoMatchAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -1009,7 +1009,7 @@ public async Task RestoreCommand_InvalidSignedPackageAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); @@ -1079,7 +1079,7 @@ public async Task RestoreCommand_SignedPackageAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); @@ -1146,7 +1146,7 @@ public async Task RestoreCommand_PathInPackageLibraryAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -1209,7 +1209,7 @@ public async Task RestoreCommand_PackageWithSameNameAsync() await SimpleTestPackageUtility.CreateFullPackageAsync(packageSource.FullName, "project1", "1.0.0"); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -1272,7 +1272,7 @@ public async Task RestoreCommand_PackageAndReferenceWithSameNameAndVersionAsync( File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -1327,7 +1327,7 @@ public async Task RestoreCommand_RestoreProjectWithNoDependenciesAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -2041,7 +2041,7 @@ private static DependencyGraphSpec CreateMinimalDependencyGraphSpec(string proje packageSpec.RestoreMetadata.ProjectUniqueName = projectPath; packageSpec.RestoreMetadata.ProjectStyle = ProjectStyle.PackageReference; packageSpec.RestoreMetadata.OutputPath = outputPath; - + packageSpec.RestoreMetadata.CacheFilePath = Path.Combine(outputPath, "project.nuget.cache"); var dgSpec = new DependencyGraphSpec(); dgSpec.AddProject(packageSpec); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreSemVerTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreSemVerTests.cs index f5269819c4c..155ab9e21b2 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreSemVerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreSemVerTests.cs @@ -1,13 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; using NuGet.ProjectModel; @@ -56,7 +54,7 @@ public async Task RestoreSemVer_RestorePackageFloatOnReleaseLabelAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -173,7 +171,7 @@ public async Task RestoreSemVer_RestorePackageWithMultipleReleaseLabelsAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -246,7 +244,7 @@ public async Task RestoreSemVer_RestorePackageWithMetadata_IdenticalAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -319,7 +317,7 @@ public async Task RestoreSemVer_RestorePackageWithMetadata_MetadataOnlyInProject File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -392,7 +390,7 @@ public async Task RestoreSemVer_RestorePackageWithMetadata_MetadataOnlyInPackage File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -464,7 +462,7 @@ public async Task RestoreSemVer_RestorePackageWithMetadata_DifferentMetadataDoes File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimePackageTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimePackageTests.cs index 1ffa5031681..a4c34281e93 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimePackageTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimePackageTests.cs @@ -136,7 +136,7 @@ public async Task RuntimePackage_RejectedPackagesAreNotMerged() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); @@ -203,7 +203,7 @@ public async Task RuntimePackage_BasicRuntimePackageRestore() }".Replace("_FRAMEWORK_", framework)); var specPath = Path.Combine(projectDir, "TestProject", "project.json"); - var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath); + var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath).EnsureProjectJsonRestoreMetadata(); var request = new TestRestoreRequest(spec, sources, packagesDir, logger); request.LockFilePath = Path.Combine(projectDir, "project.lock.json"); diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimeTargetsTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimeTargetsTests.cs index afb15407b1f..83883964b64 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimeTargetsTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RuntimeTargetsTests.cs @@ -53,7 +53,7 @@ public async Task RestoreTargets_RestoreWithNoRuntimesAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -126,7 +126,7 @@ public async Task RestoreTargets_RestoreWithRuntimesAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -221,7 +221,7 @@ public async Task RestoreTargets_RestoreWithRuntimes_ExcludeAllAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) @@ -313,7 +313,7 @@ public async Task RestoreTargets_RestoreWithRuntimesAndNearestFrameworkAsync() File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); - var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); + var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1).EnsureProjectJsonRestoreMetadata(); var logger = new TestLogger(); var request = new TestRestoreRequest(spec1, sources, packagesDir.FullName, logger) diff --git a/test/TestUtilities/Test.Utility/Commands/ProjectJsonTestHelpers.cs b/test/TestUtilities/Test.Utility/Commands/ProjectJsonTestHelpers.cs index cbadc9fa48e..6dfbf04a73e 100644 --- a/test/TestUtilities/Test.Utility/Commands/ProjectJsonTestHelpers.cs +++ b/test/TestUtilities/Test.Utility/Commands/ProjectJsonTestHelpers.cs @@ -84,6 +84,20 @@ public static PackageSpec EnsureRestoreMetadata(this PackageSpec spec) return spec; } + /// + /// Add restore metadata only if not already set. + /// Sets the project style to PackageReference. + /// + public static PackageSpec EnsureProjectJsonRestoreMetadata(this PackageSpec spec) + { + if (string.IsNullOrEmpty(spec.RestoreMetadata?.ProjectUniqueName)) + { + return spec.WithProjectJsonTestRestoreMetadata(); + } + + return spec; + } + public static PackageSpec WithTestProjectReference(this PackageSpec parent, PackageSpec child, params NuGetFramework[] frameworks) { var spec = parent.Clone(); @@ -147,5 +161,30 @@ public static PackageSpec WithTestRestoreMetadata(this PackageSpec spec) } return updated; } + + private static PackageSpec WithProjectJsonTestRestoreMetadata(this PackageSpec spec) + { + var updated = spec.Clone(); + var metadata = new ProjectRestoreMetadata(); + updated.RestoreMetadata = metadata; + + var msbuildProjectFilePath = Path.Combine(Path.GetDirectoryName(spec.FilePath), spec.Name + ".csproj"); + var msbuildProjectExtensionsPath = Path.Combine(Path.GetDirectoryName(spec.FilePath), "obj"); + metadata.ProjectStyle = ProjectStyle.ProjectJson; + metadata.OutputPath = msbuildProjectExtensionsPath; + metadata.ProjectPath = msbuildProjectFilePath; + metadata.ProjectJsonPath = spec.FilePath; + metadata.ProjectName = spec.Name; + metadata.ProjectUniqueName = msbuildProjectFilePath; + metadata.CacheFilePath = NoOpRestoreUtilities.GetProjectCacheFilePath(msbuildProjectExtensionsPath); + metadata.ConfigFilePaths = new List(); + + foreach (var framework in updated.TargetFrameworks) + { + metadata.TargetFrameworks.Add(new ProjectRestoreMetadataFrameworkInfo(framework.FrameworkName) { }); + } + + return updated; + } } } diff --git a/test/TestUtilities/Test.Utility/Commands/TestRestoreRequest.cs b/test/TestUtilities/Test.Utility/Commands/TestRestoreRequest.cs index f8d2d00b28c..28c47d408c3 100644 --- a/test/TestUtilities/Test.Utility/Commands/TestRestoreRequest.cs +++ b/test/TestUtilities/Test.Utility/Commands/TestRestoreRequest.cs @@ -153,6 +153,10 @@ public TestRestoreRequest( clientPolicyContext, log) { + // We need the dependency graph spec to go through the proper no-op code paths + DependencyGraphSpec = new DependencyGraphSpec(); + DependencyGraphSpec.AddProject(project); + DependencyGraphSpec.AddRestore(project.RestoreMetadata.ProjectUniqueName); } } } From e520afebaf0f75b3239378dc80d8192288ef2145 Mon Sep 17 00:00:00 2001 From: Heng Liu <45407901+heng-liu@users.noreply.github.com> Date: Wed, 11 Nov 2020 16:01:57 +0000 Subject: [PATCH 038/129] skip a flaky test (#3762) --- test/EndToEnd/tests/GetPackageTest.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/EndToEnd/tests/GetPackageTest.ps1 b/test/EndToEnd/tests/GetPackageTest.ps1 index 3085b9f062d..d2ee8cf9064 100644 --- a/test/EndToEnd/tests/GetPackageTest.ps1 +++ b/test/EndToEnd/tests/GetPackageTest.ps1 @@ -497,6 +497,7 @@ function Test-GetInstalledPackageWithFilterReturnsCorrectPackage function Test-GetPackageUpdatesAfterSwitchToSourceThatDoesNotContainInstalledPackageId { + [SkipTest('https://github.com/NuGet/Home/issues/10254')] param ( $context From 299bfdee44815bbce90e704f0a3753526967afe7 Mon Sep 17 00:00:00 2001 From: Heng Liu <45407901+heng-liu@users.noreply.github.com> Date: Wed, 11 Nov 2020 18:44:07 +0000 Subject: [PATCH 039/129] Fix conditions of "stop on error" and "continue on error" in E2E tests (#3759) --- build/templates/End_To_End_Tests_On_Windows.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/templates/End_To_End_Tests_On_Windows.yml b/build/templates/End_To_End_Tests_On_Windows.yml index 3df93e290a0..f8d9fd54c67 100644 --- a/build/templates/End_To_End_Tests_On_Windows.yml +++ b/build/templates/End_To_End_Tests_On_Windows.yml @@ -63,11 +63,11 @@ steps: - task: PowerShell@1 displayName: "RunFunctionalTests.ps1 (stop on error)" timeoutInMinutes: 75 - continueOnError: "true" + continueOnError: "false" inputs: scriptName: "$(System.DefaultWorkingDirectory)\\artifacts\\EndToEnd\\scripts\\RunFunctionalTests.ps1" arguments: "-PMCCommand $(EndToEndTestCommandToRunPart) -PMCLaunchWaitTimeInSecs 30 -EachTestTimoutInSecs 600 -NuGetDropPath $(System.DefaultWorkingDirectory)\\artifacts -FuncTestRoot $(System.DefaultWorkingDirectory)\\artifacts -RunCounter $(Build.BuildNumber) -VSVersion 16.0" - condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" + condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" - task: PowerShell@1 displayName: "RunFunctionalTests.ps1 (continue on error)" @@ -76,7 +76,7 @@ steps: inputs: scriptName: "$(System.DefaultWorkingDirectory)\\artifacts\\EndToEnd\\scripts\\RunFunctionalTests.ps1" arguments: "-PMCCommand $(EndToEndTestCommandToRunPart) -PMCLaunchWaitTimeInSecs 30 -EachTestTimoutInSecs 600 -NuGetDropPath $(System.DefaultWorkingDirectory)\\artifacts -FuncTestRoot $(System.DefaultWorkingDirectory)\\artifacts -RunCounter $(Build.BuildNumber) -VSVersion 16.0" - condition: "and(succeeded(), not(eq(variables['IsOfficialBuild'], 'true')))" + condition: "and(succeeded(), eq(variables['IsOfficialBuild'], 'true'))" - task: PublishTestResults@2 displayName: "Publish Test Results" From 48681db6df318bd132ccd48f5255c03b0065085b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Wed, 11 Nov 2020 15:57:02 -0800 Subject: [PATCH 040/129] Fix round-tripping of netcoreapp5.0 parsing (#3756) Fixes: https://github.com/NuGet/Home/issues/10177 --- src/NuGet.Core/NuGet.Frameworks/NuGetFrameworkFactory.cs | 5 ++++- .../NuGet.Frameworks.Test/NuGetFrameworkParseTests.cs | 4 +++- .../NuGet.Frameworks.Test/NuGetFrameworkTests.cs | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/NuGet.Core/NuGet.Frameworks/NuGetFrameworkFactory.cs b/src/NuGet.Core/NuGet.Frameworks/NuGetFrameworkFactory.cs index c76584d9c40..212b6d13853 100644 --- a/src/NuGet.Core/NuGet.Frameworks/NuGetFrameworkFactory.cs +++ b/src/NuGet.Core/NuGet.Frameworks/NuGetFrameworkFactory.cs @@ -342,7 +342,10 @@ public static NuGetFramework ParseFolder(string folderName, IFrameworkNameProvid var profileShort = parts.Item3; if (version.Major >= 5 - && StringComparer.OrdinalIgnoreCase.Equals(FrameworkConstants.FrameworkIdentifiers.Net, framework)) + && (StringComparer.OrdinalIgnoreCase.Equals(FrameworkConstants.FrameworkIdentifiers.Net, framework) + || StringComparer.OrdinalIgnoreCase.Equals(FrameworkConstants.FrameworkIdentifiers.NetCoreApp, framework) + ) + ) { // net should be treated as netcoreapp in 5.0 and later framework = FrameworkConstants.FrameworkIdentifiers.NetCoreApp; diff --git a/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkParseTests.cs b/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkParseTests.cs index abd6920926c..f1d885f9058 100644 --- a/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkParseTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkParseTests.cs @@ -226,6 +226,9 @@ public void NuGetFramework_ProfileName(string folder, string expected) [InlineData("netcoreapp1.5", ".NETCoreApp,Version=v1.5")] [InlineData("netcoreapp2.0", ".NetCoreApp,Version=v2.0")] [InlineData("netcoreapp3.0", ".NetCoreApp,Version=v3.0")] + [InlineData("net5.0", "netcoreapp5.0")] + [InlineData("net5.0-windows", "netcoreapp5.0-windows")] + [InlineData("net5.0-windows10.0", "netcoreapp5.0-windows10.0")] [InlineData("net5.0-android", "net5.0-android")] [InlineData("net5.0-android", "net5.0-android0.0")] [InlineData("net5.0-android10.0", "net5.0-android10")] @@ -251,7 +254,6 @@ public void NuGetFramework_ParseToShortName(string expected, string fullName) // Net5.0 ERA [InlineData("net5.0", ".NETCoreApp,Version=v5.0", "")] [InlineData("net10.1.2.3", ".NETCoreApp,Version=v10.1.2.3", "")] - [InlineData("netcoreapp5.0", ".NETCoreApp,Version=v5.0", "")] [InlineData("net5.0-android", ".NETCoreApp,Version=v5.0", "android,Version=0.0")] [InlineData("net5.0-ios14.0", ".NETCoreApp,Version=v5.0", "ios,Version=14.0")] diff --git a/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkTests.cs b/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkTests.cs index 89bd7832fac..737df4c123f 100644 --- a/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGetFrameworkTests.cs @@ -16,6 +16,9 @@ public class NuGetFrameworkTests [InlineData("net45", "net45")] [InlineData("net5.0", "net5.0")] [InlineData("net50", "net5.0")] + [InlineData("netcoreapp5.0", "net5.0")] + [InlineData("netcoreapp5.0-windows", "net5.0-windows")] + [InlineData("netcoreapp5.0-windows10.0", "net5.0-windows10.0")] [InlineData("net5.0-windows7.0", "net5.0-windows7.0")] [InlineData("net5.0-android11.0", "net5.0-android11.0")] [InlineData("portable-net45+win8+monoandroid", "portable-net45+win8")] From 6984cab03682d364e6371fee182708e77bd42927 Mon Sep 17 00:00:00 2001 From: Heng Liu <45407901+heng-liu@users.noreply.github.com> Date: Thu, 12 Nov 2020 05:15:23 +0000 Subject: [PATCH 041/129] remove IncludeSymbols=true from common.targets (#3758) --- build/common.targets | 1 - 1 file changed, 1 deletion(-) diff --git a/build/common.targets b/build/common.targets index 197878d61a3..78311be8c6a 100644 --- a/build/common.targets +++ b/build/common.targets @@ -144,7 +144,6 @@ Properties="Configuration=$(Configuration); VisualStudioVersion=$(VisualStudioVersion); PackageOutputPath=$(NupkgOutputDirectory); - IncludeSymbols=true; NoBuild=true;"> From 5798b9c19f658e9b69ed9f9cdc6706357ba993c5 Mon Sep 17 00:00:00 2001 From: Damon Tivel Date: Mon, 16 Nov 2020 15:59:42 -0800 Subject: [PATCH 042/129] PM UI: fix exception on window close (#3764) Progress on https://github.com/NuGet/Home/issues/9935. --- .../PackageManagerToolWindowPane.cs | 13 +--- .../PackageManagerWindowPane.cs | 8 +-- .../Xamls/PackageManagerControl.xaml.cs | 71 ++++++++++--------- 3 files changed, 42 insertions(+), 50 deletions(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerToolWindowPane.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerToolWindowPane.cs index 7db44f87422..e3b1b971e4b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerToolWindowPane.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerToolWindowPane.cs @@ -2,12 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; -using System.Threading; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using NuGet.VisualStudio; namespace NuGet.PackageManagement.UI { @@ -73,15 +70,9 @@ protected override void Dispose(bool disposing) public int OnClose(ref uint pgrfSaveOptions) { - PackageManagerControl content = _content; - - if (content != null) + if (_content is PackageManagerControl content) { - NuGetUIThreadHelper.JoinableTaskFactory.Run(async () => - { - await content.SaveSettingsAsync(CancellationToken.None); - }); - + content.SaveSettings(); content.Model.Context.UserSettingsManager.PersistSettings(); } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerWindowPane.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerWindowPane.cs index 1f0216a7e49..22f8e37fd0e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerWindowPane.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/PackageManagerWindowPane.cs @@ -2,11 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Threading; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using NuGet.VisualStudio; namespace NuGet.PackageManagement.UI { @@ -67,13 +65,11 @@ protected override void Dispose(bool disposing) public int OnClose(ref uint pgrfSaveOptions) { - NuGetUIThreadHelper.JoinableTaskFactory.Run(async () => - { - await _content.SaveSettingsAsync(CancellationToken.None); - }); + _content.SaveSettings(); _content.Model.Context.UserSettingsManager.PersistSettings(); pgrfSaveOptions = (uint)__FRAMECLOSE.FRAMECLOSE_NoSave; + return VSConstants.S_OK; } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs index 77de5b7aef1..09fbe177424 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs @@ -67,6 +67,7 @@ public partial class PackageManagerControl : UserControl, IVsWindowSearch private bool _loadedAndInitialized = false; private bool _recommendPackages = false; private (string modelVersion, string vsixVersion)? _recommenderVersion; + private string _settingsKey; private PackageManagerControl() { @@ -132,7 +133,8 @@ private async ValueTask InitializeAsync(PackageManagerModel model, INuGetUILogge _topPanel.CreateAndAddConsolidateTab(); } - var settings = await LoadSettingsAsync(CancellationToken.None); + _settingsKey = await GetSettingsKeyAsync(CancellationToken.None); + UserSettings settings = LoadSettings(); InitializeFilterList(settings); InitSourceRepoList(settings); ApplySettings(settings, Settings); @@ -233,6 +235,8 @@ private async Task SolutionManager_ProjectRenamedAsync(IProjectContextInfo proje if (currentProjectMetadata.FullPath == renamedProjectMetadata.FullPath) { + _settingsKey = GetProjectSettingsKey(renamedProjectMetadata.Name); + await SetTitleAsync(currentProjectMetadata); } } @@ -495,11 +499,10 @@ private void Sources_PackageSourcesChanged(object sender, EventArgs e) var timeSpan = GetTimeSinceLastRefreshAndRestart(); ResetTabDataLoadFlags(); - NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(() => Sources_PackageSourcesChangedAsync(timeSpan)) - .PostOnFailure(nameof(PackageManagerControl), nameof(Sources_PackageSourcesChanged)); + Sources_PackageSourcesChanged(timeSpan); } - private async Task Sources_PackageSourcesChangedAsync(TimeSpan timeSpan) + private void Sources_PackageSourcesChanged(TimeSpan timeSpan) { try { @@ -513,7 +516,7 @@ private async Task Sources_PackageSourcesChangedAsync(TimeSpan timeSpan) } else { - await SaveSettingsAsync(CancellationToken.None); + SaveSettings(); SearchPackagesAndRefreshUpdateCount(useCacheForUpdates: false); EmitRefreshEvent(timeSpan, RefreshOperationSource.PackageSourcesChanged, RefreshOperationStatus.Success); } @@ -528,38 +531,46 @@ private async Task GetSettingsKeyAsync(CancellationToken cancellationTok { string key; - if (!Model.IsSolution) + if (Model.IsSolution) + { + key = "solution"; + } + else { IProjectContextInfo project = Model.Context.Projects.First(); IProjectMetadataContextInfo projectMetadata = await project.GetMetadataAsync( Model.Context.ServiceBroker, cancellationToken); - string projectName; - if (string.IsNullOrEmpty(projectMetadata.Name)) - { - projectName = "unknown"; - } - else - { - projectName = projectMetadata.Name; - } + return GetProjectSettingsKey(projectMetadata.Name); + } - key = "project:" + projectName; + return key; + } + + private static string GetProjectSettingsKey(string projectName) + { + string value; + + if (string.IsNullOrEmpty(projectName)) + { + value = "unknown"; } else { - key = "solution"; + value = projectName; } - return key; + return "project:" + value; } // Save the settings of this doc window in the UIContext. Note that the settings // are not guaranteed to be persisted. We need to call Model.Context.SaveSettings() // to persist the settings. - public async Task SaveSettingsAsync(CancellationToken cancellationToken) + public void SaveSettings() { + Assumes.NotNullOrEmpty(_settingsKey); + var settings = new UserSettings { SourceRepository = SelectedSource?.SourceName, @@ -575,14 +586,14 @@ public async Task SaveSettingsAsync(CancellationToken cancellationToken) }; _packageDetail._solutionView.SaveSettings(settings); - string settingsKey = await GetSettingsKeyAsync(cancellationToken); - Model.Context.UserSettingsManager.AddSettings(settingsKey, settings); + Model.Context.UserSettingsManager.AddSettings(_settingsKey, settings); } - private async Task LoadSettingsAsync(CancellationToken cancellationToken) + private UserSettings LoadSettings() { - string settingsKey = await GetSettingsKeyAsync(cancellationToken); - var settings = Model.Context.UserSettingsManager.GetSettings(settingsKey); + Assumes.NotNullOrEmpty(_settingsKey); + + UserSettings settings = Model.Context.UserSettingsManager.GetSettings(_settingsKey); if (PreviewWindow.IsDoNotShowPreviewWindowEnabled()) { @@ -1192,18 +1203,12 @@ private void SourceRepoList_SelectionChanged(object sender, EventArgs e) _topPanel.SourceToolTip.Visibility = Visibility.Visible; _topPanel.SourceToolTip.DataContext = SelectedSource.GetTooltip(); - NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(() => SourceRepoList_SelectionChangedAsync(timeSpan)) - .PostOnFailure(nameof(PackageManagerControl), nameof(SourceRepoList_SelectionChanged)); + SaveSettings(); + SearchPackagesAndRefreshUpdateCount(useCacheForUpdates: false); + EmitRefreshEvent(timeSpan, RefreshOperationSource.SourceSelectionChanged, RefreshOperationStatus.Success); } } - private async Task SourceRepoList_SelectionChangedAsync(TimeSpan timeSpan) - { - await SaveSettingsAsync(CancellationToken.None); - SearchPackagesAndRefreshUpdateCount(useCacheForUpdates: false); - EmitRefreshEvent(timeSpan, RefreshOperationSource.SourceSelectionChanged, RefreshOperationStatus.Success); - } - private void Filter_SelectionChanged(object sender, FilterChangedEventArgs e) { if (_initialized) From 8852cd3edb6fee6d9e8d671aa0bd44c18d5b50e3 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Mon, 16 Nov 2020 20:10:59 -0800 Subject: [PATCH 043/129] When restoring packages.config projects, ensure the target framework is read during the project walk (#3763) * Fix packages.config framework reading * stuff * feedback --- .../NuGet.Build.Tasks/NuGet.targets | 5 +- .../Utility/MSBuildRestoreUtility.cs | 2 +- .../Commands/RestoreCommandTests.cs | 73 +++++++++++++++++++ .../NuGet.CommandLine.FuncTest.csproj | 11 ++- .../compiler/resources/pc.packages.lock.json | 13 ++++ 5 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/compiler/resources/pc.packages.lock.json diff --git a/src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets b/src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets index a1c2d9bc1a6..8b0c4923613 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets +++ b/src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets @@ -510,7 +510,7 @@ Copyright (c) .NET Foundation. All rights reserved. $(_OutputRepositoryPath) $(_OutputConfigFilePaths) $(_OutputPackagesPath) - + @(_RestoreTargetFrameworksOutputFiltered) + diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/MSBuildRestoreUtility.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/MSBuildRestoreUtility.cs index 46a3c68ae15..77e41a3ec5c 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/MSBuildRestoreUtility.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/MSBuildRestoreUtility.cs @@ -779,7 +779,7 @@ private static PackageSpec GetBaseSpec(IMSBuildItem specItem, ProjectStyle proje spec.FilePath = specItem.GetProperty("ProjectPath"); spec.RestoreMetadata.ProjectName = specItem.GetProperty("ProjectName"); - if (projectStyle == ProjectStyle.DotnetCliTool || projectStyle == ProjectStyle.Unknown) + if (projectStyle == ProjectStyle.DotnetCliTool || projectStyle == ProjectStyle.Unknown || projectStyle == ProjectStyle.PackagesConfig) { var tfmProperty = specItem.GetProperty("TargetFrameworks"); if (!string.IsNullOrEmpty(tfmProperty)) diff --git a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/RestoreCommandTests.cs b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/RestoreCommandTests.cs index bff63525d77..7cb95728b33 100644 --- a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/RestoreCommandTests.cs +++ b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/RestoreCommandTests.cs @@ -4,11 +4,16 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; +using System.Threading; using System.Threading.Tasks; +using FluentAssertions; using NuGet.CommandLine.Test; +using NuGet.Common; using NuGet.Frameworks; using NuGet.Packaging; using NuGet.ProjectModel; +using NuGet.Protocol; using NuGet.Test.Utility; using Xunit; @@ -500,6 +505,66 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( } } + [Fact] + public async Task RestorePackagesConfig_WithExistingLockFile_LockedMode_Succeeds() + { + // Arrange + using (var pathContext = new SimpleTestPathContext()) + { + // Set up solution, project, and packages + var solution = new SimpleTestSolutionContext(pathContext.SolutionRoot); + + var net461 = NuGetFramework.Parse("net461"); + + var projectA = SimpleTestProjectContext.CreateLegacyPackageReference( + "a", + pathContext.SolutionRoot, + net461); + + var packageX = new SimpleTestPackageContext() + { + Id = "x", + Version = "1.0.0" + }; + packageX.Files.Clear(); + packageX.AddFile("lib/net461/x.dll"); + + solution.Projects.Add(projectA); + solution.Create(pathContext.SolutionRoot); + Util.CreateFile(Path.GetDirectoryName(projectA.ProjectPath), "packages.config", +@" + +"); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageX); + + // Preconditions, regular restore + var result = RunRestore(pathContext, _successExitCode); + result.Success.Should().BeTrue(because: result.AllOutput); + new FileInfo(projectA.NuGetLockFileOutputPath).Exists.Should().BeFalse(); + + // Write expected lock file + var packagePath = LocalFolderUtility.GetPackagesV3(pathContext.PackageSource, NullLogger.Instance).Single().Path; + + string contentHash = null; + using (var reader = new PackageArchiveReader(packagePath)) + { + contentHash = reader.GetContentHash(CancellationToken.None); + } + + var expectedLockFile = GetResource("NuGet.CommandLine.FuncTest.compiler.resources.pc.packages.lock.json").Replace("TEMPLATE", contentHash); + File.WriteAllText(projectA.NuGetLockFileOutputPath, expectedLockFile); + + // Run lockedmode restore. + result = RunRestore(pathContext, _successExitCode, "-LockedMode"); + result.Success.Should().BeTrue(because: result.AllOutput); + new FileInfo(projectA.NuGetLockFileOutputPath).Exists.Should().BeTrue(); + } + } + [Fact] public async Task Restore_LegacyPackageReference_EmbedInteropPackage() { @@ -838,5 +903,13 @@ public static CommandRunnerResult RunRestore(SimpleTestPathContext pathContext, return r; } + + public static string GetResource(string name) + { + using (var reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(name))) + { + return reader.ReadToEnd(); + } + } } } diff --git a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/NuGet.CommandLine.FuncTest.csproj b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/NuGet.CommandLine.FuncTest.csproj index 566ec40a717..d2144172ea2 100644 --- a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/NuGet.CommandLine.FuncTest.csproj +++ b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/NuGet.CommandLine.FuncTest.csproj @@ -9,6 +9,14 @@ A functional (end-to-end) test suite for NuGet.CommandLine. Contains tests for every nuget.exe command. + + + + + + + + @@ -27,8 +35,7 @@ - + diff --git a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/compiler/resources/pc.packages.lock.json b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/compiler/resources/pc.packages.lock.json new file mode 100644 index 00000000000..d41daa072b3 --- /dev/null +++ b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/compiler/resources/pc.packages.lock.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "dependencies": { + ".NETFramework,Version=v4.6.1": { + "x": { + "type": "Direct", + "requested": "[1.0.0, 1.0.0]", + "resolved": "1.0.0", + "contentHash": "TEMPLATE" + } + } + } +} From aed5629cba5e7adf348b3500ebd4a832ef8ebb51 Mon Sep 17 00:00:00 2001 From: David Maas Date: Tue, 17 Nov 2020 20:09:03 -0600 Subject: [PATCH 044/129] Added error when specifying a package icon or license file with the incorrect path casing. (#3754) This implements the design set forth in https://github.com/NuGet/Home/pull/10049 --- .../NuGet.Common/PathUtil/PathUtility.cs | 12 ++- .../Authoring/PackageBuilder.cs | 75 +++++++++++--- .../Resources/NuGetResources.Designer.cs | 18 ++++ .../Resources/NuGetResources.resx | 8 ++ .../PackCommandTests.cs | 98 +++++++++++++++++++ 5 files changed, 193 insertions(+), 18 deletions(-) diff --git a/src/NuGet.Core/NuGet.Common/PathUtil/PathUtility.cs b/src/NuGet.Core/NuGet.Common/PathUtil/PathUtility.cs index c92323c7f80..3e27acfcc4e 100644 --- a/src/NuGet.Core/NuGet.Common/PathUtil/PathUtility.cs +++ b/src/NuGet.Core/NuGet.Common/PathUtil/PathUtility.cs @@ -15,9 +15,13 @@ public static class PathUtility private static readonly Lazy _isFileSystemCaseInsensitive = new Lazy(CheckIfFileSystemIsCaseInsensitive); /// - /// Returns OrdinalIgnoreCase windows and mac. Ordinal for linux. + /// Returns OrdinalIgnoreCase Windows and Mac. Ordinal for Linux. (Do not use with package paths) /// /// + /// + /// This method should not be used with package paths. + /// Package paths are always case sensitive, using this with package paths leads to bugs like https://github.com/NuGet/Home/issues/9817. + /// public static StringComparer GetStringComparerBasedOnOS() { if (IsFileSystemCaseInsensitive) @@ -29,9 +33,13 @@ public static StringComparer GetStringComparerBasedOnOS() } /// - /// Returns OrdinalIgnoreCase windows and mac. Ordinal for linux. + /// Returns OrdinalIgnoreCase Windows and Mac. Ordinal for Linux. (Do not use with package paths) /// /// + /// + /// This method should not be used with package paths. + /// Package paths are always case sensitive, using this with package paths leads to bugs like https://github.com/NuGet/Home/issues/9817. + /// public static StringComparison GetStringComparisonBasedOnOS() { if (IsFileSystemCaseInsensitive) diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs index 8e6c5bc3551..a32a51e3059 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs @@ -619,6 +619,39 @@ private static void ValidateFrameworkAssemblies(IEnumerableLooks for the specified file within the package + /// The file path to search for + /// The list of files to search within + /// If the file was not found, this will be a path which almost matched but had the incorrect case + /// An matching the specified path or null + private static IPackageFile FindFileInPackage(string filePath, IEnumerable packageFiles, out string filePathIncorrectCase) + { + filePathIncorrectCase = null; + var strippedFilePath = PathUtility.StripLeadingDirectorySeparators(filePath); + + foreach (var packageFile in packageFiles) + { + var strippedPackageFilePath = PathUtility.StripLeadingDirectorySeparators(packageFile.Path); + + // This must use a case-sensitive string comparison, even on systems where file paths are normally case-sensitive. + // This is because Zip files are treated as case-sensitive. (See https://github.com/NuGet/Home/issues/9817) + if (strippedPackageFilePath.Equals(strippedFilePath, StringComparison.Ordinal)) + { + // Found the requested file in the package + filePathIncorrectCase = null; + return packageFile; + } + // Check for files that exist with the wrong file casing + else if (filePathIncorrectCase is null && strippedPackageFilePath.Equals(strippedFilePath, StringComparison.OrdinalIgnoreCase)) + { + filePathIncorrectCase = strippedPackageFilePath; + } + } + + // We searched all of the package files and didn't find what we were looking for + return null; + } + private void ValidateLicenseFile(IEnumerable files, LicenseMetadata licenseMetadata) { if (!PackageTypes.Contains(PackageType.SymbolsPackage) && licenseMetadata?.Type == LicenseType.File) @@ -630,11 +663,20 @@ private void ValidateLicenseFile(IEnumerable files, LicenseMetadat { throw new PackagingException(NuGetLogCode.NU5031, string.Format(CultureInfo.CurrentCulture, NuGetResources.Manifest_LicenseFileExtensionIsInvalid, licenseMetadata.License)); } - var strippedLicenseFileLocation = PathUtility.StripLeadingDirectorySeparators(licenseMetadata.License); - var count = files.Where(e => PathUtility.StripLeadingDirectorySeparators(e.Path).Equals(strippedLicenseFileLocation, PathUtility.GetStringComparisonBasedOnOS())).Count(); - if (count == 0) + + if (FindFileInPackage(licenseMetadata.License, files, out var licenseFilePathWithIncorrectCase) is null) { - throw new PackagingException(NuGetLogCode.NU5030, string.Format(CultureInfo.CurrentCulture, NuGetResources.Manifest_LicenseFileIsNotInNupkg, licenseMetadata.License)); + string errorMessage; + if (licenseFilePathWithIncorrectCase is null) + { + errorMessage = string.Format(CultureInfo.CurrentCulture, NuGetResources.Manifest_LicenseFileIsNotInNupkg, licenseMetadata.License); + } + else + { + errorMessage = string.Format(CultureInfo.CurrentCulture, NuGetResources.Manifest_LicenseFileIsNotInNupkgWithHint, licenseMetadata.License, licenseFilePathWithIncorrectCase); + } + + throw new PackagingException(NuGetLogCode.NU5030, errorMessage); } } } @@ -651,21 +693,22 @@ private void ValidateIconFile(IEnumerable files, string iconPath) if (!PackageTypes.Contains(PackageType.SymbolsPackage) && !string.IsNullOrEmpty(iconPath)) { // Validate entry - var iconPathStripped = PathUtility.StripLeadingDirectorySeparators(iconPath); + IPackageFile iconFile = FindFileInPackage(iconPath, files, out var iconPathWithIncorrectCase); - var iconFileList = files.Where(f => - iconPathStripped.Equals( - PathUtility.StripLeadingDirectorySeparators(f.Path), - PathUtility.GetStringComparisonBasedOnOS())); - - if (iconFileList.Count() == 0) + if (iconFile is null) { - throw new PackagingException( - NuGetLogCode.NU5046, - string.Format(CultureInfo.CurrentCulture, NuGetResources.IconNoFileElement, iconPath)); - } + string errorMessage; + if (iconPathWithIncorrectCase is null) + { + errorMessage = string.Format(CultureInfo.CurrentCulture, NuGetResources.IconNoFileElement, iconPath); + } + else + { + errorMessage = string.Format(CultureInfo.CurrentCulture, NuGetResources.IconNoFileElementWithHint, iconPath, iconPathWithIncorrectCase); + } - IPackageFile iconFile = iconFileList.First(); + throw new PackagingException(NuGetLogCode.NU5046, errorMessage); + } try { diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs index e3a91e2c913..b3042a8f7a0 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs @@ -132,6 +132,15 @@ internal static string IconNoFileElement { } } + /// + /// Looks up a localized string similar to The icon file '{0}' does not exist in the package. (Did you mean '{1}'?). + /// + internal static string IconNoFileElementWithHint { + get { + return ResourceManager.GetString("IconNoFileElementWithHint", resourceCulture); + } + } + /// /// Looks up a localized string similar to The schema version of '{0}' is incompatible with version {1} of NuGet. Please upgrade NuGet to the latest version from http://go.microsoft.com/fwlink/?LinkId=213942.. /// @@ -222,6 +231,15 @@ internal static string Manifest_LicenseFileIsNotInNupkg { } } + /// + /// Looks up a localized string similar to The license file '{0}' does not exist in the package. (Did you mean '{1}'?). + /// + internal static string Manifest_LicenseFileIsNotInNupkgWithHint { + get { + return ResourceManager.GetString("Manifest_LicenseFileIsNotInNupkgWithHint", resourceCulture); + } + } + /// /// Looks up a localized string similar to The licenseUrl and license elements cannot be used together.. /// diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx index d7809fd4e98..9933041e403 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx @@ -212,4 +212,12 @@ The element 'icon' cannot be empty. Please, don't localize icon + + The icon file '{0}' does not exist in the package. (Did you mean '{1}'?) + 0 - the icon file, 1 - hint to guessed icon file + + + The license file '{0}' does not exist in the package. (Did you mean '{1}'?) + 0 - the license file, 1 - hint to guessed licensed file + \ No newline at end of file diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs index 2bc96eb23e7..b8bec7f0805 100644 --- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs @@ -3960,6 +3960,54 @@ public void PackCommand_PackLicense_PackBasicLicenseFile_FileNotInPackage() } } + [PlatformFact(Platform.Windows)] + public void PackCommand_PackLicense_PackBasicLicenseFile_FileIncorrectCasing() + { + using (var testDirectory = msbuildFixture.CreateTestDirectory()) + { + // Set up + var realLicenseFileName = "LICENSE.txt"; + var nuspecLicenseFileName = "License.txt"; + var projectName = "ClassLibrary1"; + var workingDirectory = Path.Combine(testDirectory, projectName); + msbuildFixture.CreateDotnetNewProject(testDirectory.Path, projectName, " classlib"); + var projectFile = Path.Combine(workingDirectory, $"{projectName}.csproj"); + var licenseFile = Path.Combine(workingDirectory, realLicenseFileName); + + var licenseText = "Random licenseFile"; + File.WriteAllText(licenseFile, licenseText); + Assert.True(File.Exists(licenseFile)); + + // Setup LicenseFile + using (var stream = new FileStream(projectFile, FileMode.Open, FileAccess.ReadWrite)) + { + var xml = XDocument.Load(stream); + ProjectFileUtils.AddProperty(xml, "PackageLicenseFile", nuspecLicenseFileName); + + var attributes = new Dictionary(); + attributes["Pack"] = "true"; + attributes["PackagePath"] = realLicenseFileName; + var properties = new Dictionary(); + ProjectFileUtils.AddItem( + xml, + "None", + realLicenseFileName, + NuGetFramework.AnyFramework, + properties, + attributes); + + ProjectFileUtils.WriteXmlToFile(xml, stream); + } + + msbuildFixture.RestoreProject(workingDirectory, projectName, string.Empty); + var result = msbuildFixture.PackProject(workingDirectory, projectName, $"-o {workingDirectory}", validateSuccess: false); + + Assert.False(result.Success); + Assert.Contains(NuGetLogCode.NU5030.ToString(), result.Output); + Assert.Contains($"'{realLicenseFileName}'", result.Output, StringComparison.Ordinal); // Check for "Did you mean 'LICENSE.txt'?" + } + } + [PlatformFact(Platform.Windows)] public void PackCommand_PackLicense_PackBasicLicenseFile_FileExtensionNotValid() { @@ -4558,6 +4606,56 @@ public void PackCommand_PackageIcon_MissingFile_Fails() } } + [PlatformFact(Platform.Windows)] + public void PackCommand_PackageIcon_IncorrectCasing_Fails() + { + var testDirBuilder = TestDirectoryBuilder.Create(); + var projectBuilder = ProjectFileBuilder.Create(); + + testDirBuilder + .WithFile("test\\icon.jpg", 10); + + projectBuilder + .WithProjectName("test") + .WithPackageIcon("ICON.JPG") + .WithItem(itemType: "None", itemPath: "icon.jpg", packagePath: "icon.jpg", pack: "true"); + + using (var srcDir = msbuildFixture.Build(testDirBuilder)) + { + projectBuilder.Build(msbuildFixture, srcDir.Path); + var result = msbuildFixture.PackProject(projectBuilder.ProjectFolder, projectBuilder.ProjectName, string.Empty, validateSuccess: false); + + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(NuGetLogCode.NU5046.ToString(), result.Output); + Assert.Contains("'icon.jpg'", result.Output, StringComparison.Ordinal); // Check for "Did you mean 'icon.jpg'?" + } + } + + [PlatformFact(Platform.Windows)] + public void PackCommand_PackageIcon_IncorrectFolderCasing_Fails() + { + var testDirBuilder = TestDirectoryBuilder.Create(); + var projectBuilder = ProjectFileBuilder.Create(); + + testDirBuilder + .WithFile("test\\icon.jpg", 10); + + projectBuilder + .WithProjectName("test") + .WithPackageIcon("FOLDER\\icon.jpg") + .WithItem(itemType: "None", itemPath: "icon.jpg", packagePath: "folder\\icon.jpg", pack: "true"); + + using (var srcDir = msbuildFixture.Build(testDirBuilder)) + { + projectBuilder.Build(msbuildFixture, srcDir.Path); + var result = msbuildFixture.PackProject(projectBuilder.ProjectFolder, projectBuilder.ProjectName, string.Empty, validateSuccess: false); + + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(NuGetLogCode.NU5046.ToString(), result.Output); + Assert.Contains("'folder/icon.jpg'", result.Output, StringComparison.Ordinal); // Check for "Did you mean 'folder/icon.jpg'?" + } + } + [PlatformTheory(Platform.Windows)] [InlineData("snupkg")] [InlineData("symbols.nupkg")] From a7babb9ca535b2a929d8bc04a87dbe163a83296e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 17 Nov 2020 19:01:17 -0800 Subject: [PATCH 045/129] update shipped APIs (#3768) Ref: https://github.com/NuGet/Client.Engineering/issues/627 --- .../NuGet.VisualStudio/PublicAPI.Shipped.txt | 9 +++++++++ .../NuGet.VisualStudio/PublicAPI.Unshipped.txt | 9 --------- .../NuGet.Build.Tasks/PublicAPI.Shipped.txt | 4 ++++ .../NuGet.Build.Tasks/PublicAPI.Unshipped.txt | 6 +----- .../PublicAPI/net472/PublicAPI.Shipped.txt | 3 +++ .../PublicAPI/net472/PublicAPI.Unshipped.txt | 3 --- .../PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt | 3 +++ .../PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt | 3 --- .../PublicAPI/netstandard2.0/PublicAPI.Shipped.txt | 3 +++ .../netstandard2.0/PublicAPI.Unshipped.txt | 3 --- src/NuGet.Core/NuGet.Common/PublicAPI.Unshipped.txt | 1 - .../PublicAPI/net45/PublicAPI.Shipped.txt | 2 ++ .../PublicAPI/net45/PublicAPI.Unshipped.txt | 2 -- .../PublicAPI/net472/PublicAPI.Shipped.txt | 2 ++ .../PublicAPI/net472/PublicAPI.Unshipped.txt | 2 -- .../PublicAPI/netstandard2.0/PublicAPI.Shipped.txt | 2 ++ .../netstandard2.0/PublicAPI.Unshipped.txt | 2 -- .../NuGet.Configuration/PublicAPI.Shipped.txt | 8 ++++++++ .../NuGet.Configuration/PublicAPI.Unshipped.txt | 8 -------- .../PublicAPI.Shipped.txt | 4 ++++ .../PublicAPI.Unshipped.txt | 4 ---- .../PublicAPI/net40/PublicAPI.Shipped.txt | 6 +++++- .../PublicAPI/net40/PublicAPI.Unshipped.txt | 4 ---- .../PublicAPI/net45/PublicAPI.Shipped.txt | 5 +++++ .../PublicAPI/net45/PublicAPI.Unshipped.txt | 5 ----- .../PublicAPI/net472/PublicAPI.Shipped.txt | 6 +++++- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 4 ---- .../PublicAPI/netstandard2.0/PublicAPI.Shipped.txt | 6 +++++- .../netstandard2.0/PublicAPI.Unshipped.txt | 4 ---- .../NuGet.LibraryModel/PublicAPI.Shipped.txt | 1 + .../NuGet.LibraryModel/PublicAPI.Unshipped.txt | 3 +-- .../NuGet.PackageManagement/PublicAPI.Shipped.txt | 8 ++++++++ .../NuGet.PackageManagement/PublicAPI.Unshipped.txt | 8 -------- .../NuGet.ProjectModel/PublicAPI.Shipped.txt | 6 ++++++ .../NuGet.ProjectModel/PublicAPI.Unshipped.txt | 6 ------ .../PublicAPI/net472/PublicAPI.Shipped.txt | 13 +++++++++++++ .../PublicAPI/net472/PublicAPI.Unshipped.txt | 13 ------------- .../PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt | 13 +++++++++++++ .../PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt | 13 ------------- .../PublicAPI/netstandard2.0/PublicAPI.Shipped.txt | 13 +++++++++++++ .../netstandard2.0/PublicAPI.Unshipped.txt | 13 ------------- .../NuGet.Versioning/PublicAPI.Shipped.txt | 6 ++++++ .../NuGet.Versioning/PublicAPI.Unshipped.txt | 6 ------ 43 files changed, 122 insertions(+), 123 deletions(-) delete mode 100644 src/NuGet.Core/NuGet.Common/PublicAPI.Unshipped.txt diff --git a/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Shipped.txt b/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Shipped.txt index 2aea52b24c4..44ef01d27c9 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Shipped.txt +++ b/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Shipped.txt @@ -53,11 +53,20 @@ NuGet.VisualStudio.IVsFrameworkCompatibility.GetNearest(System.Runtime.Versionin NuGet.VisualStudio.IVsFrameworkCompatibility.GetNetStandardFrameworks() -> System.Collections.Generic.IEnumerable NuGet.VisualStudio.IVsFrameworkCompatibility2 NuGet.VisualStudio.IVsFrameworkCompatibility2.GetNearest(System.Runtime.Versioning.FrameworkName targetFramework, System.Collections.Generic.IEnumerable fallbackTargetFrameworks, System.Collections.Generic.IEnumerable frameworks) -> System.Runtime.Versioning.FrameworkName +NuGet.VisualStudio.IVsFrameworkCompatibility3 +NuGet.VisualStudio.IVsFrameworkCompatibility3.GetNearest(NuGet.VisualStudio.IVsNuGetFramework targetFramework, System.Collections.Generic.IEnumerable fallbackTargetFrameworks, System.Collections.Generic.IEnumerable frameworks) -> NuGet.VisualStudio.IVsNuGetFramework +NuGet.VisualStudio.IVsFrameworkCompatibility3.GetNearest(NuGet.VisualStudio.IVsNuGetFramework targetFramework, System.Collections.Generic.IEnumerable frameworks) -> NuGet.VisualStudio.IVsNuGetFramework NuGet.VisualStudio.IVsFrameworkParser NuGet.VisualStudio.IVsFrameworkParser.GetShortFrameworkName(System.Runtime.Versioning.FrameworkName frameworkName) -> string NuGet.VisualStudio.IVsFrameworkParser.ParseFrameworkName(string shortOrFullName) -> System.Runtime.Versioning.FrameworkName +NuGet.VisualStudio.IVsFrameworkParser2 +NuGet.VisualStudio.IVsFrameworkParser2.TryParse(string input, out NuGet.VisualStudio.IVsNuGetFramework nuGetFramework) -> bool NuGet.VisualStudio.IVsGlobalPackagesInitScriptExecutor NuGet.VisualStudio.IVsGlobalPackagesInitScriptExecutor.ExecuteInitScriptAsync(string packageId, string packageVersion) -> System.Threading.Tasks.Task +NuGet.VisualStudio.IVsNuGetFramework +NuGet.VisualStudio.IVsNuGetFramework.TargetFrameworkMoniker.get -> string +NuGet.VisualStudio.IVsNuGetFramework.TargetPlatformMinVersion.get -> string +NuGet.VisualStudio.IVsNuGetFramework.TargetPlatformMoniker.get -> string NuGet.VisualStudio.IVsPackageInstaller NuGet.VisualStudio.IVsPackageInstaller.InstallPackage(NuGet.IPackageRepository repository, EnvDTE.Project project, string packageId, string version, bool ignoreDependencies, bool skipAssemblyReferences) -> void NuGet.VisualStudio.IVsPackageInstaller.InstallPackage(string source, EnvDTE.Project project, string packageId, System.Version version, bool ignoreDependencies) -> void diff --git a/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Unshipped.txt b/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Unshipped.txt index 74244acbea1..e69de29bb2d 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Unshipped.txt +++ b/src/NuGet.Clients/NuGet.VisualStudio/PublicAPI.Unshipped.txt @@ -1,9 +0,0 @@ -NuGet.VisualStudio.IVsFrameworkCompatibility3 -NuGet.VisualStudio.IVsFrameworkCompatibility3.GetNearest(NuGet.VisualStudio.IVsNuGetFramework targetFramework, System.Collections.Generic.IEnumerable fallbackTargetFrameworks, System.Collections.Generic.IEnumerable frameworks) -> NuGet.VisualStudio.IVsNuGetFramework -NuGet.VisualStudio.IVsFrameworkCompatibility3.GetNearest(NuGet.VisualStudio.IVsNuGetFramework targetFramework, System.Collections.Generic.IEnumerable frameworks) -> NuGet.VisualStudio.IVsNuGetFramework -NuGet.VisualStudio.IVsFrameworkParser2 -NuGet.VisualStudio.IVsFrameworkParser2.TryParse(string input, out NuGet.VisualStudio.IVsNuGetFramework nuGetFramework) -> bool -NuGet.VisualStudio.IVsNuGetFramework -NuGet.VisualStudio.IVsNuGetFramework.TargetFrameworkMoniker.get -> string -NuGet.VisualStudio.IVsNuGetFramework.TargetPlatformMinVersion.get -> string -NuGet.VisualStudio.IVsNuGetFramework.TargetPlatformMoniker.get -> string \ No newline at end of file diff --git a/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Shipped.txt index d59a8dffeec..8e77bae2937 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Shipped.txt @@ -80,6 +80,8 @@ NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectName.get NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectName.set -> void NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetFramework.get -> string NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetFramework.set -> void +NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetPlatform.get -> string +NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetPlatform.set -> void NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.FallbackTargetFrameworks.get -> string[] NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.FallbackTargetFrameworks.set -> void NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.GetReferenceNearestTargetFrameworkTask() -> void @@ -275,6 +277,8 @@ NuGet.Build.Tasks.RestoreTaskEx.MSBuildBinPath.get -> string NuGet.Build.Tasks.RestoreTaskEx.MSBuildBinPath.set -> void NuGet.Build.Tasks.RestoreTaskEx.NoCache.get -> bool NuGet.Build.Tasks.RestoreTaskEx.NoCache.set -> void +NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.get -> string +NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.set -> void NuGet.Build.Tasks.RestoreTaskEx.ProjectFullPath.get -> string NuGet.Build.Tasks.RestoreTaskEx.ProjectFullPath.set -> void NuGet.Build.Tasks.RestoreTaskEx.Recursive.get -> bool diff --git a/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt index b5b8ddb6851..5d7e88fdfb0 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Build.Tasks/PublicAPI.Unshipped.txt @@ -1,8 +1,4 @@ -NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetPlatform.get -> string -NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask.CurrentProjectTargetPlatform.set -> void NuGet.Build.Tasks.RestoreTaskEx.MSBuildStartupDirectory.get -> string NuGet.Build.Tasks.RestoreTaskEx.MSBuildStartupDirectory.set -> void -NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.get -> string -NuGet.Build.Tasks.RestoreTaskEx.ProcessFileName.set -> void static NuGet.Build.Tasks.BuildTasksUtility.GetFallbackFolders(string startupDirectory, string projectDirectory, string[] fallbackFolders, string[] fallbackFoldersOverride, System.Collections.Generic.IEnumerable additionalProjectFallbackFolders, System.Collections.Generic.IEnumerable additionalProjectFallbackFoldersExcludes, NuGet.Configuration.ISettings settings) -> string[] -static NuGet.Build.Tasks.BuildTasksUtility.GetSources(string startupDirectory, string projectDirectory, string[] sources, string[] sourcesOverride, System.Collections.Generic.IEnumerable additionalProjectSources, NuGet.Configuration.ISettings settings) -> string[] \ No newline at end of file +static NuGet.Build.Tasks.BuildTasksUtility.GetSources(string startupDirectory, string projectDirectory, string[] sources, string[] sourcesOverride, System.Collections.Generic.IEnumerable additionalProjectSources, NuGet.Configuration.ISettings settings) -> string[] diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Shipped.txt index dcbc45c9728..1c7209138b3 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Shipped.txt @@ -950,6 +950,8 @@ NuGet.Commands.VerifyArgs.Logger.get -> NuGet.Common.ILogger NuGet.Commands.VerifyArgs.Logger.set -> void NuGet.Commands.VerifyArgs.PackagePath.get -> string NuGet.Commands.VerifyArgs.PackagePath.set -> void +NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList +NuGet.Commands.VerifyArgs.PackagePaths.set -> void NuGet.Commands.VerifyArgs.Verification NuGet.Commands.VerifyArgs.Verification.All = 1 -> NuGet.Commands.VerifyArgs.Verification NuGet.Commands.VerifyArgs.Verification.Signatures = 2 -> NuGet.Commands.VerifyArgs.Verification @@ -1091,6 +1093,7 @@ static NuGet.Commands.LockFileUtils.ExcludeItems(NuGet.ProjectModel.LockFileTarg static NuGet.Commands.LockFileUtils.ToDirectorySeparator(string path) -> string static NuGet.Commands.MSBuildProjectFactory.GetTargetPathForSourceFile(string sourcePath, string projectDirectory) -> string static NuGet.Commands.MSBuildProjectFactory.ProjectCreator(NuGet.Commands.PackArgs packArgs, string path) -> NuGet.Commands.IProjectFactory +static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(string projectFilePath, string targetFrameworks, string targetFramework, string targetFrameworkMoniker, string targetPlatformIdentifier, string targetPlatformVersion, string targetPlatformMinVersion) -> System.Collections.Generic.IEnumerable static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(string projectFilePath, string targetFrameworks, string targetFramework, string targetFrameworkMoniker, string targetPlatformIdentifier, string targetPlatformVersion, string targetPlatformMinVersion, bool isXnaWindowsPhoneProject, bool isManagementPackProject) -> System.Collections.Generic.IEnumerable diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt index f139652d4be..dec825d99a5 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,4 +1 @@ -NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList -NuGet.Commands.VerifyArgs.PackagePaths.set -> void -static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.PushRunner.Run(NuGet.Configuration.ISettings settings, NuGet.Configuration.IPackageSourceProvider sourceProvider, System.Collections.Generic.IList packagePaths, string source, string apiKey, string symbolSource, string symbolApiKey, int timeoutSeconds, bool disableBuffering, bool noSymbols, bool noServiceEndpoint, bool skipDuplicate, NuGet.Common.ILogger logger) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt index 35c12d78481..6a0515fbaa9 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt @@ -949,6 +949,8 @@ NuGet.Commands.VerifyArgs.Logger.get -> NuGet.Common.ILogger NuGet.Commands.VerifyArgs.Logger.set -> void NuGet.Commands.VerifyArgs.PackagePath.get -> string NuGet.Commands.VerifyArgs.PackagePath.set -> void +NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList +NuGet.Commands.VerifyArgs.PackagePaths.set -> void NuGet.Commands.VerifyArgs.Verification NuGet.Commands.VerifyArgs.Verification.All = 1 -> NuGet.Commands.VerifyArgs.Verification NuGet.Commands.VerifyArgs.Verification.Signatures = 2 -> NuGet.Commands.VerifyArgs.Verification @@ -1090,6 +1092,7 @@ static NuGet.Commands.LockFileUtils.ExcludeItems(NuGet.ProjectModel.LockFileTarg static NuGet.Commands.LockFileUtils.ToDirectorySeparator(string path) -> string static NuGet.Commands.MSBuildProjectFactory.GetTargetPathForSourceFile(string sourcePath, string projectDirectory) -> string static NuGet.Commands.MSBuildProjectFactory.ProjectCreator(NuGet.Commands.PackArgs packArgs, string path) -> NuGet.Commands.IProjectFactory +static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(string projectFilePath, string targetFrameworks, string targetFramework, string targetFrameworkMoniker, string targetPlatformIdentifier, string targetPlatformVersion, string targetPlatformMinVersion) -> System.Collections.Generic.IEnumerable static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(string projectFilePath, string targetFrameworks, string targetFramework, string targetFrameworkMoniker, string targetPlatformIdentifier, string targetPlatformVersion, string targetPlatformMinVersion, bool isXnaWindowsPhoneProject, bool isManagementPackProject) -> System.Collections.Generic.IEnumerable diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt index f139652d4be..dec825d99a5 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt @@ -1,4 +1 @@ -NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList -NuGet.Commands.VerifyArgs.PackagePaths.set -> void -static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.PushRunner.Run(NuGet.Configuration.ISettings settings, NuGet.Configuration.IPackageSourceProvider sourceProvider, System.Collections.Generic.IList packagePaths, string source, string apiKey, string symbolSource, string symbolApiKey, int timeoutSeconds, bool disableBuffering, bool noSymbols, bool noServiceEndpoint, bool skipDuplicate, NuGet.Common.ILogger logger) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index 2772c63bf7b..ddb21dcb242 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -948,6 +948,8 @@ NuGet.Commands.VerifyArgs.Logger.get -> NuGet.Common.ILogger NuGet.Commands.VerifyArgs.Logger.set -> void NuGet.Commands.VerifyArgs.PackagePath.get -> string NuGet.Commands.VerifyArgs.PackagePath.set -> void +NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList +NuGet.Commands.VerifyArgs.PackagePaths.set -> void NuGet.Commands.VerifyArgs.Verification NuGet.Commands.VerifyArgs.Verification.All = 1 -> NuGet.Commands.VerifyArgs.Verification NuGet.Commands.VerifyArgs.Verification.Signatures = 2 -> NuGet.Commands.VerifyArgs.Verification @@ -1089,6 +1091,7 @@ static NuGet.Commands.LockFileUtils.ExcludeItems(NuGet.ProjectModel.LockFileTarg static NuGet.Commands.LockFileUtils.ToDirectorySeparator(string path) -> string static NuGet.Commands.MSBuildProjectFactory.GetTargetPathForSourceFile(string sourcePath, string projectDirectory) -> string static NuGet.Commands.MSBuildProjectFactory.ProjectCreator(NuGet.Commands.PackArgs packArgs, string path) -> NuGet.Commands.IProjectFactory +static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(string projectFilePath, string targetFrameworks, string targetFramework, string targetFrameworkMoniker, string targetPlatformIdentifier, string targetPlatformVersion, string targetPlatformMinVersion) -> System.Collections.Generic.IEnumerable static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(string projectFilePath, string targetFrameworks, string targetFramework, string targetFrameworkMoniker, string targetPlatformIdentifier, string targetPlatformVersion, string targetPlatformMinVersion, bool isXnaWindowsPhoneProject, bool isManagementPackProject) -> System.Collections.Generic.IEnumerable diff --git a/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index f139652d4be..dec825d99a5 100644 --- a/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Commands/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,4 +1 @@ -NuGet.Commands.VerifyArgs.PackagePaths.get -> System.Collections.Generic.IReadOnlyList -NuGet.Commands.VerifyArgs.PackagePaths.set -> void -static NuGet.Commands.MSBuildProjectFrameworkUtility.GetProjectFramework(string projectFilePath, string targetFrameworkMoniker, string targetPlatformMoniker, string targetPlatformMinVersion) -> NuGet.Frameworks.NuGetFramework static NuGet.Commands.PushRunner.Run(NuGet.Configuration.ISettings settings, NuGet.Configuration.IPackageSourceProvider sourceProvider, System.Collections.Generic.IList packagePaths, string source, string apiKey, string symbolSource, string symbolApiKey, int timeoutSeconds, bool disableBuffering, bool noSymbols, bool noServiceEndpoint, bool skipDuplicate, NuGet.Common.ILogger logger) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI.Unshipped.txt deleted file mode 100644 index d95caecce0d..00000000000 --- a/src/NuGet.Core/NuGet.Common/PublicAPI.Unshipped.txt +++ /dev/null @@ -1 +0,0 @@ -NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode \ No newline at end of file diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Shipped.txt index aeab9c9d3d1..c6935fa6ee4 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Shipped.txt @@ -170,6 +170,8 @@ NuGet.Common.NuGetLogCode.NU1006 = 1006 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1007 = 1007 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1008 = 1008 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1009 = 1009 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1100 = 1100 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1101 = 1101 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1102 = 1102 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt index 27e57301d51..18b158606de 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -1,4 +1,2 @@ -NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode -NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Shipped.txt index a74e789bbcc..20cd82a5f1b 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Shipped.txt @@ -170,6 +170,8 @@ NuGet.Common.NuGetLogCode.NU1006 = 1006 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1007 = 1007 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1008 = 1008 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1009 = 1009 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1100 = 1100 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1101 = 1101 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1102 = 1102 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt index 27e57301d51..18b158606de 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,4 +1,2 @@ -NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode -NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index a74e789bbcc..20cd82a5f1b 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -170,6 +170,8 @@ NuGet.Common.NuGetLogCode.NU1006 = 1006 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1007 = 1007 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1008 = 1008 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1009 = 1009 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1100 = 1100 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1101 = 1101 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1102 = 1102 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 27e57301d51..18b158606de 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,4 +1,2 @@ -NuGet.Common.NuGetLogCode.NU1010 = 1010 -> NuGet.Common.NuGetLogCode -NuGet.Common.NuGetLogCode.NU1011 = 1011 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Configuration/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Configuration/PublicAPI.Shipped.txt index f13d7617891..d432f5e7c31 100644 --- a/src/NuGet.Core/NuGet.Configuration/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Configuration/PublicAPI.Shipped.txt @@ -82,6 +82,8 @@ NuGet.Configuration.IPackageSourceProvider.RemovePackageSource(string name) -> v NuGet.Configuration.IPackageSourceProvider.SaveActivePackageSource(NuGet.Configuration.PackageSource source) -> void NuGet.Configuration.IPackageSourceProvider.SavePackageSources(System.Collections.Generic.IEnumerable sources) -> void NuGet.Configuration.IPackageSourceProvider.UpdatePackageSource(NuGet.Configuration.PackageSource source, bool updateCredentials, bool updateEnabled) -> void +NuGet.Configuration.IPackageSourceProvider2 +NuGet.Configuration.IPackageSourceProvider2.SavePackageSources(System.Collections.Generic.IEnumerable sources, NuGet.Configuration.PackageSourceUpdateOptions packageSourceUpdateOptions) -> void NuGet.Configuration.IProxyCache NuGet.Configuration.IProxyCache.Add(System.Net.IWebProxy proxy) -> void NuGet.Configuration.IProxyCache.GetProxy(System.Uri uri) -> System.Net.IWebProxy @@ -183,8 +185,13 @@ NuGet.Configuration.PackageSourceProvider.PackageSourcesChanged -> System.EventH NuGet.Configuration.PackageSourceProvider.RemovePackageSource(string name) -> void NuGet.Configuration.PackageSourceProvider.SaveActivePackageSource(NuGet.Configuration.PackageSource source) -> void NuGet.Configuration.PackageSourceProvider.SavePackageSources(System.Collections.Generic.IEnumerable sources) -> void +NuGet.Configuration.PackageSourceProvider.SavePackageSources(System.Collections.Generic.IEnumerable sources, NuGet.Configuration.PackageSourceUpdateOptions sourceUpdateSettings) -> void NuGet.Configuration.PackageSourceProvider.Settings.get -> NuGet.Configuration.ISettings NuGet.Configuration.PackageSourceProvider.UpdatePackageSource(NuGet.Configuration.PackageSource source, bool updateCredentials, bool updateEnabled) -> void +NuGet.Configuration.PackageSourceUpdateOptions +NuGet.Configuration.PackageSourceUpdateOptions.PackageSourceUpdateOptions(bool updateCredentials, bool updateEnabled) -> void +NuGet.Configuration.PackageSourceUpdateOptions.UpdateCredentials.get -> bool +NuGet.Configuration.PackageSourceUpdateOptions.UpdateEnabled.get -> bool NuGet.Configuration.ProxyCache NuGet.Configuration.ProxyCache.Add(System.Net.IWebProxy proxy) -> void NuGet.Configuration.ProxyCache.GetCredential(System.Uri proxyAddress, string authType) -> System.Net.NetworkCredential @@ -497,6 +504,7 @@ static readonly NuGet.Configuration.NuGetConstants.V1FeedUrl -> string static readonly NuGet.Configuration.NuGetConstants.V2LegacyFeedUrl -> string static readonly NuGet.Configuration.NuGetConstants.V2LegacyOfficialPackageSourceUrl -> string static readonly NuGet.Configuration.OwnersItem.OwnersListSeparator -> char +static readonly NuGet.Configuration.PackageSourceUpdateOptions.Default -> NuGet.Configuration.PackageSourceUpdateOptions static readonly NuGet.Configuration.Settings.DefaultSettingsFileName -> string static readonly NuGet.Configuration.Settings.OrderedSettingsFileNames -> string[] static readonly NuGet.Configuration.Settings.SupportedMachineWideConfigExtension -> string[] diff --git a/src/NuGet.Core/NuGet.Configuration/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Configuration/PublicAPI.Unshipped.txt index 1bb527fc1d5..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.Configuration/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Configuration/PublicAPI.Unshipped.txt @@ -1,8 +0,0 @@ -NuGet.Configuration.IPackageSourceProvider2 -NuGet.Configuration.IPackageSourceProvider2.SavePackageSources(System.Collections.Generic.IEnumerable sources, NuGet.Configuration.PackageSourceUpdateOptions packageSourceUpdateOptions) -> void -NuGet.Configuration.PackageSourceProvider.SavePackageSources(System.Collections.Generic.IEnumerable sources, NuGet.Configuration.PackageSourceUpdateOptions sourceUpdateSettings) -> void -NuGet.Configuration.PackageSourceUpdateOptions -NuGet.Configuration.PackageSourceUpdateOptions.PackageSourceUpdateOptions(bool updateCredentials, bool updateEnabled) -> void -NuGet.Configuration.PackageSourceUpdateOptions.UpdateCredentials.get -> bool -NuGet.Configuration.PackageSourceUpdateOptions.UpdateEnabled.get -> bool -static readonly NuGet.Configuration.PackageSourceUpdateOptions.Default -> NuGet.Configuration.PackageSourceUpdateOptions \ No newline at end of file diff --git a/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Shipped.txt index 6240b81b25e..cd9913edf10 100644 --- a/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Shipped.txt @@ -30,6 +30,9 @@ NuGet.DependencyResolver.GraphItem.IsCentralTransitive.get -> bool NuGet.DependencyResolver.GraphItem.IsCentralTransitive.set -> void NuGet.DependencyResolver.GraphItem.Key.get -> NuGet.LibraryModel.LibraryIdentity NuGet.DependencyResolver.GraphItem.Key.set -> void +NuGet.DependencyResolver.GraphItemKeyComparer +NuGet.DependencyResolver.GraphItemKeyComparer.Equals(NuGet.DependencyResolver.GraphItem x, NuGet.DependencyResolver.GraphItem y) -> bool +NuGet.DependencyResolver.GraphItemKeyComparer.GetHashCode(NuGet.DependencyResolver.GraphItem obj) -> int NuGet.DependencyResolver.GraphNode NuGet.DependencyResolver.GraphNode.Disposition.get -> NuGet.DependencyResolver.Disposition NuGet.DependencyResolver.GraphNode.Disposition.set -> void @@ -134,6 +137,7 @@ override NuGet.DependencyResolver.LockFileCacheKey.GetHashCode() -> int override NuGet.DependencyResolver.LockFileCacheKey.ToString() -> string override NuGet.DependencyResolver.RemoteMatch.Equals(object obj) -> bool override NuGet.DependencyResolver.RemoteMatch.GetHashCode() -> int +static NuGet.DependencyResolver.GraphItemKeyComparer.Instance.get -> NuGet.DependencyResolver.GraphItemKeyComparer static NuGet.DependencyResolver.GraphOperations.Analyze(this NuGet.DependencyResolver.GraphNode root) -> NuGet.DependencyResolver.AnalyzeResult static NuGet.DependencyResolver.GraphOperations.Dump(this NuGet.DependencyResolver.GraphNode root, System.Action write) -> void static NuGet.DependencyResolver.GraphOperations.ForEach(this NuGet.DependencyResolver.GraphNode root, System.Action, TContext> visitor, TContext context) -> void diff --git a/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Unshipped.txt index 85003f71710..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.DependencyResolver.Core/PublicAPI.Unshipped.txt @@ -1,4 +0,0 @@ -NuGet.DependencyResolver.GraphItemKeyComparer -NuGet.DependencyResolver.GraphItemKeyComparer.Equals(NuGet.DependencyResolver.GraphItem x, NuGet.DependencyResolver.GraphItem y) -> bool -NuGet.DependencyResolver.GraphItemKeyComparer.GetHashCode(NuGet.DependencyResolver.GraphItem obj) -> int -static NuGet.DependencyResolver.GraphItemKeyComparer.Instance.get -> NuGet.DependencyResolver.GraphItemKeyComparer \ No newline at end of file diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Shipped.txt index 4be07e87c14..4483f744a0b 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Shipped.txt @@ -73,6 +73,7 @@ NuGet.Frameworks.FrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framewo NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetIdentifier(string framework, out string identifier) -> bool +NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -151,6 +152,7 @@ NuGet.Frameworks.IFrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framew NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetIdentifier(string identifierShortName, out string identifier) -> bool +NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -174,6 +176,7 @@ NuGet.Frameworks.IPortableFrameworkMappings.ProfileOptionalFrameworks.get -> Sys NuGet.Frameworks.NuGetFramework NuGet.Frameworks.NuGetFramework.AllFrameworkVersions.get -> bool NuGet.Frameworks.NuGetFramework.DotNetFrameworkName.get -> string +NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string NuGet.Frameworks.NuGetFramework.Equals(NuGet.Frameworks.NuGetFramework other) -> bool NuGet.Frameworks.NuGetFramework.Framework.get -> string NuGet.Frameworks.NuGetFramework.GetDotNetFrameworkName(NuGet.Frameworks.IFrameworkNameProvider mappings) -> string @@ -189,8 +192,8 @@ NuGet.Frameworks.NuGetFramework.IsUnsupported.get -> bool NuGet.Frameworks.NuGetFramework.NuGetFramework(NuGet.Frameworks.NuGetFramework framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework, System.Version version) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string frameworkProfile) -> void +NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.Platform.get -> string NuGet.Frameworks.NuGetFramework.PlatformVersion.get -> System.Version NuGet.Frameworks.NuGetFramework.Profile.get -> string @@ -278,6 +281,7 @@ static NuGet.Frameworks.FrameworkRuntimePair.GetName(NuGet.Frameworks.NuGetFrame static NuGet.Frameworks.FrameworkRuntimePair.GetTargetGraphName(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> string static NuGet.Frameworks.NuGetFramework.Parse(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.Parse(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework +static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFrameworkName(string frameworkName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Unshipped.txt index 59e10bde008..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net40/PublicAPI.Unshipped.txt @@ -1,4 +0,0 @@ -NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string -static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt index 1bc79238776..aa2ebd6c2fc 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt @@ -73,6 +73,7 @@ NuGet.Frameworks.FrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framewo NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetIdentifier(string framework, out string identifier) -> bool +NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -151,6 +152,7 @@ NuGet.Frameworks.IFrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framew NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetIdentifier(string identifierShortName, out string identifier) -> bool +NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -174,6 +176,7 @@ NuGet.Frameworks.IPortableFrameworkMappings.ProfileOptionalFrameworks.get -> Sys NuGet.Frameworks.NuGetFramework NuGet.Frameworks.NuGetFramework.AllFrameworkVersions.get -> bool NuGet.Frameworks.NuGetFramework.DotNetFrameworkName.get -> string +NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string NuGet.Frameworks.NuGetFramework.Equals(NuGet.Frameworks.NuGetFramework other) -> bool NuGet.Frameworks.NuGetFramework.Framework.get -> string NuGet.Frameworks.NuGetFramework.GetDotNetFrameworkName(NuGet.Frameworks.IFrameworkNameProvider mappings) -> string @@ -189,6 +192,7 @@ NuGet.Frameworks.NuGetFramework.IsUnsupported.get -> bool NuGet.Frameworks.NuGetFramework.NuGetFramework(NuGet.Frameworks.NuGetFramework framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework, System.Version version) -> void +NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string frameworkProfile) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.Platform.get -> string NuGet.Frameworks.NuGetFramework.PlatformVersion.get -> System.Version @@ -277,6 +281,7 @@ static NuGet.Frameworks.FrameworkRuntimePair.GetName(NuGet.Frameworks.NuGetFrame static NuGet.Frameworks.FrameworkRuntimePair.GetTargetGraphName(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> string static NuGet.Frameworks.NuGetFramework.Parse(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.Parse(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework +static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFrameworkName(string frameworkName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt index 6efc8c0d6f2..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -1,5 +0,0 @@ -NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string -NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string frameworkProfile) -> void -static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Shipped.txt index 0845b7e41ca..aa2ebd6c2fc 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Shipped.txt @@ -73,6 +73,7 @@ NuGet.Frameworks.FrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framewo NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetIdentifier(string framework, out string identifier) -> bool +NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -151,6 +152,7 @@ NuGet.Frameworks.IFrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framew NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetIdentifier(string identifierShortName, out string identifier) -> bool +NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -174,6 +176,7 @@ NuGet.Frameworks.IPortableFrameworkMappings.ProfileOptionalFrameworks.get -> Sys NuGet.Frameworks.NuGetFramework NuGet.Frameworks.NuGetFramework.AllFrameworkVersions.get -> bool NuGet.Frameworks.NuGetFramework.DotNetFrameworkName.get -> string +NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string NuGet.Frameworks.NuGetFramework.Equals(NuGet.Frameworks.NuGetFramework other) -> bool NuGet.Frameworks.NuGetFramework.Framework.get -> string NuGet.Frameworks.NuGetFramework.GetDotNetFrameworkName(NuGet.Frameworks.IFrameworkNameProvider mappings) -> string @@ -189,8 +192,8 @@ NuGet.Frameworks.NuGetFramework.IsUnsupported.get -> bool NuGet.Frameworks.NuGetFramework.NuGetFramework(NuGet.Frameworks.NuGetFramework framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework, System.Version version) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string frameworkProfile) -> void +NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.Platform.get -> string NuGet.Frameworks.NuGetFramework.PlatformVersion.get -> System.Version NuGet.Frameworks.NuGetFramework.Profile.get -> string @@ -278,6 +281,7 @@ static NuGet.Frameworks.FrameworkRuntimePair.GetName(NuGet.Frameworks.NuGetFrame static NuGet.Frameworks.FrameworkRuntimePair.GetTargetGraphName(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> string static NuGet.Frameworks.NuGetFramework.Parse(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.Parse(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework +static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFrameworkName(string frameworkName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Unshipped.txt index 59e10bde008..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,4 +0,0 @@ -NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string -static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index 0845b7e41ca..aa2ebd6c2fc 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -73,6 +73,7 @@ NuGet.Frameworks.FrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framewo NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetIdentifier(string framework, out string identifier) -> bool +NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -151,6 +152,7 @@ NuGet.Frameworks.IFrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Framew NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetIdentifier(string identifierShortName, out string identifier) -> bool +NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool @@ -174,6 +176,7 @@ NuGet.Frameworks.IPortableFrameworkMappings.ProfileOptionalFrameworks.get -> Sys NuGet.Frameworks.NuGetFramework NuGet.Frameworks.NuGetFramework.AllFrameworkVersions.get -> bool NuGet.Frameworks.NuGetFramework.DotNetFrameworkName.get -> string +NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string NuGet.Frameworks.NuGetFramework.Equals(NuGet.Frameworks.NuGetFramework other) -> bool NuGet.Frameworks.NuGetFramework.Framework.get -> string NuGet.Frameworks.NuGetFramework.GetDotNetFrameworkName(NuGet.Frameworks.IFrameworkNameProvider mappings) -> string @@ -189,8 +192,8 @@ NuGet.Frameworks.NuGetFramework.IsUnsupported.get -> bool NuGet.Frameworks.NuGetFramework.NuGetFramework(NuGet.Frameworks.NuGetFramework framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework, System.Version version) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string frameworkProfile) -> void +NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void NuGet.Frameworks.NuGetFramework.Platform.get -> string NuGet.Frameworks.NuGetFramework.PlatformVersion.get -> System.Version NuGet.Frameworks.NuGetFramework.Profile.get -> string @@ -278,6 +281,7 @@ static NuGet.Frameworks.FrameworkRuntimePair.GetName(NuGet.Frameworks.NuGetFrame static NuGet.Frameworks.FrameworkRuntimePair.GetTargetGraphName(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> string static NuGet.Frameworks.NuGetFramework.Parse(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.Parse(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework +static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework static NuGet.Frameworks.NuGetFramework.ParseFrameworkName(string frameworkName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 59e10bde008..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,4 +0,0 @@ -NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string -static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework diff --git a/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Shipped.txt index 0dc76a5014e..2560dbdff32 100644 --- a/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Shipped.txt @@ -149,6 +149,7 @@ override NuGet.LibraryModel.CentralPackageVersion.ToString() -> string override NuGet.LibraryModel.DownloadDependency.Equals(object obj) -> bool override NuGet.LibraryModel.DownloadDependency.GetHashCode() -> int override NuGet.LibraryModel.DownloadDependency.ToString() -> string +override NuGet.LibraryModel.FrameworkDependency.GetHashCode() -> int override NuGet.LibraryModel.Library.ToString() -> string override NuGet.LibraryModel.LibraryDependency.Equals(object obj) -> bool override NuGet.LibraryModel.LibraryDependency.GetHashCode() -> int diff --git a/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Unshipped.txt index cf1621e4479..6049534ea3e 100644 --- a/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.LibraryModel/PublicAPI.Unshipped.txt @@ -1,2 +1 @@ -override NuGet.LibraryModel.FrameworkDependency.GetHashCode() -> int -static NuGet.LibraryModel.LibraryDependency.ApplyCentralVersionInformation(System.Collections.Generic.IList packageReferences, System.Collections.Generic.IDictionary centralPackageVersions) -> void \ No newline at end of file +static NuGet.LibraryModel.LibraryDependency.ApplyCentralVersionInformation(System.Collections.Generic.IList packageReferences, System.Collections.Generic.IDictionary centralPackageVersions) -> void diff --git a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt index 42565e41c4e..3282a8caac5 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt @@ -182,6 +182,7 @@ NuGet.PackageManagement.NuGetPackageManager.PreviewInstallPackageAsync(NuGet.Pro NuGet.PackageManagement.NuGetPackageManager.PreviewInstallPackageAsync(NuGet.ProjectManagement.NuGetProject nuGetProject, NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Collections.Generic.IEnumerable primarySources, System.Collections.Generic.IEnumerable secondarySources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.PackageManagement.NuGetPackageManager.PreviewInstallPackageAsync(NuGet.ProjectManagement.NuGetProject nuGetProject, string packageId, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, NuGet.Protocol.Core.Types.SourceRepository primarySourceRepository, System.Collections.Generic.IEnumerable secondarySources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.PackageManagement.NuGetPackageManager.PreviewInstallPackageAsync(NuGet.ProjectManagement.NuGetProject nuGetProject, string packageId, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Collections.Generic.IEnumerable primarySources, System.Collections.Generic.IEnumerable secondarySources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> +NuGet.PackageManagement.NuGetPackageManager.PreviewProjectsInstallPackageAsync(System.Collections.Generic.IReadOnlyCollection nuGetProjects, NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Collections.Generic.IReadOnlyCollection activeSources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.PackageManagement.NuGetPackageManager.PreviewUninstallPackageAsync(NuGet.ProjectManagement.NuGetProject nuGetProject, NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.PackageManagement.UninstallationContext uninstallationContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.PackageManagement.NuGetPackageManager.PreviewUninstallPackageAsync(NuGet.ProjectManagement.NuGetProject nuGetProject, string packageId, NuGet.PackageManagement.UninstallationContext uninstallationContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.PackageManagement.NuGetPackageManager.PreviewUpdatePackagesAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, System.Collections.Generic.IEnumerable nuGetProjects, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Collections.Generic.IEnumerable primarySources, System.Collections.Generic.IEnumerable secondarySources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> @@ -363,6 +364,7 @@ NuGet.ProjectManagement.BuildIntegratedInstallationContext.SuppressParent.set -> NuGet.ProjectManagement.BuildIntegratedInstallationContext.UnsuccessfulFrameworks.get -> System.Collections.Generic.IEnumerable NuGet.ProjectManagement.BuildIntegratedPackageReference NuGet.ProjectManagement.BuildIntegratedPackageReference.BuildIntegratedPackageReference(NuGet.LibraryModel.LibraryDependency dependency, NuGet.Frameworks.NuGetFramework projectFramework) -> void +NuGet.ProjectManagement.BuildIntegratedPackageReference.BuildIntegratedPackageReference(NuGet.LibraryModel.LibraryDependency dependency, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Packaging.Core.PackageIdentity installedVersion) -> void NuGet.ProjectManagement.BuildIntegratedPackageReference.Dependency.get -> NuGet.LibraryModel.LibraryDependency NuGet.ProjectManagement.BuildIntegratedProjectUtility NuGet.ProjectManagement.CollectionsUtility @@ -559,6 +561,7 @@ NuGet.ProjectManagement.MessageLevel.Debug = 2 -> NuGet.ProjectManagement.Messag NuGet.ProjectManagement.MessageLevel.Error = 3 -> NuGet.ProjectManagement.MessageLevel NuGet.ProjectManagement.MessageLevel.Info = 0 -> NuGet.ProjectManagement.MessageLevel NuGet.ProjectManagement.MessageLevel.Warning = 1 -> NuGet.ProjectManagement.MessageLevel +NuGet.ProjectManagement.MessageLevelExtensions NuGet.ProjectManagement.NuGetActionType NuGet.ProjectManagement.NuGetActionType.Install = 0 -> NuGet.ProjectManagement.NuGetActionType NuGet.ProjectManagement.NuGetActionType.Reinstall = 2 -> NuGet.ProjectManagement.NuGetActionType @@ -688,10 +691,14 @@ const NuGet.ProjectManagement.ProjectBuildProperties.RuntimeIdentifierGraphPath const NuGet.ProjectManagement.ProjectBuildProperties.RuntimeIdentifiers = "RuntimeIdentifiers" -> string const NuGet.ProjectManagement.ProjectBuildProperties.RuntimeSupports = "RuntimeSupports" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TargetFramework = "TargetFramework" -> string +const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkIdentifier = "TargetFrameworkIdentifier" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkMoniker = "TargetFrameworkMoniker" -> string +const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkProfile = "TargetFrameworkProfile" -> string +const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkVersion = "TargetFrameworkVersion" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworks = "TargetFrameworks" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TargetPlatformIdentifier = "TargetPlatformIdentifier" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TargetPlatformMinVersion = "TargetPlatformMinVersion" -> string +const NuGet.ProjectManagement.ProjectBuildProperties.TargetPlatformMoniker = "TargetPlatformMoniker" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TargetPlatformVersion = "TargetPlatformVersion" -> string const NuGet.ProjectManagement.ProjectBuildProperties.TreatWarningsAsErrors = "TreatWarningsAsErrors" -> string const NuGet.ProjectManagement.ProjectBuildProperties.Version = "Version" -> string @@ -846,6 +853,7 @@ static NuGet.ProjectManagement.JsonConfigUtility.RemoveDependency(Newtonsoft.Jso static NuGet.ProjectManagement.MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(NuGet.Frameworks.NuGetFramework projectTargetFramework, System.Collections.Generic.IEnumerable itemGroups) -> NuGet.Packaging.FrameworkSpecificGroup static NuGet.ProjectManagement.MSBuildNuGetProjectSystemUtility.IsValid(NuGet.Packaging.FrameworkSpecificGroup frameworkSpecificGroup) -> bool static NuGet.ProjectManagement.MSBuildNuGetProjectSystemUtility.Normalize(NuGet.Packaging.FrameworkSpecificGroup group) -> NuGet.Packaging.FrameworkSpecificGroup +static NuGet.ProjectManagement.MessageLevelExtensions.ToLogLevel(this NuGet.ProjectManagement.MessageLevel messageLevel) -> NuGet.Common.LogLevel static NuGet.ProjectManagement.NuGetProject.GetUniqueNameOrName(NuGet.ProjectManagement.NuGetProject nuGetProject) -> string static NuGet.ProjectManagement.SourceControlUtility.DisableSourceControlMode(NuGet.Configuration.ISettings settings) -> void static NuGet.ProjectManagement.SourceControlUtility.GetSourceControlManager(NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext) -> NuGet.ProjectManagement.SourceControlManager diff --git a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt index 6c6d7def642..c83933042c9 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Unshipped.txt @@ -1,9 +1 @@ -NuGet.PackageManagement.NuGetPackageManager.PreviewProjectsInstallPackageAsync(System.Collections.Generic.IReadOnlyCollection nuGetProjects, NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.PackageManagement.ResolutionContext resolutionContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Collections.Generic.IReadOnlyCollection activeSources, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> NuGet.PackageManagement.NuGetPackageManager.PreviewProjectsUninstallPackageAsync(System.Collections.Generic.IReadOnlyCollection nuGetProjects, string packageId, NuGet.PackageManagement.UninstallationContext uninstallationContext, NuGet.ProjectManagement.INuGetProjectContext nuGetProjectContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> -NuGet.ProjectManagement.BuildIntegratedPackageReference.BuildIntegratedPackageReference(NuGet.LibraryModel.LibraryDependency dependency, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Packaging.Core.PackageIdentity installedVersion) -> void -NuGet.ProjectManagement.MessageLevelExtensions -const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkIdentifier = "TargetFrameworkIdentifier" -> string -const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkProfile = "TargetFrameworkProfile" -> string -const NuGet.ProjectManagement.ProjectBuildProperties.TargetFrameworkVersion = "TargetFrameworkVersion" -> string -const NuGet.ProjectManagement.ProjectBuildProperties.TargetPlatformMoniker = "TargetPlatformMoniker" -> string -static NuGet.ProjectManagement.MessageLevelExtensions.ToLogLevel(this NuGet.ProjectManagement.MessageLevel messageLevel) -> NuGet.Common.LogLevel diff --git a/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Shipped.txt index 9e1d85c8b74..455bff5ba7e 100644 --- a/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Shipped.txt @@ -72,6 +72,7 @@ NuGet.ProjectModel.DependencyGraphSpec.Json.get -> Newtonsoft.Json.Linq.JObject NuGet.ProjectModel.DependencyGraphSpec.Projects.get -> System.Collections.Generic.IReadOnlyList NuGet.ProjectModel.DependencyGraphSpec.Restore.get -> System.Collections.Generic.IReadOnlyList NuGet.ProjectModel.DependencyGraphSpec.Save(string path) -> void +NuGet.ProjectModel.DependencyGraphSpec.WithPackageSpecs(System.Collections.Generic.IEnumerable packageSpecs) -> NuGet.ProjectModel.DependencyGraphSpec NuGet.ProjectModel.DependencyGraphSpec.WithProjectClosure(string projectUniqueName) -> NuGet.ProjectModel.DependencyGraphSpec NuGet.ProjectModel.DependencyGraphSpec.WithReplacedSpec(NuGet.ProjectModel.PackageSpec project) -> NuGet.ProjectModel.DependencyGraphSpec NuGet.ProjectModel.DependencyGraphSpec.WithoutRestores() -> NuGet.ProjectModel.DependencyGraphSpec @@ -145,6 +146,7 @@ NuGet.ProjectModel.LockFile.CentralTransitiveDependencyGroups.set -> void NuGet.ProjectModel.LockFile.Equals(NuGet.ProjectModel.LockFile other) -> bool NuGet.ProjectModel.LockFile.GetLibrary(string name, NuGet.Versioning.NuGetVersion version) -> NuGet.ProjectModel.LockFileLibrary NuGet.ProjectModel.LockFile.GetTarget(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> NuGet.ProjectModel.LockFileTarget +NuGet.ProjectModel.LockFile.GetTarget(string frameworkAlias, string runtimeIdentifier) -> NuGet.ProjectModel.LockFileTarget NuGet.ProjectModel.LockFile.IsValidForPackageSpec(NuGet.ProjectModel.PackageSpec spec) -> bool NuGet.ProjectModel.LockFile.IsValidForPackageSpec(NuGet.ProjectModel.PackageSpec spec, int requestLockFileVersion) -> bool NuGet.ProjectModel.LockFile.Libraries.get -> System.Collections.Generic.IList @@ -488,6 +490,8 @@ NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.ProjectReferences.get -> NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.ProjectReferences.set -> void NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.ProjectRestoreMetadataFrameworkInfo() -> void NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.ProjectRestoreMetadataFrameworkInfo(NuGet.Frameworks.NuGetFramework frameworkName) -> void +NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.TargetAlias.get -> string +NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.TargetAlias.set -> void NuGet.ProjectModel.ProjectRestoreReference NuGet.ProjectModel.ProjectRestoreReference.Clone() -> NuGet.ProjectModel.ProjectRestoreReference NuGet.ProjectModel.ProjectRestoreReference.Equals(NuGet.ProjectModel.ProjectRestoreReference other) -> bool @@ -540,6 +544,8 @@ NuGet.ProjectModel.TargetFrameworkInformation.Imports.get -> System.Collections. NuGet.ProjectModel.TargetFrameworkInformation.Imports.set -> void NuGet.ProjectModel.TargetFrameworkInformation.RuntimeIdentifierGraphPath.get -> string NuGet.ProjectModel.TargetFrameworkInformation.RuntimeIdentifierGraphPath.set -> void +NuGet.ProjectModel.TargetFrameworkInformation.TargetAlias.get -> string +NuGet.ProjectModel.TargetFrameworkInformation.TargetAlias.set -> void NuGet.ProjectModel.TargetFrameworkInformation.TargetFrameworkInformation() -> void NuGet.ProjectModel.TargetFrameworkInformation.Warn.get -> bool NuGet.ProjectModel.TargetFrameworkInformation.Warn.set -> void diff --git a/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Unshipped.txt index 48b6576908b..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.ProjectModel/PublicAPI.Unshipped.txt @@ -1,6 +0,0 @@ -NuGet.ProjectModel.DependencyGraphSpec.WithPackageSpecs(System.Collections.Generic.IEnumerable packageSpecs) -> NuGet.ProjectModel.DependencyGraphSpec -NuGet.ProjectModel.LockFile.GetTarget(string frameworkAlias, string runtimeIdentifier) -> NuGet.ProjectModel.LockFileTarget -NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.TargetAlias.get -> string -NuGet.ProjectModel.ProjectRestoreMetadataFrameworkInfo.TargetAlias.set -> void -NuGet.ProjectModel.TargetFrameworkInformation.TargetAlias.get -> string -NuGet.ProjectModel.TargetFrameworkInformation.TargetAlias.set -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt index 5a6084c2d2c..4a9523abb5a 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt @@ -98,6 +98,7 @@ NuGet.Protocol.Core.Types.IPackageSearchMetadata.RequireLicenseAcceptance.get -> NuGet.Protocol.Core.Types.IPackageSearchMetadata.Summary.get -> string NuGet.Protocol.Core.Types.IPackageSearchMetadata.Tags.get -> string NuGet.Protocol.Core.Types.IPackageSearchMetadata.Title.get -> string +NuGet.Protocol.Core.Types.IPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.Core.Types.ISourceRepositoryProvider NuGet.Protocol.Core.Types.ISourceRepositoryProvider.CreateRepository(NuGet.Configuration.PackageSource source) -> NuGet.Protocol.Core.Types.SourceRepository NuGet.Protocol.Core.Types.ISourceRepositoryProvider.CreateRepository(NuGet.Configuration.PackageSource source, NuGet.Protocol.FeedType type) -> NuGet.Protocol.Core.Types.SourceRepository @@ -196,6 +197,8 @@ NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetada NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Tags.set -> void NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Title.get -> string NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Title.set -> void +NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable +NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.set -> void NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.WithDeprecation(NuGet.Common.AsyncLazy lazyDeprecationFactory) -> NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.WithVersions(NuGet.Common.AsyncLazy> lazyVersionsFactory) -> NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder NuGet.Protocol.Core.Types.PackageSearchMetadataExtensions @@ -630,6 +633,7 @@ NuGet.Protocol.LocalPackageSearchMetadata.RequireLicenseAcceptance.get -> bool NuGet.Protocol.LocalPackageSearchMetadata.Summary.get -> string NuGet.Protocol.LocalPackageSearchMetadata.Tags.get -> string NuGet.Protocol.LocalPackageSearchMetadata.Title.get -> string +NuGet.Protocol.LocalPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.LocalPackageSearchResource NuGet.Protocol.LocalPackageSearchResource.LocalPackageSearchResource(NuGet.Protocol.FindLocalPackagesResource localResource) -> void NuGet.Protocol.LocalPackageSearchResourceProvider @@ -737,6 +741,7 @@ NuGet.Protocol.PackageSearchMetadata.Summary.get -> string NuGet.Protocol.PackageSearchMetadata.Tags.get -> string NuGet.Protocol.PackageSearchMetadata.Title.get -> string NuGet.Protocol.PackageSearchMetadata.Version.get -> NuGet.Versioning.NuGetVersion +NuGet.Protocol.PackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.PackageSearchMetadataRegistration NuGet.Protocol.PackageSearchMetadataRegistration.CatalogUri.get -> System.Uri NuGet.Protocol.PackageSearchMetadataRegistration.PackageSearchMetadataRegistration() -> void @@ -769,6 +774,7 @@ NuGet.Protocol.PackageSearchMetadataV2Feed.Summary.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Tags.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Title.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Version.get -> NuGet.Versioning.NuGetVersion +NuGet.Protocol.PackageSearchMetadataV2Feed.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.PackageSearchResourceV2Feed NuGet.Protocol.PackageSearchResourceV2Feed.PackageSearchResourceV2Feed(NuGet.Protocol.HttpSourceResource httpSourceResource, string baseAddress, NuGet.Configuration.PackageSource packageSource) -> void NuGet.Protocol.PackageSearchResourceV2FeedProvider @@ -781,6 +787,10 @@ NuGet.Protocol.PackageUpdateResourceV2Provider NuGet.Protocol.PackageUpdateResourceV2Provider.PackageUpdateResourceV2Provider() -> void NuGet.Protocol.PackageUpdateResourceV3Provider NuGet.Protocol.PackageUpdateResourceV3Provider.PackageUpdateResourceV3Provider() -> void +NuGet.Protocol.PackageVulnerabilityMetadata +NuGet.Protocol.PackageVulnerabilityMetadata.AdvisoryUrl.get -> System.Uri +NuGet.Protocol.PackageVulnerabilityMetadata.PackageVulnerabilityMetadata() -> void +NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int NuGet.Protocol.PluginFindPackageByIdResourceProvider NuGet.Protocol.PluginFindPackageByIdResourceProvider.PluginFindPackageByIdResourceProvider() -> void NuGet.Protocol.Plugins.AutomaticProgressReporter @@ -1517,6 +1527,7 @@ const NuGet.Protocol.Core.Types.NuGetResourceProviderPositions.First = "First" - const NuGet.Protocol.Core.Types.NuGetResourceProviderPositions.Last = "Last" -> string const NuGet.Protocol.Core.Types.NuGetTestMode.NuGetTestClientName = "NuGet Test Client" -> string const NuGet.Protocol.JsonExtensions.JsonSerializationMaxDepth = 512 -> int +const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string const NuGet.Protocol.JsonProperties.AllRepositorySigned = "allRepositorySigned" -> string const NuGet.Protocol.JsonProperties.AlternatePackage = "alternatePackage" -> string const NuGet.Protocol.JsonProperties.Authors = "authors" -> string @@ -1551,6 +1562,7 @@ const NuGet.Protocol.JsonProperties.ProjectUrl = "projectUrl" -> string const NuGet.Protocol.JsonProperties.Published = "published" -> string const NuGet.Protocol.JsonProperties.Range = "range" -> string const NuGet.Protocol.JsonProperties.RequireLicenseAcceptance = "requireLicenseAcceptance" -> string +const NuGet.Protocol.JsonProperties.Severity = "severity" -> string const NuGet.Protocol.JsonProperties.SigningCertificates = "signingCertificates" -> string const NuGet.Protocol.JsonProperties.Subject = "subject" -> string const NuGet.Protocol.JsonProperties.SubjectId = "@id" -> string @@ -1561,6 +1573,7 @@ const NuGet.Protocol.JsonProperties.Title = "title" -> string const NuGet.Protocol.JsonProperties.Type = "@type" -> string const NuGet.Protocol.JsonProperties.Version = "version" -> string const NuGet.Protocol.JsonProperties.Versions = "versions" -> string +const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string const NuGet.Protocol.StsAuthenticationHandler.STSEndPointHeader = "X-NuGet-STS-EndPoint" -> string const NuGet.Protocol.StsAuthenticationHandler.STSRealmHeader = "X-NuGet-STS-Realm" -> string const NuGet.Protocol.StsAuthenticationHandler.STSTokenHeader = "X-NuGet-STS-Token" -> string diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index d5fdde29f64..b28a243f453 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,14 +1 @@ -NuGet.Protocol.Core.Types.IPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.set -> void -NuGet.Protocol.LocalPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageSearchMetadataV2Feed.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageVulnerabilityMetadata -NuGet.Protocol.PackageVulnerabilityMetadata.PackageVulnerabilityMetadata() -> void -NuGet.Protocol.PackageVulnerabilityMetadata.AdvisoryUrl.get -> System.Uri -NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int -const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string -const NuGet.Protocol.JsonProperties.Severity = "severity" -> string -const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string NuGet.Protocol.Core.Types.PackageUpdateResource.Push(System.Collections.Generic.IList packagePaths, string symbolSource, int timeoutInSecond, bool disableBuffering, System.Func getApiKey, System.Func getSymbolApiKey, bool noServiceEndpoint, bool skipDuplicate, NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, NuGet.Common.ILogger log) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt index 02fc54c2089..e1dec7248da 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt @@ -98,6 +98,7 @@ NuGet.Protocol.Core.Types.IPackageSearchMetadata.RequireLicenseAcceptance.get -> NuGet.Protocol.Core.Types.IPackageSearchMetadata.Summary.get -> string NuGet.Protocol.Core.Types.IPackageSearchMetadata.Tags.get -> string NuGet.Protocol.Core.Types.IPackageSearchMetadata.Title.get -> string +NuGet.Protocol.Core.Types.IPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.Core.Types.ISourceRepositoryProvider NuGet.Protocol.Core.Types.ISourceRepositoryProvider.CreateRepository(NuGet.Configuration.PackageSource source) -> NuGet.Protocol.Core.Types.SourceRepository NuGet.Protocol.Core.Types.ISourceRepositoryProvider.CreateRepository(NuGet.Configuration.PackageSource source, NuGet.Protocol.FeedType type) -> NuGet.Protocol.Core.Types.SourceRepository @@ -196,6 +197,8 @@ NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetada NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Tags.set -> void NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Title.get -> string NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Title.set -> void +NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable +NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.set -> void NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.WithDeprecation(NuGet.Common.AsyncLazy lazyDeprecationFactory) -> NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.WithVersions(NuGet.Common.AsyncLazy> lazyVersionsFactory) -> NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder NuGet.Protocol.Core.Types.PackageSearchMetadataExtensions @@ -630,6 +633,7 @@ NuGet.Protocol.LocalPackageSearchMetadata.RequireLicenseAcceptance.get -> bool NuGet.Protocol.LocalPackageSearchMetadata.Summary.get -> string NuGet.Protocol.LocalPackageSearchMetadata.Tags.get -> string NuGet.Protocol.LocalPackageSearchMetadata.Title.get -> string +NuGet.Protocol.LocalPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.LocalPackageSearchResource NuGet.Protocol.LocalPackageSearchResource.LocalPackageSearchResource(NuGet.Protocol.FindLocalPackagesResource localResource) -> void NuGet.Protocol.LocalPackageSearchResourceProvider @@ -737,6 +741,7 @@ NuGet.Protocol.PackageSearchMetadata.Summary.get -> string NuGet.Protocol.PackageSearchMetadata.Tags.get -> string NuGet.Protocol.PackageSearchMetadata.Title.get -> string NuGet.Protocol.PackageSearchMetadata.Version.get -> NuGet.Versioning.NuGetVersion +NuGet.Protocol.PackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.PackageSearchMetadataRegistration NuGet.Protocol.PackageSearchMetadataRegistration.CatalogUri.get -> System.Uri NuGet.Protocol.PackageSearchMetadataRegistration.PackageSearchMetadataRegistration() -> void @@ -769,6 +774,7 @@ NuGet.Protocol.PackageSearchMetadataV2Feed.Summary.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Tags.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Title.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Version.get -> NuGet.Versioning.NuGetVersion +NuGet.Protocol.PackageSearchMetadataV2Feed.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.PackageSearchResourceV2Feed NuGet.Protocol.PackageSearchResourceV2Feed.PackageSearchResourceV2Feed(NuGet.Protocol.HttpSourceResource httpSourceResource, string baseAddress, NuGet.Configuration.PackageSource packageSource) -> void NuGet.Protocol.PackageSearchResourceV2FeedProvider @@ -781,6 +787,10 @@ NuGet.Protocol.PackageUpdateResourceV2Provider NuGet.Protocol.PackageUpdateResourceV2Provider.PackageUpdateResourceV2Provider() -> void NuGet.Protocol.PackageUpdateResourceV3Provider NuGet.Protocol.PackageUpdateResourceV3Provider.PackageUpdateResourceV3Provider() -> void +NuGet.Protocol.PackageVulnerabilityMetadata +NuGet.Protocol.PackageVulnerabilityMetadata.AdvisoryUrl.get -> System.Uri +NuGet.Protocol.PackageVulnerabilityMetadata.PackageVulnerabilityMetadata() -> void +NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int NuGet.Protocol.PluginFindPackageByIdResourceProvider NuGet.Protocol.PluginFindPackageByIdResourceProvider.PluginFindPackageByIdResourceProvider() -> void NuGet.Protocol.Plugins.AutomaticProgressReporter @@ -1513,6 +1523,7 @@ const NuGet.Protocol.Core.Types.NuGetResourceProviderPositions.First = "First" - const NuGet.Protocol.Core.Types.NuGetResourceProviderPositions.Last = "Last" -> string const NuGet.Protocol.Core.Types.NuGetTestMode.NuGetTestClientName = "NuGet Test Client" -> string const NuGet.Protocol.JsonExtensions.JsonSerializationMaxDepth = 512 -> int +const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string const NuGet.Protocol.JsonProperties.AllRepositorySigned = "allRepositorySigned" -> string const NuGet.Protocol.JsonProperties.AlternatePackage = "alternatePackage" -> string const NuGet.Protocol.JsonProperties.Authors = "authors" -> string @@ -1547,6 +1558,7 @@ const NuGet.Protocol.JsonProperties.ProjectUrl = "projectUrl" -> string const NuGet.Protocol.JsonProperties.Published = "published" -> string const NuGet.Protocol.JsonProperties.Range = "range" -> string const NuGet.Protocol.JsonProperties.RequireLicenseAcceptance = "requireLicenseAcceptance" -> string +const NuGet.Protocol.JsonProperties.Severity = "severity" -> string const NuGet.Protocol.JsonProperties.SigningCertificates = "signingCertificates" -> string const NuGet.Protocol.JsonProperties.Subject = "subject" -> string const NuGet.Protocol.JsonProperties.SubjectId = "@id" -> string @@ -1557,6 +1569,7 @@ const NuGet.Protocol.JsonProperties.Title = "title" -> string const NuGet.Protocol.JsonProperties.Type = "@type" -> string const NuGet.Protocol.JsonProperties.Version = "version" -> string const NuGet.Protocol.JsonProperties.Versions = "versions" -> string +const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string override NuGet.Protocol.AutoCompleteResourceV2Feed.IdStartsWith(string packageIdPrefix, bool includePrerelease, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> override NuGet.Protocol.AutoCompleteResourceV2Feed.VersionStartsWith(string packageId, string versionPrefix, bool includePrerelease, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> override NuGet.Protocol.AutoCompleteResourceV2FeedProvider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt index d5fdde29f64..b28a243f453 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt @@ -1,14 +1 @@ -NuGet.Protocol.Core.Types.IPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.set -> void -NuGet.Protocol.LocalPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageSearchMetadataV2Feed.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageVulnerabilityMetadata -NuGet.Protocol.PackageVulnerabilityMetadata.PackageVulnerabilityMetadata() -> void -NuGet.Protocol.PackageVulnerabilityMetadata.AdvisoryUrl.get -> System.Uri -NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int -const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string -const NuGet.Protocol.JsonProperties.Severity = "severity" -> string -const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string NuGet.Protocol.Core.Types.PackageUpdateResource.Push(System.Collections.Generic.IList packagePaths, string symbolSource, int timeoutInSecond, bool disableBuffering, System.Func getApiKey, System.Func getSymbolApiKey, bool noServiceEndpoint, bool skipDuplicate, NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, NuGet.Common.ILogger log) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index 02fc54c2089..e1dec7248da 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -98,6 +98,7 @@ NuGet.Protocol.Core.Types.IPackageSearchMetadata.RequireLicenseAcceptance.get -> NuGet.Protocol.Core.Types.IPackageSearchMetadata.Summary.get -> string NuGet.Protocol.Core.Types.IPackageSearchMetadata.Tags.get -> string NuGet.Protocol.Core.Types.IPackageSearchMetadata.Title.get -> string +NuGet.Protocol.Core.Types.IPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.Core.Types.ISourceRepositoryProvider NuGet.Protocol.Core.Types.ISourceRepositoryProvider.CreateRepository(NuGet.Configuration.PackageSource source) -> NuGet.Protocol.Core.Types.SourceRepository NuGet.Protocol.Core.Types.ISourceRepositoryProvider.CreateRepository(NuGet.Configuration.PackageSource source, NuGet.Protocol.FeedType type) -> NuGet.Protocol.Core.Types.SourceRepository @@ -196,6 +197,8 @@ NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetada NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Tags.set -> void NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Title.get -> string NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Title.set -> void +NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable +NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.set -> void NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.WithDeprecation(NuGet.Common.AsyncLazy lazyDeprecationFactory) -> NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.WithVersions(NuGet.Common.AsyncLazy> lazyVersionsFactory) -> NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder NuGet.Protocol.Core.Types.PackageSearchMetadataExtensions @@ -630,6 +633,7 @@ NuGet.Protocol.LocalPackageSearchMetadata.RequireLicenseAcceptance.get -> bool NuGet.Protocol.LocalPackageSearchMetadata.Summary.get -> string NuGet.Protocol.LocalPackageSearchMetadata.Tags.get -> string NuGet.Protocol.LocalPackageSearchMetadata.Title.get -> string +NuGet.Protocol.LocalPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.LocalPackageSearchResource NuGet.Protocol.LocalPackageSearchResource.LocalPackageSearchResource(NuGet.Protocol.FindLocalPackagesResource localResource) -> void NuGet.Protocol.LocalPackageSearchResourceProvider @@ -737,6 +741,7 @@ NuGet.Protocol.PackageSearchMetadata.Summary.get -> string NuGet.Protocol.PackageSearchMetadata.Tags.get -> string NuGet.Protocol.PackageSearchMetadata.Title.get -> string NuGet.Protocol.PackageSearchMetadata.Version.get -> NuGet.Versioning.NuGetVersion +NuGet.Protocol.PackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.PackageSearchMetadataRegistration NuGet.Protocol.PackageSearchMetadataRegistration.CatalogUri.get -> System.Uri NuGet.Protocol.PackageSearchMetadataRegistration.PackageSearchMetadataRegistration() -> void @@ -769,6 +774,7 @@ NuGet.Protocol.PackageSearchMetadataV2Feed.Summary.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Tags.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Title.get -> string NuGet.Protocol.PackageSearchMetadataV2Feed.Version.get -> NuGet.Versioning.NuGetVersion +NuGet.Protocol.PackageSearchMetadataV2Feed.Vulnerabilities.get -> System.Collections.Generic.IEnumerable NuGet.Protocol.PackageSearchResourceV2Feed NuGet.Protocol.PackageSearchResourceV2Feed.PackageSearchResourceV2Feed(NuGet.Protocol.HttpSourceResource httpSourceResource, string baseAddress, NuGet.Configuration.PackageSource packageSource) -> void NuGet.Protocol.PackageSearchResourceV2FeedProvider @@ -781,6 +787,10 @@ NuGet.Protocol.PackageUpdateResourceV2Provider NuGet.Protocol.PackageUpdateResourceV2Provider.PackageUpdateResourceV2Provider() -> void NuGet.Protocol.PackageUpdateResourceV3Provider NuGet.Protocol.PackageUpdateResourceV3Provider.PackageUpdateResourceV3Provider() -> void +NuGet.Protocol.PackageVulnerabilityMetadata +NuGet.Protocol.PackageVulnerabilityMetadata.AdvisoryUrl.get -> System.Uri +NuGet.Protocol.PackageVulnerabilityMetadata.PackageVulnerabilityMetadata() -> void +NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int NuGet.Protocol.PluginFindPackageByIdResourceProvider NuGet.Protocol.PluginFindPackageByIdResourceProvider.PluginFindPackageByIdResourceProvider() -> void NuGet.Protocol.Plugins.AutomaticProgressReporter @@ -1513,6 +1523,7 @@ const NuGet.Protocol.Core.Types.NuGetResourceProviderPositions.First = "First" - const NuGet.Protocol.Core.Types.NuGetResourceProviderPositions.Last = "Last" -> string const NuGet.Protocol.Core.Types.NuGetTestMode.NuGetTestClientName = "NuGet Test Client" -> string const NuGet.Protocol.JsonExtensions.JsonSerializationMaxDepth = 512 -> int +const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string const NuGet.Protocol.JsonProperties.AllRepositorySigned = "allRepositorySigned" -> string const NuGet.Protocol.JsonProperties.AlternatePackage = "alternatePackage" -> string const NuGet.Protocol.JsonProperties.Authors = "authors" -> string @@ -1547,6 +1558,7 @@ const NuGet.Protocol.JsonProperties.ProjectUrl = "projectUrl" -> string const NuGet.Protocol.JsonProperties.Published = "published" -> string const NuGet.Protocol.JsonProperties.Range = "range" -> string const NuGet.Protocol.JsonProperties.RequireLicenseAcceptance = "requireLicenseAcceptance" -> string +const NuGet.Protocol.JsonProperties.Severity = "severity" -> string const NuGet.Protocol.JsonProperties.SigningCertificates = "signingCertificates" -> string const NuGet.Protocol.JsonProperties.Subject = "subject" -> string const NuGet.Protocol.JsonProperties.SubjectId = "@id" -> string @@ -1557,6 +1569,7 @@ const NuGet.Protocol.JsonProperties.Title = "title" -> string const NuGet.Protocol.JsonProperties.Type = "@type" -> string const NuGet.Protocol.JsonProperties.Version = "version" -> string const NuGet.Protocol.JsonProperties.Versions = "versions" -> string +const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string override NuGet.Protocol.AutoCompleteResourceV2Feed.IdStartsWith(string packageIdPrefix, bool includePrerelease, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> override NuGet.Protocol.AutoCompleteResourceV2Feed.VersionStartsWith(string packageId, string versionPrefix, bool includePrerelease, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> override NuGet.Protocol.AutoCompleteResourceV2FeedProvider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index d5fdde29f64..b28a243f453 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,14 +1 @@ -NuGet.Protocol.Core.Types.IPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.Vulnerabilities.set -> void -NuGet.Protocol.LocalPackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageSearchMetadata.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageSearchMetadataV2Feed.Vulnerabilities.get -> System.Collections.Generic.IEnumerable -NuGet.Protocol.PackageVulnerabilityMetadata -NuGet.Protocol.PackageVulnerabilityMetadata.PackageVulnerabilityMetadata() -> void -NuGet.Protocol.PackageVulnerabilityMetadata.AdvisoryUrl.get -> System.Uri -NuGet.Protocol.PackageVulnerabilityMetadata.Severity.get -> int -const NuGet.Protocol.JsonProperties.AdvisoryUrl = "advisoryUrl" -> string -const NuGet.Protocol.JsonProperties.Severity = "severity" -> string -const NuGet.Protocol.JsonProperties.Vulnerabilities = "vulnerabilities" -> string NuGet.Protocol.Core.Types.PackageUpdateResource.Push(System.Collections.Generic.IList packagePaths, string symbolSource, int timeoutInSecond, bool disableBuffering, System.Func getApiKey, System.Func getSymbolApiKey, bool noServiceEndpoint, bool skipDuplicate, NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, NuGet.Common.ILogger log) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Versioning/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Versioning/PublicAPI.Shipped.txt index 550f72be523..9cbff4a385e 100644 --- a/src/NuGet.Core/NuGet.Versioning/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Versioning/PublicAPI.Shipped.txt @@ -56,6 +56,8 @@ NuGet.Versioning.SemanticVersion.SemanticVersion(int major, int minor, int patch NuGet.Versioning.SemanticVersion.SemanticVersion(int major, int minor, int patch, string releaseLabel) -> void NuGet.Versioning.SemanticVersion.SemanticVersion(int major, int minor, int patch, string releaseLabel, string metadata) -> void NuGet.Versioning.SemanticVersion.TryFormatter(string format, System.IFormatProvider formatProvider, out string formattedString) -> bool +NuGet.Versioning.SemanticVersionConverter +NuGet.Versioning.SemanticVersionConverter.SemanticVersionConverter() -> void NuGet.Versioning.VersionComparer NuGet.Versioning.VersionComparer.Compare(NuGet.Versioning.SemanticVersion x, NuGet.Versioning.SemanticVersion y) -> int NuGet.Versioning.VersionComparer.Equals(NuGet.Versioning.SemanticVersion x, NuGet.Versioning.SemanticVersion y) -> bool @@ -123,6 +125,10 @@ override NuGet.Versioning.NuGetVersion.ToString() -> string override NuGet.Versioning.SemanticVersion.Equals(object obj) -> bool override NuGet.Versioning.SemanticVersion.GetHashCode() -> int override NuGet.Versioning.SemanticVersion.ToString() -> string +override NuGet.Versioning.SemanticVersionConverter.CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) -> bool +override NuGet.Versioning.SemanticVersionConverter.CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) -> bool +override NuGet.Versioning.SemanticVersionConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) -> object +override NuGet.Versioning.SemanticVersionConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) -> object override NuGet.Versioning.VersionRange.Equals(object obj) -> bool override NuGet.Versioning.VersionRange.GetHashCode() -> int override NuGet.Versioning.VersionRange.ToString() -> string diff --git a/src/NuGet.Core/NuGet.Versioning/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Versioning/PublicAPI.Unshipped.txt index f773bcd269c..e69de29bb2d 100644 --- a/src/NuGet.Core/NuGet.Versioning/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Versioning/PublicAPI.Unshipped.txt @@ -1,6 +0,0 @@ -NuGet.Versioning.SemanticVersionConverter -NuGet.Versioning.SemanticVersionConverter.SemanticVersionConverter() -> void -override NuGet.Versioning.SemanticVersionConverter.CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) -> bool -override NuGet.Versioning.SemanticVersionConverter.CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) -> bool -override NuGet.Versioning.SemanticVersionConverter.ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) -> object -override NuGet.Versioning.SemanticVersionConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) -> object From a4e62bada86d0987eab7b0b1bbd8b977efa07406 Mon Sep 17 00:00:00 2001 From: Fernando Aguilar Date: Thu, 19 Nov 2020 14:28:00 -0800 Subject: [PATCH 046/129] Removes special projects from Up-To-Date project counter (#3738) Fixes https://github.com/NuGet/Home/issues/10038 --- .../NuGet.SolutionRestoreManager/SolutionRestoreJob.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs b/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs index c97ffa554a8..e4f24da4f40 100644 --- a/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs +++ b/src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs @@ -385,6 +385,9 @@ private async Task RestorePackageSpecProjectsAsync( { // Run solution based up to date check. var projectsNeedingRestore = _solutionUpToDateChecker.PerformUpToDateCheck(originalDgSpec, _logger).AsList(); + var specialReferencesCount = originalDgSpec.Projects + .Where(x => x.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference && x.RestoreMetadata.ProjectStyle != ProjectStyle.PackagesConfig && x.RestoreMetadata.ProjectStyle != ProjectStyle.ProjectJson) + .Count(); dgSpec = originalDgSpec; // Only use the optimization results if the restore is not `force`. // Still run the optimization check anyways to prep the cache. @@ -394,10 +397,10 @@ private async Task RestorePackageSpecProjectsAsync( dgSpec = originalDgSpec.WithoutRestores(); foreach (var uniqueProjectId in projectsNeedingRestore) { - dgSpec.AddRestore(uniqueProjectId); + dgSpec.AddRestore(uniqueProjectId); // Fill DGSpec copy only with restore-needed projects } - // recorded the number of up to date projects - _upToDateProjectCount = originalDgSpec.Restore.Count - projectsNeedingRestore.Count; + // Calculate the number of up to date projects + _upToDateProjectCount = originalDgSpec.Restore.Count - specialReferencesCount - projectsNeedingRestore.Count; _noOpProjectsCount = _upToDateProjectCount; } } From b560e8161003b683708339bafcb2bbb4d070a3c3 Mon Sep 17 00:00:00 2001 From: Fernando Aguilar Date: Thu, 19 Nov 2020 17:39:49 -0800 Subject: [PATCH 047/129] Adds icon filename extension validation (#3716) Fixes https://github.com/NuGet/Home/issues/9311 --- .../NuGet.Common/Errors/NuGetLogCode.cs | 22 +++- .../PublicAPI/net45/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net472/PublicAPI.Unshipped.txt | 1 + .../netstandard2.0/PublicAPI.Unshipped.txt | 1 + .../Authoring/PackageBuilder.cs | 29 +++-- .../Resources/NuGetResources.Designer.cs | 9 ++ .../Resources/NuGetResources.resx | 4 + .../NuGetPackCommandTest.cs | 46 ++++++++ .../PackageBuilderTest.cs | 102 ++++++++++++++---- 9 files changed, 183 insertions(+), 32 deletions(-) diff --git a/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs b/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs index ea0c78d6c10..f988b98072d 100644 --- a/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs +++ b/src/NuGet.Core/NuGet.Common/Errors/NuGetLogCode.cs @@ -5,8 +5,12 @@ namespace NuGet.Common { /// /// This enum is used to quantify NuGet error and warning codes. + /// + /// + /// /// Format - NUxyzw where NU is the prefix indicating NuGet and xyzw is a 4 digit code - /// + /// + /// /// Numbers - xyzw /// x - 'x' is the largest digit and should be used to quantify a set of errors. /// For example 1yzw are set of restore related errors and no other code path should use the range 1000 to 1999 for errors or warnings. @@ -18,12 +22,15 @@ namespace NuGet.Common /// /// zw - 'zw' are the least two digit. /// These could be used for different errors or warnings within the broad categories set by digits 'xy'. - /// + /// + /// /// Groups: /// 1000-1999 - Restore /// 3000-3999 - Signing /// 5000-5999 - Packaging + /// /// + /// /// Sub groups for Restore: /// error/warning - Reason /// 1000/1500 - Input @@ -31,10 +38,12 @@ namespace NuGet.Common /// 1200/1700 - Compat /// 1300/1800 - Feed /// 1400/1900 - Package + /// /// + /// /// All new codes need a corresponding MarkDown file under https://github.com/NuGet/docs.microsoft.com-nuget/tree/master/docs/reference/errors-and-warnings. - /// - /// + /// + /// public enum NuGetLogCode { /// @@ -683,6 +692,11 @@ public enum NuGetLogCode /// NU5037 = 5037, + /// + /// Invalid icon extension error + /// + NU5045 = 5045, + /// /// Error_Manifest_IconCannotOpenFile /// diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt index 18b158606de..33dcefd7875 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -1,2 +1,3 @@ NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU5045 = 5045 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt index 18b158606de..33dcefd7875 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,2 +1,3 @@ NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU5045 = 5045 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 18b158606de..33dcefd7875 100644 --- a/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Common/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,2 +1,3 @@ NuGet.Common.NuGetLogCode.NU5501 = 5501 -> NuGet.Common.NuGetLogCode NuGet.Common.NuGetLogCode.NU1012 = 1012 -> NuGet.Common.NuGetLogCode +NuGet.Common.NuGetLogCode.NU5045 = 5045 -> NuGet.Common.NuGetLogCode diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs index a32a51e3059..3e42631bd4a 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/PackageBuilder.cs @@ -314,7 +314,7 @@ string IPackageMetadata.Tags { get { - return String.Join(" ", Tags); + return string.Join(" ", Tags); } } @@ -580,7 +580,7 @@ public static void ValidateReferenceAssemblies(IEnumerable files, } var libFiles = new HashSet(from file in files - where !String.IsNullOrEmpty(file.Path) && file.Path.StartsWith("lib", StringComparison.OrdinalIgnoreCase) + where !string.IsNullOrEmpty(file.Path) && file.Path.StartsWith("lib", StringComparison.OrdinalIgnoreCase) select Path.GetFileName(file.Path), StringComparer.OrdinalIgnoreCase); foreach (var reference in packageAssemblyReferences.SelectMany(p => p.References)) @@ -590,7 +590,7 @@ public static void ValidateReferenceAssemblies(IEnumerable files, !libFiles.Contains(reference + ".exe") && !libFiles.Contains(reference + ".winmd")) { - throw new PackagingException(NuGetLogCode.NU5018, String.Format(CultureInfo.CurrentCulture, NuGetResources.Manifest_InvalidReference, reference)); + throw new PackagingException(NuGetLogCode.NU5018, string.Format(CultureInfo.CurrentCulture, NuGetResources.Manifest_InvalidReference, reference)); } } } @@ -683,15 +683,26 @@ private void ValidateLicenseFile(IEnumerable files, LicenseMetadat /// /// Given a list of resolved files, - /// determine which file will be used as the icon file and validate its size. + /// determine which file will be used as the icon file and validate its size and extension. /// /// Files resolved from the file entries in the nuspec - /// iconpath found in the .nuspec + /// icon entry found in the .nuspec /// When a validation rule is not met private void ValidateIconFile(IEnumerable files, string iconPath) { if (!PackageTypes.Contains(PackageType.SymbolsPackage) && !string.IsNullOrEmpty(iconPath)) { + var ext = Path.GetExtension(iconPath); + if (string.IsNullOrEmpty(ext) || ( + !ext.Equals(".jpeg", StringComparison.OrdinalIgnoreCase) && + !ext.Equals(".jpg", StringComparison.OrdinalIgnoreCase) && + !ext.Equals(".png", StringComparison.OrdinalIgnoreCase))) + { + throw new PackagingException( + NuGetLogCode.NU5045, + string.Format(CultureInfo.CurrentCulture, NuGetResources.IconInvalidExtension, iconPath)); + } + // Validate entry IPackageFile iconFile = FindFileInPackage(iconPath, files, out var iconPathWithIncorrectCase); @@ -963,7 +974,7 @@ public void AddFiles(string basePath, string source, string destination, string if (!PathResolver.IsWildcardSearch(source) && !PathResolver.IsDirectoryPath(source) && !searchFiles.Any() && string.IsNullOrEmpty(exclude)) { throw new PackagingException(NuGetLogCode.NU5019, - String.Format(CultureInfo.CurrentCulture, NuGetResources.PackageAuthoring_FileNotFound, source)); + string.Format(CultureInfo.CurrentCulture, NuGetResources.PackageAuthoring_FileNotFound, source)); } Files.AddRange(searchFiles); @@ -1017,7 +1028,7 @@ internal static string ResolvePackagePath(string searchDirectory, string searchP { packagePath = Path.GetFileName(fullPath); } - return Path.Combine(targetPath ?? String.Empty, packagePath); + return Path.Combine(targetPath ?? string.Empty, packagePath); } /// @@ -1048,7 +1059,7 @@ private static bool IsKnownFolder(string targetPath) private static void ExcludeFiles(List searchFiles, string basePath, string exclude) { - if (String.IsNullOrEmpty(exclude)) + if (string.IsNullOrEmpty(exclude)) { return; } @@ -1197,7 +1208,7 @@ private void WriteOpcPackageProperties(ZipArchive package, string psmdcpPath) new XAttribute(XNamespace.Xmlns + "dc", dcText), new XAttribute(XNamespace.Xmlns + "dcterms", dctermsText), new XAttribute(XNamespace.Xmlns + "xsi", xsiText), - new XElement(dc + "creator", String.Join(", ", Authors)), + new XElement(dc + "creator", string.Join(", ", Authors)), new XElement(dc + "description", Description), new XElement(dc + "identifier", Id), new XElement(core + "version", Version.ToString()), diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs index b3042a8f7a0..356f485a36f 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.Designer.cs @@ -105,6 +105,15 @@ internal static string IconErrorEmpty { } } + /// + /// Looks up a localized string similar to The 'icon' element '{0}' has an invalid file extension. Valid options are .png, .jpg or .jpeg.. + /// + internal static string IconInvalidExtension { + get { + return ResourceManager.GetString("IconInvalidExtension", resourceCulture); + } + } + /// /// Looks up a localized string similar to The icon file size must not exceed 1 megabyte.. /// diff --git a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx index 9933041e403..9f605616b3b 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx +++ b/src/NuGet.Core/NuGet.Packaging/PackageCreation/Resources/NuGetResources.resx @@ -220,4 +220,8 @@ The license file '{0}' does not exist in the package. (Did you mean '{1}'?) 0 - the license file, 1 - hint to guessed licensed file + + The 'icon' element '{0}' has an invalid file extension. Valid options are .png, .jpg or .jpeg. + 0 - Icon entry in the nuspec + \ No newline at end of file diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs index a19efe1430a..e315963767f 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/NuGetPackCommandTest.cs @@ -5984,6 +5984,52 @@ public void PackCommand_PackIcon_MissingIconFile_Fails() TestPackIconFailure(testDirBuilder, NuGetLogCode.NU5019.ToString()); } + [Theory] + [InlineData(".jpg")] + [InlineData(".PnG")] + [InlineData(".jpEg")] + public void PackCommand_PackIcon_ValidExtension_Succeeds(string fileExtension) + { + NuspecBuilder nuspecBuilder = NuspecBuilder.Create(); + TestDirectoryBuilder testDirBuilder = TestDirectoryBuilder.Create(); + var rng = new Random(); + + var iconFile = $"icon{fileExtension}"; + + nuspecBuilder + .WithFile(iconFile) + .WithIcon(iconFile); + + testDirBuilder + .WithNuspec(nuspecBuilder) + .WithFile(iconFile, rng.Next(1, 1024)); + + TestPackIconSuccess(testDirBuilder, iconFile); + } + + [Theory] + [InlineData(".x")] + [InlineData(".jpeg.x")] + [InlineData("")] + public void PackCommand_PackIcon_InvalidExtension_Fails(string fileExtension) + { + NuspecBuilder nuspecBuilder = NuspecBuilder.Create(); + TestDirectoryBuilder testDirBuilder = TestDirectoryBuilder.Create(); + var rng = new Random(); + + var iconFile = $"icon{fileExtension}"; + + nuspecBuilder + .WithFile(iconFile) + .WithIcon(iconFile); + + testDirBuilder + .WithNuspec(nuspecBuilder) + .WithFile(iconFile, rng.Next(1, 1024)); + + TestPackIconFailure(testDirBuilder, NuGetLogCode.NU5045.ToString()); + } + [Theory] [InlineData(SymbolPackageFormat.Snupkg)] [InlineData(SymbolPackageFormat.SymbolsNupkg)] diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs index eccda8c3848..14e99ae4a47 100644 --- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs +++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageBuilderTest.cs @@ -2626,6 +2626,58 @@ public void PackageBuilderWorksWithFileNameWithoutAnExtension() } } + [Theory] + [InlineData(".txt")] + [InlineData("")] + public void Icon_InvalidExtension_ThrowsException(string fileExtension) + { + var testDirBuilder = TestDirectoryBuilder.Create(); + var nuspecBuilder = NuspecBuilder.Create(); + var rng = new Random(); + + var iconFile = $"icon{fileExtension}"; + var errorMessage = $"The 'icon' element '{iconFile}' has an invalid file extension. Valid options are .png, .jpg or .jpeg."; + + nuspecBuilder + .WithIcon(iconFile) + .WithFile(iconFile); + + testDirBuilder + .WithFile(iconFile, rng.Next(1, PackageBuilder.MaxIconFileSize)) + .WithNuspec(nuspecBuilder); + + SavePackageAndAssertException( + testDirBuilder: testDirBuilder, + exceptionMessage: errorMessage); + } + + [Theory] + [InlineData(".jpeg")] + [InlineData(".jpg")] + [InlineData(".png")] + [InlineData(".PnG")] + [InlineData(".PNG")] + [InlineData(".jPG")] + [InlineData(".jpEG")] + public void Icon_ValidExtension_Succeeds(string fileExtension) + { + var testDirBuilder = TestDirectoryBuilder.Create(); + var nuspecBuilder = NuspecBuilder.Create(); + var rng = new Random(); + + var iconFile = $"icon{fileExtension}"; + + nuspecBuilder + .WithIcon(iconFile) + .WithFile(iconFile); + + testDirBuilder + .WithFile(iconFile, rng.Next(1, PackageBuilder.MaxIconFileSize)) + .WithNuspec(nuspecBuilder); + + SavePackageAndAssertIcon(testDirBuilder, iconFile); + } + [Fact] public void Icon_IconMaxFileSizeExceeded_ThrowsException() { @@ -2640,7 +2692,7 @@ public void Icon_IconMaxFileSizeExceeded_ThrowsException() .WithFile("icon.jpg", PackageBuilder.MaxIconFileSize + 1) .WithNuspec(nuspecBuilder); - TestIconPackaging( + SavePackageAndAssertException( testDirBuilder: testDirBuilder, exceptionMessage: "The icon file size must not exceed 1 megabyte."); } @@ -2659,28 +2711,28 @@ public void Icon_IconFileEntryNotFound_ThrowsException() .WithFile("icono.jpg", 100) .WithNuspec(nuspecBuilder); - TestIconPackaging( + SavePackageAndAssertException( testDirBuilder: testDirBuilder, exceptionMessage: "The icon file 'icon.jpg' does not exist in the package."); } [Fact] - public void Icon_HappyPath_Suceed() + public void Icon_HappyPath_Succeeds() { var testDirBuilder = TestDirectoryBuilder.Create(); var nuspecBuilder = NuspecBuilder.Create(); + var iconFile = "icon.jpg"; + var rng = new Random(); nuspecBuilder - .WithIcon("icon.jpg") - .WithFile("icon.jpg"); + .WithIcon(iconFile) + .WithFile(iconFile); testDirBuilder - .WithFile("icon.jpg", 400) + .WithFile(iconFile, rng.Next(1, 1024)) .WithNuspec(nuspecBuilder); - TestIconPackaging( - testDirBuilder: testDirBuilder, - exceptionMessage: null); + SavePackageAndAssertIcon(testDirBuilder, iconFile); } [Fact(Skip = "Need to solve https://github.com/NuGet/Home/issues/6941 to run this test case")] @@ -2703,12 +2755,13 @@ public void Icon_MultipleIconFilesResolved_ThrowsException() .WithFile($"folder2{dirSep}file.txt", 2) .WithNuspec(nuspecBuilder); - TestIconPackaging( + SavePackageAndAssertException( testDirBuilder: testDirBuilder, exceptionMessage: "Multiple files resolved as the embedded icon."); } - private void TestIconPackaging(TestDirectoryBuilder testDirBuilder, string exceptionMessage) + + private void SavePackageAndAssertIcon(TestDirectoryBuilder testDirBuilder, string iconFileEntry) { using (var sourceDir = testDirBuilder.Build()) using (var nuspecStream = File.OpenRead(testDirBuilder.NuspecPath)) //sourceDir.NuspecPath @@ -2716,19 +2769,30 @@ private void TestIconPackaging(TestDirectoryBuilder testDirBuilder, string excep { PackageBuilder pkgBuilder = new PackageBuilder(nuspecStream, testDirBuilder.BaseDir); //sourceDir.BaseDir - if (exceptionMessage != null) - { - ExceptionAssert.Throws( - () => pkgBuilder.Save(outputNuPkgStream), - exceptionMessage); - } - else + pkgBuilder.Save(outputNuPkgStream); + + outputNuPkgStream.Seek(0, SeekOrigin.Begin); + + using (var par = new PackageArchiveReader(outputNuPkgStream)) { - pkgBuilder.Save(outputNuPkgStream); + Assert.Equal(iconFileEntry, par.NuspecReader.GetIcon()); } } } + private void SavePackageAndAssertException(TestDirectoryBuilder testDirBuilder, string exceptionMessage) + { + using (var sourceDir = testDirBuilder.Build()) + using (var nuspecStream = File.OpenRead(testDirBuilder.NuspecPath)) //sourceDir.NuspecPath + using (var outputNuPkgStream = new MemoryStream()) + { + PackageBuilder pkgBuilder = new PackageBuilder(nuspecStream, testDirBuilder.BaseDir); //sourceDir.BaseDir + + var ex = Assert.Throws(() => pkgBuilder.Save(outputNuPkgStream)); + Assert.Equal(exceptionMessage, ex.Message); + } + } + [Theory] [InlineData(@".\test1.txt", "test1.txt")] [InlineData(@".\test\..\test1.txt", "test1.txt")] From 81bb917887dc0ff7f07a1ac51ce5a64f36aaf94f Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Mon, 23 Nov 2020 17:22:38 -0800 Subject: [PATCH 048/129] Change the way how config file is read while applying transformations (#3752) * read xml from reader * use xmlreader with default settings * reverted access modifier * changed root element name * reverted changes due to merge * updated xml reader settings --- build/Shared/XmlUtility.cs | 3 +- .../FileModifiers/XdtTransformer.cs | 12 +++--- .../GlobalSuppressions.cs | 1 - .../FileModifiers/XdtTransformerTests.cs | 37 ++++++++++++++++++- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/build/Shared/XmlUtility.cs b/build/Shared/XmlUtility.cs index 0f915af2225..e194e56a19a 100644 --- a/build/Shared/XmlUtility.cs +++ b/build/Shared/XmlUtility.cs @@ -78,12 +78,13 @@ internal static string GetEncodedXMLName(string name) /// Creates an instance of with safe settings /// A set of . /// - private static XmlReaderSettings GetXmlReaderSettings(LoadOptions options) + internal static XmlReaderSettings GetXmlReaderSettings(LoadOptions options) { XmlReaderSettings rs = new XmlReaderSettings(); if ((options & LoadOptions.PreserveWhitespace) == 0) rs.IgnoreWhitespace = true; rs.IgnoreProcessingInstructions = true; + rs.DtdProcessing = DtdProcessing.Prohibit; return rs; } } diff --git a/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XdtTransformer.cs b/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XdtTransformer.cs index 76b545c1409..310034528cd 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XdtTransformer.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/FileModifiers/XdtTransformer.cs @@ -7,8 +7,11 @@ using System.IO; using System.Threading; using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; using Microsoft.Web.XmlTransform; using NuGet.PackageManagement; +using static NuGet.Shared.XmlUtility; namespace NuGet.ProjectManagement { @@ -91,7 +94,7 @@ public async Task RevertFileAsync( await PerformXdtTransformAsync(streamTaskFactory, targetPath, projectSystem, cancellationToken); } - private static async Task PerformXdtTransformAsync( + internal static async Task PerformXdtTransformAsync( Func> streamTaskFactory, string targetPath, IMSBuildProjectSystem msBuildNuGetProjectSystem, @@ -107,13 +110,12 @@ private static async Task PerformXdtTransformAsync( { using (var document = new XmlTransformableDocument()) { - document.PreserveWhitespace = true; - // make sure we close the input stream immediately so that we can override // the file below when we save to it. - using (var inputStream = File.OpenRead(FileSystemUtility.GetFullPath(msBuildNuGetProjectSystem.ProjectFullPath, targetPath))) + string path = FileSystemUtility.GetFullPath(msBuildNuGetProjectSystem.ProjectFullPath, targetPath); + using (var reader = XmlReader.Create(path, GetXmlReaderSettings(LoadOptions.PreserveWhitespace))) { - document.Load(inputStream); + document.Load(reader); } var succeeded = transformation.Apply(document); diff --git a/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs index ce05168b8b5..a79e9acd364 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/GlobalSuppressions.cs @@ -153,7 +153,6 @@ [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'bool StreamUtility.ContentEquals(Stream stream, Stream otherStream)', validate parameter 'stream' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.StreamUtility.ContentEquals(System.IO.Stream,System.IO.Stream)~System.Boolean")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'bool StreamUtility.IsBinary(Stream stream)', validate parameter 'stream' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.StreamUtility.IsBinary(System.IO.Stream)~System.Boolean")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Stream StreamUtility.StreamFromString(string content, Encoding encoding)', validate parameter 'encoding' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.StreamUtility.StreamFromString(System.String,System.Text.Encoding)~System.IO.Stream")] -[assembly: SuppressMessage("Build", "CA3075:Unsafe overload of 'Load' method", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.XdtTransformer.PerformXdtTransformAsync(System.Func{System.Threading.Tasks.Task{System.IO.Stream}},System.String,NuGet.ProjectManagement.IMSBuildProjectSystem,System.Threading.CancellationToken)~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'void XElementExtensions.AddIndented(XContainer container, XContainer content)', validate parameter 'content' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.XElementExtensions.AddIndented(System.Xml.Linq.XContainer,System.Xml.Linq.XContainer)")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'IEnumerable XElementExtensions.ElementsNoNamespace(XContainer container, string localName)', validate parameter 'container' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.XElementExtensions.ElementsNoNamespace(System.Xml.Linq.XContainer,System.String)~System.Collections.Generic.IEnumerable{System.Xml.Linq.XElement}")] [assembly: SuppressMessage("Build", "CA1062:In externally visible method 'XElement XElementExtensions.Except(XElement source, XElement target)', validate parameter 'source' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "", Scope = "member", Target = "~M:NuGet.ProjectManagement.XElementExtensions.Except(System.Xml.Linq.XElement,System.Xml.Linq.XElement)~System.Xml.Linq.XElement")] diff --git a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/FileModifiers/XdtTransformerTests.cs b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/FileModifiers/XdtTransformerTests.cs index 4e204c12543..a7595d51b91 100644 --- a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/FileModifiers/XdtTransformerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/FileModifiers/XdtTransformerTests.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Xml; using Moq; using NuGet.ProjectManagement; using NuGet.Test.Utility; @@ -88,7 +89,7 @@ public async Task TransformFileAsync_TransformsFile() using (var reader = new StreamReader(stream)) { var actualResult = reader.ReadToEnd(); - var expectedResult = "\t\t\t\t\td\t\t\t"; + var expectedResult = "\r\n \r\n \r\n d\r\n \r\n \r\n"; Assert.Equal(expectedResult, actualResult); } @@ -102,6 +103,40 @@ await test.Transformer.TransformFileAsync( } } + [Fact] + public async Task PerformXdtTransformAsync_InSecureXmlFailsToTransform_Throws() + { + using (var test = new XdtTransformerTest("$c$")) + { + var projectFileOriginalContent = + @" + + + +]> +"; + + File.WriteAllText(test.TargetFile.FullName, projectFileOriginalContent); + + test.ProjectSystem.SetupGet(x => x.ProjectFullPath) + .Returns(test.TargetFile.DirectoryName); + test.ProjectSystem.SetupGet(x => x.ProjectName) + .Returns("ProjectName"); + test.ProjectSystem.Setup(x => x.GetPropertyValue(It.IsNotNull())) + .Returns("d"); + + var exception = await Assert.ThrowsAsync( + () => XdtTransformer.PerformXdtTransformAsync( + test.StreamTaskFactory, + test.TargetFile.Name, + test.ProjectSystem.Object, + CancellationToken.None)); + + Assert.IsType(exception.InnerException); + } + } + [Fact] public async Task RevertFileAsync_ThrowsForNullStreamTaskFactory() { From e223c9d791d0cf42211affb21f2142f7562ed060 Mon Sep 17 00:00:00 2001 From: Heng Liu <45407901+heng-liu@users.noreply.github.com> Date: Wed, 25 Nov 2020 00:54:38 +0000 Subject: [PATCH 049/129] Update the SDK and msbuild package version (#3777) --- build/bootstrap.proj | 2 +- build/config.props | 4 +- build/packages.targets | 9 +- .../NuGet.VisualStudio.Client/.vsixignore | 2 + .../App.config | 11 ++ .../CpsPackageReferenceProjectTests.cs | 9 +- .../App.config | 11 ++ .../App.config | 11 ++ .../MsbuildIntegrationTestFixture.cs | 110 ------------------ .../PackTaskTests.cs | 22 ++-- 10 files changed, 59 insertions(+), 132 deletions(-) create mode 100644 test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/App.config create mode 100644 test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/App.config create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/App.config diff --git a/build/bootstrap.proj b/build/bootstrap.proj index 7f0683f8326..8e989abcad0 100644 --- a/build/bootstrap.proj +++ b/build/bootstrap.proj @@ -23,7 +23,7 @@ - + diff --git a/build/config.props b/build/config.props index 99af188585a..a7045961442 100644 --- a/build/config.props +++ b/build/config.props @@ -37,8 +37,8 @@ true - master 5.0.100-preview.7.20319.6 - "master 5.0.100-preview.4.20258.7" + master 5.0.100 + "master 5.0.100" $(OverrideCliBranchForTesting) master $(OverrideCliTargetBranches) diff --git a/build/packages.targets b/build/packages.targets index 873850ccb71..55f164f8992 100644 --- a/build/packages.targets +++ b/build/packages.targets @@ -1,14 +1,13 @@ - 16.6.0 + 16.8.0 9.0.1 4.3.0 16.6.255 16.6.30107.105 16.153.0 16.7.56 - - 5.0.0-preview.3.20214.6 + 5.0.0 @@ -64,8 +63,8 @@ - - + + diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Client/.vsixignore b/src/NuGet.Clients/NuGet.VisualStudio.Client/.vsixignore index f4422055bf8..7d97080b86e 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Client/.vsixignore +++ b/src/NuGet.Clients/NuGet.VisualStudio.Client/.vsixignore @@ -110,3 +110,5 @@ System.Threading.Tasks.Extensions.dll System.Web.Http.dll VSLangProj157.dll Microsoft.DataAI.NuGetRecommender.Contracts.dll +System.Text.Encodings.Web.dll +System.Text.Json.dll diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/App.config b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/App.config new file mode 100644 index 00000000000..dd044bbc99e --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs index b6cbc8edcd8..c431fb34ac0 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/CpsPackageReferenceProjectTests.cs @@ -741,7 +741,7 @@ await nuGetPackageManager.ExecuteNuGetProjectActionsAsync( [Fact] public async Task TestPackageManager_UpgradePackageFor_TopParentProject_Success() { - using (var testDirectory = TestDirectory.Create()) + using (var testDirectory = new SimpleTestPathContext()) using (var testSolutionManager = new TestSolutionManager()) { // Set up Package Source @@ -752,16 +752,15 @@ public async Task TestPackageManager_UpgradePackageFor_TopParentProject_Success( var packageA = packageA_Version100.Identity; var packageB = packageB_Version100.Identity; var packageB_UpgradeVersion = packageB_Version200.Identity; - var packageSource = Path.Combine(testDirectory, "packageSource"); await SimpleTestPackageUtility.CreateFolderFeedV3Async( - packageSource, + testDirectory.PackageSource, PackageSaveMode.Defaultv3, packageA_Version100, packageB_Version100, packageB_Version200 ); - sources.Add(new PackageSource(packageSource)); + sources.Add(new PackageSource(testDirectory.PackageSource)); var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(sources); // Project @@ -787,7 +786,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( for (var i = numberOfProjects - 1; i >= 0; i--) { var projectName = $"project{i}"; - var projectFullPath = Path.Combine(testDirectory.Path, projectName, projectName + ".csproj"); + var projectFullPath = Path.Combine(testDirectory.SolutionRoot, projectName, projectName + ".csproj"); var project = CreateTestCpsPackageReferenceProject(projectName, projectFullPath, projectCache); // We need to treat NU1605 warning as error. diff --git a/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/App.config b/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/App.config new file mode 100644 index 00000000000..dd044bbc99e --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/App.config b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/App.config new file mode 100644 index 00000000000..dd044bbc99e --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Implementation.Test/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs index 7f2939a428f..a8ef176d89b 100644 --- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs @@ -41,9 +41,6 @@ public MsbuildIntegrationTestFixture() var sdkPath = Directory.EnumerateDirectories(Path.Combine(_cliDirectory, "sdk")).Single(); - // TODO - remove when shipping. See https://github.com/NuGet/Home/issues/8952 - PatchSDKWithCryptographyDlls(sdkPath); - MsBuildSdksPath = Path.Combine(sdkPath, "Sdks"); _templateDirectory = new SimpleTestPathContext(); @@ -652,112 +649,5 @@ private static void DeleteDirectory(string path) } } - - // Temporary added methods for processing deps.json files for patching - - /// - /// Temporary patching process to bring in Cryptography DLLs for testing while SDK gets around to including them in 5.0. - /// See also: https://github.com/NuGet/Home/issues/8508 - /// - private void PatchSDKWithCryptographyDlls(string sdkPath) - { - var assemblyNames = new string[1] { "System.Security.Cryptography.Pkcs.dll" }; - PatchDepsJsonFiles(assemblyNames, sdkPath); - - string userProfilePath = Environment.GetEnvironmentVariable(RuntimeEnvironmentHelper.IsWindows ? "USERPROFILE" : "HOME"); - string globalPackagesPath = Path.Combine(userProfilePath, ".nuget", "packages"); - - CopyNewlyAddedDlls(assemblyNames, Directory.GetCurrentDirectory(), sdkPath); - } - - private void PatchDepsJsonFiles(string[] assemblyNames, string patchDir) - { - string[] fileNames = new string[3] { "dotnet.deps.json", "MSBuild.deps.json", "NuGet.CommandLine.XPlat.deps.json" }; - string[] fullNames = fileNames.Select(filename => Path.Combine(patchDir, filename)).ToArray(); - PatchDepsJsonWithNewlyAddedDlls(assemblyNames, fullNames); - } - - private void CopyNewlyAddedDlls(string[] assemblyNames, string copyFromPath, string copyToPath) - { - foreach (var assemblyName in assemblyNames) - { - File.Copy( - Path.Combine(copyFromPath, assemblyName), - Path.Combine(copyToPath, assemblyName) - ); - } - } - - private void PatchDepsJsonWithNewlyAddedDlls(string[] assemblyNames, string[] filePaths) - { - foreach (string assemblyName in assemblyNames) - { - foreach (string filePath in filePaths) - { - JObject jsonFile = GetJson(filePath); - - JObject targets = jsonFile.GetJObjectProperty("targets"); - - JObject netcoreapp50 = targets.GetJObjectProperty(".NETCoreApp,Version=v5.0"); - - JProperty nugetBuildTasksProperty = netcoreapp50.Properties(). - FirstOrDefault(prop => prop.Name.StartsWith("NuGet.Build.Tasks/", StringComparison.OrdinalIgnoreCase)); - - JObject nugetBuildTasks = nugetBuildTasksProperty.Value.FromJToken(); - - JObject runtime = nugetBuildTasks.GetJObjectProperty("runtime"); - - var assemblyPath = Path.Combine(Directory.GetCurrentDirectory(), assemblyName); - var assemblyVersion = Assembly.LoadFile(assemblyPath).GetName().Version.ToString(); - var assemblyFileVersion = FileVersionInfo.GetVersionInfo(assemblyPath).FileVersion; - var jproperty = new JProperty("lib/netcoreapp5.0/" + assemblyName, - new JObject - { - new JProperty("assemblyVersion", assemblyVersion), - new JProperty("fileVersion", assemblyFileVersion), - } - ); - runtime.Add(jproperty); - nugetBuildTasks["runtime"] = runtime; - netcoreapp50[nugetBuildTasksProperty.Name] = nugetBuildTasks; - targets[".NETCoreApp,Version=v5.0"] = netcoreapp50; - jsonFile["targets"] = targets; - SaveJson(jsonFile, filePath); - } - } - } - - private JObject GetJson(string jsonFilePath) - { - try - { - return FileUtility.SafeRead(jsonFilePath, (stream, filePath) => - { - using (var reader = new StreamReader(stream)) - { - return JObject.Parse(reader.ReadToEnd()); - } - }); - } - catch (Exception ex) - { - throw new InvalidOperationException( - string.Format("Failed to read json file at {0}: {1}", jsonFilePath, ex.Message), - ex - ); - } - } - - private void SaveJson(JObject json, string jsonFilePath) - { - FileUtility.Replace((outputPath) => - { - using (var writer = new StreamWriter(outputPath, append: false, encoding: Encoding.UTF8)) - { - writer.Write(json.ToString()); - } - }, - jsonFilePath); - } } } diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/PackTaskTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/PackTaskTests.cs index 3046cf5390a..ed26c61003a 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/PackTaskTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Pack.Test/PackTaskTests.cs @@ -369,22 +369,26 @@ public void PackTask_MapsAllProperties() Formatting = Formatting.Indented }; + var jsonModelBefore = JObject.FromObject(target, JsonSerializer.Create(settings)); + // Exclude properties on the build task but not used for the pack task request. - var excludedProperties = new[] + var excludedBuildEngineProperty = new List(jsonModelBefore.Properties(). + Where(p => p.Name.StartsWith("BuildEngine", StringComparison.OrdinalIgnoreCase)). + Select(p => p.Name)); + + var excludedOtherProperties = new[] { - "BuildEngine", - "BuildEngine2", - "BuildEngine3", - "BuildEngine4", - "BuildEngine5", - "BuildEngine6", "HostObject", "Log", "PackTaskLogic", }; - var jsonModelBefore = JObject.FromObject(target, JsonSerializer.Create(settings)); - foreach (var property in excludedProperties) + foreach (var property in excludedBuildEngineProperty) + { + jsonModelBefore.Remove(property); + } + + foreach (var property in excludedOtherProperties) { jsonModelBefore.Remove(property); } From af5e8aafed2fd0a335db03d0407e3b87ef22341d Mon Sep 17 00:00:00 2001 From: Jean-Pierre Briede Date: Wed, 25 Nov 2020 11:37:54 -0800 Subject: [PATCH 050/129] Make RadioButton's default style be based on the VS style (#3778) --- .../NuGet.PackageManagement.UI/Resources/Resources.xaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml index a520f4253fb..2606131e8a7 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Resources.xaml @@ -4,7 +4,8 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:nuget="clr-namespace:NuGet.PackageManagement.UI" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Utilities"> + xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Utilities" + xmlns:vs="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0"> @@ -228,6 +229,8 @@ + + + ItemsSource="{Binding Path=DependencySets}"> From d4037306963c41837b0369c0e1b491b8de0b5338 Mon Sep 17 00:00:00 2001 From: Damon Tivel Date: Tue, 19 Jan 2021 21:57:01 -0800 Subject: [PATCH 111/129] Codespaces: register all MessagePack formatters (#3854) Fix https://github.com/NuGet/Home/issues/10467 --- .../NuGetServiceMessagePackRpcDescriptor.cs | 18 ++++-- ...GetServiceMessagePackRpcDescriptorTests.cs | 57 +++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetServiceMessagePackRpcDescriptorTests.cs diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs index 09e3f15ea7c..e58227e6996 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/NuGetServiceMessagePackRpcDescriptor.cs @@ -50,12 +50,16 @@ protected override JsonRpc CreateJsonRpc(IJsonRpcMessageHandler handler) return new NuGetJsonRpc(handler); } - private static MessagePackSerializerOptions CreateMessagePackSerializerOptions() + // Non-private for testing purposes only. + internal static IMessagePackFormatter[] CreateMessagePackFormatters() { - var formatters = new IMessagePackFormatter[] + return new IMessagePackFormatter[] { AlternatePackageMetadataContextInfoFormatter.Instance, FloatRangeFormatter.Instance, + IInstalledAndTransitivePackagesFormatter.Instance, + ILogMessageFormatter.Instance, + ImplicitProjectActionFormatter.Instance, IPackageReferenceContextInfoFormatter.Instance, IProjectContextInfoFormatter.Instance, IProjectMetadataContextInfoFormatter.Instance, @@ -68,16 +72,22 @@ private static MessagePackSerializerOptions CreateMessagePackSerializerOptions() PackageIdentityFormatter.Instance, PackageReferenceFormatter.Instance, PackageSearchMetadataContextInfoFormatter.Instance, - PackageSourceFormatter.Instance, PackageSourceContextInfoFormatter.Instance, + PackageSourceFormatter.Instance, PackageSourceUpdateOptionsFormatter.Instance, PackageVulnerabilityMetadataContextInfoFormatter.Instance, ProjectActionFormatter.Instance, - VersionRangeFormatter.Instance, + RemoteErrorFormatter.Instance, SearchFilterFormatter.Instance, SearchResultContextInfoFormatter.Instance, VersionInfoContextInfoFormatter.Instance, + VersionRangeFormatter.Instance }; + } + + private static MessagePackSerializerOptions CreateMessagePackSerializerOptions() + { + IMessagePackFormatter[] formatters = CreateMessagePackFormatters(); var resolvers = new IFormatterResolver[] { MessagePack.MessagePackSerializerOptions.Standard.Resolver }; return MessagePack.MessagePackSerializerOptions.Standard diff --git a/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetServiceMessagePackRpcDescriptorTests.cs b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetServiceMessagePackRpcDescriptorTests.cs new file mode 100644 index 00000000000..4cc5966322d --- /dev/null +++ b/test/NuGet.Clients.Tests/NuGet.VisualStudio.Internal.Contracts.Test/NuGetServiceMessagePackRpcDescriptorTests.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using MessagePack.Formatters; +using Xunit; + +namespace NuGet.VisualStudio.Internal.Contracts.Test +{ + public class NuGetServiceMessagePackRpcDescriptorTests + { + [Fact] + public void CreateMessagePackFormatters_Always_RegistersAllFormatters() + { + IMessagePackFormatter[] registeredFormatters = NuGetServiceMessagePackRpcDescriptor.CreateMessagePackFormatters(); + IReadOnlyList definedFormatters = FindDefinedMessagePackFormatters(); + + HashSet registeredFormatterNames = registeredFormatters + .Select(formatter => formatter.GetType().FullName) + .ToHashSet(); + + HashSet definedFormatterNames = definedFormatters + .Where(definedFormatter => !definedFormatter.Equals(typeof(NuGetMessagePackFormatter<>))) // Exclude the base class. + .Select(formatter => formatter.FullName) + .ToHashSet(); + + definedFormatterNames.ExceptWith(registeredFormatterNames); + + if (definedFormatterNames.Count > 0) + { + var message = new StringBuilder($"The following formatters are not registered. Did you define a new one and forget to register it?"); + + message.AppendLine(); + + foreach (string definedFormatterName in definedFormatterNames) + { + message.AppendLine(definedFormatterName); + } + + Assert.True(false, message.ToString()); + } + } + + private static IReadOnlyList FindDefinedMessagePackFormatters() + { + Assembly assembly = typeof(NuGetServiceMessagePackRpcDescriptor).Assembly; + + return assembly.GetTypes() + .Where(type => type.GetInterfaces().Contains(typeof(IMessagePackFormatter))) + .ToList(); + } + } +} From 2cdb0fc86c6cc1f6a56ec0c28121a9c091d934df Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Wed, 20 Jan 2021 13:02:57 -0800 Subject: [PATCH 112/129] Remove the explicit net45 target from NuGet.Frameworks (#3855) --- .../NuGet.Frameworks/NuGet.Frameworks.csproj | 2 +- .../PublicAPI/net45/PublicAPI.Shipped.txt | 376 ------------------ .../PublicAPI/net45/PublicAPI.Unshipped.txt | 0 3 files changed, 1 insertion(+), 377 deletions(-) delete mode 100644 src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt delete mode 100644 src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt diff --git a/src/NuGet.Core/NuGet.Frameworks/NuGet.Frameworks.csproj b/src/NuGet.Core/NuGet.Frameworks/NuGet.Frameworks.csproj index 4f3ac234cd3..a4647839c23 100644 --- a/src/NuGet.Core/NuGet.Frameworks/NuGet.Frameworks.csproj +++ b/src/NuGet.Core/NuGet.Frameworks/NuGet.Frameworks.csproj @@ -5,7 +5,7 @@ NuGet's understanding of target frameworks. $(TargetFrameworksLibrary) - $(TargetFrameworks);net40;net45 + $(TargetFrameworks);net40 $(NoWarn);CS1591;CS1574;CS1573 5 diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt deleted file mode 100644 index aa2ebd6c2fc..00000000000 --- a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Shipped.txt +++ /dev/null @@ -1,376 +0,0 @@ -NuGet.Frameworks.AssetTargetFallbackFramework -NuGet.Frameworks.AssetTargetFallbackFramework.AsFallbackFramework() -> NuGet.Frameworks.FallbackFramework -NuGet.Frameworks.AssetTargetFallbackFramework.AssetTargetFallbackFramework(NuGet.Frameworks.NuGetFramework framework, System.Collections.Generic.IReadOnlyList fallbackFrameworks) -> void -NuGet.Frameworks.AssetTargetFallbackFramework.Equals(NuGet.Frameworks.AssetTargetFallbackFramework other) -> bool -NuGet.Frameworks.AssetTargetFallbackFramework.Fallback.get -> System.Collections.Generic.IReadOnlyList -NuGet.Frameworks.AssetTargetFallbackFramework.RootFramework.get -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.CompatibilityListProvider -NuGet.Frameworks.CompatibilityListProvider.CompatibilityListProvider(NuGet.Frameworks.IFrameworkNameProvider nameProvider, NuGet.Frameworks.IFrameworkCompatibilityProvider compatibilityProvider) -> void -NuGet.Frameworks.CompatibilityListProvider.GetFrameworksSupporting(NuGet.Frameworks.NuGetFramework target) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.CompatibilityMappingComparer -NuGet.Frameworks.CompatibilityMappingComparer.CompatibilityMappingComparer() -> void -NuGet.Frameworks.CompatibilityMappingComparer.Equals(NuGet.Frameworks.OneWayCompatibilityMappingEntry x, NuGet.Frameworks.OneWayCompatibilityMappingEntry y) -> bool -NuGet.Frameworks.CompatibilityMappingComparer.GetHashCode(NuGet.Frameworks.OneWayCompatibilityMappingEntry obj) -> int -NuGet.Frameworks.CompatibilityProvider -NuGet.Frameworks.CompatibilityProvider.CompatibilityProvider(NuGet.Frameworks.IFrameworkNameProvider mappings) -> void -NuGet.Frameworks.CompatibilityProvider.IsCompatible(NuGet.Frameworks.NuGetFramework target, NuGet.Frameworks.NuGetFramework candidate) -> bool -NuGet.Frameworks.CompatibilityTable -NuGet.Frameworks.CompatibilityTable.CompatibilityTable(System.Collections.Generic.IEnumerable frameworks) -> void -NuGet.Frameworks.CompatibilityTable.CompatibilityTable(System.Collections.Generic.IEnumerable frameworks, NuGet.Frameworks.IFrameworkNameProvider mappings, NuGet.Frameworks.IFrameworkCompatibilityProvider compat) -> void -NuGet.Frameworks.CompatibilityTable.GetNearest(NuGet.Frameworks.NuGetFramework framework) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.CompatibilityTable.HasFramework(NuGet.Frameworks.NuGetFramework framework) -> bool -NuGet.Frameworks.CompatibilityTable.TryGetCompatible(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable compatible) -> bool -NuGet.Frameworks.DefaultCompatibilityProvider -NuGet.Frameworks.DefaultCompatibilityProvider.DefaultCompatibilityProvider() -> void -NuGet.Frameworks.DefaultFrameworkMappings -NuGet.Frameworks.DefaultFrameworkMappings.CompatibilityMappings.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.DefaultFrameworkMappings.DefaultFrameworkMappings() -> void -NuGet.Frameworks.DefaultFrameworkMappings.EquivalentFrameworkPrecedence.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.DefaultFrameworkMappings.EquivalentFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultFrameworkMappings.EquivalentProfiles.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.DefaultFrameworkMappings.FullNameReplacements.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultFrameworkMappings.IdentifierShortNames.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultFrameworkMappings.IdentifierSynonyms.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultFrameworkMappings.NonPackageBasedFrameworkPrecedence.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.DefaultFrameworkMappings.PackageBasedFrameworkPrecedence.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.DefaultFrameworkMappings.ProfileShortNames.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.DefaultFrameworkMappings.ShortNameReplacements.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultFrameworkMappings.SubSetFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultFrameworkNameProvider -NuGet.Frameworks.DefaultFrameworkNameProvider.DefaultFrameworkNameProvider() -> void -NuGet.Frameworks.DefaultPortableFrameworkMappings -NuGet.Frameworks.DefaultPortableFrameworkMappings.CompatibilityMappings.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultPortableFrameworkMappings.DefaultPortableFrameworkMappings() -> void -NuGet.Frameworks.DefaultPortableFrameworkMappings.ProfileFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.DefaultPortableFrameworkMappings.ProfileOptionalFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.FallbackFramework -NuGet.Frameworks.FallbackFramework.Equals(NuGet.Frameworks.FallbackFramework other) -> bool -NuGet.Frameworks.FallbackFramework.Fallback.get -> System.Collections.Generic.IReadOnlyList -NuGet.Frameworks.FallbackFramework.FallbackFramework(NuGet.Frameworks.NuGetFramework framework, System.Collections.Generic.IReadOnlyList fallbackFrameworks) -> void -NuGet.Frameworks.FrameworkConstants -NuGet.Frameworks.FrameworkConstants.CommonFrameworks -NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers -NuGet.Frameworks.FrameworkConstants.PlatformIdentifiers -NuGet.Frameworks.FrameworkConstants.SpecialIdentifiers -NuGet.Frameworks.FrameworkException -NuGet.Frameworks.FrameworkException.FrameworkException(string message) -> void -NuGet.Frameworks.FrameworkExpander -NuGet.Frameworks.FrameworkExpander.Expand(NuGet.Frameworks.NuGetFramework framework) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.FrameworkExpander.FrameworkExpander() -> void -NuGet.Frameworks.FrameworkExpander.FrameworkExpander(NuGet.Frameworks.IFrameworkNameProvider mappings) -> void -NuGet.Frameworks.FrameworkNameHelpers -NuGet.Frameworks.FrameworkNameProvider -NuGet.Frameworks.FrameworkNameProvider.AddFrameworkPrecedenceMappings(System.Collections.Generic.IDictionary destination, System.Collections.Generic.IEnumerable mappings) -> void -NuGet.Frameworks.FrameworkNameProvider.CompareEquivalentFrameworks(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> int -NuGet.Frameworks.FrameworkNameProvider.CompareFrameworks(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> int -NuGet.Frameworks.FrameworkNameProvider.FrameworkNameProvider(System.Collections.Generic.IEnumerable mappings, System.Collections.Generic.IEnumerable portableMappings) -> void -NuGet.Frameworks.FrameworkNameProvider.GetCompatibleCandidates() -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.FrameworkNameProvider.GetFullNameReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.FrameworkNameProvider.GetNetStandardVersions() -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.FrameworkNameProvider.GetShortNameReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.FrameworkNameProvider.GetVersionString(string framework, System.Version version) -> string -NuGet.Frameworks.FrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetIdentifier(string framework, out string identifier) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(string profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(string shortPortableProfiles, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableProfile(System.Collections.Generic.IEnumerable supportedFrameworks, out int profileNumber) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetPortableProfileNumber(string profile, out int profileNumber) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetProfile(string frameworkIdentifier, string profileShortName, out string profile) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetShortIdentifier(string identifier, out string identifierShortName) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetShortProfile(string frameworkIdentifier, string profile, out string profileShortName) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetSubSetFrameworks(string frameworkIdentifier, out System.Collections.Generic.IEnumerable subSetFrameworks) -> bool -NuGet.Frameworks.FrameworkNameProvider.TryGetVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.FrameworkPrecedenceSorter -NuGet.Frameworks.FrameworkPrecedenceSorter.Compare(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> int -NuGet.Frameworks.FrameworkPrecedenceSorter.FrameworkPrecedenceSorter(NuGet.Frameworks.IFrameworkNameProvider mappings, bool allEquivalent) -> void -NuGet.Frameworks.FrameworkRange -NuGet.Frameworks.FrameworkRange.Equals(NuGet.Frameworks.FrameworkRange other) -> bool -NuGet.Frameworks.FrameworkRange.FrameworkIdentifier.get -> string -NuGet.Frameworks.FrameworkRange.FrameworkRange(NuGet.Frameworks.NuGetFramework min, NuGet.Frameworks.NuGetFramework max) -> void -NuGet.Frameworks.FrameworkRange.FrameworkRange(NuGet.Frameworks.NuGetFramework min, NuGet.Frameworks.NuGetFramework max, bool includeMin, bool includeMax) -> void -NuGet.Frameworks.FrameworkRange.IncludeMax.get -> bool -NuGet.Frameworks.FrameworkRange.IncludeMin.get -> bool -NuGet.Frameworks.FrameworkRange.Max.get -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.FrameworkRange.Min.get -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.FrameworkRange.Satisfies(NuGet.Frameworks.NuGetFramework framework) -> bool -NuGet.Frameworks.FrameworkRangeComparer -NuGet.Frameworks.FrameworkRangeComparer.Equals(NuGet.Frameworks.FrameworkRange x, NuGet.Frameworks.FrameworkRange y) -> bool -NuGet.Frameworks.FrameworkRangeComparer.FrameworkRangeComparer() -> void -NuGet.Frameworks.FrameworkRangeComparer.GetHashCode(NuGet.Frameworks.FrameworkRange obj) -> int -NuGet.Frameworks.FrameworkReducer -NuGet.Frameworks.FrameworkReducer.FrameworkReducer() -> void -NuGet.Frameworks.FrameworkReducer.FrameworkReducer(NuGet.Frameworks.IFrameworkNameProvider mappings, NuGet.Frameworks.IFrameworkCompatibilityProvider compat) -> void -NuGet.Frameworks.FrameworkReducer.GetNearest(NuGet.Frameworks.NuGetFramework framework, System.Collections.Generic.IEnumerable possibleFrameworks) -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.FrameworkReducer.ReduceDownwards(System.Collections.Generic.IEnumerable frameworks) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.FrameworkReducer.ReduceEquivalent(System.Collections.Generic.IEnumerable frameworks) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.FrameworkReducer.ReduceUpwards(System.Collections.Generic.IEnumerable frameworks) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.FrameworkRuntimePair -NuGet.Frameworks.FrameworkRuntimePair.Clone() -> NuGet.Frameworks.FrameworkRuntimePair -NuGet.Frameworks.FrameworkRuntimePair.CompareTo(NuGet.Frameworks.FrameworkRuntimePair other) -> int -NuGet.Frameworks.FrameworkRuntimePair.Equals(NuGet.Frameworks.FrameworkRuntimePair other) -> bool -NuGet.Frameworks.FrameworkRuntimePair.Framework.get -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.FrameworkRuntimePair.FrameworkRuntimePair(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> void -NuGet.Frameworks.FrameworkRuntimePair.Name.get -> string -NuGet.Frameworks.FrameworkRuntimePair.RuntimeIdentifier.get -> string -NuGet.Frameworks.FrameworkSpecificMapping -NuGet.Frameworks.FrameworkSpecificMapping.FrameworkIdentifier.get -> string -NuGet.Frameworks.FrameworkSpecificMapping.FrameworkSpecificMapping(string frameworkIdentifier, System.Collections.Generic.KeyValuePair mapping) -> void -NuGet.Frameworks.FrameworkSpecificMapping.FrameworkSpecificMapping(string frameworkIdentifier, string key, string value) -> void -NuGet.Frameworks.FrameworkSpecificMapping.Mapping.get -> System.Collections.Generic.KeyValuePair -NuGet.Frameworks.IFrameworkCompatibilityListProvider -NuGet.Frameworks.IFrameworkCompatibilityListProvider.GetFrameworksSupporting(NuGet.Frameworks.NuGetFramework target) -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkCompatibilityProvider -NuGet.Frameworks.IFrameworkCompatibilityProvider.IsCompatible(NuGet.Frameworks.NuGetFramework framework, NuGet.Frameworks.NuGetFramework other) -> bool -NuGet.Frameworks.IFrameworkMappings -NuGet.Frameworks.IFrameworkMappings.CompatibilityMappings.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkMappings.EquivalentFrameworkPrecedence.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkMappings.EquivalentFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IFrameworkMappings.EquivalentProfiles.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkMappings.FullNameReplacements.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IFrameworkMappings.IdentifierShortNames.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IFrameworkMappings.IdentifierSynonyms.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IFrameworkMappings.NonPackageBasedFrameworkPrecedence.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkMappings.PackageBasedFrameworkPrecedence.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkMappings.ProfileShortNames.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkMappings.ShortNameReplacements.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IFrameworkMappings.SubSetFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IFrameworkNameProvider -NuGet.Frameworks.IFrameworkNameProvider.CompareEquivalentFrameworks(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> int -NuGet.Frameworks.IFrameworkNameProvider.CompareFrameworks(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> int -NuGet.Frameworks.IFrameworkNameProvider.GetCompatibleCandidates() -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkNameProvider.GetFullNameReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.IFrameworkNameProvider.GetNetStandardVersions() -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IFrameworkNameProvider.GetShortNameReplacement(NuGet.Frameworks.NuGetFramework framework) -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.IFrameworkNameProvider.GetVersionString(string framework, System.Version version) -> string -NuGet.Frameworks.IFrameworkNameProvider.TryGetCompatibilityMappings(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.FrameworkRange range, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetEquivalentFrameworks(NuGet.Frameworks.NuGetFramework framework, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetIdentifier(string identifierShortName, out string identifier) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPlatformVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableCompatibilityMappings(int profile, out System.Collections.Generic.IEnumerable supportedFrameworkRanges) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(int profile, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(string profile, bool includeOptional, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableFrameworks(string shortPortableProfiles, out System.Collections.Generic.IEnumerable frameworks) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableProfile(System.Collections.Generic.IEnumerable supportedFrameworks, out int profileNumber) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetPortableProfileNumber(string profile, out int profileNumber) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetProfile(string frameworkIdentifier, string profileShortName, out string profile) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetShortIdentifier(string identifier, out string identifierShortName) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetShortProfile(string frameworkIdentifier, string profile, out string profileShortName) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetSubSetFrameworks(string frameworkIdentifier, out System.Collections.Generic.IEnumerable subSetFrameworkIdentifiers) -> bool -NuGet.Frameworks.IFrameworkNameProvider.TryGetVersion(string versionString, out System.Version version) -> bool -NuGet.Frameworks.IFrameworkSpecific -NuGet.Frameworks.IFrameworkSpecific.TargetFramework.get -> NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.IFrameworkTargetable -NuGet.Frameworks.IFrameworkTargetable.SupportedFrameworks.get -> System.Collections.Generic.IEnumerable -NuGet.Frameworks.IPortableFrameworkMappings -NuGet.Frameworks.IPortableFrameworkMappings.CompatibilityMappings.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IPortableFrameworkMappings.ProfileFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.IPortableFrameworkMappings.ProfileOptionalFrameworks.get -> System.Collections.Generic.IEnumerable> -NuGet.Frameworks.NuGetFramework -NuGet.Frameworks.NuGetFramework.AllFrameworkVersions.get -> bool -NuGet.Frameworks.NuGetFramework.DotNetFrameworkName.get -> string -NuGet.Frameworks.NuGetFramework.DotNetPlatformName.get -> string -NuGet.Frameworks.NuGetFramework.Equals(NuGet.Frameworks.NuGetFramework other) -> bool -NuGet.Frameworks.NuGetFramework.Framework.get -> string -NuGet.Frameworks.NuGetFramework.GetDotNetFrameworkName(NuGet.Frameworks.IFrameworkNameProvider mappings) -> string -NuGet.Frameworks.NuGetFramework.GetShortFolderName() -> string -NuGet.Frameworks.NuGetFramework.HasPlatform.get -> bool -NuGet.Frameworks.NuGetFramework.HasProfile.get -> bool -NuGet.Frameworks.NuGetFramework.IsAgnostic.get -> bool -NuGet.Frameworks.NuGetFramework.IsAny.get -> bool -NuGet.Frameworks.NuGetFramework.IsPCL.get -> bool -NuGet.Frameworks.NuGetFramework.IsPackageBased.get -> bool -NuGet.Frameworks.NuGetFramework.IsSpecificFramework.get -> bool -NuGet.Frameworks.NuGetFramework.IsUnsupported.get -> bool -NuGet.Frameworks.NuGetFramework.NuGetFramework(NuGet.Frameworks.NuGetFramework framework) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string framework, System.Version version) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string frameworkProfile) -> void -NuGet.Frameworks.NuGetFramework.NuGetFramework(string frameworkIdentifier, System.Version frameworkVersion, string platform, System.Version platformVersion) -> void -NuGet.Frameworks.NuGetFramework.Platform.get -> string -NuGet.Frameworks.NuGetFramework.PlatformVersion.get -> System.Version -NuGet.Frameworks.NuGetFramework.Profile.get -> string -NuGet.Frameworks.NuGetFramework.Version.get -> System.Version -NuGet.Frameworks.NuGetFrameworkExtensions -NuGet.Frameworks.NuGetFrameworkFullComparer -NuGet.Frameworks.NuGetFrameworkFullComparer.Equals(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> bool -NuGet.Frameworks.NuGetFrameworkFullComparer.GetHashCode(NuGet.Frameworks.NuGetFramework obj) -> int -NuGet.Frameworks.NuGetFrameworkFullComparer.NuGetFrameworkFullComparer() -> void -NuGet.Frameworks.NuGetFrameworkNameComparer -NuGet.Frameworks.NuGetFrameworkNameComparer.Equals(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> bool -NuGet.Frameworks.NuGetFrameworkNameComparer.GetHashCode(NuGet.Frameworks.NuGetFramework obj) -> int -NuGet.Frameworks.NuGetFrameworkNameComparer.NuGetFrameworkNameComparer() -> void -NuGet.Frameworks.NuGetFrameworkSorter -NuGet.Frameworks.NuGetFrameworkSorter.Compare(NuGet.Frameworks.NuGetFramework x, NuGet.Frameworks.NuGetFramework y) -> int -NuGet.Frameworks.NuGetFrameworkSorter.NuGetFrameworkSorter() -> void -NuGet.Frameworks.NuGetFrameworkUtility -NuGet.Frameworks.OneWayCompatibilityMappingEntry -NuGet.Frameworks.OneWayCompatibilityMappingEntry.Equals(NuGet.Frameworks.OneWayCompatibilityMappingEntry other) -> bool -NuGet.Frameworks.OneWayCompatibilityMappingEntry.OneWayCompatibilityMappingEntry(NuGet.Frameworks.FrameworkRange targetFramework, NuGet.Frameworks.FrameworkRange supportedFramework) -> void -NuGet.Frameworks.OneWayCompatibilityMappingEntry.SupportedFrameworkRange.get -> NuGet.Frameworks.FrameworkRange -NuGet.Frameworks.OneWayCompatibilityMappingEntry.TargetFrameworkRange.get -> NuGet.Frameworks.FrameworkRange -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.AspNet = "ASP.NET" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.AspNetCore = "ASP.NETCore" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Dnx = "DNX" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.DnxCore = "DNXCore" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.DotNet = "dotnet" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.MonoAndroid = "MonoAndroid" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.MonoMac = "MonoMac" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.MonoTouch = "MonoTouch" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Native = "native" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Net = ".NETFramework" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.NetCore = ".NETCore" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.NetCoreApp = ".NETCoreApp" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.NetMicro = ".NETMicroFramework" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.NetPlatform = ".NETPlatform" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.NetStandard = ".NETStandard" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.NetStandardApp = ".NETStandardApp" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Portable = ".NETPortable" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Silverlight = "Silverlight" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Tizen = "Tizen" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.UAP = "UAP" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.WinRT = "WinRT" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.Windows = "Windows" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.WindowsPhone = "WindowsPhone" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.WindowsPhoneApp = "WindowsPhoneApp" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinIOs = "Xamarin.iOS" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinMac = "Xamarin.Mac" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinPlayStation3 = "Xamarin.PlayStation3" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinPlayStation4 = "Xamarin.PlayStation4" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinPlayStationVita = "Xamarin.PlayStationVita" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinTVOS = "Xamarin.TVOS" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinWatchOS = "Xamarin.WatchOS" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinXbox360 = "Xamarin.Xbox360" -> string -const NuGet.Frameworks.FrameworkConstants.FrameworkIdentifiers.XamarinXboxOne = "Xamarin.XboxOne" -> string -const NuGet.Frameworks.FrameworkConstants.PlatformIdentifiers.Windows = "Windows" -> string -const NuGet.Frameworks.FrameworkConstants.PlatformIdentifiers.WindowsPhone = "WindowsPhone" -> string -const NuGet.Frameworks.FrameworkConstants.SpecialIdentifiers.Agnostic = "Agnostic" -> string -const NuGet.Frameworks.FrameworkConstants.SpecialIdentifiers.Any = "Any" -> string -const NuGet.Frameworks.FrameworkConstants.SpecialIdentifiers.Unsupported = "Unsupported" -> string -override NuGet.Frameworks.AssetTargetFallbackFramework.Equals(object obj) -> bool -override NuGet.Frameworks.AssetTargetFallbackFramework.GetHashCode() -> int -override NuGet.Frameworks.FallbackFramework.Equals(object obj) -> bool -override NuGet.Frameworks.FallbackFramework.GetHashCode() -> int -override NuGet.Frameworks.FrameworkRange.Equals(object obj) -> bool -override NuGet.Frameworks.FrameworkRange.GetHashCode() -> int -override NuGet.Frameworks.FrameworkRange.ToString() -> string -override NuGet.Frameworks.FrameworkRuntimePair.Equals(object obj) -> bool -override NuGet.Frameworks.FrameworkRuntimePair.GetHashCode() -> int -override NuGet.Frameworks.FrameworkRuntimePair.ToString() -> string -override NuGet.Frameworks.NuGetFramework.Equals(object obj) -> bool -override NuGet.Frameworks.NuGetFramework.GetHashCode() -> int -override NuGet.Frameworks.NuGetFramework.ToString() -> string -override NuGet.Frameworks.OneWayCompatibilityMappingEntry.ToString() -> string -static NuGet.Frameworks.CompatibilityListProvider.Default.get -> NuGet.Frameworks.IFrameworkCompatibilityListProvider -static NuGet.Frameworks.DefaultCompatibilityProvider.Instance.get -> NuGet.Frameworks.IFrameworkCompatibilityProvider -static NuGet.Frameworks.DefaultFrameworkMappings.Instance.get -> NuGet.Frameworks.IFrameworkMappings -static NuGet.Frameworks.DefaultFrameworkNameProvider.Instance.get -> NuGet.Frameworks.IFrameworkNameProvider -static NuGet.Frameworks.DefaultPortableFrameworkMappings.Instance.get -> NuGet.Frameworks.IPortableFrameworkMappings -static NuGet.Frameworks.FrameworkNameHelpers.GetFolderName(string identifierShortName, string versionString, string profileShortName) -> string -static NuGet.Frameworks.FrameworkNameHelpers.GetPortableProfileNumberString(int profileNumber) -> string -static NuGet.Frameworks.FrameworkNameHelpers.GetVersion(string versionString) -> System.Version -static NuGet.Frameworks.FrameworkNameHelpers.GetVersionString(System.Version version) -> string -static NuGet.Frameworks.FrameworkRuntimePair.GetName(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> string -static NuGet.Frameworks.FrameworkRuntimePair.GetTargetGraphName(NuGet.Frameworks.NuGetFramework framework, string runtimeIdentifier) -> string -static NuGet.Frameworks.NuGetFramework.Parse(string folderName) -> NuGet.Frameworks.NuGetFramework -static NuGet.Frameworks.NuGetFramework.Parse(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework -static NuGet.Frameworks.NuGetFramework.ParseComponents(string targetFrameworkMoniker, string targetPlatformMoniker) -> NuGet.Frameworks.NuGetFramework -static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName) -> NuGet.Frameworks.NuGetFramework -static NuGet.Frameworks.NuGetFramework.ParseFolder(string folderName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework -static NuGet.Frameworks.NuGetFramework.ParseFrameworkName(string frameworkName, NuGet.Frameworks.IFrameworkNameProvider mappings) -> NuGet.Frameworks.NuGetFramework -static NuGet.Frameworks.NuGetFramework.operator !=(NuGet.Frameworks.NuGetFramework left, NuGet.Frameworks.NuGetFramework right) -> bool -static NuGet.Frameworks.NuGetFramework.operator ==(NuGet.Frameworks.NuGetFramework left, NuGet.Frameworks.NuGetFramework right) -> bool -static NuGet.Frameworks.NuGetFrameworkExtensions.GetNearest(this System.Collections.Generic.IEnumerable items, NuGet.Frameworks.NuGetFramework projectFramework) -> T -static NuGet.Frameworks.NuGetFrameworkExtensions.IsDesktop(this NuGet.Frameworks.NuGetFramework framework) -> bool -static NuGet.Frameworks.NuGetFrameworkUtility.GetNearest(System.Collections.Generic.IEnumerable items, NuGet.Frameworks.NuGetFramework framework) -> T -static NuGet.Frameworks.NuGetFrameworkUtility.GetNearest(System.Collections.Generic.IEnumerable items, NuGet.Frameworks.NuGetFramework framework, NuGet.Frameworks.IFrameworkNameProvider frameworkMappings, NuGet.Frameworks.IFrameworkCompatibilityProvider compatibilityProvider) -> T -static NuGet.Frameworks.NuGetFrameworkUtility.GetNearest(System.Collections.Generic.IEnumerable items, NuGet.Frameworks.NuGetFramework framework, NuGet.Frameworks.IFrameworkNameProvider frameworkMappings, NuGet.Frameworks.IFrameworkCompatibilityProvider compatibilityProvider, System.Func selector) -> T -static NuGet.Frameworks.NuGetFrameworkUtility.GetNearest(System.Collections.Generic.IEnumerable items, NuGet.Frameworks.NuGetFramework framework, System.Func selector) -> T -static NuGet.Frameworks.NuGetFrameworkUtility.IsCompatibleWithFallbackCheck(NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Frameworks.NuGetFramework candidate) -> bool -static NuGet.Frameworks.NuGetFrameworkUtility.IsNetCore50AndUp(NuGet.Frameworks.NuGetFramework framework) -> bool -static NuGet.Frameworks.OneWayCompatibilityMappingEntry.Comparer.get -> NuGet.Frameworks.CompatibilityMappingComparer -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.AspNet -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.AspNet50 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.AspNetCore -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.AspNetCore50 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Dnx -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Dnx45 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Dnx451 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Dnx452 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DnxCore -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DnxCore50 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet50 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet51 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet52 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet53 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet54 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet55 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.DotNet56 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net11 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net2 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net35 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net4 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net403 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net45 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net451 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net452 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net46 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net461 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net462 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net463 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Net50 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCore45 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCore451 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCore50 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp10 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp11 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp20 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp21 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp22 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp30 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp31 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard10 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard11 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard12 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard13 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard14 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard15 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard16 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard17 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard20 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandard21 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetStandardApp15 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.SL4 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.SL5 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Tizen3 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Tizen4 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Tizen6 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.UAP10 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.WP7 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.WP75 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.WP8 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.WP81 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.WPA81 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Win10 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Win8 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.CommonFrameworks.Win81 -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.FrameworkConstants.DotNetAll -> NuGet.Frameworks.FrameworkRange -static readonly NuGet.Frameworks.FrameworkConstants.EmptyVersion -> System.Version -static readonly NuGet.Frameworks.FrameworkConstants.MaxVersion -> System.Version -static readonly NuGet.Frameworks.FrameworkConstants.Version10 -> System.Version -static readonly NuGet.Frameworks.FrameworkConstants.Version5 -> System.Version -static readonly NuGet.Frameworks.NuGetFramework.AgnosticFramework -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.NuGetFramework.AnyFramework -> NuGet.Frameworks.NuGetFramework -static readonly NuGet.Frameworks.NuGetFramework.Comparer -> System.Collections.Generic.IEqualityComparer -static readonly NuGet.Frameworks.NuGetFramework.FrameworkNameComparer -> System.Collections.Generic.IEqualityComparer -static readonly NuGet.Frameworks.NuGetFramework.UnsupportedFramework -> NuGet.Frameworks.NuGetFramework -virtual NuGet.Frameworks.NuGetFramework.GetShortFolderName(NuGet.Frameworks.IFrameworkNameProvider mappings) -> string diff --git a/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Frameworks/PublicAPI/net45/PublicAPI.Unshipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 From a9807946cb84aff7230ad6ca058208cc485969bb Mon Sep 17 00:00:00 2001 From: Heng Liu <45407901+heng-liu@users.noreply.github.com> Date: Thu, 21 Jan 2021 05:15:57 +0000 Subject: [PATCH 113/129] Ensure all packages are created in CI (#3852) --- build/build.proj | 33 ++++++++++++++++++++++++++ build/common.targets | 14 +++++++++++ build/templates/Build_and_UnitTest.yml | 9 +++++++ 3 files changed, 56 insertions(+) diff --git a/build/build.proj b/build/build.proj index b12388909c2..b69842da92c 100644 --- a/build/build.proj +++ b/build/build.proj @@ -334,6 +334,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -83,7 +83,7 @@ - + diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs index c08ae071882..56ed1fbb80e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs @@ -1493,8 +1493,6 @@ public void ExecuteAction(Func performAction, Action setOptions) Model.CachedUpdates = null; ResetTabDataLoadFlags(); - _actionCompleted?.Invoke(this, EventArgs.Empty); - NuGetEventTrigger.Instance.TriggerEvent(NuGetEvent.PackageOperationEnd); IsEnabled = true; _isExecutingAction = false; if (_isRefreshRequired) @@ -1504,6 +1502,9 @@ public void ExecuteAction(Func performAction, Action setOptions) EmitRefreshEvent(timeSinceLastRefresh, RefreshOperationSource.ExecuteAction, RefreshOperationStatus.Success); _isRefreshRequired = false; } + + _actionCompleted?.Invoke(this, EventArgs.Empty); + NuGetEventTrigger.Instance.TriggerEvent(NuGetEvent.PackageOperationEnd); } }) .PostOnFailure(nameof(PackageManagerControl), nameof(ExecuteAction)); diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs index b9d94e4d944..6171f53d821 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs @@ -804,14 +804,7 @@ private async Task EnsureInitializeAsync() } else { - // Check if the cache is initialized. - // It is possible that the cache is not initialized, since, - // the solution was not saved and/or there were no projects in the solution - if (!_cacheInitialized && _solutionOpenedRaised) - { - await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - await EnsureNuGetAndVsProjectAdapterCacheAsync(); - } + await EnsureNuGetAndVsProjectAdapterCacheAsync(); } } catch (Exception e) diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreLoggingTests.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreLoggingTests.cs index 49b53753d23..c42f7bbeabb 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreLoggingTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreLoggingTests.cs @@ -322,7 +322,7 @@ public void RestoreLogging_VerifyCompatErrorNU1201Properties() log.FilePath.Should().Be(projectA.ProjectPath); log.LibraryId.Should().Be("b"); log.Level.Should().Be(LogLevel.Error); - log.TargetGraphs.ShouldBeEquivalentTo(new[] { netcoreapp1.DotNetFrameworkName }); + log.TargetGraphs.Should().BeEquivalentTo(new[] { netcoreapp1.DotNetFrameworkName }); log.Message.Should().Be("Project b is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Project b supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)"); } } @@ -364,7 +364,7 @@ public async Task RestoreLogging_VerifyCompatErrorNU1202PropertiesAsync() log.FilePath.Should().Be(projectA.ProjectPath); log.LibraryId.Should().Be("x"); log.Level.Should().Be(LogLevel.Error); - log.TargetGraphs.ShouldBeEquivalentTo(new[] { netcoreapp1.DotNetFrameworkName }); + log.TargetGraphs.Should().BeEquivalentTo(new[] { netcoreapp1.DotNetFrameworkName }); log.Message.Should().Be("Package x 1.0.0 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package x 1.0.0 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)"); } } diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs index f453c56443a..e12cd7b892a 100644 --- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs +++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs @@ -4702,7 +4702,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( // Assert lib.CompileTimeAssemblies.Select(e => e.Path) - .ShouldBeEquivalentTo(new[] { "lib/net45/a.dll" }, + .Should().BeEquivalentTo(new[] { "lib/net45/a.dll" }, "no compatible assets were found for ns2.0"); r.AllOutput.Should().Contain("This package may not be fully compatible with your project."); @@ -4761,7 +4761,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var lib = graph.GetTargetLibrary("x"); lib.CompileTimeAssemblies.Select(e => e.Path) - .ShouldBeEquivalentTo(new[] { "ref/netstandard1.0/a.dll" }, + .Should().BeEquivalentTo(new[] { "ref/netstandard1.0/a.dll" }, "ATF does not fallback to lib/net45 if other assets were found."); lib.RuntimeAssemblies.Should().BeEmpty(); @@ -4813,10 +4813,10 @@ public void RestoreNetCore_AssetTargetFallbackWithProjectReference_VerifyFallbac var lib = graph.GetTargetLibrary("b"); lib.CompileTimeAssemblies.Select(e => e.Path) - .ShouldBeEquivalentTo(new[] { "bin/placeholder/b.dll" }); + .Should().BeEquivalentTo(new[] { "bin/placeholder/b.dll" }); lib.RuntimeAssemblies.Select(e => e.Path) - .ShouldBeEquivalentTo(new[] { "bin/placeholder/b.dll" }); + .Should().BeEquivalentTo(new[] { "bin/placeholder/b.dll" }); lib.BuildMultiTargeting.Should().BeEmpty(); lib.Build.Should().BeEmpty(); @@ -4988,7 +4988,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var r = Util.RestoreSolution(pathContext); // Assert - projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).ShouldBeEquivalentTo(new[] { "m", "x", "y", "z" }); + projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).Should().BeEquivalentTo(new[] { "m", "x", "y", "z" }); } } @@ -5050,7 +5050,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var r = Util.RestoreSolution(pathContext); // Assert - projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).ShouldBeEquivalentTo(new[] { "x", "y" }); + projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).Should().BeEquivalentTo(new[] { "x", "y" }); } } @@ -5112,7 +5112,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var r = Util.RestoreSolution(pathContext); // Assert - projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).ShouldBeEquivalentTo(new[] { "x", "y" }); + projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).Should().BeEquivalentTo(new[] { "x", "y" }); // Verify fallback folder added projectA.AssetsFile.PackageFolders.Select(e => e.Path).Should().Contain(extraSourceA); @@ -5177,7 +5177,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var r = Util.RestoreSolution(pathContext); // Assert - projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).ShouldBeEquivalentTo(new[] { "x", "y" }); + projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).Should().BeEquivalentTo(new[] { "x", "y" }); // Verify the fallback folder was not added projectA.AssetsFile.PackageFolders.Select(e => e.Path).Should().NotContain(extraSourceA); @@ -5226,7 +5226,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var r = Util.RestoreSolution(pathContext); // Assert - projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).ShouldBeEquivalentTo(new[] { "x" }); + projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).Should().BeEquivalentTo(new[] { "x" }); // Verify the fallback folder was not added projectA.AssetsFile.PackageFolders.Select(e => e.Path).Should().NotContain(extraFallback.Path); @@ -5274,7 +5274,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( var r = Util.RestoreSolution(pathContext); // Assert - projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).ShouldBeEquivalentTo(new[] { "x" }); + projectA.AssetsFile.Libraries.Select(e => e.Name).OrderBy(e => e).Should().BeEquivalentTo(new[] { "x" }); // Verify the fallback folder was added projectA.AssetsFile.PackageFolders.Select(e => e.Path).Should().Contain(extraFallback.Path); @@ -8563,7 +8563,7 @@ public void RestoreNetCore_PackagesLockFile_WithProjectChangeRuntimeAndLockedMod Assert.True(File.Exists(projectA.NuGetLockFileOutputPath)); var lockFile = PackagesLockFileFormat.Read(projectA.NuGetLockFileOutputPath); var lockRuntimes = lockFile.Targets.Where(t => t.RuntimeIdentifier != null).Select(t => t.RuntimeIdentifier).ToList(); - intitialRuntimes.ShouldBeEquivalentTo(lockRuntimes); + intitialRuntimes.Should().BeEquivalentTo(lockRuntimes); // Setup - change runtimes projectA.Properties.Add("RestoreLockedMode", "true"); @@ -8579,7 +8579,7 @@ public void RestoreNetCore_PackagesLockFile_WithProjectChangeRuntimeAndLockedMod lockFile = PackagesLockFileFormat.Read(projectA.NuGetLockFileOutputPath); lockRuntimes = lockFile.Targets.Where(t => t.RuntimeIdentifier != null).Select(t => t.RuntimeIdentifier).ToList(); // No change expected in the lock file. - intitialRuntimes.ShouldBeEquivalentTo(lockRuntimes); + intitialRuntimes.Should().BeEquivalentTo(lockRuntimes); Assert.Contains("NU1004", r.Errors); var logCodes = projectA.AssetsFile.LogMessages.Select(e => e.Code); Assert.Contains(NuGetLogCode.NU1004, logCodes); @@ -8621,7 +8621,7 @@ public void RestoreNetCore_PackagesLockFile_WithProjectChangeFramweorksAndLocked var lockFile = PackagesLockFileFormat.Read(projectA.NuGetLockFileOutputPath); var lockFrameworks = lockFile.Targets.Select(t => t.TargetFramework.DotNetFrameworkName).Distinct().ToList(); _output.WriteLine($"PackageLockFrameworks First Evaluation: {string.Join(",", lockFrameworks)}"); - lockFrameworks.ShouldBeEquivalentTo(lockFrameworkTransformed); + lockFrameworks.Should().BeEquivalentTo(lockFrameworkTransformed); // Setup - change frameworks projectA.Properties.Add("RestoreLockedMode", "true"); @@ -8637,7 +8637,7 @@ public void RestoreNetCore_PackagesLockFile_WithProjectChangeFramweorksAndLocked lockFrameworks = lockFile.Targets.Select(t => t.TargetFramework.DotNetFrameworkName).Distinct().ToList(); _output.WriteLine($"PackageLockFrameworks Second Evaluation: {string.Join(",", lockFrameworks)}"); // The frameworks should not change in the lock file. - lockFrameworks.ShouldBeEquivalentTo(lockFrameworkTransformed); + lockFrameworks.Should().BeEquivalentTo(lockFrameworkTransformed); Assert.Contains("NU1004", r.Errors); var logCodes = projectA.AssetsFile.LogMessages.Select(e => e.Code); Assert.Contains(NuGetLogCode.NU1004, logCodes); @@ -9014,7 +9014,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( //Verify the RIDS are not the same after reordering. //Lock file is not ordered based on input RIDs so Validating the reorder here. var originalTargets = packagesLockFile.Targets.Where(t => t.RuntimeIdentifier != null).Select(t => t.RuntimeIdentifier).ToList(); - runtimeidentifiers.ShouldBeEquivalentTo(originalTargets); + runtimeidentifiers.Should().BeEquivalentTo(originalTargets); //Nuget.exe test so reordering to make it not match. It should still restore correctly packagesLockFile.Targets = packagesLockFile.Targets. diff --git a/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/VsSolutionRestoreServiceTests.cs b/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/VsSolutionRestoreServiceTests.cs index 973cb1895dd..66ae0263947 100644 --- a/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/VsSolutionRestoreServiceTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/VsSolutionRestoreServiceTests.cs @@ -835,8 +835,8 @@ public async Task NominateProjectAsync_VerifySourcesAreCombinedAcrossFrameworks( var metadata = actualRestoreSpec.Projects.Single().RestoreMetadata; // Assert - metadata.Sources.Select(e => e.Source).ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a", "b", "d" }); - metadata.FallbackFolders.ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x", "y", "z" }); + metadata.Sources.Select(e => e.Source).Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a", "b", "d" }); + metadata.FallbackFolders.Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x", "y", "z" }); } [Fact] @@ -885,8 +885,8 @@ public async Task NominateProjectAsync_PRI2_VerifySourcesAreCombinedAcrossFramew var metadata = actualRestoreSpec.Projects.Single().RestoreMetadata; // Assert - metadata.Sources.Select(e => e.Source).ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a", "b", "d" }); - metadata.FallbackFolders.ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x", "y", "z" }); + metadata.Sources.Select(e => e.Source).Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a", "b", "d" }); + metadata.FallbackFolders.Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x", "y", "z" }); } [Fact] @@ -919,8 +919,8 @@ public async Task NominateProjectAsync_VerifyExcludedFallbackFoldersAreRemoved() var metadata = actualRestoreSpec.Projects.Single().RestoreMetadata; // Assert - metadata.Sources.Select(e => e.Source).ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); - metadata.FallbackFolders.ShouldBeEquivalentTo(new[] { "base" }); + metadata.Sources.Select(e => e.Source).Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); + metadata.FallbackFolders.Should().BeEquivalentTo(new[] { "base" }); } [Fact] @@ -957,8 +957,8 @@ public async Task NominateProjectAsync_PRI2_VerifyExcludedFallbackFoldersAreRemo var metadata = actualRestoreSpec.Projects.Single().RestoreMetadata; // Assert - metadata.Sources.Select(e => e.Source).ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); - metadata.FallbackFolders.ShouldBeEquivalentTo(new[] { "base" }); + metadata.Sources.Select(e => e.Source).Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); + metadata.FallbackFolders.Should().BeEquivalentTo(new[] { "base" }); } [Fact] @@ -994,8 +994,8 @@ public async Task NominateProjectAsync_VerifyToolRestoresUseAdditionalSourcesAnd var metadata = actualRestoreSpec.Projects.Single(e => e.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetCliTool).RestoreMetadata; // Assert - metadata.Sources.Select(e => e.Source).ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); - metadata.FallbackFolders.ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x" }); + metadata.Sources.Select(e => e.Source).Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); + metadata.FallbackFolders.Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x" }); } [Fact] @@ -1035,8 +1035,8 @@ public async Task NominateProjectAsync_PRI2_VerifyToolRestoresUseAdditionalSourc var metadata = actualRestoreSpec.Projects.Single(e => e.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetCliTool).RestoreMetadata; // Assert - metadata.Sources.Select(e => e.Source).ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); - metadata.FallbackFolders.ShouldBeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x" }); + metadata.Sources.Select(e => e.Source).Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "a" }); + metadata.FallbackFolders.Should().BeEquivalentTo(new[] { "base", VSRestoreSettingsUtilities.AdditionalValue, "x" }); } [Theory] diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs index 4a5193c3dce..1c2ca7917a8 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs @@ -1904,7 +1904,7 @@ public void RestoreCommand_PathTooLongException() var command = new RestoreCommand(request); // Act - new Func(async () => await command.ExecuteAsync()).ShouldThrow(); + new Func(async () => await command.ExecuteAsync()).Should().Throw(); } } diff --git a/test/NuGet.Core.Tests/Microsoft.Build.NuGetSdkResolver.Tests/GlobalJsonReader_Tests.cs b/test/NuGet.Core.Tests/Microsoft.Build.NuGetSdkResolver.Tests/GlobalJsonReader_Tests.cs index 48470e305f7..8f1a76f4f20 100644 --- a/test/NuGet.Core.Tests/Microsoft.Build.NuGetSdkResolver.Tests/GlobalJsonReader_Tests.cs +++ b/test/NuGet.Core.Tests/Microsoft.Build.NuGetSdkResolver.Tests/GlobalJsonReader_Tests.cs @@ -43,7 +43,7 @@ public void GlobalJsonWithComments() var context = new MockSdkResolverContext(Path.Combine(testDirectory, "foo.proj")); - GlobalJsonReader.GetMSBuildSdkVersions(context).ShouldAllBeEquivalentTo(new Dictionary + GlobalJsonReader.GetMSBuildSdkVersions(context).Should().BeEquivalentTo(new Dictionary { ["foo"] = "1.0.0" }); diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs index e61889f80f4..3d539649eff 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/BuildTasksUtilityTests.cs @@ -33,7 +33,7 @@ public void GetSources_WithRestoreSourcesProperty_ResolvesAgainstProjectDirector ); // Assert - effectiveSources.ShouldBeEquivalentTo(new[] { Path.Combine(projectDirectory, relativePath) }); + effectiveSources.Should().BeEquivalentTo(new[] { Path.Combine(projectDirectory, relativePath) }); } } @@ -58,7 +58,7 @@ public void GetSources_WithRestoreSourcesGlobal_Property_ResolvesAgainstWorkingD ); // Assert - effectiveSources.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); + effectiveSources.Should().BeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); } } } diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs index 2c413a4dc31..b289275c020 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/MSBuildStaticGraphRestoreTests.cs @@ -44,7 +44,7 @@ public void GetFrameworkReferences_WhenDuplicatesExist_DuplicatesIgnored() var actual = MSBuildStaticGraphRestore.GetFrameworkReferences(project); - actual.ShouldBeEquivalentTo(new List + actual.Should().BeEquivalentTo(new List { new FrameworkDependency("FrameworkA", FrameworkDependencyFlags.None), new FrameworkDependency("FrameworkB", FrameworkDependencyFlags.All), @@ -68,7 +68,7 @@ public void GetOriginalTargetFrameworks_WhenTargetFramworksSpecified_HasCorrectT var actual = MSBuildStaticGraphRestore.GetTargetFrameworkStrings(project); - actual.ShouldBeEquivalentTo(expected); + actual.Should().BeEquivalentTo(expected); } [Fact] @@ -91,7 +91,7 @@ public void GetPackageDownloads_WhenDuplicatesExist_DuplicatesIgnored() var actual = MSBuildStaticGraphRestore.GetPackageDownloads(project); - actual.ShouldBeEquivalentTo(new List + actual.Should().BeEquivalentTo(new List { new DownloadDependency("PackageA", VersionRange.Parse("[1.1.1]")), new DownloadDependency("PackageB", VersionRange.Parse("[1.2.3]")), @@ -125,7 +125,7 @@ public void GetPackageDownloads_WhenNotExactVersion_ThrowsException(string versi var _ = MSBuildStaticGraphRestore.GetPackageDownloads(project).ToList(); }; - act.ShouldThrow().WithMessage($"'{expected ?? VersionRange.Parse(version).OriginalString}' is not an exact version like '[1.0.0]'. Only exact versions are allowed with PackageDownload."); + act.Should().Throw().WithMessage($"'{expected ?? VersionRange.Parse(version).OriginalString}' is not an exact version like '[1.0.0]'. Only exact versions are allowed with PackageDownload."); } } @@ -157,7 +157,7 @@ public void GetPackageReferences_WhenDuplicatesOrMetadataSpecified_DuplicatesIgn var actual = MSBuildStaticGraphRestore.GetPackageReferences(project, false); - actual.ShouldBeEquivalentTo(new List + actual.Should().BeEquivalentTo(new List { new LibraryDependency { @@ -294,7 +294,7 @@ public void GetProjectReferences_WhenDuplicateExistsOrMetadataSpecified_Duplicat var actual = MSBuildStaticGraphRestore.GetProjectReferences(project); - actual.ShouldBeEquivalentTo(new[] + actual.Should().BeEquivalentTo(new[] { new ProjectRestoreReference { @@ -364,7 +364,7 @@ public void GetProjectRestoreMetadataFrameworkInfos_WhenProjectReferenceSpecifie var actual = MSBuildStaticGraphRestore.GetProjectRestoreMetadataFrameworkInfos(targetFrameworkInfos, projects); - actual.ShouldBeEquivalentTo(new[] + actual.Should().BeEquivalentTo(new[] { new ProjectRestoreMetadataFrameworkInfo(FrameworkConstants.CommonFrameworks.Net45) { @@ -438,14 +438,14 @@ public void GetProjectTargetFrameworks_WhenMultipleTargetFrameworks_CorrectTarge var actual = MSBuildStaticGraphRestore.GetProjectTargetFrameworks(project, innerNodes); - actual.Keys.ShouldBeEquivalentTo( + actual.Keys.Should().BeEquivalentTo( new[] { "net45", "netstandard2.0" }); - actual.Values.Select(i => i.FullPath).ShouldBeEquivalentTo( + actual.Values.Select(i => i.FullPath).Should().BeEquivalentTo( new[] { "Project-net45", @@ -600,7 +600,7 @@ public void GetSources_WhenPerTargetFrameworkSources_CorrectSourcesDetected() var actual = MSBuildStaticGraphRestore.GetSources(project, projectsByTargetFramework, settings); - actual.ShouldBeEquivalentTo(new[] + actual.Should().BeEquivalentTo(new[] { new PackageSource("https://source1"), new PackageSource("https://source2"), @@ -633,7 +633,7 @@ public void GetSources_WhenRestoreSourcesAndRestoreSourcesOverrideSpecified_Corr var actual = MSBuildStaticGraphRestore.GetSources(project, new[] { project }, settings); - actual.ShouldBeEquivalentTo(new[] + actual.Should().BeEquivalentTo(new[] { new PackageSource("https://source3"), }); @@ -659,7 +659,7 @@ public void GetSources_WhenRestoreSourcesSpecified_CorrectSourcesDetected() var actual = MSBuildStaticGraphRestore.GetSources(project, new[] { project }, settings); - actual.ShouldBeEquivalentTo(new[] + actual.Should().BeEquivalentTo(new[] { new PackageSource("https://source1"), new PackageSource("https://source2"), diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/ProjectItemInstanceEvaluatedIncludeComparerTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/ProjectItemInstanceEvaluatedIncludeComparerTests.cs index 34e7a53a828..ea3a006df35 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/ProjectItemInstanceEvaluatedIncludeComparerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Console.Test/ProjectItemInstanceEvaluatedIncludeComparerTests.cs @@ -36,7 +36,7 @@ public void ProjectItemInstanceEvaluatedIncludeComparer_GetHashCode_DeDupesWhenD items.Count.Should().Be(1); }; - act.ShouldNotThrow(); + act.Should().NotThrow(); } } } diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs index e3298903d58..db028e8a3e3 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetRestoreSettingTaskTests.cs @@ -42,7 +42,7 @@ public void GetRestoreSettingsTask_GetValueGetLastValue() RestoreSettingsUtils.GetValue( () => null, () => null, - () => Array.Empty()).ShouldBeEquivalentTo(Array.Empty()); + () => Array.Empty()).Should().BeEquivalentTo(Array.Empty()); } [Fact] @@ -168,7 +168,7 @@ public void GetRestoreSettingsTask_VerifyRestoreAdditionalProjectSourcesAreAppen // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB"), Path.Combine(testDir, "sourceC") }); + task.OutputSources.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB"), Path.Combine(testDir, "sourceC") }); } } @@ -200,7 +200,7 @@ public void GetRestoreSettingsTask_VerifyRestoreAdditionalProjectFallbackFolders // Assert result.Should().BeTrue(); - task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB"), Path.Combine(testDir, "sourceC") }); + task.OutputFallbackFolders.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB"), Path.Combine(testDir, "sourceC") }); } } @@ -237,7 +237,7 @@ public void GetRestoreSettingsTask_VerifyRestoreAdditionalProjectFallbackFolders // Assert result.Should().BeTrue(); - task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB") }); + task.OutputFallbackFolders.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "sourceA"), Path.Combine(testDir, "sourceB") }); } } @@ -291,8 +291,8 @@ public void GetRestoreSettingsTask_VerifyAggregationAcrossFrameworks() // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "base"), Path.Combine(testDir, "a"), Path.Combine(testDir, "b"), Path.Combine(testDir, "c"), Path.Combine(testDir, "d") }); - task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "base"), Path.Combine(testDir, "m"), Path.Combine(testDir, "n"), Path.Combine(testDir, "s"), Path.Combine(testDir, "t") }); + task.OutputSources.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "base"), Path.Combine(testDir, "a"), Path.Combine(testDir, "b"), Path.Combine(testDir, "c"), Path.Combine(testDir, "d") }); + task.OutputFallbackFolders.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "base"), Path.Combine(testDir, "m"), Path.Combine(testDir, "n"), Path.Combine(testDir, "s"), Path.Combine(testDir, "t") }); } } @@ -319,8 +319,8 @@ public void GetRestoreSettingsTask_VerifyNullPerFrameworkSettings() // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "base") }); - task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "base") }); + task.OutputSources.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "base") }); + task.OutputFallbackFolders.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "base") }); } } @@ -347,8 +347,8 @@ public void GetRestoreSettingsTask_VerifyEmptyPerFrameworkSettings() // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "base") }); - task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(testDir, "base") }); + task.OutputSources.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "base") }); + task.OutputFallbackFolders.Should().BeEquivalentTo(new[] { Path.Combine(testDir, "base") }); } } @@ -384,7 +384,7 @@ public void GetRestoreSettingsTask_VerifyDisabledSourcesAreExcluded() // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { @"https://nuget.org/v2/api" }); + task.OutputSources.Should().BeEquivalentTo(new[] { @"https://nuget.org/v2/api" }); } } @@ -545,7 +545,7 @@ public void GetRestoreSettingsTask_RestoreTaskBased_PackageReference_ProjectLeve // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { "https://api.nuget.org/v3/index.json" }); + task.OutputSources.Should().BeEquivalentTo(new[] { "https://api.nuget.org/v3/index.json" }); task.OutputFallbackFolders.Should().BeEmpty(); task.OutputConfigFilePaths.Should().Contain(configFile); } @@ -588,7 +588,7 @@ public void GetRestoreSettingsTask_NuGetExeBased_PackageReference_ProjectLevelCo // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { "https://api.nuget.org/v3/index.json" }); + task.OutputSources.Should().BeEquivalentTo(new[] { "https://api.nuget.org/v3/index.json" }); task.OutputFallbackFolders.Should().BeEmpty(); task.OutputConfigFilePaths.Should().Contain(rootConfigFile); task.OutputConfigFilePaths.Should().NotContain(projectLevelConfigFile); @@ -633,7 +633,7 @@ public void GetRestoreSettingsTask_WithRestoreRootDirectory_ProjectLevelConfigIs // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { "https://api.nuget.org/v3/index.json" }); + task.OutputSources.Should().BeEquivalentTo(new[] { "https://api.nuget.org/v3/index.json" }); task.OutputFallbackFolders.Should().BeEmpty(); task.OutputConfigFilePaths.Should().Contain(rootConfigFile); task.OutputConfigFilePaths.Should().NotContain(projectLevelConfigFile); @@ -672,7 +672,7 @@ public void GetRestoreSettingsTask_WithRestoreSourcesOverride_ResolvesAgainstWor // Assert result.Should().BeTrue(); - task.OutputSources.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); + task.OutputSources.Should().BeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); } } @@ -707,7 +707,7 @@ public void GetRestoreSettingsTask_WithFallbackFoldersOverride_ResolvesAgainstWo // Assert result.Should().BeTrue(); - task.OutputFallbackFolders.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); + task.OutputFallbackFolders.Should().BeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) }); } } diff --git a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/TaskLoggingQueueTests.cs b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/TaskLoggingQueueTests.cs index ff1f67d79c7..b0a95e6d839 100644 --- a/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/TaskLoggingQueueTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/TaskLoggingQueueTests.cs @@ -83,7 +83,7 @@ public void TaskLoggingQueue_Process_ThrowsIfInvalidMessageType() } }; - act.ShouldThrow(); + act.Should().Throw(); } } } diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/DiagnosticUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/DiagnosticUtilityTests.cs index c78286cdb5c..036115d48ac 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/DiagnosticUtilityTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/DiagnosticUtilityTests.cs @@ -103,7 +103,7 @@ public void GivenASingleMessageVerifySameReturned() var messages = new List(); messages.Add(RestoreLogMessage.CreateWarning(NuGetLogCode.NU1000, "test", "a", "abc")); - DiagnosticUtility.MergeOnTargetGraph(messages).ShouldBeEquivalentTo(messages); + DiagnosticUtility.MergeOnTargetGraph(messages).Should().BeEquivalentTo(messages); } [Fact] @@ -116,7 +116,7 @@ public void GivenADuplicateMessagesVerifySingleMessageReturned() var outMessages = DiagnosticUtility.MergeOnTargetGraph(messages).ToList(); outMessages.Count.Should().Be(1); - outMessages.Single().TargetGraphs.ShouldAllBeEquivalentTo(new[] { "abc" }); + outMessages.Single().TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); } [Fact] @@ -129,7 +129,7 @@ public void GivenADuplicateMessagesVerifySingleMessageReturnedWithAllFramweworks var outMessages = DiagnosticUtility.MergeOnTargetGraph(messages).ToList(); outMessages.Count.Should().Be(1); - outMessages.Single().TargetGraphs.ShouldAllBeEquivalentTo(new[] { "abc", "xyz" }); + outMessages.Single().TargetGraphs.Should().BeEquivalentTo(new[] { "abc", "xyz" }); } [Fact] diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/MSBuildRestoreUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/MSBuildRestoreUtilityTests.cs index 62ff15829fc..da4af16eeef 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/MSBuildRestoreUtilityTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/MSBuildRestoreUtilityTests.cs @@ -237,14 +237,14 @@ public void MSBuildRestoreUtility_GivenDifferentProjectPathCasingsVerifyResult() // Assert // Verify package dependencies and framework references are the same - project1SpecWithSameCasings.TargetFrameworks.ShouldBeEquivalentTo(project1SpecWithDifferentCasings.TargetFrameworks); - project2SpecWithSameCasings.TargetFrameworks.ShouldBeEquivalentTo(project2SpecWithDifferentCasings.TargetFrameworks); + project1SpecWithSameCasings.TargetFrameworks.Should().BeEquivalentTo(project1SpecWithDifferentCasings.TargetFrameworks); + project2SpecWithSameCasings.TargetFrameworks.Should().BeEquivalentTo(project2SpecWithDifferentCasings.TargetFrameworks); // Verify project references are the same var projectReferencesSame = project1SpecWithSameCasings.RestoreMetadata.TargetFrameworks[0].ProjectReferences.Select(e => e.ProjectPath.ToLowerInvariant()); var projectReferencesDiff = project1SpecWithDifferentCasings.RestoreMetadata.TargetFrameworks[0].ProjectReferences.Select(e => e.ProjectPath.ToLowerInvariant()); - projectReferencesSame.ShouldBeEquivalentTo(projectReferencesDiff); + projectReferencesSame.Should().BeEquivalentTo(projectReferencesDiff); } } @@ -711,7 +711,7 @@ public void MSBuildRestoreUtility_AggregateSources(string values, string exclude var expectedValues = expected.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); MSBuildRestoreUtility.AggregateSources(inputValues, excludeValues) - .ShouldBeEquivalentTo(expectedValues); + .Should().BeEquivalentTo(expectedValues); } [Fact] @@ -2691,8 +2691,8 @@ public void MSBuildRestoreUtility_GetPackageSpec_NetCoreVerifyProjectWideWarning // Assert props.AllWarningsAsErrors.Should().BeTrue(); - props.NoWarn.ShouldBeEquivalentTo(new[] { NuGetLogCode.NU1100, NuGetLogCode.NU1101 }); - props.WarningsAsErrors.ShouldBeEquivalentTo(new[] { NuGetLogCode.NU1001, NuGetLogCode.NU1002 }); + props.NoWarn.Should().BeEquivalentTo(new[] { NuGetLogCode.NU1100, NuGetLogCode.NU1101 }); + props.WarningsAsErrors.Should().BeEquivalentTo(new[] { NuGetLogCode.NU1001, NuGetLogCode.NU1002 }); } } @@ -2806,7 +2806,7 @@ public void MSBuildRestoreUtility_GetPackageSpec_NetCoreVerifyPackageWarningProp var packageDependency = project1Spec.TargetFrameworks[0].Dependencies[0]; // Assert - packageDependency.NoWarn.ShouldBeEquivalentTo(new[] { NuGetLogCode.NU1001, NuGetLogCode.NU1002 }); + packageDependency.NoWarn.Should().BeEquivalentTo(new[] { NuGetLogCode.NU1001, NuGetLogCode.NU1002 }); } } @@ -2956,7 +2956,7 @@ public void MSBuildRestoreUtility_GetNuGetLogCodes_ParsesPropertyWithOneCode(str // Assert codes.Should().NotBeNull(); - codes.ShouldBeEquivalentTo(new[] { NuGetLogCode.NU1107 }); + codes.Should().BeEquivalentTo(new[] { NuGetLogCode.NU1107 }); } [Theory] @@ -3006,7 +3006,7 @@ public void MSBuildRestoreUtility_GetNuGetLogCodes_ParsesPropertyWithMultipleCod // Assert codes.Should().NotBeNull(); - codes.ShouldBeEquivalentTo(new[] { NuGetLogCode.NU1107, NuGetLogCode.NU1701 }); + codes.Should().BeEquivalentTo(new[] { NuGetLogCode.NU1107, NuGetLogCode.NU1701 }); } [Theory] diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/TransitiveNoWarnUtilsTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/TransitiveNoWarnUtilsTests.cs index 98c372425e3..144b8b1a943 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/TransitiveNoWarnUtilsTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/TransitiveNoWarnUtilsTests.cs @@ -302,10 +302,10 @@ public void MergePackageSpecificWarningProperties_MergesNonEmptyCollections() // Assert mergedNoWarnForNet461.Should().NotBeNull(); - mergedNoWarnForNet461.ShouldBeEquivalentTo(expectedNoWarnForNet461); + mergedNoWarnForNet461.Should().BeEquivalentTo(expectedNoWarnForNet461); mergedNoWarnForNetcoreapp.Should().NotBeNull(); - mergedNoWarnForNetcoreapp.ShouldBeEquivalentTo(expectedNoWarnForNetcoreapp); + mergedNoWarnForNetcoreapp.Should().BeEquivalentTo(expectedNoWarnForNetcoreapp); } // Tests for TransitiveNoWarnUtils.MergeProjectWideWarningProperties @@ -393,7 +393,7 @@ public void MergeProjectWideWarningProperties_MergesNonEmptyCollections( // Assert merged.Should().NotBeNull(); - merged.ShouldBeEquivalentTo(expected); + merged.Should().BeEquivalentTo(expected); } @@ -488,7 +488,7 @@ public void ExtractPackageSpecificNoWarnForFrameworks_InputWithProperties() // Assert result.Should().NotBeNull(); - result.ShouldBeEquivalentTo(expected); + result.Should().BeEquivalentTo(expected); } // Tests for TransitiveNoWarnUtils.ExtractPackageSpecificNoWarnForFramework @@ -586,9 +586,9 @@ public void ExtractPackageSpecificNoWarnForFramework_InputWithProperties() // Assert resultNet461.Should().NotBeNull(); - resultNet461.ShouldBeEquivalentTo(expected[net461]); + resultNet461.Should().BeEquivalentTo(expected[net461]); resultNetcoreapp.Should().NotBeNull(); - resultNetcoreapp.ShouldBeEquivalentTo(expected[netcoreapp]); + resultNetcoreapp.Should().BeEquivalentTo(expected[netcoreapp]); } // Tests for TransitiveNoWarnUtils.DependencyNode equality diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/UnexpectedDependencyMessagesTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/UnexpectedDependencyMessagesTests.cs index 0e29d434e6a..302eb2e57d5 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/UnexpectedDependencyMessagesTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/UnexpectedDependencyMessagesTests.cs @@ -221,7 +221,7 @@ public void GivenAGraphWithMultipleIssuesForTheSamePackageVerifyBothMessagesLogg var logs = UnexpectedDependencyMessages.GetMissingLowerBounds(targetGraphs, ignore).ToList(); - logs.Select(e => e.Message).ShouldBeEquivalentTo(new[] + logs.Select(e => e.Message).Should().BeEquivalentTo(new[] { "x 9.0.0 does not provide an inclusive lower bound for dependency b (<= 5.0.0). An approximate best match of b 2.0.0 was resolved.", "y 8.0.0 does not provide an inclusive lower bound for dependency b (> 1.0.0 && <= 6.0.0). An approximate best match of b 3.0.0 was resolved." @@ -457,7 +457,7 @@ public void GivenAProjectWithABumpedDependencyVerifyMessage() var log = UnexpectedDependencyMessages.GetBumpedUpDependencies(indexedGraphs, project, ignore).Single(); log.Code.Should().Be(NuGetLogCode.NU1601); - log.TargetGraphs.ShouldBeEquivalentTo(new[] { "net46/win10" }); + log.TargetGraphs.Should().BeEquivalentTo(new[] { "net46/win10" }); log.Message.Should().Be("Dependency specified was x (>= 1.0.0) but ended up with X 2.0.0."); } @@ -496,7 +496,7 @@ public void GivenAGraphIsMissingALowerBoundVerifyWarningIncludesGraphName() var log = UnexpectedDependencyMessages.GetMissingLowerBounds(targetGraphs, ignore).Single(); - log.TargetGraphs.ShouldBeEquivalentTo(new[] { "net46/win10" }); + log.TargetGraphs.Should().BeEquivalentTo(new[] { "net46/win10" }); log.Code.Should().Be(NuGetLogCode.NU1602); } @@ -514,10 +514,10 @@ public void GivenAProjectWithMultipleDependencyBoundIssuesVerifyWarnings() var logs = UnexpectedDependencyMessages.GetProjectDependenciesMissingLowerBounds(project); - logs.Select(e => e.Code).ShouldAllBeEquivalentTo(NuGetLogCode.NU1604); - logs.Select(e => e.Level).ShouldAllBeEquivalentTo(LogLevel.Warning); + logs.Select(e => e.Code).Should().AllBeEquivalentTo(NuGetLogCode.NU1604); + logs.Select(e => e.Level).Should().AllBeEquivalentTo(LogLevel.Warning); logs.Select(e => e.Message) - .ShouldBeEquivalentTo(new[] + .Should().BeEquivalentTo(new[] { "Project dependency x (< 2.0.0) does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results.", "Project dependency y (< 3.0.0) does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results." @@ -581,7 +581,7 @@ public void GivenAProjectWithATopLevelDependencyVerifyAllFrameworksInTargetGraph var log = UnexpectedDependencyMessages.GetProjectDependenciesMissingLowerBounds(project).Single(); log.Code.Should().Be(NuGetLogCode.NU1604); - log.TargetGraphs.ShouldBeEquivalentTo(new[] { NuGetFramework.Parse("netstandard2.0").DotNetFrameworkName, NuGetFramework.Parse("net46").DotNetFrameworkName }); + log.TargetGraphs.Should().BeEquivalentTo(new[] { NuGetFramework.Parse("netstandard2.0").DotNetFrameworkName, NuGetFramework.Parse("net46").DotNetFrameworkName }); } [Fact] @@ -600,7 +600,7 @@ public void GivenAProjectWithAFrameworkSpecificDependencyVerifySingleTargetGraph var log = UnexpectedDependencyMessages.GetProjectDependenciesMissingLowerBounds(project).Single(); log.Code.Should().Be(NuGetLogCode.NU1604); - log.TargetGraphs.ShouldBeEquivalentTo( + log.TargetGraphs.Should().BeEquivalentTo( new[] { NuGetFramework.Parse("netstandard2.0").DotNetFrameworkName }, "net46 contains a valid range that should be filtered out"); } diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/UnresolvedMessagesTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/UnresolvedMessagesTests.cs index 8573d8cca45..321ceff78b7 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/UnresolvedMessagesTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/UnresolvedMessagesTests.cs @@ -38,7 +38,7 @@ public async Task GivenAnUnresolvedProjectWithExistingProjectVerifyMessage() message.Code.Should().Be(NuGetLogCode.NU1105); message.LibraryId.Should().Be(path); message.Message.Should().Contain($"Unable to find project information for '{path}'"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } } @@ -55,7 +55,7 @@ public async Task GivenAnUnresolvedProjectWithNotFoundVerifyMessage() message.Code.Should().Be(NuGetLogCode.NU1104); message.LibraryId.Should().Be(path); message.Message.Should().Contain($"Unable to find project '{path}'"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } @@ -70,7 +70,7 @@ public async Task GivenAnUnresolvedReferenceVerifyMessage() message.Code.Should().Be(NuGetLogCode.NU1100); message.LibraryId.Should().Be("x"); message.Message.Should().Contain("Unable to resolve 'reference/x ' for 'abc'"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } @@ -86,7 +86,7 @@ public async Task GivenAnUnresolvedPackageWithPreRelVersionsAndPreRelRangeVerify message.LibraryId.Should().Be("x"); message.Message.Should().Contain("Unable to find package x with version (>= 4.0.0-beta && <= 5.0.0)"); message.Message.Should().Contain("Found 2 version(s) in http://nuget.org/a/ [ Nearest version: 4.4.0-beta.2 ]"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } @@ -102,7 +102,7 @@ public async Task GivenAnUnresolvedPackageWithPreRelVersionsVerifyMessage() message.LibraryId.Should().Be("x"); message.Message.Should().Contain("Unable to find a stable package x with version (>= 4.0.0 && <= 5.0.0)"); message.Message.Should().Contain("Found 2 version(s) in http://nuget.org/a/ [ Nearest version: 4.4.0-beta.2 ]"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } @@ -118,7 +118,7 @@ public async Task GivenAnUnresolvedPackageWithVersionsVerifyMessage() message.LibraryId.Should().Be("x"); message.Message.Should().Contain("Unable to find package x with version (= 4.0.0)"); message.Message.Should().Contain("Found 2 version(s) in http://nuget.org/a/ [ Nearest version: 5.0.0 ]"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } @@ -141,7 +141,7 @@ public async Task GivenAnUnresolvedPackageWithNoVersionsAndMultipleSourcesVerify message.Code.Should().Be(NuGetLogCode.NU1101); message.LibraryId.Should().Be("x"); message.Message.Should().Be("Unable to find package x. No packages exist with this id in source(s): http://nuget.org/a/, http://nuget.org/b/"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { targetGraphName }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { targetGraphName }); message.Level.Should().Be(LogLevel.Error); } @@ -156,7 +156,7 @@ public async Task GivenAnUnresolvedPackageWithNoVersionsVerifyMessage() message.Code.Should().Be(NuGetLogCode.NU1101); message.LibraryId.Should().Be("x"); message.Message.Should().Be("Unable to find package x. No packages exist with this id in source(s): http://nuget.org/a/"); - message.TargetGraphs.ShouldBeEquivalentTo(new[] { "abc" }); + message.TargetGraphs.Should().BeEquivalentTo(new[] { "abc" }); message.Level.Should().Be(LogLevel.Error); } @@ -184,8 +184,8 @@ public async Task GivenAMultipleSourcesVerifyInfosReturned() var infos = await UnresolvedMessages.GetSourceInfosForIdAsync("a", VersionRange.Parse("1.0.0"), remoteLibraryProviders, cacheContext.Object, NullLogger.Instance, CancellationToken.None); infos.Count.Should().Be(2); - infos[0].Value.ShouldBeEquivalentTo(versions1); - infos[1].Value.ShouldBeEquivalentTo(versions2); + infos[0].Value.Should().BeEquivalentTo(versions1); + infos[1].Value.Should().BeEquivalentTo(versions2); infos[0].Key.Source.Should().Be("http://nuget.org/a/"); infos[1].Key.Source.Should().Be("http://nuget.org/b/"); } @@ -209,7 +209,7 @@ public async Task GivenAnEmptySourceVerifySourceInfoContainsAllVersions() var info = await UnresolvedMessages.GetSourceInfoForIdAsync(provider.Object, "a", context.Object, NullLogger.Instance, CancellationToken.None); - info.Value.ShouldBeEquivalentTo(versions); + info.Value.Should().BeEquivalentTo(versions); info.Key.Source.Should().Be(source.Source); } @@ -239,7 +239,7 @@ public void GivenARangeWithExclusiveBoundsVerifyExactMatchesCanStillBeSelected() NuGetVersion.Parse("2.0.0") }; - UnresolvedMessages.GetBestMatch(versions, range).ShouldBeEquivalentTo(NuGetVersion.Parse("1.0.0")); + UnresolvedMessages.GetBestMatch(versions, range).Should().BeEquivalentTo(NuGetVersion.Parse("1.0.0")); } [Fact] @@ -251,7 +251,7 @@ public void GivenARangeWithExclusiveBoundsVerifyExactMatchesCanStillBeSelectedFo NuGetVersion.Parse("2.0.0") }; - UnresolvedMessages.GetBestMatch(versions, range).ShouldBeEquivalentTo(NuGetVersion.Parse("2.0.0")); + UnresolvedMessages.GetBestMatch(versions, range).Should().BeEquivalentTo(NuGetVersion.Parse("2.0.0")); } [Theory] @@ -270,7 +270,7 @@ public void GivenRangeOf1To2VerifyBestMatch(string expected, string versionStrin var range = VersionRange.Parse("[1.0.0, 2.0.0]"); var versions = new SortedSet(versionStrings.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(NuGetVersion.Parse)); - UnresolvedMessages.GetBestMatch(versions, range).ShouldBeEquivalentTo(NuGetVersion.Parse(expected)); + UnresolvedMessages.GetBestMatch(versions, range).Should().BeEquivalentTo(NuGetVersion.Parse(expected)); } [Theory] @@ -288,7 +288,7 @@ public void GivenVersionRangeVerifyBestMatch(string versionRange, string expecte var range = VersionRange.Parse(versionRange); var versions = new SortedSet(versionStrings.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(NuGetVersion.Parse)); Assert.Null(range.FindBestMatch(versions)); - UnresolvedMessages.GetBestMatch(versions, range).ShouldBeEquivalentTo(NuGetVersion.Parse(expectedVersion)); + UnresolvedMessages.GetBestMatch(versions, range).Should().BeEquivalentTo(NuGetVersion.Parse(expectedVersion)); } [Fact] diff --git a/test/NuGet.Core.Tests/NuGet.Configuration.Test/PackageSourceTests.cs b/test/NuGet.Core.Tests/NuGet.Configuration.Test/PackageSourceTests.cs index fb4666b61cb..4fc9fa6888a 100644 --- a/test/NuGet.Core.Tests/NuGet.Configuration.Test/PackageSourceTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Configuration.Test/PackageSourceTests.cs @@ -32,9 +32,9 @@ public void Clone_CopiesAllPropertyValuesFromSource() // source credential result.Credentials.Should().NotBeNull(); - result.Credentials.Source.ShouldBeEquivalentTo(source.Credentials.Source); - result.Credentials.Username.ShouldBeEquivalentTo(source.Credentials.Username); - result.Credentials.IsPasswordClearText.ShouldBeEquivalentTo(source.Credentials.IsPasswordClearText); + result.Credentials.Source.Should().BeEquivalentTo(source.Credentials.Source); + result.Credentials.Username.Should().BeEquivalentTo(source.Credentials.Username); + result.Credentials.IsPasswordClearText.Should().Be(source.Credentials.IsPasswordClearText); } [Fact] diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositorySignatureInfoUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositorySignatureInfoUtilityTests.cs index 88046de5ffb..54123f21a73 100644 --- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositorySignatureInfoUtilityTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositorySignatureInfoUtilityTests.cs @@ -25,7 +25,7 @@ public void GetSignedPackageVerifierSettings_NullFallbackSettingsThrows() Action action = () => RepositorySignatureInfoUtility.GetSignedPackageVerifierSettings(repoSignatureInfo: null, fallbackSettings: null); // Assert - action.ShouldThrow(); + action.Should().Throw(); } [Fact] @@ -96,7 +96,7 @@ public void GetSignedPackageVerifierSettings_RepoSignatureInfoFalseAllSignedDoes var settings = RepositorySignatureInfoUtility.GetSignedPackageVerifierSettings(repoSignatureInfo, _defaultSettings); // Assert - settings.ShouldBeEquivalentTo(_defaultSettings); + settings.Should().BeEquivalentTo(_defaultSettings); } [Fact] @@ -110,7 +110,7 @@ public void GetSignedPackageVerifierSettings_RepoSignatureInfoFalseAllSignedDoes var settings = RepositorySignatureInfoUtility.GetSignedPackageVerifierSettings(repoSignatureInfo, _verifyCommandDefaultSettings); // Assert - settings.ShouldBeEquivalentTo(_verifyCommandDefaultSettings); + settings.Should().BeEquivalentTo(_verifyCommandDefaultSettings); } [Fact] @@ -154,7 +154,7 @@ public void GetRepositoryAllowList_RepoSignatureInfoCertificateListWithOneEntryC var allowList = RepositorySignatureInfoUtility.GetRepositoryAllowList(repoCertificateInfo); // Assert - allowList.ShouldBeEquivalentTo(expectedAllowList); + allowList.Should().BeEquivalentTo(expectedAllowList); } [Fact] @@ -210,7 +210,7 @@ public void GetRepositoryAllowList_RepoSignatureInfoCertificateListWithMultipleE var allowList = RepositorySignatureInfoUtility.GetRepositoryAllowList(repoCertificateInfo); // Assert - allowList.ShouldBeEquivalentTo(expectedAllowList); + allowList.Should().BeEquivalentTo(expectedAllowList); } } } diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/TrustedSignersProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/TrustedSignersProviderTests.cs index e5871ee0b4c..09998ee5506 100644 --- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/TrustedSignersProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/TrustedSignersProviderTests.cs @@ -119,7 +119,11 @@ public void GetTrustedSigner_WithNonEmptyTrustedSignersSection_ReturnsAllTrusted var trustedSigners = trustedSignerProvider.GetTrustedSigners(); trustedSigners.Should().NotBeNull(); trustedSigners.Count.Should().Be(3); - trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners); + trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners, + options => options + .Excluding(o => o.SelectedMemberPath == "[0].Origin") + .Excluding(o => o.SelectedMemberPath == "[1].Origin") + .Excluding(o => o.SelectedMemberPath == "[2].Origin")); } } @@ -166,7 +170,12 @@ public void GetTrustedSigner_WithItemsDifferentThanTrustedSigners_IgnoresThemAnd var trustedSigners = trustedSignerProvider.GetTrustedSigners(); trustedSigners.Should().NotBeNull(); trustedSigners.Count.Should().Be(3); - trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners); + trustedSigners.Should().BeEquivalentTo( + expectedTrustedSigners, + options => options + .Excluding(o => o.SelectedMemberPath == "[0].Origin") + .Excluding(o => o.SelectedMemberPath == "[1].Origin") + .Excluding(o => o.SelectedMemberPath == "[2].Origin")); } } @@ -196,7 +205,7 @@ public void Remove_WithEmptyListOFSignersToRemove_Throws() } [Fact] - public void Remove_SuccesffullyRemovesTrustedSigners() + public void Remove_SuccessfullyRemovesTrustedSigners() { // Arrange var config = @" @@ -237,7 +246,11 @@ public void Remove_SuccesffullyRemovesTrustedSigners() trustedSigners = trustedSignerProvider.GetTrustedSigners(); trustedSigners.Should().NotBeNull(); trustedSigners.Count.Should().Be(2); - trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners); + trustedSigners.Should().BeEquivalentTo( + expectedTrustedSigners, + options => options + .Excluding(o => o.SelectedMemberPath == "[0].Origin") + .Excluding(o => o.SelectedMemberPath == "[1].Origin")); } } @@ -283,7 +296,11 @@ public void Remove_IgnoresAnyUnexistantTrustedSigner() trustedSigners = trustedSignerProvider.GetTrustedSigners(); trustedSigners.Should().NotBeNull(); trustedSigners.Count.Should().Be(2); - trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners); + trustedSigners.Should().BeEquivalentTo( + expectedTrustedSigners, + options => options + .Excluding(o => o.SelectedMemberPath == "[0].Origin") + .Excluding(o => o.SelectedMemberPath == "[1].Origin")); } } @@ -342,7 +359,13 @@ public void AddOrUpdateTrustedSigner_WithNewTrustedSigner_AddsItSuccesfully() var trustedSigners = trustedSignerProvider.GetTrustedSigners(); trustedSigners.Should().NotBeNull(); trustedSigners.Count.Should().Be(4); - trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners); + trustedSigners.Should().BeEquivalentTo( + expectedTrustedSigners, + options => options + .Excluding(o => o.SelectedMemberPath == "[0].Origin") + .Excluding(o => o.SelectedMemberPath == "[1].Origin") + .Excluding(o => o.SelectedMemberPath == "[2].Origin") + .Excluding(o => o.SelectedMemberPath == "[3].Origin")); } } @@ -372,7 +395,7 @@ public void AddOrUpdateTrustedSigner_WithExistingTrustedSigner_UpdatesItSuccesfu var expectedTrustedSigners = new List() { - new AuthorItem("author1", new CertificateItem("abc", HashAlgorithmName.SHA256), new CertificateItem("jkl", HashAlgorithmName.SHA256)), + new AuthorItem("author1", new CertificateItem("jkl", HashAlgorithmName.SHA256)), new AuthorItem("author2", new CertificateItem("def", HashAlgorithmName.SHA256)), new RepositoryItem("repo1", "https://serviceIndex.test/v3/api.json", new CertificateItem("ghi", HashAlgorithmName.SHA256)) }; @@ -388,7 +411,11 @@ public void AddOrUpdateTrustedSigner_WithExistingTrustedSigner_UpdatesItSuccesfu var trustedSigners = trustedSignerProvider.GetTrustedSigners(); trustedSigners.Should().NotBeNull(); trustedSigners.Count.Should().Be(3); - trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners); + trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners, + options => options + .Excluding(o => o.SelectedMemberPath == "[0].Origin") + .Excluding(o => o.SelectedMemberPath == "[1].Origin") + .Excluding(o => o.SelectedMemberPath == "[2].Origin")); } } diff --git a/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/AssetTargetFallbackTests.cs b/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/AssetTargetFallbackTests.cs index ff043d93b0c..e789eae1f38 100644 --- a/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/AssetTargetFallbackTests.cs +++ b/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/AssetTargetFallbackTests.cs @@ -38,7 +38,7 @@ public void GivenImportsVerifyValuePersisted() spec.TargetFrameworks[0].Imports.Add(net461); var outSpec = spec.RoundTrip(); - outSpec.TargetFrameworks[0].Imports.ShouldBeEquivalentTo(new[] { net461 }); + outSpec.TargetFrameworks[0].Imports.Should().BeEquivalentTo(new[] { net461 }); } [Fact] diff --git a/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/LockFileExtensionsTests.cs b/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/LockFileExtensionsTests.cs index fc9892925f7..abe2b6f4b30 100644 --- a/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/LockFileExtensionsTests.cs +++ b/test/NuGet.Core.Tests/NuGet.ProjectModel.Test/LockFileExtensionsTests.cs @@ -32,7 +32,7 @@ public void GivenALogMessageVerifyTargetGraphIsReturned() var graphs = message.GetTargetGraphs(assetsFile); - graphs.Select(e => e.Name).ShouldBeEquivalentTo(new[] { expected }); + graphs.Select(e => e.Name).Should().BeEquivalentTo(new[] { expected }); } [Fact] @@ -59,7 +59,7 @@ public void GivenALogMessageWithMultipleGraphsVerifyTargetGraphsAreReturned() var graphs = message.GetTargetGraphs(assetsFile); - graphs.Select(e => e.Name).ShouldBeEquivalentTo(new[] { expected1, expected2 }); + graphs.Select(e => e.Name).Should().BeEquivalentTo(new[] { expected1, expected2 }); } [Fact] @@ -91,7 +91,7 @@ public void GivenALogMessageWithNoTargetGraphsVerifyAllGraphsAreReturned() var graphs = message.GetTargetGraphs(assetsFile); - graphs.Select(e => e.Name).ShouldBeEquivalentTo(new[] { expected1, expected2, expected3 }); + graphs.Select(e => e.Name).Should().BeEquivalentTo(new[] { expected1, expected2, expected3 }); } [Fact] @@ -131,7 +131,7 @@ public void GivenALogMessageVerifyTargetGraphLibraryIsReturned() var graphs = message.GetTargetGraphs(assetsFile); - graphs.SelectMany(e => e.Libraries).Select(e => e.Name).ShouldBeEquivalentTo(new[] { "x" }); + graphs.SelectMany(e => e.Libraries).Select(e => e.Name).Should().BeEquivalentTo(new[] { "x" }); } } } diff --git a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/ApexBaseTestClass.cs b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/ApexBaseTestClass.cs index 77a9ab6e338..35e1eaf47e4 100644 --- a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/ApexBaseTestClass.cs +++ b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/ApexBaseTestClass.cs @@ -41,11 +41,7 @@ public virtual NuGetApexTestService GetNuGetTestService() public virtual void Dispose() { - if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NUGET_TEST_CLOSE_VS_AFTER_EACH_TEST"))) - { - //test cleanup - CloseVisualStudioHost(); - } + CloseVisualStudioHost(); } } } diff --git a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetApexTestService.cs b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetApexTestService.cs index ef50ed10365..700ba799231 100644 --- a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetApexTestService.cs +++ b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetApexTestService.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; @@ -192,7 +193,7 @@ public void UninstallPackage(string projectName, string packageName, bool remove public NuGetUIProjectTestExtension GetUIWindowfromProject(ProjectTestExtension project, TimeSpan timeout, TimeSpan interval) { var uiproject = NuGetApexUITestService.GetApexTestUIProject(project.Name, timeout, interval); - return new NuGetUIProjectTestExtension(uiproject); + return new NuGetUIProjectTestExtension(uiproject, Logger); } /// @@ -202,7 +203,7 @@ public NuGetUIProjectTestExtension GetUIWindowfromProject(ProjectTestExtension p public NuGetUIProjectTestExtension GetUIWindowfromProject(ProjectTestExtension project) { var uiproject = NuGetApexUITestService.GetApexTestUIProject(project.Name, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(1)); - return new NuGetUIProjectTestExtension(uiproject); + return new NuGetUIProjectTestExtension(uiproject, Logger); } public NuGetConsoleTestExtension GetPackageManagerConsole(string project) diff --git a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetUIProjectTestExtension.cs b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetUIProjectTestExtension.cs index 074a904627c..1d888b0a23d 100644 --- a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetUIProjectTestExtension.cs +++ b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/Apex/NuGetUIProjectTestExtension.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.Test.Apex.Services; using NuGet.PackageManagement.UI; using NuGet.PackageManagement.UI.TestContract; using NuGet.Packaging.Core; @@ -13,13 +15,15 @@ namespace NuGet.Tests.Apex public class NuGetUIProjectTestExtension : NuGetBaseTestExtension { private ApexTestUIProject _uiproject; - private TimeSpan _timeout = TimeSpan.FromSeconds(5); + private TimeSpan _timeout = TimeSpan.FromMinutes(1); + private ITestLogger _logger; public bool IsSolution { get => _uiproject.IsSolution; } - public NuGetUIProjectTestExtension(ApexTestUIProject project) + public NuGetUIProjectTestExtension(ApexTestUIProject project, ITestLogger logger) { _uiproject = project; + _logger = logger; } public bool SeachPackgeFromUI(string searchText) @@ -29,20 +33,34 @@ public bool SeachPackgeFromUI(string searchText) public bool InstallPackageFromUI(string packageId, string version) { - return _uiproject.WaitForActionComplete(() => _uiproject.InstallPackage(packageId, version), _timeout); + Stopwatch sw = Stopwatch.StartNew(); + bool result = _uiproject.WaitForActionComplete(() => _uiproject.InstallPackage(packageId, version), _timeout); + sw.Stop(); + + _logger.WriteMessage($"{nameof(InstallPackageFromUI)} took {sw.ElapsedMilliseconds}ms to complete"); + return result; } public bool UninstallPackageFromUI(string packageId) { - return _uiproject.WaitForActionComplete(() => _uiproject.UninstallPackage(packageId), _timeout); + Stopwatch sw = Stopwatch.StartNew(); + bool result = _uiproject.WaitForActionComplete(() => _uiproject.UninstallPackage(packageId), _timeout); + sw.Stop(); + + _logger.WriteMessage($"{nameof(UninstallPackageFromUI)} took {sw.ElapsedMilliseconds}ms to complete"); + return result; } public bool UpdatePackageFromUI(string packageId, string version) { - return _uiproject.WaitForActionComplete( - () => _uiproject.UpdatePackage( - new List() { new PackageIdentity(packageId, NuGetVersion.Parse(version)) }), + Stopwatch sw = Stopwatch.StartNew(); + bool result = _uiproject.WaitForActionComplete( + () => _uiproject.UpdatePackage(new List() { new PackageIdentity(packageId, NuGetVersion.Parse(version)) }), _timeout); + sw.Stop(); + + _logger.WriteMessage($"{nameof(UpdatePackageFromUI)} took {sw.ElapsedMilliseconds}ms to complete"); + return result; } public void SwitchTabToBrowse() diff --git a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/NuGetEndToEndTests/NuGetUITestCase.cs b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/NuGetEndToEndTests/NuGetUITestCase.cs index 096561cad2d..c68fe8c1f82 100644 --- a/test/NuGet.Tests.Apex/NuGet.Tests.Apex/NuGetEndToEndTests/NuGetUITestCase.cs +++ b/test/NuGet.Tests.Apex/NuGet.Tests.Apex/NuGetEndToEndTests/NuGetUITestCase.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.IO; +using EnvDTE; using Microsoft.Test.Apex.VisualStudio.Solution; using Xunit; using Xunit.Abstractions; @@ -31,9 +32,10 @@ public void SearchPackageFromUI() solutionService.CreateEmptySolution(); var project = solutionService.AddProject(ProjectLanguage.CSharp, ProjectTemplate.ClassLibrary, ProjectTargetFramework.V46, "TestProject"); VisualStudio.ClearOutputWindow(); + solutionService.SaveAll(); // Act - dte.ExecuteCommand("Project.ManageNuGetPackages"); + OpenNuGetPackageManagerWithDte(); var nugetTestService = GetNuGetTestService(); var uiwindow = nugetTestService.GetUIWindowfromProject(project); uiwindow.SwitchTabToBrowse(); @@ -54,9 +56,10 @@ public void InstallPackageFromUI() solutionService.CreateEmptySolution(); var project = solutionService.AddProject(ProjectLanguage.CSharp, ProjectTemplate.ClassLibrary, ProjectTargetFramework.V46, "TestProject"); VisualStudio.ClearOutputWindow(); + solutionService.SaveAll(); // Act - dte.ExecuteCommand("Project.ManageNuGetPackages"); + OpenNuGetPackageManagerWithDte(); var nugetTestService = GetNuGetTestService(); var uiwindow = nugetTestService.GetUIWindowfromProject(project); uiwindow.InstallPackageFromUI("newtonsoft.json", "9.0.1"); @@ -76,14 +79,15 @@ public void InstallPackageToProjectsFromUI() solutionService.CreateEmptySolution(); var project = solutionService.AddProject(ProjectLanguage.CSharp, ProjectTemplate.ClassLibrary, ProjectTargetFramework.V46, "TestProject"); var nuProject = solutionService.AddProject(ProjectLanguage.CSharp, ProjectTemplate.ClassLibrary, ProjectTargetFramework.V46, "NuProject"); + solutionService.SaveAll(); // Act - dte.ExecuteCommand("Project.ManageNuGetPackages"); + OpenNuGetPackageManagerWithDte(); var nugetTestService = GetNuGetTestService(); var uiwindow = nugetTestService.GetUIWindowfromProject(nuProject); uiwindow.InstallPackageFromUI("newtonsoft.json", "9.0.1"); VisualStudio.SelectProjectInSolutionExplorer(project.Name); - dte.ExecuteCommand("Project.ManageNuGetPackages"); + OpenNuGetPackageManagerWithDte(); VisualStudio.ClearOutputWindow(); var uiwindow2 = nugetTestService.GetUIWindowfromProject(project); @@ -94,7 +98,7 @@ public void InstallPackageToProjectsFromUI() CommonUtility.AssertPackageInPackagesConfig(VisualStudio, nuProject, "newtonsoft.json", "9.0.1", XunitLogger); } - [StaFact(Skip = "https://github.com/NuGet/Home/issues/10412")] + [StaFact] public void UninstallPackageFromUI() { // Arrange @@ -104,8 +108,10 @@ public void UninstallPackageFromUI() solutionService.CreateEmptySolution(); var project = solutionService.AddProject(ProjectLanguage.CSharp, ProjectTemplate.ClassLibrary, ProjectTargetFramework.V46, "TestProject"); + solutionService.SaveAll(); + FileInfo packagesConfigFile = GetPackagesConfigFile(project); - dte.ExecuteCommand("Project.ManageNuGetPackages"); + OpenNuGetPackageManagerWithDte(); var nugetTestService = GetNuGetTestService(); var uiwindow = nugetTestService.GetUIWindowfromProject(project); uiwindow.InstallPackageFromUI("newtonsoft.json", "9.0.1"); @@ -134,9 +140,10 @@ public void UpdatePackageFromUI() solutionService.CreateEmptySolution(); var project = solutionService.AddProject(ProjectLanguage.CSharp, ProjectTemplate.ClassLibrary, ProjectTargetFramework.V46, "TestProject"); VisualStudio.ClearWindows(); + solutionService.SaveAll(); // Act - dte.ExecuteCommand("Project.ManageNuGetPackages"); + OpenNuGetPackageManagerWithDte(); var nugetTestService = GetNuGetTestService(); var uiwindow = nugetTestService.GetUIWindowfromProject(project); uiwindow.InstallPackageFromUI("newtonsoft.json", "9.0.1"); @@ -149,6 +156,34 @@ public void UpdatePackageFromUI() CommonUtility.AssertPackageInPackagesConfig(VisualStudio, project, "newtonsoft.json", "10.0.3", XunitLogger); } + private void OpenNuGetPackageManagerWithDte() + { + VisualStudio.ObjectModel.Solution.WaitForOperationsInProgress(TimeSpan.FromMinutes(3)); + WaitForCommandAvailable("Project.ManageNuGetPackages", TimeSpan.FromMinutes(1)); + VisualStudio.Dte.ExecuteCommand("Project.ManageNuGetPackages"); + } + + private void WaitForCommandAvailable(string commandName, TimeSpan timeout) + { + WaitForCommandAvailable(VisualStudio.Dte.Commands.Item(commandName), timeout); + } + + private void WaitForCommandAvailable(Command cmd, TimeSpan timeout) + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + while (stopWatch.Elapsed < timeout) + { + if (cmd.IsAvailable) + { + return; + } + System.Threading.Thread.Sleep(250); + } + + XunitLogger.LogWarning($"Timed out waiting for {cmd.Name} to be available"); + } + private static FileInfo GetPackagesConfigFile(ProjectTestExtension project) { var projectFile = new FileInfo(project.FullPath); @@ -174,4 +209,4 @@ private static void WaitForFileNotExists(FileInfo file) $"{file.FullName} still existed after {Timeout}."); } } -} \ No newline at end of file +} From dfa9a83f1e1fddc6fc7479a79227bdcf560c5563 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 22 Jan 2021 16:30:32 -0800 Subject: [PATCH 116/129] Simplify the PR template, add checkboxes, remove redundant info (#3851) --- .github/PULL_REQUEST_TEMPLATE.md | 35 +++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ec7cf79346a..aa3787e2de3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,16 +1,31 @@ + ## Bug -Fixes: Link_to_issue (search [NuGet/Home](https://github.com/NuGet/Home/issues), and create one if you can't find a suitable issue) -Regression: Yes/No -* Last working version: -* How are we preventing it in future: + + +Fixes: -## Fix +Regression? Last working version: -Details: Details_about_the_fix +## Description + -## Testing/Validation +## PR Checklist -Tests Added: Yes/No -Reason for not adding tests: -Validation: +- [ ] PR has a meaningful title +- [ ] PR has a linked issue. +- [ ] Described changes + +- **Tests** + - [ ] Automated tests added + - **OR** + + - [ ] Test exception + - **OR** + - [ ] N/A + +- **Documentation** + + - [ ] Documentation PR or issue filled + - **OR** + - [ ] N/A From ff9d0f1bb2a072595f4b1979635274b140e49d15 Mon Sep 17 00:00:00 2001 From: Erdembayar Yondon Date: Fri, 22 Jan 2021 17:18:40 -0800 Subject: [PATCH 117/129] Understand PMC and Powershell usages (#3755) * Event to track how many times commands are executed on PMC. * Batch count of commands executed on PMC. * Fix format. * Add telemetry for how many times PMC was openened. Add telemetry for if PMC opened by default without user gesture. Add telemetry for how many times powershell commands executed. * Add code comment for automatically loaded PMC. * There are 2 seperate instances of PowerShellHost.cs can be created for PM UI and PM PMC. So make change to accommodiate this concern. * Combine 2 events make less number of event (just 1) to emit. * Fix typos. * Add actual origin which caused init.ps1 to run into telemetry. * Make names of telemetry event a constants. * Get donnie's advise for naming. * Remove init.ps1 telemetry because current scenario doesn't capture initial run of install new package with init.ps1. It's bit complicated. * Address Andy's code review comment. * Remove unused variable. * Send single event for both PMUI and PMC powershell events. * Make powershell telemetry works for with and without solution load. * No need to emit separate nugetvssolutionclose if there were no solution at all. * Refactor code so it's not much mix too much telemetry code into other code. * Add telemetry detecting Nuget command and load of init.ps1 for packages. * Move telemetry logic into seperate class VsPowerShellHostTelemetryEmit for emitting telemetry in PowerShellHost.cs * Fix formatting. * Remove manually typed consts with centralized one. * Move INuGetTelemetryAggregator so we don't have to publish new api. * Clean up * Fix typos * Start recording PMC usage without any solution load as seperate 'NuGetVSInstanceClose' event with 'SolutionLoaded' = false flag. Otherwise it's almost impossible to separate them. * Clean up * Add missing telemetry property * INuGetTelemetryCollector doesn't need to be Lazy since it's used immediately. * Address code review comment by Nikolche. * Remove unnecessary load of assembly. * Revert unneeded change. * Separate telemtry collector and emitter. * Move solution events to VSSolutionManager.cs * Make telemetry collector thread safe. * Refactor to use separate telemetry-event classes. * Correct class name same to file name. * Address PR comment by Fernando * Fix typo. * Correct event class names * Clean up and improve Powershell/PowershellTelemetryEmitter. * Fix typos. * Stop passing telemetry event between different methods. * Improve reaadability * Move no any solution is loaded and not executed any command logic to PowerShellHostTelemetryProcessor.cs * Correct prefix . * Refactor whole design after consulting with Andy. * Fix reopen flag might not work from dispose on PMC window. * Correct window count logic. * Improve formatting and fix PMC, PMUI loaded not set from after load from init.ps1 * Correct solution count. * Address PR comment Nkolche. * Address remaining review comments from Andy. * Clean up fix and fix typos. * Fix if PMC opened without solution then that window load is not counted. * Address PR comments by Fernando. * Address latest Andy's comments (removing prefix etc) * Address latest PR comment from Andy and Fernando. Now solution close event called vs/nuget/solutionclose and vs instance close event called vs/nuget/instanceclose. * Fix naming conventions. --- .../Xamls/ConsoleContainer.xaml.cs | 17 + .../NuGetPowerShellBaseCommand.cs | 4 + .../IDE/VSSolutionManager.cs | 7 +- src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs | 12 + .../NuGetPowerShellUsageCollector.cs | 365 ++++++++++++++++++ .../Powershell/NuGetPowerShellUsage.cs | 72 ++++ .../PowerShellHost.cs | 46 ++- 7 files changed, 509 insertions(+), 14 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs diff --git a/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs b/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs index f8c5cc3a737..6c715d45e8d 100644 --- a/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs +++ b/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs @@ -14,6 +14,7 @@ using NuGet.VisualStudio; using NuGet.VisualStudio.Common; using NuGet.VisualStudio.Internal.Contracts; +using NuGet.VisualStudio.Telemetry.PowerShell; namespace NuGetConsole { @@ -28,6 +29,9 @@ public ConsoleContainer() { InitializeComponent(); + Loaded += ConsoleContainer_Loaded; + Unloaded += ConsoleContainer_UnLoaded; + ThreadHelper.JoinableTaskFactory.StartOnIdle( async () => { @@ -76,6 +80,9 @@ public void NotifyInitializationCompleted() public void Dispose() { + Loaded -= ConsoleContainer_Loaded; + Unloaded -= ConsoleContainer_UnLoaded; + // Use more verbose null-checking syntax to avoid ISB001 misfiring. if (_solutionManager != null) { @@ -84,5 +91,15 @@ public void Dispose() GC.SuppressFinalize(this); } + + void ConsoleContainer_Loaded(object sender, RoutedEventArgs e) + { + NuGetPowerShellUsage.RaisePmcWindowsLoadEvent(isLoad: true); + } + + void ConsoleContainer_UnLoaded(object sender, RoutedEventArgs e) + { + NuGetPowerShellUsage.RaisePmcWindowsLoadEvent(isLoad: false); + } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs index 0b5917d81d5..831d3e57341 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs @@ -28,6 +28,7 @@ using NuGet.Protocol.Core.Types; using NuGet.Versioning; using NuGet.VisualStudio; +using NuGet.VisualStudio.Telemetry.PowerShell; using ExecutionContext = NuGet.ProjectManagement.ExecutionContext; namespace NuGet.PackageManagement.PowerShellCmdlets @@ -214,6 +215,9 @@ protected override sealed void ProcessRecord() stopWatch.Start(); try { + // Record NuGetCmdlet executed + NuGetPowerShellUsage.RaiseNuGetCmdletExecutedEvent(); + ProcessRecordCore(); } catch (Exception ex) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs index 6171f53d821..ac72279f510 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs @@ -26,6 +26,7 @@ using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.VisualStudio; +using NuGet.VisualStudio.Telemetry.PowerShell; using IAsyncServiceProvider = Microsoft.VisualStudio.Shell.IAsyncServiceProvider; using Task = System.Threading.Tasks.Task; @@ -184,8 +185,6 @@ private async Task InitializeAsync() }); }); - TelemetryActivity.NuGetTelemetryService = new NuGetVSTelemetryService(); - _vsMonitorSelection = await _asyncServiceProvider.GetServiceAsync(); var solutionLoadedGuid = VSConstants.UICONTEXT.SolutionExistsAndFullyLoaded_guid; @@ -499,6 +498,8 @@ private async Task OnSolutionExistsAndFullyLoadedAsync() SolutionOpening?.Invoke(this, EventArgs.Empty); + NuGetPowerShellUsage.RaiseSolutionOpenEvent(); + // although the SolutionOpened event fires, the solution may be only in memory (e.g. when // doing File - New File). In that case, we don't want to act on the event. if (!await IsSolutionOpenAsync()) @@ -526,6 +527,8 @@ private void OnAfterClosing() private void OnBeforeClosing() { + NuGetPowerShellUsage.RaiseSolutionCloseEvent(); + SolutionClosing?.Invoke(this, EventArgs.Empty); } diff --git a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs index c85519b6d86..e487567017f 100644 --- a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs +++ b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs @@ -28,6 +28,7 @@ using NuGet.VisualStudio.Common; using NuGet.VisualStudio.Internal.Contracts; using NuGet.VisualStudio.Telemetry; +using NuGet.VisualStudio.Telemetry.PowerShell; using NuGetConsole; using NuGetConsole.Implementation; using ContractsNuGetServices = NuGet.VisualStudio.Contracts.NuGetServices; @@ -96,6 +97,7 @@ public sealed class NuGetPackage : AsyncPackage, IVsPackageExtensionProvider, IV private uint _solutionExistsCookie; private bool _powerConsoleCommandExecuting; private bool _initialized; + private NuGetPowerShellUsageCollector _nuGetPowerShellUsageCollector; public NuGetPackage() { @@ -145,6 +147,9 @@ public NuGetPackage() /// protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) { + _nuGetPowerShellUsageCollector = new NuGetPowerShellUsageCollector(); + NuGet.Common.TelemetryActivity.NuGetTelemetryService = new NuGetVSTelemetryService(); + await base.InitializeAsync(cancellationToken, progress); // Add our command handlers for menu (commands must exist in the .vsct file) @@ -179,6 +184,8 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke ThreadHelper.JoinableTaskFactory); await NuGetBrokeredServiceFactory.ProfferServicesAsync(this); + + VsShellUtilities.ShutdownToken.Register(RegisterEmitVSInstancePowerShellTelemetry); } /// @@ -1247,6 +1254,11 @@ private void OnBeginShutDown() _dteEvents = null; } + private void RegisterEmitVSInstancePowerShellTelemetry() + { + NuGetPowerShellUsage.RaiseVSInstanceCloseEvent(); + } + #region IVsPersistSolutionOpts // Called by the shell when a solution is opened and the SUO file is read. diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs new file mode 100644 index 00000000000..5e9405f3a41 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs @@ -0,0 +1,365 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using NuGet.Common; +using NuGet.VisualStudio.Telemetry.PowerShell; + +namespace NuGet.VisualStudio.Telemetry +{ + public sealed class NuGetPowerShellUsageCollector : IDisposable + { + // PMC, PMUI powershell telemetry consts + public const string PmcExecuteCommandCount = nameof(PmcExecuteCommandCount); + public const string PmuiExecuteCommandCount = nameof(PmuiExecuteCommandCount); + public const string NuGetCommandUsed = nameof(NuGetCommandUsed); + public const string InitPs1LoadPmui = nameof(InitPs1LoadPmui); + public const string InitPs1LoadPmc = nameof(InitPs1LoadPmc); + public const string InitPs1LoadedFromPmcFirst = nameof(InitPs1LoadedFromPmcFirst); + public const string LoadedFromPmui = nameof(LoadedFromPmui); + public const string FirstTimeLoadedFromPmui = nameof(FirstTimeLoadedFromPmui); + public const string LoadedFromPmc = nameof(LoadedFromPmc); + public const string FirstTimeLoadedFromPmc = nameof(FirstTimeLoadedFromPmc); + public const string SolutionLoaded = nameof(SolutionLoaded); + public const string Trigger = nameof(Trigger); + public const string Pmc = nameof(Pmc); + public const string Pmui = nameof(Pmui); + + // PMC UI Console Container telemetry consts + public const string PmcWindowLoadCount = nameof(PmcWindowLoadCount); + public const string ReOpenAtStart = nameof(ReOpenAtStart); + + // Const name for emitting when VS solution close or VS instance close. + public const string SolutionClose = nameof(SolutionClose); + public const string InstanceClose = nameof(InstanceClose); + public const string PowerShellHost = "PowerShellHost."; + public const string SolutionCount = nameof(SolutionCount); + public const string PmcPowerShellLoadedSolutionCount = nameof(PmcPowerShellLoadedSolutionCount); + public const string PmuiPowerShellLoadedSolutionCount = nameof(PmuiPowerShellLoadedSolutionCount); + public const string PowerShellLoaded = nameof(PowerShellLoaded); + + private int _solutionCount; + private SolutionData _vsSolutionData; + private readonly InstanceData _vsInstanceData; + private object _lock = new object(); + + public NuGetPowerShellUsageCollector() + { + _vsSolutionData = new SolutionData(); + _vsInstanceData = new InstanceData(); + + NuGetPowerShellUsage.PowerShellLoadEvent += NuGetPowerShellUsage_PMCLoadEventHandler; + NuGetPowerShellUsage.PowerShellCommandExecuteEvent += NuGetPowerShellUsage_PowerShellCommandExecuteEventHandler; + NuGetPowerShellUsage.NuGetCmdletExecutedEvent += NuGetPowerShellUsage_NuGetCmdletExecutedEventHandler; + NuGetPowerShellUsage.InitPs1LoadEvent += NuGetPowerShellUsage_InitPs1LoadEventHandler; + NuGetPowerShellUsage.PmcWindowsEvent += NuGetPowerShellUsage_PMCWindowsEventHandler; + NuGetPowerShellUsage.SolutionOpenEvent += NuGetPowerShellUsage_SolutionOpenHandler; + NuGetPowerShellUsage.SolutionCloseEvent += NuGetPowerShellUsage_SolutionCloseHandler; + NuGetPowerShellUsage.VSInstanceCloseEvent += NuGetPowerShellUsage_VSInstanseCloseHandler; + } + + private void NuGetPowerShellUsage_PMCLoadEventHandler(bool isPMC) + { + AddPowerShellLoadedData(isPMC, _vsSolutionData); + } + + internal void AddPowerShellLoadedData(bool isPMC, SolutionData vsSolutionData) + { + lock (_lock) + { + if (isPMC) + { + if (!vsSolutionData.LoadedFromPmc) + { + vsSolutionData.FirstTimeLoadedFromPmc = true; + _vsInstanceData.PmcLoadedSolutionCount++; + } + + vsSolutionData.LoadedFromPmc = true; + } + else + { + if (!vsSolutionData.LoadedFromPmui) + { + vsSolutionData.FirstTimeLoadedFromPmui = true; + _vsInstanceData.PmuiLoadedSolutionCount++; + } + + vsSolutionData.LoadedFromPmui = true; + } + } + } + + private void NuGetPowerShellUsage_PowerShellCommandExecuteEventHandler(bool isPMC) + { + AddPowerShellCommandExecuteData(isPMC, _vsSolutionData); + } + + internal void AddPowerShellCommandExecuteData(bool isPMC, SolutionData vsSolutionData) + { + lock (_lock) + { + // Please note: Direct PMC and PMUI don't share same code path for installing packages with *.ps1 files + if (isPMC) + { + // For PMC all installation done in one pass so no double counting. + vsSolutionData.PmcExecuteCommandCount++; + _vsInstanceData.PmcExecuteCommandCount++; + } + else + { + // This one is called for both init.ps1 and install.ps1 seperately. + // install.ps1 running inside MSBuildNuGetProject.cs (InstallPackageAsync method) may result in duplicate counting. + // Also this concern valid for dependent packages (of installing package) with *.ps1 files. + vsSolutionData.PmuiExecuteCommandCount++; + _vsInstanceData.PmuiExecuteCommandCount++; + } + } + } + + private void NuGetPowerShellUsage_NuGetCmdletExecutedEventHandler() + { + AddNuGetCmdletExecutedData(_vsSolutionData); + } + + internal void AddNuGetCmdletExecutedData(SolutionData vsSolutionData) + { + lock (_lock) + { + vsSolutionData.NuGetCommandUsed = true; + } + } + + private void NuGetPowerShellUsage_InitPs1LoadEventHandler(bool isPMC) + { + AddInitPs1LoadData(isPMC, _vsSolutionData); + } + + internal void AddInitPs1LoadData(bool isPMC, SolutionData vsSolutionData) + { + lock (_lock) + { + if (isPMC && (!vsSolutionData.FirstTimeLoadedFromPmc && !vsSolutionData.FirstTimeLoadedFromPmui)) + { + vsSolutionData.InitPs1LoadedFromPmcFirst = true; + } + + if (isPMC) + { + vsSolutionData.InitPs1LoadPmc = true; + + if (!vsSolutionData.LoadedFromPmc) + { + vsSolutionData.FirstTimeLoadedFromPmc = true; + _vsInstanceData.PmcLoadedSolutionCount++; + } + + vsSolutionData.LoadedFromPmc = true; + } + else + { + vsSolutionData.InitPs1LoadPmui = true; + + if (!vsSolutionData.LoadedFromPmui) + { + vsSolutionData.FirstTimeLoadedFromPmui = true; + _vsInstanceData.PmuiLoadedSolutionCount++; + } + + vsSolutionData.LoadedFromPmui = true; + } + } + } + + private void NuGetPowerShellUsage_PMCWindowsEventHandler(bool isLoad) + { + AddPMCWindowsEventData(isLoad); + } + + internal void AddPMCWindowsEventData(bool isLoad) + { + lock (_lock) + { + if (isLoad) + { + _vsSolutionData.PmcWindowLoadCount++; + _vsInstanceData.PmcWindowLoadCount++; + } + + // Shutdown call happen before Unload event for PMCWindow so VSInstanceClose event going to have current up to date status. + _vsInstanceData.ReOpenAtStart = isLoad; + } + } + + private void NuGetPowerShellUsage_SolutionOpenHandler() + { + lock (_lock) + { + // Edge case: PMC used without solution load + if (!_vsSolutionData.SolutionLoaded && _vsSolutionData.PmcExecuteCommandCount > 0) + { + // PMC used before any solution is loaded, let's emit what we have for nugetvsinstanceclose event. + TelemetryActivity.EmitTelemetryEvent(_vsSolutionData.ToTelemetryEvent()); + ClearSolutionData(); + } + + if (_vsSolutionData.LoadedFromPmc) + { + _vsInstanceData.PmcLoadedSolutionCount++; + } + + if (_vsSolutionData.LoadedFromPmui) + { + _vsInstanceData.PmuiLoadedSolutionCount++; + } + + _vsInstanceData.SolutionCount = ++_solutionCount; + _vsSolutionData.SolutionLoaded = true; + } + } + + private void NuGetPowerShellUsage_SolutionCloseHandler() + { + lock (_lock) + { + TelemetryActivity.EmitTelemetryEvent(_vsSolutionData.ToTelemetryEvent()); + ClearSolutionData(); + } + } + + private void NuGetPowerShellUsage_VSInstanseCloseHandler() + { + lock (_lock) + { + // Edge case: PMC used without solution load + if (!_vsSolutionData.SolutionLoaded && _vsSolutionData.PmcExecuteCommandCount > 0) + { + // PMC used before any solution is loaded, let's emit what we have for nugetvsinstanceclose event. + TelemetryActivity.EmitTelemetryEvent(_vsSolutionData.ToTelemetryEvent()); + } + + // Emit VS Instance telemetry + TelemetryActivity.EmitTelemetryEvent(_vsInstanceData.ToTelemetryEvent()); + } + } + + // If open new solution then need to clear previous solution events. But powershell remain loaded in memory. + private void ClearSolutionData() + { + bool pmcPowershellLoad = _vsSolutionData.LoadedFromPmc; + bool pmuiPowershellLoad = _vsSolutionData.LoadedFromPmui; + + _vsSolutionData = new SolutionData(); + + _vsSolutionData.LoadedFromPmc = pmcPowershellLoad; + _vsSolutionData.LoadedFromPmui = pmuiPowershellLoad; + } + + public void Dispose() + { + NuGetPowerShellUsage.PowerShellLoadEvent -= NuGetPowerShellUsage_PMCLoadEventHandler; + NuGetPowerShellUsage.PowerShellCommandExecuteEvent -= NuGetPowerShellUsage_PowerShellCommandExecuteEventHandler; + NuGetPowerShellUsage.NuGetCmdletExecutedEvent -= NuGetPowerShellUsage_NuGetCmdletExecutedEventHandler; + NuGetPowerShellUsage.InitPs1LoadEvent -= NuGetPowerShellUsage_InitPs1LoadEventHandler; + NuGetPowerShellUsage.PmcWindowsEvent -= NuGetPowerShellUsage_PMCWindowsEventHandler; + NuGetPowerShellUsage.SolutionOpenEvent -= NuGetPowerShellUsage_SolutionOpenHandler; + NuGetPowerShellUsage.SolutionCloseEvent -= NuGetPowerShellUsage_SolutionCloseHandler; + NuGetPowerShellUsage.VSInstanceCloseEvent -= NuGetPowerShellUsage_VSInstanseCloseHandler; + } + + internal class SolutionData + { + internal bool FirstTimeLoadedFromPmc { get; set; } + internal bool FirstTimeLoadedFromPmui { get; set; } + internal bool InitPs1LoadedFromPmcFirst { get; set; } + internal bool InitPs1LoadPmc { get; set; } + internal bool InitPs1LoadPmui { get; set; } + internal bool LoadedFromPmc { get; set; } + internal bool LoadedFromPmui { get; set; } + internal bool NuGetCommandUsed { get; set; } + internal int PmcExecuteCommandCount { get; set; } + internal int PmcWindowLoadCount { get; set; } + internal int PmuiExecuteCommandCount { get; set; } + internal bool SolutionLoaded { get; set; } + + internal SolutionData() + { + FirstTimeLoadedFromPmc = false; + FirstTimeLoadedFromPmui = false; + InitPs1LoadedFromPmcFirst = false; + InitPs1LoadPmc = false; + InitPs1LoadPmui = false; + LoadedFromPmc = false; + LoadedFromPmui = false; + NuGetCommandUsed = false; + PmcExecuteCommandCount = 0; + PmcWindowLoadCount = 0; + PmuiExecuteCommandCount = 0; + SolutionLoaded = false; + + } + + internal TelemetryEvent ToTelemetryEvent() + { + var telemetry = new TelemetryEvent(SolutionClose, + new Dictionary() + { + { PowerShellHost + NuGetPowerShellUsageCollector.FirstTimeLoadedFromPmc , FirstTimeLoadedFromPmc }, + { PowerShellHost + NuGetPowerShellUsageCollector.FirstTimeLoadedFromPmui , FirstTimeLoadedFromPmui }, + { PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadedFromPmcFirst , InitPs1LoadedFromPmcFirst }, + { PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadPmc , InitPs1LoadPmc }, + { PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadPmui , InitPs1LoadPmui }, + { PowerShellHost + NuGetPowerShellUsageCollector.LoadedFromPmc , LoadedFromPmc }, + { PowerShellHost + NuGetPowerShellUsageCollector.LoadedFromPmui , LoadedFromPmui }, + { PowerShellHost + NuGetPowerShellUsageCollector.NuGetCommandUsed , NuGetCommandUsed }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmcExecuteCommandCount , PmcExecuteCommandCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmcWindowLoadCount , PmcWindowLoadCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmuiExecuteCommandCount , PmuiExecuteCommandCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.SolutionLoaded , SolutionLoaded } + }); + + return telemetry; + } + } + + internal class InstanceData + { + internal int PmcExecuteCommandCount { get; set; } + internal int PmcWindowLoadCount { get; set; } + internal int PmuiExecuteCommandCount { get; set; } + internal int PmcLoadedSolutionCount { get; set; } + internal int PmuiLoadedSolutionCount { get; set; } + internal bool ReOpenAtStart { get; set; } + internal int SolutionCount { get; set; } + + internal InstanceData() + { + PmcExecuteCommandCount = 0; + PmcWindowLoadCount = 0; + PmuiExecuteCommandCount = 0; + PmcLoadedSolutionCount = 0; + PmuiLoadedSolutionCount = 0; + ReOpenAtStart = false; + SolutionCount = 0; + } + + internal TelemetryEvent ToTelemetryEvent() + { + var telemetry = new TelemetryEvent(InstanceClose, + new Dictionary() + { + { PowerShellHost + NuGetPowerShellUsageCollector.PmcExecuteCommandCount , PmcExecuteCommandCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmcWindowLoadCount , PmcWindowLoadCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmuiExecuteCommandCount , PmuiExecuteCommandCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmcPowerShellLoadedSolutionCount , PmcLoadedSolutionCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.PmuiPowerShellLoadedSolutionCount , PmuiLoadedSolutionCount }, + { PowerShellHost + NuGetPowerShellUsageCollector.ReOpenAtStart , ReOpenAtStart }, + { PowerShellHost + NuGetPowerShellUsageCollector.SolutionCount , SolutionCount }, + }); + + return telemetry; + } + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs new file mode 100644 index 00000000000..2241b429648 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace NuGet.VisualStudio.Telemetry.PowerShell +{ + public static class NuGetPowerShellUsage + { + public delegate void SolutionOpenHandler(); + public static event SolutionOpenHandler SolutionOpenEvent; + + public delegate void SolutionCloseHandler(); + public static event SolutionCloseHandler SolutionCloseEvent; + + public delegate void VSInstanceCloseHandler(); + public static event VSInstanceCloseHandler VSInstanceCloseEvent; + + public delegate void PowerShellLoadEventHandler(bool isPMC); + public static event PowerShellLoadEventHandler PowerShellLoadEvent; + + public delegate void PowerShellCommandExecuteEventHandler(bool isPMC); + public static event PowerShellCommandExecuteEventHandler PowerShellCommandExecuteEvent; + + public delegate void NuGetCmdletExecutedEventHandler(); + public static event NuGetCmdletExecutedEventHandler NuGetCmdletExecutedEvent; + + public delegate void InitPs1LoadEventHandler(bool isPMC); + public static event InitPs1LoadEventHandler InitPs1LoadEvent; + + public delegate void PmcWindowEventHandler(bool isLoad); + public static event PmcWindowEventHandler PmcWindowsEvent; + + public static void RaisePowerShellLoadEvent(bool isPMC) + { + PowerShellLoadEvent?.Invoke(isPMC); + } + + public static void RaiseCommandExecuteEvent(bool isPMC) + { + PowerShellCommandExecuteEvent?.Invoke(isPMC); + } + + public static void RaiseNuGetCmdletExecutedEvent() + { + NuGetCmdletExecutedEvent?.Invoke(); + } + + public static void RaiseInitPs1LoadEvent(bool isPMC) + { + InitPs1LoadEvent?.Invoke(isPMC); + } + + public static void RaisePmcWindowsLoadEvent(bool isLoad) + { + PmcWindowsEvent?.Invoke(isLoad); + } + + public static void RaiseSolutionOpenEvent() + { + SolutionOpenEvent?.Invoke(); + } + + public static void RaiseSolutionCloseEvent() + { + SolutionCloseEvent?.Invoke(); + } + + public static void RaiseVSInstanceCloseEvent() + { + VSInstanceCloseEvent?.Invoke(); + } + } +} diff --git a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs index 1b08399b451..7c9428fe7d3 100644 --- a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs +++ b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs @@ -29,6 +29,7 @@ using NuGet.Protocol.Core.Types; using NuGet.VisualStudio; using NuGet.VisualStudio.Telemetry; +using NuGet.VisualStudio.Telemetry.PowerShell; using Task = System.Threading.Tasks.Task; namespace NuGetConsole.Host.PowerShell.Implementation @@ -38,6 +39,7 @@ internal abstract class PowerShellHost : IHost, IPathExpansion, IDisposable private static readonly string AggregateSourceName = Resources.AggregateSourceName; private static readonly TimeSpan ExecuteInitScriptsRetryDelay = TimeSpan.FromMilliseconds(400); private static readonly int MaxTasks = 16; + private static bool PowerShellLoaded = false; private Microsoft.VisualStudio.Threading.AsyncLazy _vsMonitorSelection; private IVsMonitorSelection VsMonitorSelection => ThreadHelper.JoinableTaskFactory.Run(_vsMonitorSelection.GetValueAsync); @@ -114,7 +116,6 @@ protected PowerShellHost(string name, IRestoreEvents restoreEvents, IRunspaceMan _sourceControlManagerProvider = new Lazy( () => ServiceLocator.GetInstanceSafe()); _commonOperations = new Lazy(() => ServiceLocator.GetInstanceSafe()); - _name = name; IsCommandEnabled = true; @@ -300,6 +301,7 @@ public void Initialize(IConsole console) { try { + bool _isPmc = console is IWpfConsole; var result = _runspaceManager.GetRunspace(console, _name); Runspace = result.Item1; _nugetHost = result.Item2; @@ -312,10 +314,24 @@ public void Initialize(IConsole console) } UpdateWorkingDirectory(); + + if (!PowerShellLoaded) + { + var telemetryEvent = new TelemetryEvent(NuGetPowerShellUsageCollector.PowerShellLoaded, new Dictionary + { + { NuGetPowerShellUsageCollector.Trigger, _isPmc ? NuGetPowerShellUsageCollector.Pmc : NuGetPowerShellUsageCollector.Pmui } + }); + + TelemetryActivity.EmitTelemetryEvent(telemetryEvent); + PowerShellLoaded = true; + } + + NuGetPowerShellUsage.RaisePowerShellLoadEvent(isPMC: _isPmc); + await ExecuteInitScriptsAsync(); // check if PMC console is actually opened, then only hook to solution load/close events. - if (console is IWpfConsole) + if (_isPmc) { // Hook up solution events _solutionManager.Value.SolutionOpened += (_, __) => HandleSolutionOpened(); @@ -471,20 +487,24 @@ private async Task ExecuteInitPs1Async(string installPath, PackageIdentity ident AddPathToEnvironment(toolsPath); var scriptPath = Path.Combine(toolsPath, PowerShellScripts.Init); - if (File.Exists(scriptPath) && - _scriptExecutor.Value.TryMarkVisited(identity, PackageInitPS1State.FoundAndExecuted)) + if (File.Exists(scriptPath)) { - // always execute init script on a background thread - await TaskScheduler.Default; + NuGetPowerShellUsage.RaiseInitPs1LoadEvent(isPMC: _activeConsole is IWpfConsole); - var request = new ScriptExecutionRequest(scriptPath, installPath, identity, project: null); + if (_scriptExecutor.Value.TryMarkVisited(identity, PackageInitPS1State.FoundAndExecuted)) + { + // always execute init script on a background thread + await TaskScheduler.Default; - Runspace.Invoke( - request.BuildCommand(), - request.BuildInput(), - outputResults: true); + var request = new ScriptExecutionRequest(scriptPath, installPath, identity, project: null); - return; + Runspace.Invoke( + request.BuildCommand(), + request.BuildInput(), + outputResults: true); + + return; + } } } @@ -528,6 +548,8 @@ public bool Execute(IConsole console, string command, params object[] inputs) throw new ArgumentNullException(nameof(command)); } + NuGetPowerShellUsage.RaiseCommandExecuteEvent(isPMC: console is IWpfConsole); + // since install.ps1/uninstall.ps1 could depend on init scripts, so we need to make sure // to run it once for each solution NuGetUIThreadHelper.JoinableTaskFactory.Run(async () => From a724fe0ebd6bf24e11841bab9a9706b5f6d6de7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Bried=C3=A9?= Date: Fri, 22 Jan 2021 21:21:37 -0800 Subject: [PATCH 118/129] Change the background and foreground colors in the PMUI to increase contrast ratio in Light theme and use the correct colors for doc well UI (#3858) --- .../NuGet.PackageManagement.UI/Resources/Brushes.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Brushes.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Brushes.cs index 518ce75dac4..78e3597ce0e 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Brushes.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources/Brushes.cs @@ -176,19 +176,19 @@ public static void LoadVsBrushes() ComboBoxBorderKey = VsBrushes.ComboBoxBorderKey; ControlLinkTextHoverKey = VsBrushes.ControlLinkTextHoverKey; ControlLinkTextKey = VsBrushes.ControlLinkTextKey; - DetailPaneBackground = VsBrushes.BrandedUIBackgroundKey; - HeaderBackground = VsBrushes.BrandedUIBackgroundKey; + DetailPaneBackground = CommonDocumentColors.PageBrushKey; + HeaderBackground = CommonDocumentColors.PageBrushKey; InfoBackgroundKey = VsBrushes.InfoBackgroundKey; InfoTextKey = VsBrushes.InfoTextKey; - LegalMessageBackground = VsBrushes.BrandedUIBackgroundKey; - ListPaneBackground = VsBrushes.BrandedUIBackgroundKey; + LegalMessageBackground = CommonDocumentColors.PageBrushKey; + ListPaneBackground = CommonDocumentColors.PageBrushKey; SplitterBackgroundKey = VsBrushes.CommandShelfBackgroundGradientKey; ToolWindowBorderKey = VsBrushes.ToolWindowBorderKey; ToolWindowButtonDownBorderKey = VsBrushes.ToolWindowButtonDownBorderKey; ToolWindowButtonDownKey = VsBrushes.ToolWindowButtonDownKey; ToolWindowButtonHoverActiveBorderKey = VsBrushes.ToolWindowButtonHoverActiveBorderKey; ToolWindowButtonHoverActiveKey = VsBrushes.ToolWindowButtonHoverActiveKey; - UIText = VsBrushes.BrandedUITextKey; + UIText = CommonDocumentColors.PageTextBrushKey; WindowTextKey = VsBrushes.WindowTextKey; HeaderColorsDefaultBrushKey = HeaderColors.DefaultBrushKey; From 45aa09baf3c222f00d237025535ec8f402783aa9 Mon Sep 17 00:00:00 2001 From: Andy Zivkovic Date: Sun, 24 Jan 2021 06:56:17 -0800 Subject: [PATCH 119/129] Add package source to "installing " message at normal verbosity (#3849) --- .../NuGet.Packaging.Extraction.csproj | 3 +- .../Strings.Designer.cs | 55 +++++++++++++++++-- .../NuGet.Packaging.Extraction/Strings.resx | 28 +++++++++- .../NuGet.Packaging/PackageExtractor.cs | 16 +----- .../NuGet.Packaging/StringFormatter.cs | 24 ++++++++ .../NuGet.Packaging/Strings.Designer.cs | 6 +- src/NuGet.Core/NuGet.Packaging/Strings.resx | 8 ++- .../MsbuildRestoreTaskTests.cs | 11 +++- .../PackageExtractorTests.cs | 8 +-- test/TestUtilities/Test.Utility/TestLogger.cs | 2 + 10 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 src/NuGet.Core/NuGet.Packaging/StringFormatter.cs diff --git a/src/NuGet.Core/NuGet.Packaging.Extraction/NuGet.Packaging.Extraction.csproj b/src/NuGet.Core/NuGet.Packaging.Extraction/NuGet.Packaging.Extraction.csproj index 71a74aaa487..f122be3c990 100644 --- a/src/NuGet.Core/NuGet.Packaging.Extraction/NuGet.Packaging.Extraction.csproj +++ b/src/NuGet.Core/NuGet.Packaging.Extraction/NuGet.Packaging.Extraction.csproj @@ -1,4 +1,4 @@ - + @@ -291,6 +291,7 @@ + diff --git a/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.Designer.cs b/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.Designer.cs index d9c53ee8263..b92296b5f04 100644 --- a/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.Designer.cs +++ b/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -39,7 +39,7 @@ internal Strings() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NuGet.Packaging.Extraction.Strings", typeof(Strings).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NuGet.Packaging.Strings", typeof(Strings).Assembly); resourceMan = temp; } return resourceMan; @@ -745,11 +745,11 @@ internal static string InvalidUrl { } /// - /// Looks up a localized string similar to Installing {0} {1}.. + /// Looks up a localized string similar to Installed {0} {1} from {2} with content hash {3}.. /// - internal static string Log_InstallingPackage { + internal static string Log_InstalledPackage { get { - return ResourceManager.GetString("Log_InstallingPackage", resourceCulture); + return ResourceManager.GetString("Log_InstalledPackage", resourceCulture); } } @@ -789,6 +789,51 @@ internal static string MissingPackageTypeName { } } + /// + /// Looks up a localized string similar to Some dependency group TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromDependencyGroups { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromDependencyGroups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some reference assembly group TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromFrameworkAssemblyGroups { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromFrameworkAssemblyGroups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some framework assembly reference TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromFrameworkAssemblyReferences { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromFrameworkAssemblyReferences", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some included files are included under TFMs which are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromIncludedFiles { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromIncludedFiles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some reference group TFMs are missing a platform version: {0}. + /// + internal static string MissingTargetPlatformVersionsFromReferenceGroups { + get { + return ResourceManager.GetString("MissingTargetPlatformVersionsFromReferenceGroups", resourceCulture); + } + } + /// /// Looks up a localized string similar to Multiple {0} attributes are not allowed.. /// diff --git a/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.resx b/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.resx index 0ca29278171..e2a6db5a063 100644 --- a/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.resx +++ b/src/NuGet.Core/NuGet.Packaging.Extraction/Strings.resx @@ -138,10 +138,12 @@ Null or empty package id - - Installing {0} {1}. + + Installed {0} {1} from {2} with content hash {3}. 0 - package id -1 - package version +1 - package version +2 - package source +3 - hex byte string, representing content hash Fail to load packages.config as XML file. Please check it. @@ -839,6 +841,26 @@ Valid from: The timestamp service responded with HTTP status code '{0}' ('{1}'). {0} is the httpResponse.StatusCode, {1} is the httpResponse.ReasonPhrase. + + Some dependency group TFMs are missing a platform version: {0} + 0 - comma-separated list of dependency group TFMs + + + Some reference assembly group TFMs are missing a platform version: {0} + 0 - comma-separated list of reference assembly group TFMs + + + Some included files are included under TFMs which are missing a platform version: {0} + 0 - comma-separated list of files with bad TFMs + + + Some reference group TFMs are missing a platform version: {0} + 0 - comma-separated list of reference group TFMs + + + Some framework assembly reference TFMs are missing a platform version: {0} + 0 - comma-separated list of reference group TFMs + '{0}' cannot be null. 0 - property name diff --git a/src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs b/src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs index bd83b6ad3f1..35cf7e7d81d 100644 --- a/src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs +++ b/src/NuGet.Core/NuGet.Packaging/PackageExtractor.cs @@ -398,12 +398,6 @@ public static async Task InstallFromSourceAsync( logger.LogVerbose( $"Acquired lock for the installation of {packageIdentity.Id} {packageIdentity.Version}"); - logger.LogInformation(string.Format( - CultureInfo.CurrentCulture, - Strings.Log_InstallingPackage, - packageIdentity.Id, - packageIdentity.Version)); - cancellationToken.ThrowIfCancellationRequested(); // We do not stop the package extraction after this point @@ -555,7 +549,7 @@ await VerifyPackageSignatureAsync( File.Move(tempNupkgMetadataPath, nupkgMetadataFilePath); - logger.LogVerbose($"Completed installation of {packageIdentity.Id} {packageIdentity.Version} from {source} with content hash {contentHash}"); + logger.LogInformation(StringFormatter.Log_InstalledPackage(packageIdentity.Id, packageIdentity.Version.OriginalVersion, source, contentHash)); packageExtractionTelemetryEvent.SetResult(NuGetOperationStatus.Succeeded); return true; @@ -643,12 +637,6 @@ public static async Task InstallFromSourceAsync( logger.LogVerbose( $"Acquired lock for the installation of {packageIdentity.Id} {packageIdentity.Version}"); - logger.LogInformation(string.Format( - CultureInfo.CurrentCulture, - Strings.Log_InstallingPackage, - packageIdentity.Id, - packageIdentity.Version)); - cancellationToken.ThrowIfCancellationRequested(); // We do not stop the package extraction after this point @@ -828,7 +816,7 @@ await packageDownloader.CoreReader.CopyFilesAsync( File.Move(tempNupkgMetadataFilePath, nupkgMetadataFilePath); - logger.LogVerbose($"Completed installation of {packageIdentity.Id} {packageIdentity.Version} from {packageDownloader.Source} with content hash {contentHash}"); + logger.LogInformation(StringFormatter.Log_InstalledPackage(packageIdentity.Id, packageIdentity.Version.OriginalVersion, packageDownloader.Source, contentHash)); packageExtractionTelemetryEvent.SetResult(NuGetOperationStatus.Succeeded); return true; diff --git a/src/NuGet.Core/NuGet.Packaging/StringFormatter.cs b/src/NuGet.Core/NuGet.Packaging/StringFormatter.cs new file mode 100644 index 00000000000..00e0717c49b --- /dev/null +++ b/src/NuGet.Core/NuGet.Packaging/StringFormatter.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Globalization; + +namespace NuGet.Packaging +{ + internal static class StringFormatter + { + internal static string Log_InstalledPackage( + string packageId, + string packageVersion, + string source, + string contentHash) + { + return string.Format(CultureInfo.CurrentCulture, + Strings.Log_InstalledPackage, + packageId, + packageVersion, + source, + contentHash); + } + } +} diff --git a/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs b/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs index ab4e58c23d5..b92296b5f04 100644 --- a/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs +++ b/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs @@ -745,11 +745,11 @@ internal static string InvalidUrl { } /// - /// Looks up a localized string similar to Installing {0} {1}.. + /// Looks up a localized string similar to Installed {0} {1} from {2} with content hash {3}.. /// - internal static string Log_InstallingPackage { + internal static string Log_InstalledPackage { get { - return ResourceManager.GetString("Log_InstallingPackage", resourceCulture); + return ResourceManager.GetString("Log_InstalledPackage", resourceCulture); } } diff --git a/src/NuGet.Core/NuGet.Packaging/Strings.resx b/src/NuGet.Core/NuGet.Packaging/Strings.resx index 2a162c2da55..e2a6db5a063 100644 --- a/src/NuGet.Core/NuGet.Packaging/Strings.resx +++ b/src/NuGet.Core/NuGet.Packaging/Strings.resx @@ -138,10 +138,12 @@ Null or empty package id - - Installing {0} {1}. + + Installed {0} {1} from {2} with content hash {3}. 0 - package id -1 - package version +1 - package version +2 - package source +3 - hex byte string, representing content hash Fail to load packages.config as XML file. Please check it. diff --git a/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs b/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs index 05a49551d22..f5ea8422020 100644 --- a/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs +++ b/test/NuGet.Core.FuncTests/Msbuild.Integration.Test/MsbuildRestoreTaskTests.cs @@ -8,9 +8,12 @@ using System.Threading.Tasks; using System.Xml.Linq; using FluentAssertions; +using NuGet.Common; using NuGet.Frameworks; +using NuGet.Packaging; using NuGet.ProjectModel; using NuGet.Test.Utility; +using NuGet.Versioning; using Xunit; namespace Msbuild.Integration.Test @@ -232,7 +235,9 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( // Assert Assert.True(result.ExitCode == 0, result.AllOutput); - Assert.Contains("Installing x 1.0.0", result.AllOutput); + var resolver = new VersionFolderPathResolver(pathContext.UserPackagesFolder); + var nupkg = NupkgMetadataFileFormat.Read(resolver.GetNupkgMetadataPath(packageX.Id, NuGetVersion.Parse(packageX.Version)), NullLogger.Instance); + Assert.Contains($"Installed x 1.0.0 from {pathContext.PackageSource} with content hash {nupkg.ContentHash}.", result.AllOutput); Assert.Contains(configAPath, result.AllOutput); } } @@ -289,7 +294,9 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async( // Assert Assert.True(result.ExitCode == 0, result.AllOutput); - Assert.Contains("Installing x 1.0.0", result.AllOutput); + var resolver = new VersionFolderPathResolver(pathContext.UserPackagesFolder); + var nupkg = NupkgMetadataFileFormat.Read(resolver.GetNupkgMetadataPath(packageX.Id, NuGetVersion.Parse(packageX.Version)), NullLogger.Instance); + Assert.Contains($"Installed x 1.0.0 from {pathContext.PackageSource} with content hash {nupkg.ContentHash}.", result.AllOutput); Assert.Contains(configAPath, result.AllOutput); } } diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs index be982f01800..c5fb55c47bd 100644 --- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs @@ -3766,7 +3766,7 @@ public async Task InstallFromSourceAsync_PluginPackageDownloader() } [Fact] - public async Task InstallFromSourceAsync_LogsSourceOnVerboseLevel() + public async Task InstallFromSourceAsync_LogsSourceOnNormalLevel() { // Arrange using (var testDirectory = TestDirectory.Create()) @@ -3804,7 +3804,7 @@ await PackageExtractor.InstallFromSourceAsync( // Assert File.Exists(resolver.GetPackageFilePath(identity.Id, identity.Version)).Should().BeTrue(); var nupkgMetadata = NupkgMetadataFileFormat.Read(resolver.GetNupkgMetadataPath(identity.Id, identity.Version)); - testLogger.VerboseMessages.Should().Contain($"Completed installation of {identity.Id} {identity.Version} from {source} with content hash {nupkgMetadata.ContentHash}"); + testLogger.InformationMessages.Should().Contain($"Installed {identity.Id} {identity.Version} from {source} with content hash {nupkgMetadata.ContentHash}."); } } } @@ -3855,7 +3855,7 @@ await PackageExtractor.InstallFromSourceAsync( } [Fact] - public async Task InstallFromSourceAsync_WithPackageDownloader_LogsSourceOnVerboseLevel() + public async Task InstallFromSourceAsync_WithPackageDownloader_LogsSourceOnNormalLevel() { // Arrange using (var testDirectory = TestDirectory.Create()) @@ -3899,7 +3899,7 @@ public async Task InstallFromSourceAsync_WithPackageDownloader_LogsSourceOnVerbo // Assert File.Exists(resolver.GetPackageFilePath(identity.Id, identity.Version)).Should().BeTrue(); var nupkgMetadata = NupkgMetadataFileFormat.Read(resolver.GetNupkgMetadataPath(identity.Id, identity.Version)); - testLogger.VerboseMessages.Should().Contain($"Completed installation of {identity.Id} {identity.Version} from {source} with content hash {nupkgMetadata.ContentHash}"); + testLogger.InformationMessages.Should().Contain($"Installed {identity.Id} {identity.Version} from {source} with content hash {nupkgMetadata.ContentHash}."); } } } diff --git a/test/TestUtilities/Test.Utility/TestLogger.cs b/test/TestUtilities/Test.Utility/TestLogger.cs index 6733157cebf..c00ba0ba303 100644 --- a/test/TestUtilities/Test.Utility/TestLogger.cs +++ b/test/TestUtilities/Test.Utility/TestLogger.cs @@ -29,6 +29,7 @@ public TestLogger(ITestOutputHelper output) public ConcurrentQueue DebugMessages { get; } = new ConcurrentQueue(); public ConcurrentQueue VerboseMessages { get; } = new ConcurrentQueue(); public ConcurrentQueue MinimalMessages { get; } = new ConcurrentQueue(); + public ConcurrentQueue InformationMessages { get; } = new ConcurrentQueue(); public ConcurrentQueue ErrorMessages { get; } = new ConcurrentQueue(); public ConcurrentQueue WarningMessages { get; } = new ConcurrentQueue(); @@ -56,6 +57,7 @@ public void LogError(string data) public void LogInformation(string data) { Messages.Enqueue(data); + InformationMessages.Enqueue(data); DumpMessage("INFO ", data); } From 280a1f978b574f0296135c829f0df6e9e3d0dbf4 Mon Sep 17 00:00:00 2001 From: Damon Tivel Date: Mon, 25 Jan 2021 12:24:46 -0800 Subject: [PATCH 120/129] PM UI: propagate implicit actions for "Preview Changes" summary in update package operation (#3859) Fix https://github.com/NuGet/Home/issues/10483 --- .../Services/NuGetProjectManagerService.cs | 77 +++++---- .../NuGetProjectManagerServiceTests.cs | 162 +++++++++++++++++- 2 files changed, 200 insertions(+), 39 deletions(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs index 6dac8b8da27..934c92117a8 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetProjectManagerService.cs @@ -443,30 +443,7 @@ public async ValueTask> GetInstallActionsAsync( foreach (ResolvedAction resolvedAction in resolvedActions) { - List? implicitActions = null; - - if (resolvedAction.Action is BuildIntegratedProjectAction buildIntegratedAction) - { - implicitActions = new List(); - - foreach (NuGetProjectAction? buildAction in buildIntegratedAction.GetProjectActions()) - { - var implicitAction = new ImplicitProjectAction( - CreateProjectActionId(), - buildAction.PackageIdentity, - buildAction.NuGetProjectActionType); - - implicitActions.Add(implicitAction); - } - } - - string projectId = resolvedAction.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); - var projectAction = new ProjectAction( - CreateProjectActionId(), - projectId, - resolvedAction.Action.PackageIdentity, - resolvedAction.Action.NuGetProjectActionType, - implicitActions); + ProjectAction projectAction = CreateProjectAction(resolvedAction); _state.ResolvedActions[projectAction.Id] = resolvedAction; @@ -578,26 +555,20 @@ public async ValueTask> GetUpdateActionsAsync( NuGetPackageManager packageManager = await _sharedState.PackageManager.GetValueAsync(cancellationToken); IEnumerable actions = await packageManager.PreviewUpdatePackagesAsync( - packageIdentities.ToList(), - projects, - resolutionContext, - projectContext, - primarySources, - secondarySources, - cancellationToken); + packageIdentities.ToList(), + projects, + resolutionContext, + projectContext, + primarySources, + secondarySources, + cancellationToken); var projectActions = new List(); foreach (NuGetProjectAction action in actions) { - string projectId = action.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); var resolvedAction = new ResolvedAction(action.Project, action); - var projectAction = new ProjectAction( - CreateProjectActionId(), - projectId, - action.PackageIdentity, - action.NuGetProjectActionType, - implicitActions: null); + ProjectAction projectAction = CreateProjectAction(resolvedAction); _state.ResolvedActions[projectAction.Id] = resolvedAction; @@ -622,6 +593,36 @@ public async ValueTask> GetProjectsWith return await Task.WhenAll(tasks); } + private static ProjectAction CreateProjectAction(ResolvedAction resolvedAction) + { + List? implicitActions = null; + + if (resolvedAction.Action is BuildIntegratedProjectAction buildIntegratedAction) + { + implicitActions = new List(); + + foreach (NuGetProjectAction buildAction in buildIntegratedAction.GetProjectActions()) + { + var implicitAction = new ImplicitProjectAction( + CreateProjectActionId(), + buildAction.PackageIdentity, + buildAction.NuGetProjectActionType); + + implicitActions.Add(implicitAction); + } + } + + string projectId = resolvedAction.Project.GetMetadata(NuGetProjectMetadataKeys.ProjectId); + var projectAction = new ProjectAction( + CreateProjectActionId(), + projectId, + resolvedAction.Action.PackageIdentity, + resolvedAction.Action.NuGetProjectActionType, + implicitActions); + + return projectAction; + } + private static string CreateProjectActionId() { return Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); diff --git a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs index 38186843717..de291def403 100644 --- a/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs +++ b/test/NuGet.Clients.Tests/NuGet.PackageManagement.VisualStudio.Test/Services/NuGetProjectManagerServiceTests.cs @@ -21,6 +21,7 @@ using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; +using NuGet.LibraryModel; using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.ProjectManagement; @@ -108,7 +109,7 @@ await PerformOperationAsync(async (projectManager) => } [Fact] - public async Task GetInstallActionsAsync_WithProjectReferenceProject_WhenUpdatingPackage_ReturnsCorrectActions() + public async Task GetInstallActionsAsync_WithPackageReferenceProject_WhenUpdatingPackage_ReturnsCorrectActions() { const string projectName = "a"; string projectId = Guid.NewGuid().ToString(); @@ -210,6 +211,8 @@ await PerformOperationAsync(async (projectManager) => Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType); await projectManager.ExecuteActionsAsync(actions, CancellationToken.None); + + AddPackageDependency(projectSystemCache, projectNames, packageSpec, packageV1); }); await PerformOperationAsync(async (projectManager) => @@ -387,6 +390,163 @@ public async Task GetInstalledPackagesAsync_WhenProjectReturnsNullPackageReferen } } + [Fact] + public async Task GetUpdateActionsAsync_WithPackageReferenceProject_WhenUpdatingPackage_ReturnsCorrectActions() + { + const string projectName = "a"; + string projectId = Guid.NewGuid().ToString(); + var projectSystemCache = new ProjectSystemCache(); + + using (TestDirectory testDirectory = TestDirectory.Create()) + { + var packageV1 = new SimpleTestPackageContext(packageId: "b", version: "1.0.0"); + var packageV2 = new SimpleTestPackageContext(packageV1.Id, version: "2.0.0"); + string packageSourceDirectoryPath = Path.Combine(testDirectory, "packageSource"); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + packageSourceDirectoryPath, + PackageSaveMode.Defaultv3, + packageV1, + packageV2); + + var packageSource = new PackageSource(packageSourceDirectoryPath); + var packageSources = new List() { packageSource }; + + Initialize(packageSources); + + string projectFullPath = Path.Combine(testDirectory.Path, $"{projectName}.csproj"); + var unconfiguredProject = new Mock(); + var configuredProject = new Mock(); + var projectServices = new Mock(); + var packageReferencesService = new Mock(); + var result = new Mock(); + + unconfiguredProject.Setup(x => x.GetSuggestedConfiguredProjectAsync()) + .ReturnsAsync(configuredProject.Object); + + configuredProject.SetupGet(x => x.Services) + .Returns(projectServices.Object); + + projectServices.SetupGet(x => x.PackageReferences) + .Returns(packageReferencesService.Object); + + packageReferencesService.Setup(x => x.AddAsync(It.IsNotNull(), It.IsNotNull())) + .ReturnsAsync(new AddReferenceResult(result.Object, added: true)); + + var nuGetProjectServices = new Mock(); + + nuGetProjectServices.SetupGet(x => x.ScriptService) + .Returns(Mock.Of()); + + var project = new CpsPackageReferenceProject( + projectName: projectName, + projectUniqueName: projectFullPath, + projectFullPath: projectFullPath, + projectSystemCache, + unconfiguredProject.Object, + nuGetProjectServices.Object, + projectId); + + PackageSpec packageSpec = CreatePackageSpec( + project.ProjectName, + Path.Combine(testDirectory, "package.spec")); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectRestoreInfo.AddProject(packageSpec); + var projectNames = new ProjectNames( + fullName: projectFullPath, + uniqueName: projectFullPath, + shortName: projectName, + customUniqueName: projectName, + projectId: projectId); + projectSystemCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, Array.Empty()); + + _solutionManager.NuGetProjects.Add(project); + + string[] projectIds = new[] { projectId }; + string[] packageSourceNames = new[] { packageSource.Name }; + + await PerformOperationAsync(async (projectManager) => + { + IReadOnlyList actions = await projectManager.GetInstallActionsAsync( + projectIds, + packageV1.Identity, + VersionConstraints.None, + includePrelease: true, + DependencyBehavior.Lowest, + packageSourceNames, + CancellationToken.None); + + Assert.NotEmpty(actions); + Assert.Equal(1, actions.Count); + + ProjectAction action = actions[0]; + + Assert.Equal(packageV1.Identity, action.PackageIdentity); + Assert.Equal(NuGetProjectActionType.Install, action.ProjectActionType); + Assert.Equal(projectId, action.ProjectId); + + Assert.Equal(1, action.ImplicitActions.Count); + + ImplicitProjectAction implicitAction = action.ImplicitActions[0]; + + Assert.Equal(packageV1.Identity, implicitAction.PackageIdentity); + Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType); + + await projectManager.ExecuteActionsAsync(actions, CancellationToken.None); + + AddPackageDependency(projectSystemCache, projectNames, packageSpec, packageV1); + }); + + await PerformOperationAsync(async (projectManager) => + { + IReadOnlyList actions = await projectManager.GetUpdateActionsAsync( + projectIds, + new[] { packageV2.Identity }, + VersionConstraints.None, + includePrelease: true, + DependencyBehavior.Lowest, + packageSourceNames, + CancellationToken.None); + + Assert.NotEmpty(actions); + Assert.Equal(1, actions.Count); + + ProjectAction action = actions[0]; + + Assert.Equal(packageV2.Identity, action.PackageIdentity); + Assert.Equal(NuGetProjectActionType.Install, action.ProjectActionType); + Assert.Equal(projectId, action.ProjectId); + + Assert.Equal(2, action.ImplicitActions.Count); + + ImplicitProjectAction implicitAction = action.ImplicitActions[0]; + + Assert.Equal(packageV1.Identity, implicitAction.PackageIdentity); + Assert.Equal(NuGetProjectActionType.Uninstall, implicitAction.ProjectActionType); + + implicitAction = action.ImplicitActions[1]; + + Assert.Equal(packageV2.Identity, implicitAction.PackageIdentity); + Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType); + }); + } + } + + private static void AddPackageDependency(ProjectSystemCache projectSystemCache, ProjectNames projectNames, PackageSpec packageSpec, SimpleTestPackageContext package) + { + var dependency = new LibraryDependency() + { + LibraryRange = new LibraryRange( + name: package.Id, + versionRange: new VersionRange(package.Identity.Version), + typeConstraint: LibraryDependencyTarget.Package) + }; + + packageSpec.TargetFrameworks.First().Dependencies.Add(dependency); + DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); + projectSystemCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, Array.Empty()); + } + private void Initialize(IReadOnlyList packageSources = null) { SourceRepositoryProvider sourceRepositoryProvider; From 7c7f10070c8ddcc62006d358bfcce257fe8e7ddd Mon Sep 17 00:00:00 2001 From: Kartheek Penagamuri <52756182+kartheekp-ms@users.noreply.github.com> Date: Mon, 25 Jan 2021 16:10:06 -0800 Subject: [PATCH 121/129] remove fileshare dependency for buildinfo.json (#3856) --- build/templates/Build_and_UnitTest.yml | 2 +- scripts/cibuild/ConfigureVstsBuild.ps1 | 71 ++------------------------ 2 files changed, 5 insertions(+), 68 deletions(-) diff --git a/build/templates/Build_and_UnitTest.yml b/build/templates/Build_and_UnitTest.yml index 360bdc00560..d46fdc2ecfb 100644 --- a/build/templates/Build_and_UnitTest.yml +++ b/build/templates/Build_and_UnitTest.yml @@ -34,7 +34,7 @@ steps: - task: PowerShell@1 inputs: scriptName: "$(Build.Repository.LocalPath)\\scripts\\cibuild\\ConfigureVstsBuild.ps1" - arguments: "-BuildCounterFile $(BuildCounterFile) -BuildInfoJsonFile $(BuildInfoJsonFile) -BuildRTM $(BuildRTM) -SkipUpdateBuildNumber" + arguments: "-BuildRTM $(BuildRTM)" displayName: "Configure VSTS CI Environment" - task: PublishBuildArtifacts@1 diff --git a/scripts/cibuild/ConfigureVstsBuild.ps1 b/scripts/cibuild/ConfigureVstsBuild.ps1 index 6c4115a7e37..f087f6210ae 100644 --- a/scripts/cibuild/ConfigureVstsBuild.ps1 +++ b/scripts/cibuild/ConfigureVstsBuild.ps1 @@ -4,15 +4,8 @@ Sets build variables during a VSTS build dynamically. .DESCRIPTION This script is used to dynamically set some build variables during VSTS build. -Specifically, this script reads the buildcounter.txt file in the $(DropRoot) to -determine the build number of the artifacts, also it sets the $(NupkgOutputDir) -based on whether $(BuildRTM) is true or false. - -.PARAMETER BuildCounterFile -Path to the file in the drop root which stores the current build counter. - -.PARAMETER BuildInfoJsonFile -Path to the buildInfo.json file that is generated for every build in the output folder. +Specifically, this script determines the build number of the artifacts, +also it sets the $(NupkgOutputDir) based on whether $(BuildRTM) is true or false. .PARAMETER BuildRTM True/false depending on whether nupkgs are being with or without the release labels. @@ -22,15 +15,7 @@ True/false depending on whether nupkgs are being with or without the release lab param ( [Parameter(Mandatory=$True)] - [string]$BuildCounterFile, - - [Parameter(Mandatory=$True)] - [string]$BuildInfoJsonFile, - - [Parameter(Mandatory=$True)] - [string]$BuildRTM, - - [switch]$SkipUpdateBuildNumber + [string]$BuildRTM ) Function Get-Version { @@ -128,54 +113,10 @@ if ($BuildRTM -eq 'true') # Set the $(NupkgOutputDir) build variable in VSTS build Write-Host "##vso[task.setvariable variable=NupkgOutputDir;]ReleaseNupkgs" Write-Host "##vso[task.setvariable variable=VsixPublishDir;]VS15-RTM" - # Only for backward compatibility with orchestrated builds - if(-not $SkipUpdateBuildNumber) - { - $numberOfTries = 0 - do{ - Write-Host "Waiting for buildinfo.json to be generated..." - $numberOfTries++ - Start-Sleep -s 15 - } - until ((Test-Path $BuildInfoJsonFile) -or ($numberOfTries -gt 50)) - $json = (Get-Content $BuildInfoJsonFile -Raw) | ConvertFrom-Json - $currentBuild = [System.Decimal]::Parse($json.BuildNumber) - # Set the $(Revision) build variable in VSTS build - Write-Host "##vso[task.setvariable variable=Revision;]$currentBuild" - Write-Host "##vso[build.updatebuildnumber]$currentBuild" - $oldBuildOutputDirectory = Split-Path -Path $BuildInfoJsonFile - $branchDirectory = Split-Path -Path $oldBuildOutputDirectory - $newBuildOutputFolder = Join-Path $branchDirectory $currentBuild - if(Test-Path $newBuildOutputFolder) - { - Move-Item -Path $BuildInfoJsonFile -Destination $newBuildOutputFolder - Remove-Item -Path $oldBuildOutputDirectory -Force - } - else - { - Rename-Item $oldBuildOutputDirectory $currentBuild - } - } } else { - # Only for backward compatibility with orchestrated builds - if(-not $SkipUpdateBuildNumber) - { - $revision = Get-Content $BuildCounterFile - $newBuildCounter = [System.Decimal]::Parse($revision) - $newBuildCounter++ - Set-Content $BuildCounterFile $newBuildCounter - # Set the $(Revision) build variable in VSTS build - Write-Host "##vso[task.setvariable variable=Revision;]$newBuildCounter" - Write-Host "##vso[build.updatebuildnumber]$newBuildCounter" - Write-Host "##vso[task.setvariable variable=BuildNumber;isOutput=true]$newBuildCounter" - } - else - { - $newBuildCounter = $env:BUILD_BUILDNUMBER - } - + $newBuildCounter = $env:BUILD_BUILDNUMBER $VsTargetBranch = & $msbuildExe $env:BUILD_REPOSITORY_LOCALPATH\build\config.props /v:m /nologo /t:GetVsTargetBranch $CliTargetBranches = & $msbuildExe $env:BUILD_REPOSITORY_LOCALPATH\build\config.props /v:m /nologo /t:GetCliTargetBranches $SdkTargetBranches = & $msbuildExe $env:BUILD_REPOSITORY_LOCALPATH\build\config.props /v:m /nologo /t:GetSdkTargetBranches @@ -199,10 +140,6 @@ else New-Item $localBuildInfoJsonFilePath -Force $jsonRepresentation | ConvertTo-Json | Set-Content $localBuildInfoJsonFilePath - # Now copy the file to the remote folder. - [System.IO.Directory]::CreateDirectory([System.IO.Path]::GetDirectoryName($BuildInfoJsonFile)) - [System.IO.File]::Copy($localBuildInfoJsonFilePath, $BuildInfoJsonFile) - $productVersion = & $msbuildExe $env:BUILD_REPOSITORY_LOCALPATH\build\config.props /v:m /nologo /t:GetSemanticVersion if (-not $?) { From 7999ea9b84e9a6f558df8f3f1ac22eb54c9cc162 Mon Sep 17 00:00:00 2001 From: scoban Date: Tue, 26 Jan 2021 11:37:30 -0800 Subject: [PATCH 122/129] Add switch for building the apex project as part of the build step (#3869) --- build.ps1 | 7 ++++--- build/common.project.props | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/build.ps1 b/build.ps1 index 825952c4f66..0a1d65d8f6e 100644 --- a/build.ps1 +++ b/build.ps1 @@ -52,7 +52,8 @@ param ( [switch]$CI, [switch]$PackageEndToEnd, [switch]$SkipDelaySigning, - [switch]$Binlog + [switch]$Binlog, + [switch]$IncludeApex ) . "$PSScriptRoot\build\common.ps1" @@ -115,7 +116,7 @@ Invoke-BuildStep 'Running Restore' { Trace-Log ". `"$MSBuildExe`" $args" & $MSBuildExe @args - $args = "build\build.proj", "/t:RestoreVS", "/p:Configuration=$Configuration", "/p:ReleaseLabel=$ReleaseLabel", "/p:BuildNumber=$BuildNumber", "/v:m", "/m:1" + $args = "build\build.proj", "/t:RestoreVS", "/p:Configuration=$Configuration", "/p:ReleaseLabel=$ReleaseLabel", "/p:BuildNumber=$BuildNumber", "/p:IncludeApex=$IncludeApex", "/v:m", "/m:1" if ($Binlog) { $args += "-bl:msbuild.restore.binlog" @@ -134,7 +135,7 @@ Invoke-BuildStep 'Running Restore' { Invoke-BuildStep $VSMessage { - $args = 'build\build.proj', "/t:$VSTarget", "/p:Configuration=$Configuration", "/p:ReleaseLabel=$ReleaseLabel", "/p:BuildNumber=$BuildNumber", '/v:m', '/m:1' + $args = 'build\build.proj', "/t:$VSTarget", "/p:Configuration=$Configuration", "/p:ReleaseLabel=$ReleaseLabel", "/p:BuildNumber=$BuildNumber", "/p:IncludeApex=$IncludeApex", '/v:m', '/m:1' If ($SkipDelaySigning) { diff --git a/build/common.project.props b/build/common.project.props index 50e968e9b47..8f4140beb33 100644 --- a/build/common.project.props +++ b/build/common.project.props @@ -255,7 +255,9 @@ $(RepositoryRootDirectory)test\NuGet.Tests.Apex\*\NuGet.Tests.Apex.csproj" Condition=" '$(ExcludeTestProjects)' != 'true' " /> + + From d54f86b6442e277179f9f2b4cf66b5adcb9efdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 26 Jan 2021 16:30:38 -0800 Subject: [PATCH 123/129] Make sure all frameworkrefs have a group, even if empty (#3760) * pack tests * output empty frameworkRef groups --- .../NuGet.Build.Tasks.Pack/PackTaskLogic.cs | 26 +++++++++---------- .../PackCommandTests.cs | 24 ++++++++++++++--- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs b/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs index e7174729f32..b826d5367d4 100644 --- a/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs +++ b/src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs @@ -397,28 +397,28 @@ private void PopulateFrameworkAssemblyReferences(PackageBuilder builder, IPackTa private void PopulateFrameworkReferences(PackageBuilder builder, LockFile assetsFile) { var tfmSpecificRefs = new Dictionary>(); + bool hasAnyRefs = false; foreach (var framework in assetsFile.PackageSpec.TargetFrameworks) { var frameworkShortFolderName = framework.FrameworkName.GetShortFolderName(); + tfmSpecificRefs.Add(frameworkShortFolderName, new HashSet(ComparisonUtility.FrameworkReferenceNameComparer)); foreach (var frameworkRef in framework.FrameworkReferences.Where(e => e.PrivateAssets != FrameworkDependencyFlags.All)) { - if (tfmSpecificRefs.TryGetValue(frameworkShortFolderName, out var frameworkRefNames)) - { - frameworkRefNames.Add(frameworkRef.Name); - } - else - { - tfmSpecificRefs.Add(frameworkShortFolderName, new HashSet(ComparisonUtility.FrameworkReferenceNameComparer) { frameworkRef.Name }); - } + var frameworkRefNames = tfmSpecificRefs[frameworkShortFolderName]; + frameworkRefNames.Add(frameworkRef.Name); + hasAnyRefs = true; } } - builder.FrameworkReferenceGroups.AddRange( - tfmSpecificRefs.Select(e => - new FrameworkReferenceGroup( - NuGetFramework.Parse(e.Key), - e.Value.Select(fr => new FrameworkReference(fr))))); + if (hasAnyRefs) + { + builder.FrameworkReferenceGroups.AddRange( + tfmSpecificRefs.Select(e => + new FrameworkReferenceGroup( + NuGetFramework.Parse(e.Key), + e.Value.Select(fr => new FrameworkReference(fr))))); + } } public PackCommandRunner GetPackCommandRunner( diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs index 14325e9e672..0430792b290 100644 --- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs @@ -4539,7 +4539,7 @@ public void PackCommand_PackEmbedInteropPackage() [PlatformTheory(Platform.Windows)] [InlineData("Microsoft.NETCore.App", "true", "netcoreapp3.0", "", "netcoreapp3.0")] - [InlineData("Microsoft.NETCore.App", "false", "netcoreapp3.0", "", "netcoreapp3.0")] + [InlineData("Microsoft.NETCore.App", "false", "netcoreapp3.0", "", "")] [InlineData("Microsoft.WindowsDesktop.App", "true", "netstandard2.1;netcoreapp3.0", "netcoreapp3.0", "netcoreapp3.0")] [InlineData("Microsoft.WindowsDesktop.App;Microsoft.AspNetCore.App", "true;true", "netcoreapp3.0", "netcoreapp3.0", "netcoreapp3.0")] [InlineData("Microsoft.WindowsDesktop.App.WPF;Microsoft.WindowsDesktop.App.WindowsForms", "true;false", "netcoreapp3.0", "", "netcoreapp3.0")] @@ -4608,13 +4608,29 @@ public void PackCommand_PackProject_PacksFrameworkReferences(string frameworkRef using (var nupkgReader = new PackageArchiveReader(nupkgPath)) { - var expectedFrameworks = expectedTargetFramework.Split(';'); + var expectedFrameworks = expectedTargetFramework.Split(';').Where(fw => !string.IsNullOrEmpty(fw)); + var allFrameworks = targetFrameworks.Split(';').Where(fw => !string.IsNullOrEmpty(fw)); + var nupkgFrameworkGroups = nupkgReader.NuspecReader.GetFrameworkRefGroups(); + + if (expectedFrameworks.Any()) + { + Assert.Equal( + allFrameworks.Select(fw => NuGetFramework.Parse(fw)).ToHashSet(), + nupkgFrameworkGroups.Select(t => t.TargetFramework).ToHashSet() + ); + } + else + { + Assert.Equal( + new HashSet(), + nupkgFrameworkGroups.Select(t => t.TargetFramework).ToHashSet() + ); + } - var frameworkItems = nupkgReader.NuspecReader.GetFrameworkRefGroups(); foreach (var framework in expectedFrameworks) { var nugetFramework = NuGetFramework.Parse(framework); - var frameworkSpecificGroup = frameworkItems.Where(t => t.TargetFramework.Equals(nugetFramework)).FirstOrDefault(); + var frameworkSpecificGroup = nupkgFrameworkGroups.Where(t => t.TargetFramework.Equals(nugetFramework)).FirstOrDefault(); foreach (var frameworkRef in frameworkReftoPack) { From d9bd7c0f2b1b712a53ae32676fc8d648e061069d Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Tue, 26 Jan 2021 17:21:00 -0800 Subject: [PATCH 124/129] Enhance the coding guidelines - add rule for parameter names & namespace names (#3867) --- docs/coding-guidelines.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/coding-guidelines.md b/docs/coding-guidelines.md index a6aec4512b9..a82183d2f8e 100644 --- a/docs/coding-guidelines.md +++ b/docs/coding-guidelines.md @@ -192,6 +192,7 @@ For example the following are correct: return (string input) => // method body } ``` + 1. Prefer a using directive over fully qualifying a type. This is correct: @@ -208,6 +209,36 @@ For example the following are correct: System.Threading.Tasks.Task DoSomethingAsync() ``` +1. All the parameter names in methods and constructors should be `camelCase`. + +1. The namespace of a new class would normally match the assembly name, or a more qualfied version of it. Exceptions may apply. For example if the namespace is preserved for type forwarding purposes. For a class in `NuGet.Packaging`: + + These are correct: + + ```cs + namespace NuGet.Packaging { + public class SpecialSigningUtility + { + } + } + ... + namespace NuGet.Packaging.Signing { + public class SpecialSigningUtility + { + } + } + ``` + + This is incorrect: + + ```cs + namespace NuGet.Common { + public class SpecialSigningUtility + { + } + } + ``` + Exceptions are allowed when multiple type names coming from different namespaces are available. Many of the guidelines, wherever possible, and potentially some not listed here, are enforced by an [EditorConfig](https://editorconfig.org "EditorConfig homepage") file (`.editorconfig`) at the root of the repository. From 57b2153887123d276358d0c66101f05a3259457b Mon Sep 17 00:00:00 2001 From: Erdembayar Yondon Date: Tue, 26 Jan 2021 18:04:59 -0800 Subject: [PATCH 125/129] Address missing PR comments for Add new telemetries to track events related to PMC and Powershell usage (#3863) * Address missed PR comments from Nikolche. * Use static import suggested by Nikolche. * Address comment from Nikolche: parameter names have to be camel case. * Correct Namespace. --- .../Xamls/ConsoleContainer.xaml.cs | 2 +- .../NuGetPowerShellBaseCommand.cs | 2 +- .../IDE/VSSolutionManager.cs | 2 +- src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs | 6 +- .../NuGetPowerShellUsageCollector.cs | 57 ++++++++----------- .../Powershell/InstanceCloseEvent.cs | 29 ++++++++++ .../Powershell/NuGetPowerShellUsage.cs | 2 +- .../Powershell/PowerShellLoadedEvent.cs | 16 ++++++ .../Powershell/SolutionCloseEvent.cs | 38 +++++++++++++ .../PowerShellHost.cs | 8 +-- 10 files changed, 118 insertions(+), 44 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/InstanceCloseEvent.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/PowerShellLoadedEvent.cs create mode 100644 src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/SolutionCloseEvent.cs diff --git a/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs b/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs index 6c715d45e8d..af8ab6377c9 100644 --- a/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs +++ b/src/NuGet.Clients/NuGet.Console/Xamls/ConsoleContainer.xaml.cs @@ -13,8 +13,8 @@ using NuGet.PackageManagement.UI; using NuGet.VisualStudio; using NuGet.VisualStudio.Common; +using NuGet.VisualStudio.Common.Telemetry.PowerShell; using NuGet.VisualStudio.Internal.Contracts; -using NuGet.VisualStudio.Telemetry.PowerShell; namespace NuGetConsole { diff --git a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs index 831d3e57341..dc5b9178436 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.PowerShellCmdlets/NuGetPowerShellBaseCommand.cs @@ -28,7 +28,7 @@ using NuGet.Protocol.Core.Types; using NuGet.Versioning; using NuGet.VisualStudio; -using NuGet.VisualStudio.Telemetry.PowerShell; +using NuGet.VisualStudio.Common.Telemetry.PowerShell; using ExecutionContext = NuGet.ProjectManagement.ExecutionContext; namespace NuGet.PackageManagement.PowerShellCmdlets diff --git a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs index ac72279f510..40c69f2f02b 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/IDE/VSSolutionManager.cs @@ -26,7 +26,7 @@ using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.VisualStudio; -using NuGet.VisualStudio.Telemetry.PowerShell; +using NuGet.VisualStudio.Common.Telemetry.PowerShell; using IAsyncServiceProvider = Microsoft.VisualStudio.Shell.IAsyncServiceProvider; using Task = System.Threading.Tasks.Task; diff --git a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs index e487567017f..1b52eae5f12 100644 --- a/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs +++ b/src/NuGet.Clients/NuGet.Tools/NuGetPackage.cs @@ -26,9 +26,10 @@ using NuGet.ProjectManagement; using NuGet.VisualStudio; using NuGet.VisualStudio.Common; +using NuGet.VisualStudio.Common.Telemetry; +using NuGet.VisualStudio.Common.Telemetry.PowerShell; using NuGet.VisualStudio.Internal.Contracts; using NuGet.VisualStudio.Telemetry; -using NuGet.VisualStudio.Telemetry.PowerShell; using NuGetConsole; using NuGetConsole.Implementation; using ContractsNuGetServices = NuGet.VisualStudio.Contracts.NuGetServices; @@ -37,6 +38,7 @@ using Resx = NuGet.PackageManagement.UI.Resources; using ServiceAudience = Microsoft.VisualStudio.Shell.ServiceBroker.ServiceAudience; using Task = System.Threading.Tasks.Task; +using TelemetryActivity = NuGet.Common.TelemetryActivity; using UI = NuGet.PackageManagement.UI; namespace NuGetVSExtension @@ -148,7 +150,7 @@ public NuGetPackage() protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) { _nuGetPowerShellUsageCollector = new NuGetPowerShellUsageCollector(); - NuGet.Common.TelemetryActivity.NuGetTelemetryService = new NuGetVSTelemetryService(); + TelemetryActivity.NuGetTelemetryService = new NuGetVSTelemetryService(); await base.InitializeAsync(cancellationToken, progress); diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs index 5e9405f3a41..51c0c2de4c0 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/NuGetPowerShellUsageCollector.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using NuGet.Common; -using NuGet.VisualStudio.Telemetry.PowerShell; +using NuGet.VisualStudio.Common.Telemetry.PowerShell; -namespace NuGet.VisualStudio.Telemetry +namespace NuGet.VisualStudio.Common.Telemetry { public sealed class NuGetPowerShellUsageCollector : IDisposable { @@ -302,23 +301,20 @@ internal SolutionData() internal TelemetryEvent ToTelemetryEvent() { - var telemetry = new TelemetryEvent(SolutionClose, - new Dictionary() - { - { PowerShellHost + NuGetPowerShellUsageCollector.FirstTimeLoadedFromPmc , FirstTimeLoadedFromPmc }, - { PowerShellHost + NuGetPowerShellUsageCollector.FirstTimeLoadedFromPmui , FirstTimeLoadedFromPmui }, - { PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadedFromPmcFirst , InitPs1LoadedFromPmcFirst }, - { PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadPmc , InitPs1LoadPmc }, - { PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadPmui , InitPs1LoadPmui }, - { PowerShellHost + NuGetPowerShellUsageCollector.LoadedFromPmc , LoadedFromPmc }, - { PowerShellHost + NuGetPowerShellUsageCollector.LoadedFromPmui , LoadedFromPmui }, - { PowerShellHost + NuGetPowerShellUsageCollector.NuGetCommandUsed , NuGetCommandUsed }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmcExecuteCommandCount , PmcExecuteCommandCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmcWindowLoadCount , PmcWindowLoadCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmuiExecuteCommandCount , PmuiExecuteCommandCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.SolutionLoaded , SolutionLoaded } - }); - + var telemetry = new SolutionCloseEvent( + firstTimeLoadedFromPmc: FirstTimeLoadedFromPmc, + firstTimeLoadedFromPmui: FirstTimeLoadedFromPmui, + initPs1LoadedFromPmcFirst: InitPs1LoadedFromPmcFirst, + initPs1LoadPmc: InitPs1LoadPmc, + initPs1LoadPmui: InitPs1LoadPmui, + loadedFromPmc: LoadedFromPmc, + loadedFromPmui: LoadedFromPmui, + nuGetCommandUsed: NuGetCommandUsed, + pmcExecuteCommandCount: PmcExecuteCommandCount, + pmcWindowLoadCount: PmcWindowLoadCount, + pmuiExecuteCommandCount: PmuiExecuteCommandCount, + solutionLoaded: SolutionLoaded + ); return telemetry; } } @@ -346,18 +342,15 @@ internal InstanceData() internal TelemetryEvent ToTelemetryEvent() { - var telemetry = new TelemetryEvent(InstanceClose, - new Dictionary() - { - { PowerShellHost + NuGetPowerShellUsageCollector.PmcExecuteCommandCount , PmcExecuteCommandCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmcWindowLoadCount , PmcWindowLoadCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmuiExecuteCommandCount , PmuiExecuteCommandCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmcPowerShellLoadedSolutionCount , PmcLoadedSolutionCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.PmuiPowerShellLoadedSolutionCount , PmuiLoadedSolutionCount }, - { PowerShellHost + NuGetPowerShellUsageCollector.ReOpenAtStart , ReOpenAtStart }, - { PowerShellHost + NuGetPowerShellUsageCollector.SolutionCount , SolutionCount }, - }); - + var telemetry = new InstanceCloseEvent( + pmcExecuteCommandCount: PmcExecuteCommandCount, + pmcWindowLoadCount: PmcWindowLoadCount, + pmuiExecuteCommandCount: PmuiExecuteCommandCount, + pmcPowerShellLoadedSolutionCount: PmcLoadedSolutionCount, + pmuiPowerShellLoadedSolutionCount: PmuiLoadedSolutionCount, + reOpenAtStart: ReOpenAtStart, + solutionCount: SolutionCount + ); return telemetry; } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/InstanceCloseEvent.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/InstanceCloseEvent.cs new file mode 100644 index 00000000000..c9e6c8f4347 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/InstanceCloseEvent.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using NuGet.Common; + +namespace NuGet.VisualStudio.Common.Telemetry.PowerShell +{ + public class InstanceCloseEvent : TelemetryEvent + { + public InstanceCloseEvent( + int pmcExecuteCommandCount, + int pmcWindowLoadCount, + int pmuiExecuteCommandCount, + int pmcPowerShellLoadedSolutionCount, + int pmuiPowerShellLoadedSolutionCount, + bool reOpenAtStart, + int solutionCount + ) : base(NuGetPowerShellUsageCollector.InstanceClose) + { + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmcExecuteCommandCount] = pmcExecuteCommandCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmcWindowLoadCount] = pmcWindowLoadCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmuiExecuteCommandCount] = pmuiExecuteCommandCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmcPowerShellLoadedSolutionCount] = pmcPowerShellLoadedSolutionCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmuiPowerShellLoadedSolutionCount] = pmuiPowerShellLoadedSolutionCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.ReOpenAtStart] = reOpenAtStart; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.SolutionCount] = solutionCount; + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs index 2241b429648..2e854ccde0d 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/NuGetPowerShellUsage.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace NuGet.VisualStudio.Telemetry.PowerShell +namespace NuGet.VisualStudio.Common.Telemetry.PowerShell { public static class NuGetPowerShellUsage { diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/PowerShellLoadedEvent.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/PowerShellLoadedEvent.cs new file mode 100644 index 00000000000..d5cb0ad4356 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/PowerShellLoadedEvent.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using NuGet.Common; + +namespace NuGet.VisualStudio.Common.Telemetry.PowerShell +{ + public class PowerShellLoadedEvent : TelemetryEvent + { + public PowerShellLoadedEvent(bool isPmc) + : base(NuGetPowerShellUsageCollector.PowerShellLoaded) + { + base[NuGetPowerShellUsageCollector.Trigger] = isPmc ? NuGetPowerShellUsageCollector.Pmc : NuGetPowerShellUsageCollector.Pmui; + } + } +} diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/SolutionCloseEvent.cs b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/SolutionCloseEvent.cs new file mode 100644 index 00000000000..59a2d046eb8 --- /dev/null +++ b/src/NuGet.Clients/NuGet.VisualStudio.Common/Telemetry/Powershell/SolutionCloseEvent.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using NuGet.Common; + +namespace NuGet.VisualStudio.Common.Telemetry.PowerShell +{ + public class SolutionCloseEvent : TelemetryEvent + { + public SolutionCloseEvent( + bool firstTimeLoadedFromPmc, + bool firstTimeLoadedFromPmui, + bool initPs1LoadedFromPmcFirst, + bool initPs1LoadPmc, + bool initPs1LoadPmui, + bool loadedFromPmc, + bool loadedFromPmui, + bool nuGetCommandUsed, + int pmcExecuteCommandCount, + int pmcWindowLoadCount, + int pmuiExecuteCommandCount, + bool solutionLoaded) : base(NuGetPowerShellUsageCollector.SolutionClose) + { + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.FirstTimeLoadedFromPmc] = firstTimeLoadedFromPmc; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.FirstTimeLoadedFromPmui] = firstTimeLoadedFromPmui; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadedFromPmcFirst] = initPs1LoadedFromPmcFirst; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadPmc] = initPs1LoadPmc; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.InitPs1LoadPmui] = initPs1LoadPmui; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.LoadedFromPmc] = loadedFromPmc; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.LoadedFromPmui] = loadedFromPmui; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.NuGetCommandUsed] = nuGetCommandUsed; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmcExecuteCommandCount] = pmcExecuteCommandCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmcWindowLoadCount] = pmcWindowLoadCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.PmuiExecuteCommandCount] = pmuiExecuteCommandCount; + base[NuGetPowerShellUsageCollector.PowerShellHost + NuGetPowerShellUsageCollector.SolutionLoaded] = solutionLoaded; + } + } +} diff --git a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs index 7c9428fe7d3..6ab679cd68f 100644 --- a/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs +++ b/src/NuGet.Clients/NuGetConsole.Host.PowerShell/PowerShellHost.cs @@ -28,8 +28,8 @@ using NuGet.ProjectManagement; using NuGet.Protocol.Core.Types; using NuGet.VisualStudio; +using NuGet.VisualStudio.Common.Telemetry.PowerShell; using NuGet.VisualStudio.Telemetry; -using NuGet.VisualStudio.Telemetry.PowerShell; using Task = System.Threading.Tasks.Task; namespace NuGetConsole.Host.PowerShell.Implementation @@ -317,11 +317,7 @@ public void Initialize(IConsole console) if (!PowerShellLoaded) { - var telemetryEvent = new TelemetryEvent(NuGetPowerShellUsageCollector.PowerShellLoaded, new Dictionary - { - { NuGetPowerShellUsageCollector.Trigger, _isPmc ? NuGetPowerShellUsageCollector.Pmc : NuGetPowerShellUsageCollector.Pmui } - }); - + var telemetryEvent = new PowerShellLoadedEvent(isPmc: _isPmc); TelemetryActivity.EmitTelemetryEvent(telemetryEvent); PowerShellLoaded = true; } From 271afca7cab4a8b8d0200da9416c49523e8c04f1 Mon Sep 17 00:00:00 2001 From: donnie-msft <49205731+donnie-msft@users.noreply.github.com> Date: Tue, 26 Jan 2021 22:25:07 -0500 Subject: [PATCH 126/129] PMUI Packages List Update selection checkboxes support Screen-Reader Toggle Pattern (#3857) * Create Toggleable Automation Peer for ListBox --- .../ListBoxToggleableItemsAutomationPeer.cs | 37 ++++++++++++ .../ToggleableItemAutomationPeer.cs | 59 +++++++++++++++++++ .../GlobalSuppressions.cs | 2 + .../NuGet.PackageManagement.UI.csproj | 7 ++- .../Xamls/InfiniteScrollList.xaml.cs | 14 ++++- .../Xamls/InfiniteScrollListBox.cs | 12 +++- .../Xamls/PackageItemControl.xaml | 5 +- .../Xamls/PackageItemControl.xaml.cs | 46 +++++++++++++++ 8 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ListBoxToggleableItemsAutomationPeer.cs create mode 100644 src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ToggleableItemAutomationPeer.cs diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ListBoxToggleableItemsAutomationPeer.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ListBoxToggleableItemsAutomationPeer.cs new file mode 100644 index 00000000000..3e1e5241050 --- /dev/null +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ListBoxToggleableItemsAutomationPeer.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Windows.Automation.Peers; +using System.Windows.Controls; + +namespace NuGet.PackageManagement.UI +{ + /// + /// Automation peer to represent ListBox items which are used as toggles for an associated checkbox. + /// Specifically, this is used for the representation of in + /// the control for selecting packages to be Updated (eg, Updates tab). + /// + internal class ListBoxToggleableItemsAutomationPeer : ListBoxAutomationPeer + { + public ListBoxToggleableItemsAutomationPeer(InfiniteScrollListBox owner) + : base(owner) + { + } + + public override object GetPattern(PatternInterface patternInterface) + { + if (patternInterface == PatternInterface.Toggle) + { + return this; + } + return base.GetPattern(patternInterface); + } + + protected override ItemAutomationPeer CreateItemAutomationPeer(object item) + { + return new ToggleableItemAutomationPeer(item, this); + } + } +} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ToggleableItemAutomationPeer.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ToggleableItemAutomationPeer.cs new file mode 100644 index 00000000000..31538ea8870 --- /dev/null +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Automation/ToggleableItemAutomationPeer.cs @@ -0,0 +1,59 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Windows.Automation; +using System.Windows.Automation.Peers; +using System.Windows.Automation.Provider; + +namespace NuGet.PackageManagement.UI +{ + internal class ToggleableItemAutomationPeer : ListBoxItemAutomationPeer, IToggleProvider + { + private readonly InfiniteScrollListBox _ownerParent; + private readonly PackageItemListViewModel _owner; + + public ToggleableItemAutomationPeer(object item, SelectorAutomationPeer selectorAutomationPeer) + : base(item, selectorAutomationPeer) + { + _owner = item as PackageItemListViewModel; + _ownerParent = selectorAutomationPeer.Owner as InfiniteScrollListBox; + } + + public override object GetPattern(PatternInterface patternInterface) + { + if (patternInterface == PatternInterface.Toggle && _ownerParent?.CheckboxesEnabled == true) + { + return this; + } + + return base.GetPattern(patternInterface); + } + + /// + /// The default will be assumed to be toggled off (eg, Checked is false), therefore translating to `ToggleState.Off`. + /// + public ToggleState ToggleState + { + get + { + return _owner?.Selected == true ? ToggleState.On : ToggleState.Off; + } + set + { + if (_owner != null) + { + _owner.Selected = value == ToggleState.On; + } + } + } + + public void Toggle() + { + if (_owner != null) + { + _owner.Selected = !_owner.Selected; + } + } + } +} diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs index 1b0e00d6cf1..f2a652f9bd1 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/GlobalSuppressions.cs @@ -113,6 +113,8 @@ [assembly: SuppressMessage("Build", "CA1501:'OptionsControl' has an object hierarchy '9' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'UserControl, ContentControl, Control, FrameworkElement, UIElement, Visual, DependencyObject, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.OptionsControl")] [assembly: SuppressMessage("Build", "CA1501:'PackageItemControl' has an object hierarchy '9' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'UserControl, ContentControl, Control, FrameworkElement, UIElement, Visual, DependencyObject, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.PackageItemControl")] [assembly: SuppressMessage("Build", "CA1501:'PackageManagementFormatWindow' has an object hierarchy '12' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'VsDialogWindow, DialogWindow, DialogWindowBase, Window, ContentControl, Control, FrameworkElement, UIElement, Visual, DependencyObject, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.PackageManagementFormatWindow")] +[assembly: SuppressMessage("Build", "CA1501:'ListBoxToggleableItemsAutomationPeer' has an object hierarchy '8' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'ListBoxAutomationPeer, SelectorAutomationPeer, ItemsControlAutomationPeer, FrameworkElementAutomationPeer, UIElementAutomationPeer, AutomationPeer, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.ListBoxToggleableItemsAutomationPeer")] +[assembly: SuppressMessage("Build", "CA1501:'ToggleableItemAutomationPeer' has an object hierarchy '6' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'ListBoxItemAutomationPeer, SelectorItemAutomationPeer, ItemAutomationPeer, AutomationPeer, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.ToggleableItemAutomationPeer")] [assembly: SuppressMessage("Build", "CA1001:Type 'PackageManagerControl' owns disposable field(s) '_loadCts, _refreshCts' but is not disposable", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.PackageManagerControl")] [assembly: SuppressMessage("Build", "CA1501:'PackageManagerControl' has an object hierarchy '9' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'UserControl, ContentControl, Control, FrameworkElement, UIElement, Visual, DependencyObject, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.PackageManagerControl")] [assembly: SuppressMessage("Build", "CA1501:'PackageManagerProvidersLabel' has an object hierarchy '9' levels deep within the defining module. If possible, eliminate base classes within the hierarchy to decrease its hierarchy level below '6': 'UserControl, ContentControl, Control, FrameworkElement, UIElement, Visual, DependencyObject, DispatcherObject, Object'", Justification = "", Scope = "type", Target = "~T:NuGet.PackageManagement.UI.PackageManagerProvidersLabel")] diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj b/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj index 655b8904250..305b25161f7 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/NuGet.PackageManagement.UI.csproj @@ -1,4 +1,4 @@ - + @@ -44,6 +44,7 @@ + @@ -52,7 +53,9 @@ + + @@ -524,4 +527,4 @@ - + \ No newline at end of file diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollList.xaml.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollList.xaml.cs index 39275873b2d..0882f5e422d 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollList.xaml.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollList.xaml.cs @@ -50,6 +50,7 @@ public partial class InfiniteScrollList : UserControl private INuGetUILogger _logger; private Task _initialSearchResultTask; private readonly Lazy _joinableTaskFactory; + private bool _checkBoxesEnabled; private const string LogEntrySource = "NuGet Package Manager"; @@ -98,7 +99,18 @@ private void LoadingStatusIndicator_PropertyChanged(object sender, PropertyChang }); } - public bool CheckBoxesEnabled { get; set; } + public bool CheckBoxesEnabled + { + get => _checkBoxesEnabled; + set + { + if (_checkBoxesEnabled != value) + { + _checkBoxesEnabled = value; + _list.CheckboxesEnabled = value; + } + } + } public bool IsSolution { get; set; } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollListBox.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollListBox.cs index 478232b6ff6..182b5a26a29 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollListBox.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/InfiniteScrollListBox.cs @@ -1,13 +1,21 @@ -using System.Threading; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Windows.Automation.Peers; using System.Windows.Controls; using Microsoft.VisualStudio.Threading; -using NuGet.VisualStudio; namespace NuGet.PackageManagement.UI { internal class InfiniteScrollListBox : ListBox { + public bool CheckboxesEnabled { get; set; } + public ReentrantSemaphore ItemsLock { get; set; } + + protected override AutomationPeer OnCreateAutomationPeer() + { + return new ListBoxToggleableItemsAutomationPeer(this); + } } } diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageItemControl.xaml b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageItemControl.xaml index c67c6050c70..118d13da693 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageItemControl.xaml +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageItemControl.xaml @@ -87,8 +87,11 @@ Margin="4,12,4,0" VerticalAlignment="top" Visibility="{Binding CheckBoxesEnabled, RelativeSource={RelativeSource AncestorType={x:Type nuget:InfiniteScrollList}}, Converter={StaticResource NonVisualStateHiddenBooleanToVisibilityConverter}}" + Focusable="False" AutomationProperties.Name="{x:Static nuget:Resources.CheckBox_Selected}" - IsChecked="{Binding Selected}" /> + IsChecked="{Binding Selected}" + Checked="CheckBox_Toggled" + Unchecked="CheckBox_Toggled"/> Date: Tue, 26 Jan 2021 22:25:34 -0500 Subject: [PATCH 127/129] Updating via Checkboxes no longer causes Null Reference Exception (#3864) --- .../Xamls/PackageManagerControl.xaml.cs | 2 +- .../NuGetPackageManager.cs | 5 ++ .../NuGetPackageManagerTests.cs | 67 +++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs index 56ed1fbb80e..058338c323f 100644 --- a/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs +++ b/src/NuGet.Clients/NuGet.PackageManagement.UI/Xamls/PackageManagerControl.xaml.cs @@ -1553,7 +1553,7 @@ private void ExecuteInstallPackageCommand(object sender, ExecutedRoutedEventArgs private void PackageList_UpdateButtonClicked(PackageItemListViewModel[] selectedPackages) { var packagesToUpdate = selectedPackages - .Select(package => new PackageIdentity(package.Id, package.LatestVersion)) + .Select(package => new PackageIdentity(package.Id, package.Version)) .ToList(); UpdatePackage(packagesToUpdate); diff --git a/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs b/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs index 8d6746d1349..8f04dd861f0 100644 --- a/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs +++ b/src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs @@ -605,6 +605,11 @@ private async Task> PreviewUpdatePackagesAsync( IEnumerable secondarySources, CancellationToken token) { + if (packageIdentities == null) + { + throw new ArgumentNullException(nameof(packageIdentities)); + } + if (nuGetProjects == null) { throw new ArgumentNullException(nameof(nuGetProjects)); diff --git a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGetPackageManagerTests.cs b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGetPackageManagerTests.cs index bdabdd8fe69..126344f6c3c 100644 --- a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGetPackageManagerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGetPackageManagerTests.cs @@ -6975,6 +6975,73 @@ await nuGetPackageManager.PreviewBuildIntegratedProjectsActionsAsync( } } + /// + /// Repro for a bug caused by a NullReferenceException being thrown due to a null + /// (https://github.com/NuGet/Home/issues/9882). + /// + /// + [Fact] + public async Task TestPacMan_PreviewInstallPackage_BuildIntegrated_NullVersion_Throws() + { + // Arrange + + // Set up Package Source + var packages = new List + { + new SourcePackageDependencyInfo("a", new NuGetVersion(1, 0, 0), new PackageDependency[] { }, true, null), + new SourcePackageDependencyInfo("a", new NuGetVersion(2, 0, 0), new PackageDependency[] { }, true, null), + new SourcePackageDependencyInfo("a", new NuGetVersion(3, 0, 0), new PackageDependency[] { }, true, null), + }; + + SourceRepositoryProvider sourceRepositoryProvider = CreateSource(packages); + + // Set up NuGetProject + var fwk45 = NuGetFramework.Parse("net45"); + + var installedPackages = new List + { + new PackageReference(new PackageIdentity("a", new NuGetVersion(1, 0, 0)), fwk45, true), + }; + + var packageIdentity = _packageWithDependents[0]; + + // Create Package Manager + using (var solutionManager = new TestSolutionManager()) + { + var nuGetPackageManager = new NuGetPackageManager( + sourceRepositoryProvider, + NullSettings.Instance, + solutionManager, + new TestDeleteOnRestartManager()); + + var buildIntegratedProjectA = new Mock(); + buildIntegratedProjectA.Setup(p => p.GetInstalledPackagesAsync(CancellationToken.None)) + .Returns(() => Task.FromResult(installedPackages.AsEnumerable())); + + var projectList = new List { buildIntegratedProjectA.Object }; + solutionManager.NuGetProjects = projectList; + + // Main Act + var targets = new List + { + new PackageIdentity("a", null) + }; + + // Assert + var ex = await Assert.ThrowsAsync(async () => + { + IEnumerable result = await nuGetPackageManager.PreviewUpdatePackagesAsync( + targets, + projectList, + new ResolutionContext(), + new TestNuGetProjectContext(), + sourceRepositoryProvider.GetRepositories(), + sourceRepositoryProvider.GetRepositories(), + CancellationToken.None); + }); + } + } + private void VerifyPreviewActionsTelemetryEvents_PackagesConfig(IEnumerable actual) { Assert.True(actual.Contains(TelemetryConstants.GatherDependencyStepName)); From 045188d0965349bc8e0b97609397695c0d164613 Mon Sep 17 00:00:00 2001 From: Epsitha Ananth Date: Thu, 18 Feb 2021 11:59:06 -0800 Subject: [PATCH 128/129] update maestro task version --- build/bootstrap.proj | 2 +- build/common.project.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/bootstrap.proj b/build/bootstrap.proj index 85cce8cb23e..12a01ec0016 100644 --- a/build/bootstrap.proj +++ b/build/bootstrap.proj @@ -15,7 +15,7 @@ - + diff --git a/build/common.project.props b/build/common.project.props index 8f4140beb33..b0f07c9cb7e 100644 --- a/build/common.project.props +++ b/build/common.project.props @@ -50,7 +50,7 @@ $(ArtifactsDirectory)LocalizedFiles $(SolutionPackagesFolder)microsoft.visualstudioeng.microbuild.core\0.4.1\build\ $(SolutionPackagesFolder)microsoft.dotnet.build.tasks.feed\6.0.0-beta.20528.5\tools\netcoreapp2.1\Microsoft.DotNet.Build.Tasks.Feed.dll - $(SolutionPackagesFolder)microsoft.dotnet.maestro.tasks\1.1.0-beta.20528.3\tools\netcoreapp3.1\Microsoft.DotNet.Maestro.Tasks.dll + $(SolutionPackagesFolder)microsoft.dotnet.maestro.tasks\1.1.0-beta.20570.1\tools\netcoreapp3.1\Microsoft.DotNet.Maestro.Tasks.dll $(NoWarn);NU5105;NU5048 From cbd96cdf189506a085a23c21d456ff53f1c3224e Mon Sep 17 00:00:00 2001 From: Epsitha Ananth Date: Thu, 18 Feb 2021 12:58:14 -0800 Subject: [PATCH 129/129] update feeds version --- build/bootstrap.proj | 2 +- build/common.project.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/bootstrap.proj b/build/bootstrap.proj index 12a01ec0016..ac10fdd7d83 100644 --- a/build/bootstrap.proj +++ b/build/bootstrap.proj @@ -14,7 +14,7 @@ - + diff --git a/build/common.project.props b/build/common.project.props index b0f07c9cb7e..f3c00024594 100644 --- a/build/common.project.props +++ b/build/common.project.props @@ -49,7 +49,7 @@ $(NuGetBuildLocalizationRepository)localize $(ArtifactsDirectory)LocalizedFiles $(SolutionPackagesFolder)microsoft.visualstudioeng.microbuild.core\0.4.1\build\ - $(SolutionPackagesFolder)microsoft.dotnet.build.tasks.feed\6.0.0-beta.20528.5\tools\netcoreapp2.1\Microsoft.DotNet.Build.Tasks.Feed.dll + $(SolutionPackagesFolder)microsoft.dotnet.build.tasks.feed\6.0.0-beta.21111.3\tools\netcoreapp2.1\Microsoft.DotNet.Build.Tasks.Feed.dll $(SolutionPackagesFolder)microsoft.dotnet.maestro.tasks\1.1.0-beta.20570.1\tools\netcoreapp3.1\Microsoft.DotNet.Maestro.Tasks.dll $(NoWarn);NU5105;NU5048