diff --git a/.csharpierrc b/.csharpierrc index 636fd96..4e66fbc 100644 --- a/.csharpierrc +++ b/.csharpierrc @@ -1,3 +1,3 @@ { - "printWidth": 100 + "printWidth": 120 } diff --git a/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs b/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs index 7b2e115..a7c1d0c 100644 --- a/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs +++ b/DotNetSolutionTools.App/ViewModels/MainWindowViewModel.cs @@ -23,7 +23,7 @@ public partial class MainWindowViewModel : ViewModelBase [ObservableProperty] private ObservableCollection _parityResults = new() { }; - + [ObservableProperty] private string _resultsLabel = "Ready"; @@ -35,10 +35,7 @@ public partial class MainWindowViewModel : ViewModelBase ResultsLabel = string.Empty; try { - var results = SolutionProjectParity.CompareSolutionAndCSharpProjects( - SolutionFolderPath, - SolutionFilePath - ); + var results = SolutionProjectParity.CompareSolutionAndCSharpProjects(SolutionFolderPath, SolutionFilePath); foreach (var result in results) ParityResults.Add(result); ResultsLabel = $"{results.Count} Projects in folder missing from solution"; @@ -62,9 +59,7 @@ public partial class MainWindowViewModel : ViewModelBase ErrorMessages?.Clear(); try { - var csprojList = SolutionProjectParity.RetrieveAllCSharpProjectFullPathsFromFolder( - SolutionFolderPath - ); + var csprojList = SolutionProjectParity.RetrieveAllCSharpProjectFullPathsFromFolder(SolutionFolderPath); foreach (var csproj in csprojList) { FormatCsproj.FormatCsprojFile(csproj); @@ -83,9 +78,7 @@ public partial class MainWindowViewModel : ViewModelBase ErrorMessages?.Clear(); try { - var csprojList = SolutionProjectParity.RetrieveAllCSharpProjectFullPathsFromFolder( - SolutionFolderPath - ); + var csprojList = SolutionProjectParity.RetrieveAllCSharpProjectFullPathsFromFolder(SolutionFolderPath); foreach (var csproj in csprojList) { FormatCsproj.FormatCsprojFile(csproj); @@ -97,7 +90,7 @@ public partial class MainWindowViewModel : ViewModelBase ParityResults?.Add(e.Message); } } - + [RelayCommand] private async Task CheckForMissingImplicitUsingsInSolutionFile(CancellationToken token) { @@ -116,7 +109,7 @@ public partial class MainWindowViewModel : ViewModelBase ParityResults?.Add(e.Message); } } - + [RelayCommand] private async Task CheckForMissingTreatWarningsAsErrorsInSolutionFile(CancellationToken token) { @@ -135,7 +128,7 @@ public partial class MainWindowViewModel : ViewModelBase ParityResults?.Add(e.Message); } } - + [RelayCommand] private async Task DeleteBinAndObjFoldersInFolder(CancellationToken token) { @@ -153,7 +146,7 @@ public partial class MainWindowViewModel : ViewModelBase ParityResults?.Add(e.Message); } } - + [RelayCommand] private async Task UpdateAllProjectsToNet80(CancellationToken token) { @@ -172,6 +165,24 @@ public partial class MainWindowViewModel : ViewModelBase } } + [RelayCommand] + private async Task UpdateProjectToNet80(CancellationToken token) + { + ErrorMessages?.Clear(); + ParityResults.Clear(); + ResultsLabel = string.Empty; + try + { + await DotNetUpgrade.UpdateProjectAtPathToNet80(CsprojFilePath); + ResultsLabel = "Successfully updated project to .NET 8"; + } + catch (Exception e) + { + ResultsLabel = "Failed to update project to .NET 8"; + ParityResults?.Add(e.Message); + } + } + [RelayCommand] private async Task LoadSolutionFile(CancellationToken token) { @@ -264,7 +275,7 @@ public partial class MainWindowViewModel : ViewModelBase var json = JsonSerializer.Serialize(dto); await File.WriteAllTextAsync("./localState.json", json); } - + private async Task LoadSavedState() { try @@ -284,7 +295,7 @@ public partial class MainWindowViewModel : ViewModelBase // ignored } } - + public MainWindowViewModel() { LoadSavedState().ConfigureAwait(false); diff --git a/DotNetSolutionTools.App/Views/MainWindow.axaml b/DotNetSolutionTools.App/Views/MainWindow.axaml index 3ded040..dc39316 100644 --- a/DotNetSolutionTools.App/Views/MainWindow.axaml +++ b/DotNetSolutionTools.App/Views/MainWindow.axaml @@ -107,6 +107,15 @@ Update all projects in Solution to .NET 8.0 + diff --git a/DotNetSolutionTools.Core/DotNetUpgrade.cs b/DotNetSolutionTools.Core/DotNetUpgrade.cs index 6ba2802..f6c01ce 100644 --- a/DotNetSolutionTools.Core/DotNetUpgrade.cs +++ b/DotNetSolutionTools.Core/DotNetUpgrade.cs @@ -11,30 +11,39 @@ public static class DotNetUpgrade public static async Task UpdateProjectsInSolutionToNet80(string solutionFilePath) { var solutionFile = SolutionFile.Parse(solutionFilePath); - var csprojList = SolutionProjectParity.GetCSharpProjectObjectsFromSolutionFile( - solutionFile - ); + var csprojList = SolutionProjectParity.GetCSharpProjectObjectsFromSolutionFile(solutionFile); await UpdateProjectsToNet80(csprojList); } + public static async Task UpdateProjectAtPathToNet80(string csprojFilePath) + { + var csproj = ProjectRootElement.Open(csprojFilePath); + await UpdateProjectToNet80(csproj!); + } + private static async Task UpdateProjectsToNet80(List projects) { foreach (var project in projects) { - var targetFramework = project - .PropertyGroups - .SelectMany(x => x.Properties) - .FirstOrDefault(x => x.Name == "TargetFramework"); - if (targetFramework?.Value is "net8.0" or "net7.0" or "net6.0" or "net5.0") + await UpdateProjectToNet80(project); + } + } + + private static async Task UpdateProjectToNet80(ProjectRootElement project) + { + var targetFramework = project + .PropertyGroups + .SelectMany(x => x.Properties) + .FirstOrDefault(x => x.Name == "TargetFramework"); + if (targetFramework?.Value is "net8.0" or "net7.0" or "net6.0" or "net5.0") + { + if (targetFramework.Value is not "net8.0") { - if (targetFramework.Value is not "net8.0") - { - targetFramework.Value = "net8.0"; - project.Save(); - FormatCsproj.FormatCsprojFile(project.FullPath); - } - await UpdatePackagesToLatest(project); + targetFramework.Value = "net8.0"; + project.Save(); + FormatCsproj.FormatCsprojFile(project.FullPath); } + await UpdatePackagesToLatest(project); } } @@ -47,10 +56,16 @@ public static class DotNetUpgrade project, new ProjectOptions() { LoadSettings = ProjectLoadSettings.IgnoreMissingImports } ); - var packages = evalProject.Items.Where(x => - x.ItemType == "PackageReference" && x.HasMetadata("Version") && - x.EvaluatedInclude.StartsWith("Microsoft.")).ToList(); - + var packages = evalProject + .Items + .Where( + x => + x.ItemType == "PackageReference" + && x.HasMetadata("Version") + && x.EvaluatedInclude.StartsWith("Microsoft.") + ) + .ToList(); + var packageNameAndVersion = packages .Select( x => @@ -68,8 +83,11 @@ public static class DotNetUpgrade var shouldSave = false; foreach (var package in packageNameAndVersion) { - var latestNugetVersion = await NugetLookup.FetchPackageMetadataAsync(package.Name); - + var latestNugetVersion = await NugetLookup.FetchPackageMetadataAsync( + package.Name, + package.NugetVersion.IsPrerelease + ); + if (latestNugetVersion > package.NugetVersion) { shouldSave = true; @@ -83,6 +101,11 @@ public static class DotNetUpgrade FormatCsproj.FormatCsprojFile(project.FullPath); } } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } finally { if (evalProject is not null) diff --git a/DotNetSolutionTools.Core/Infrastructure/NugetLookup.cs b/DotNetSolutionTools.Core/Infrastructure/NugetLookup.cs index f403ff1..60c1fd7 100644 --- a/DotNetSolutionTools.Core/Infrastructure/NugetLookup.cs +++ b/DotNetSolutionTools.Core/Infrastructure/NugetLookup.cs @@ -7,20 +7,58 @@ namespace DotNetSolutionTools.Core.Infrastructure; public static class NugetLookup { - public static async Task FetchPackageMetadataAsync(string packageId) + public static async Task FetchPackageMetadataAsync(string packageId, bool isCurrentlyPrerelease) { var cache = new SourceCacheContext(); var repositories = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json"); var logger = NullLogger.Instance; var resource = await repositories.GetResourceAsync(); - var versions = await resource.GetAllVersionsAsync( - packageId, - cache, - logger, - CancellationToken.None - ); + var versions = await resource.GetAllVersionsAsync(packageId, cache, logger, CancellationToken.None); - return versions.Last(s => s.IsPrerelease == false); + var latestPrereleaseVersion = versions.LastOrDefault(s => s.IsPrerelease == true); + var latestStableVersion = versions.LastOrDefault(s => s.IsPrerelease == false); + + if (latestStableVersion is null && latestPrereleaseVersion is null) + { + Throw(packageId); + } + + if (latestStableVersion is null) + { + if (isCurrentlyPrerelease && latestPrereleaseVersion is not null) + { + return latestPrereleaseVersion; + } + else + { + Throw(packageId); + } + } + + if (latestPrereleaseVersion is null) + { + return latestStableVersion; + } + + if (latestStableVersion > latestPrereleaseVersion) + { + return latestStableVersion; + } + + if (isCurrentlyPrerelease) + { + return latestPrereleaseVersion; + } + + return latestStableVersion; + } + + public static void Throw(string packageId) + { + throw new ArgumentNullException( + "latestVersion", + $"No latest stable or prerelease Nuget package version found for {packageId}" + ); } }