dotnet / upgrade-assistant

A tool to assist developers in upgrading .NET Framework applications to .NET 6 and beyond
MIT License
1.11k stars 162 forks source link

net-cf target framework breaks upgrade tool #1194

Closed AArnott closed 2 years ago

AArnott commented 2 years ago

Describe the bug

The tool apparently cannot handle the net-cf target framework. I'm not even quite sure where it gets the problematic string from, since net-cf doesn't appear anywhere in the repo. Maybe in a nuget package dependency?

To Reproduce

git clone https://devdiv@dev.azure.com/devdiv/DevDiv/_git/ProjectServices
cd ProjectServices
upgrade-assistant .\src\Microsoft.VisualStudio.ProjectServices.sln

Select "src\Microsoft.VisualStudio.ProjectServices.Tests\Microsoft.VisualStudio.ProjectServices.Tests.csproj" as the entrypoint. After upgrading it to SDK style, the tool exits with an exception as specified below.

Exceptions (if any)

[10:29:36 ERR] Unexpected error
System.ArgumentException: Invalid portable frameworks 'net+win+wpa+wp+sl+net-cf+netmf+MonoAndroid+MonoTouch+Xamarin.iOS'. A hyphen may not be in any of the portable framework names.
   at NuGet.Frameworks.FrameworkNameProvider.TryGetPortableFrameworks(String shortPortableProfiles, IEnumerable`1& frameworks)
   at NuGet.Frameworks.NuGetFramework.ParseFolder(String folderName, IFrameworkNameProvider mappings)
   at NuGet.Client.ManagedCodeConventions.TargetFrameworkName_ParserCore(String name)
   at NuGet.Client.ManagedCodeConventions.TargetFrameworkName_Parser(String name, PatternTable table)
   at NuGet.ContentModel.ContentPropertyDefinition.TryLookup(String name, PatternTable table, Object& value)
   at NuGet.ContentModel.Infrastructure.PatternExpression.TokenSegment.TryMatch(ContentItem& item, String path, IReadOnlyDictionary`2 propertyDefinitions, Int32 startIndex, Int32& endIndex)
   at NuGet.ContentModel.Infrastructure.PatternExpression.Match(String path, IReadOnlyDictionary`2 propertyDefinitions)
   at NuGet.ContentModel.ContentItemCollection.FindItemGroups(PatternSet definition)+MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at NuGet.ContentModel.ContentItemCollection.FindBestItemGroup(SelectionCriteria criteria, PatternSet[] definitions)
   at NuGet.Commands.LockFileUtils.GetLockFileItems(IReadOnlyList`1 criteria, ContentItemCollection items, Action`1 additionalAction, MaccatalystFallback maccatalystFallback, PatternSet[] patterns)+MoveNext()
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
   at NuGet.Commands.LockFileUtils.GetBuildItemsForPackageId(IEnumerable`1 items, String packageId)+MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at NuGet.Packaging.CollectionExtensions.AddRange[T](ICollection`1 collection, IEnumerable`1 items)
   at NuGet.Commands.LockFileUtils.AddMSBuildAssets(LockFileLibrary library, RestoreTargetGraph targetGraph, LockFileTargetLibrary lockFileLib, IReadOnlyList`1 orderedCriteria, ContentItemCollection contentItems, MaccatalystFallback maccatalystFallback)
   at NuGet.Commands.LockFileUtils.AddAssets(String aliases, LockFileLibrary library, LocalPackageInfo package, RestoreTargetGraph targetGraph, LibraryIncludeFlags dependencyType, LockFileTargetLibrary lockFileLib, NuGetFramework framework, String runtimeIdentifier, ContentItemCollection contentItems, NuspecReader nuspec, IReadOnlyList`1 orderedCriteria, MaccatalystFallback maccatalystFallback)
   at NuGet.Commands.LockFileUtils.<>c__DisplayClass2_0.<CreateLockFileTargetLibrary>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at NuGet.Commands.LockFileBuilderCache.GetLockFileTargetLibrary(RestoreTargetGraph graph, NuGetFramework framework, LocalPackageInfo localPackageInfo, String aliases, LibraryIncludeFlags libraryIncludeFlags, Func`1 valueFactory)
   at NuGet.Commands.LockFileBuilder.CreateLockFile(LockFile previousLockFile, PackageSpec project, IEnumerable`1 targetGraphs, IReadOnlyList`1 localRepositories, RemoteWalkContext context, LockFileBuilderCache lockFileBuilderCache)
   at NuGet.Commands.RestoreCommand.BuildAssetsFile(LockFile existingLockFile, PackageSpec project, IEnumerable`1 graphs, IReadOnlyList`1 localRepositories, RemoteWalkContext contextForProject)
   at NuGet.Commands.RestoreCommand.ExecuteAsync(CancellationToken token)
   at NuGet.Commands.RestoreRunner.ExecuteAsync(RestoreSummaryRequest summaryRequest, CancellationToken token)
   at NuGet.Commands.RestoreRunner.CompleteTaskAsync(List`1 restoreTasks)
   at NuGet.Commands.RestoreRunner.RunWithoutCommit(IEnumerable`1 restoreRequests, RestoreArgs restoreContext)
   at Microsoft.DotNet.UpgradeAssistant.Extensions.NuGet.NuGetTransitiveDependencyIdentifier.RestoreProjectAsync(IEnumerable`1 packages, IEnumerable`1 tfms, CancellationToken token)
   at Microsoft.DotNet.UpgradeAssistant.Extensions.NuGet.NuGetTransitiveDependencyIdentifier.GetTransitiveDependenciesAsync(IEnumerable`1 packages, IEnumerable`1 tfms, CancellationToken token)
   at Microsoft.DotNet.UpgradeAssistant.Dependencies.TransitiveDependencyExtensions.IsTransitiveDependencyAsync(ITransitiveDependencyIdentifier identifier, String packageName, IEnumerable`1 packages, IEnumerable`1 tfms, CancellationToken token) in /_/src/common/Microsoft.DotNet.UpgradeAssistant.Abstractions/Dependencies/TransitiveDependencyExtensions.cs:line 110
   at Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.WindowsComponentIdentifier.IsWinRt(IProject project, CancellationToken token)
   at Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.WindowsComponentIdentifier.GetComponentsAsync(IProject project, CancellationToken token)
   at Microsoft.DotNet.UpgradeAssistant.MSBuild.MSBuildProject.GetComponentsAsync(CancellationToken token) in /_/src/components/Microsoft.DotNet.UpgradeAssistant.MSBuild/MSBuildProject.cs:line 128
   at Microsoft.DotNet.UpgradeAssistant.Extensions.Maui.MauiPlatformTargetFrameworkUpgradeStep.IsApplicableImplAsync(IUpgradeContext context, CancellationToken token)
   at Microsoft.DotNet.UpgradeAssistant.UpgradeStep.IsApplicableAsync(IUpgradeContext context, CancellationToken token) in /_/src/common/Microsoft.DotNet.UpgradeAssistant.Abstractions/UpgradeStep.cs:line 233
   at Microsoft.DotNet.UpgradeAssistant.UpgraderManager.<>c__DisplayClass9_0.<<GetStepsForContextAsync>b__0>d.MoveNext() in /_/src/components/Microsoft.DotNet.UpgradeAssistant/UpgraderManager.cs:line 168 
--- End of stack trace from previous location ---
   at System.Linq.AsyncEnumerable.WhereEnumerableAsyncIteratorWithTaskAndCancellation`1.MoveNextCore() in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Where.cs:line 339
   at System.Linq.AsyncIteratorBase`1.MoveNextAsync() in /_/Ix.NET/Source/System.Linq.Async/System/Linq/AsyncIterator.cs:line 77
   at System.Linq.AsyncIteratorBase`1.MoveNextAsync() in /_/Ix.NET/Source/System.Linq.Async/System/Linq/AsyncIterator.cs:line 77
   at System.Linq.AsyncEnumerable.<AllAsync>g__Core|207_0[TSource](IAsyncEnumerable`1 source, Func`2 predicate, CancellationToken cancellationToken) in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/All.cs:line 34
   at System.Linq.AsyncEnumerable.<AllAsync>g__Core|207_0[TSource](IAsyncEnumerable`1 source, Func`2 predicate, CancellationToken cancellationToken) in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/All.cs:line 34
   at Microsoft.DotNet.UpgradeAssistant.UpgraderManager.GetNextStepAsync(IUpgradeContext context, CancellationToken token) in /_/src/components/Microsoft.DotNet.UpgradeAssistant/UpgraderManager.cs:line 76
   at Microsoft.DotNet.UpgradeAssistant.Cli.ConsoleUpgrade.RunAsync(CancellationToken token) in /_/src/cli/Microsoft.DotNet.UpgradeAssistant.Cli/Commands/Upgrade/ConsoleUpgrade.cs:line 70
   at Microsoft.DotNet.UpgradeAssistant.Cli.ConsoleUpgrade.RunAsync(CancellationToken token) in /_/src/cli/Microsoft.DotNet.UpgradeAssistant.Cli/Commands/Upgrade/ConsoleUpgrade.cs:line 78
   at Microsoft.DotNet.UpgradeAssistant.Cli.ConsoleRunner.StartAsync(CancellationToken token) in /_/src/cli/Microsoft.DotNet.UpgradeAssistant.Cli/ConsoleRunner.cs:line 61

Further technical details

dotnet --list-sdks
6.0.106 [C:\Program Files\dotnet\sdk]
6.0.203 [C:\Program Files\dotnet\sdk]
6.0.301 [C:\Program Files\dotnet\sdk]
6.0.400-preview.22316.6 [C:\Program Files\dotnet\sdk]
7.0.100-preview.5.22307.18 [C:\Program Files\dotnet\sdk]
brandonh-msft commented 2 years ago

Confirmed repro on main as of 750da0c1701f69cf0345f0eb95db4750727eb7b1 on VS 2022 17.3 internal + net6.0.400-pre

csproj has only been changed to SDK style w/ a Target Framework of net472 at the point of the exception. Debugging now.

brandonh-msft commented 2 years ago

@AArnott appears to be coming from Nerdbank.GitVersioning. I had to decompile & get sourcelink PDBs to follow it down, but eventually landed at this parsing: image

is it possible we could simply update the version of this dependency and get rid of this issue? I'm betting the targets are incompatible with new Nuget.Versioning schemes as of 6.x and that's what we're hitting.

I think trying to build the proj in VS 2022 confirms this: image

brandonh-msft commented 2 years ago

Running with -v option gives us this; looks like the problem might actually be ReadOnlySourceTree nupkg?

Debug output ``` [12:19:56 DBG] Restoring nuget pkgs for C:\Users\hurlburb\AppData\Local\Temp\dotnet-ua\restores\cb26ae8a-84ba-47f8-b44e-9f22c1496d19\project.txt ... [12:19:56 DBG] [NuGet] Running restore with 12 concurrent jobs. [12:19:56 DBG] [NuGet] Reading project file C:\Users\hurlburb\AppData\Local\Temp\dotnet-ua\restores\cb26ae8a-84ba-47f8-b44e-9f22c1496d19\project.txt. [12:19:56 DBG] Loading Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed without pdb from UA_NuGetf5a1c39465a14757b6ff45344f4b6803 [12:19:57 DBG] [NuGet] Restoring packages for C:\Users\hurlburb\AppData\Local\Temp\dotnet-ua\restores\cb26ae8a-84ba-47f8-b44e-9f22c1496d19\project.txt... [12:19:57 DBG] [NuGet] Restoring packages for .NETFramework,Version=v4.7.2... [12:19:57 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/microsoft.visualstudio.internal.microbuild.visualstudio/index.json [12:19:57 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/readonlysourcetree/index.json [12:19:57 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/microsoft.build/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/microsoft.build.framework/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/microsoft.build.utilities.core/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/microsoft.visualstudio.telemetry/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/nerdbank.gitversioning/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/stylecop.analyzers/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/xunit/index.json [12:19:58 DBG] [NuGet] GET https://api.nuget.org/v3-flatcontainer/xunit.runner.visualstudio/index.json [12:20:13 DBG] [NuGet] NotFound https://api.nuget.org/v3-flatcontainer/microsoft.visualstudio.internal.microbuild.visualstudio/index.json 15899ms [12:20:14 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/readonlysourcetree/index.json 16835ms [12:20:16 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/microsoft.build.framework/index.json 18087ms [12:20:16 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/microsoft.visualstudio.telemetry/index.json 17903ms [12:20:18 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/microsoft.build/index.json 20489ms [12:20:20 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/stylecop.analyzers/index.json 21936ms [12:20:20 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/microsoft.build.utilities.core/index.json 22770ms [12:20:24 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/xunit/index.json 25799ms [12:20:24 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/nerdbank.gitversioning/index.json 26707ms [12:20:30 DBG] [NuGet] OK https://api.nuget.org/v3-flatcontainer/xunit.runner.visualstudio/index.json 31785ms [12:20:30 DBG] [NuGet] Resolving conflicts for .NETFramework,Version=v4.7.2... [12:20:30 DBG] [NuGet] Project dependency Microsoft.Build does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:30 DBG] [NuGet] Project dependency Microsoft.Build.Framework does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency Microsoft.Build.Utilities.Core does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency Microsoft.VisualStudio.Internal.MicroBuild.VisualStudio does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency Microsoft.VisualStudio.Telemetry does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency Nerdbank.GitVersioning does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency ReadOnlySourceTree does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency StyleCop.Analyzers does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency xunit does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Project dependency xunit.runner.visualstudio does not contain an inclusive lower bound. Include a lower bound in the dependency version to ensure consistent restore results. [12:20:31 DBG] [NuGet] Unable to find a stable package ReadOnlySourceTree with version - Found 9 version(s) in nuget.org [ Nearest version: 0.1.37-beta ] [12:20:48 INF] Saving upgrade progress file at C:\s\DevDiv\ProjectServices\src\.upgrade-assistant [12:20:49 ERR] Unexpected error System.ArgumentException: Invalid portable frameworks 'net+win+wpa+wp+sl+net-cf+netmf+MonoAndroid+MonoTouch+Xamarin.iOS'. A hyphen may not be in any of the portable framework names. ```

@mjrousos, @twsouthwick, @sunandabalu any suggestions here?

AArnott commented 2 years ago

ReadOnlySourceTree is very old and deprecated. Removing our use of it is part of the overall upgrade plan for this repo as well. But I wonder how net-cf is considered invalid. AFAIK it was a legit and existing TFM at the time I wrote that package.

brandonh-msft commented 2 years ago

If I had to bet, Nuget.Frameworks evolved and at some point stopped supporting it outright; since it's the pkg that's throwing the exception. Additionally, it's not listed in either the current or deprecated frameworks list for nuget 🤷🏻‍♂️ I also found this very old issue (2015) that calls out the same failure but has PRs "fixing" it

AArnott commented 2 years ago

Ok. It sounds like 'fixing' this would be complex, and can be avoided by removing this old dependency instead. Thanks for investigating.