dependabot-nuget 0.287.0 → 0.289.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/lib/NuGetUpdater/.gitignore +1 -0
- data/helpers/lib/NuGetUpdater/Directory.Build.targets +17 -0
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +26 -17
- data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +7 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +3 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +88 -47
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +31 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementArrayConverter.cs +39 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/ShellGitCommandHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.props +7 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +64 -53
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DotNetToolsJsonDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/GlobalJsonDiscovery.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +17 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscoveryResult.cs +3 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +3 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +429 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +12 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/JsonBuildFile.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +7 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +43 -58
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/TargetFrameworkReporter.targets +13 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +13 -43
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +4 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +5 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +40 -33
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +12 -11
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +16 -12
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/CollectionExtensions.cs +17 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ConsoleLogger.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +19 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ILogger.cs +11 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +74 -20
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathComparer.cs +31 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +46 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProjectHelper.cs +96 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +135 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +71 -38
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +66 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +11 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +808 -222
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +477 -97
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +5 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +494 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +46 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +401 -77
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +35 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +60 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +3 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestLogger.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/BindingRedirectsTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +8 -4
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +40 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/AssertEx.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/LinuxOnlyAttribute.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/PathHelperTests.cs +49 -3
- data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +3 -1
- data/lib/dependabot/nuget/file_fetcher.rb +12 -393
- data/lib/dependabot/nuget/file_parser.rb +23 -54
- data/lib/dependabot/nuget/file_updater.rb +21 -16
- data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +2 -9
- data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +183 -80
- data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +25 -3
- data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +1 -11
- data/lib/dependabot/nuget/native_helpers.rb +13 -4
- data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +17 -4
- metadata +15 -12
- data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Packages.props +0 -29
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +0 -17
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscovery.cs +0 -69
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DirectoryPackagesPropsDiscoveryResult.cs +0 -11
- data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +0 -73
- data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +0 -60
- data/lib/dependabot/nuget/native_discovery/native_directory_packages_props_discovery.rb +0 -44
@@ -2,5 +2,15 @@ namespace NuGetUpdater.Core;
|
|
2
2
|
|
3
3
|
public interface ILogger
|
4
4
|
{
|
5
|
-
void
|
5
|
+
void LogRaw(string message);
|
6
|
+
}
|
7
|
+
|
8
|
+
public static class LoggerExtensions
|
9
|
+
{
|
10
|
+
public static void Info(this ILogger logger, string message) => logger.LogWithLevel("INFO", message);
|
11
|
+
public static void Warn(this ILogger logger, string message) => logger.LogWithLevel("WARN", message);
|
12
|
+
public static void Error(this ILogger logger, string message) => logger.LogWithLevel("ERROR", message);
|
13
|
+
|
14
|
+
private static void LogWithLevel(this ILogger logger, string level, string message) => logger.LogRaw($"{GetCurrentTimestamp()} {level} {message}");
|
15
|
+
private static string GetCurrentTimestamp() => DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss");
|
6
16
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
using System.Collections.Immutable;
|
2
2
|
using System.Diagnostics.CodeAnalysis;
|
3
|
+
using System.Reflection;
|
3
4
|
using System.Text;
|
4
5
|
using System.Text.Json;
|
5
6
|
using System.Text.Json.Nodes;
|
@@ -13,7 +14,6 @@ using Microsoft.Build.Exceptions;
|
|
13
14
|
using Microsoft.Build.Locator;
|
14
15
|
using Microsoft.Extensions.FileSystemGlobbing;
|
15
16
|
|
16
|
-
using NuGet;
|
17
17
|
using NuGet.Configuration;
|
18
18
|
using NuGet.Frameworks;
|
19
19
|
using NuGet.Versioning;
|
@@ -39,19 +39,19 @@ internal static partial class MSBuildHelper
|
|
39
39
|
var defaultInstance = MSBuildLocator.QueryVisualStudioInstances().First();
|
40
40
|
MSBuildPath = defaultInstance.MSBuildPath;
|
41
41
|
MSBuildLocator.RegisterInstance(defaultInstance);
|
42
|
-
return Task.
|
42
|
+
return Task.FromResult(0);
|
43
43
|
}).Wait();
|
44
44
|
}
|
45
45
|
}
|
46
46
|
|
47
|
-
public static async Task SidelineGlobalJsonAsync(string currentDirectory, string rootDirectory, Func<Task
|
47
|
+
public static async Task<T> SidelineGlobalJsonAsync<T>(string currentDirectory, string rootDirectory, Func<Task<T>> action, ILogger? logger = null, bool retainMSBuildSdks = false)
|
48
48
|
{
|
49
49
|
logger ??= new ConsoleLogger();
|
50
50
|
var candidateDirectories = PathHelper.GetAllDirectoriesToRoot(currentDirectory, rootDirectory);
|
51
51
|
var globalJsonPaths = candidateDirectories.Select(d => Path.Combine(d, "global.json")).Where(File.Exists).Select(p => (p, p + Guid.NewGuid().ToString())).ToArray();
|
52
52
|
foreach (var (globalJsonPath, tempGlobalJsonPath) in globalJsonPaths)
|
53
53
|
{
|
54
|
-
logger.
|
54
|
+
logger.Info($"Temporarily removing `global.json` from `{Path.GetDirectoryName(globalJsonPath)}`{(retainMSBuildSdks ? " and retaining MSBuild SDK declarations" : string.Empty)}.");
|
55
55
|
File.Move(globalJsonPath, tempGlobalJsonPath);
|
56
56
|
if (retainMSBuildSdks)
|
57
57
|
{
|
@@ -73,13 +73,14 @@ internal static partial class MSBuildHelper
|
|
73
73
|
|
74
74
|
try
|
75
75
|
{
|
76
|
-
await action();
|
76
|
+
var result = await action();
|
77
|
+
return result;
|
77
78
|
}
|
78
79
|
finally
|
79
80
|
{
|
80
81
|
foreach (var (globalJsonpath, tempGlobalJsonPath) in globalJsonPaths)
|
81
82
|
{
|
82
|
-
logger.
|
83
|
+
logger.Info($"Restoring `global.json` to `{Path.GetDirectoryName(globalJsonpath)}`.");
|
83
84
|
File.Move(tempGlobalJsonPath, globalJsonpath, overwrite: retainMSBuildSdks);
|
84
85
|
}
|
85
86
|
}
|
@@ -326,7 +327,7 @@ internal static partial class MSBuildHelper
|
|
326
327
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
327
328
|
try
|
328
329
|
{
|
329
|
-
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
330
|
+
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
330
331
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", ["restore", tempProjectPath], workingDirectory: tempDirectory.FullName);
|
331
332
|
|
332
333
|
// NU1608: Detected package version outside of dependency constraint
|
@@ -346,7 +347,7 @@ internal static partial class MSBuildHelper
|
|
346
347
|
|
347
348
|
try
|
348
349
|
{
|
349
|
-
string tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
350
|
+
string tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
350
351
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", ["restore", tempProjectPath], workingDirectory: tempDirectory.FullName);
|
351
352
|
|
352
353
|
// Add Dependency[] packages to List<PackageToUpdate> existingPackages
|
@@ -397,10 +398,10 @@ internal static partial class MSBuildHelper
|
|
397
398
|
if (added == true)
|
398
399
|
{
|
399
400
|
// Add existing versions to existing list
|
400
|
-
packageManager.UpdateExistingPackagesWithNewVersions(existingDuplicate, packagesToUpdate);
|
401
|
+
packageManager.UpdateExistingPackagesWithNewVersions(existingDuplicate, packagesToUpdate, logger);
|
401
402
|
|
402
403
|
// Make relationships
|
403
|
-
await packageManager.PopulatePackageDependenciesAsync(existingDuplicate, targetFramework, Path.GetDirectoryName(projectPath));
|
404
|
+
await packageManager.PopulatePackageDependenciesAsync(existingDuplicate, targetFramework, Path.GetDirectoryName(projectPath), logger);
|
404
405
|
|
405
406
|
// Update all to new versions
|
406
407
|
foreach (var package in existingDuplicate)
|
@@ -413,10 +414,10 @@ internal static partial class MSBuildHelper
|
|
413
414
|
else
|
414
415
|
{
|
415
416
|
// Add existing versions to existing list
|
416
|
-
packageManager.UpdateExistingPackagesWithNewVersions(existingPackages, packagesToUpdate);
|
417
|
+
packageManager.UpdateExistingPackagesWithNewVersions(existingPackages, packagesToUpdate, logger);
|
417
418
|
|
418
419
|
// Make relationships
|
419
|
-
await packageManager.PopulatePackageDependenciesAsync(existingPackages, targetFramework, Path.GetDirectoryName(projectPath));
|
420
|
+
await packageManager.PopulatePackageDependenciesAsync(existingPackages, targetFramework, Path.GetDirectoryName(projectPath), logger);
|
420
421
|
|
421
422
|
// Update all to new versions
|
422
423
|
foreach (var package in existingPackages)
|
@@ -502,7 +503,7 @@ internal static partial class MSBuildHelper
|
|
502
503
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
503
504
|
try
|
504
505
|
{
|
505
|
-
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
506
|
+
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
506
507
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", ["restore", tempProjectPath], workingDirectory: tempDirectory.FullName);
|
507
508
|
ThrowOnUnauthenticatedFeed(stdOut);
|
508
509
|
|
@@ -626,7 +627,7 @@ internal static partial class MSBuildHelper
|
|
626
627
|
return projectRoot;
|
627
628
|
}
|
628
629
|
|
629
|
-
private static IEnumerable<PackageSource>? LoadPackageSources(string nugetConfigPath)
|
630
|
+
private static IEnumerable<PackageSource>? LoadPackageSources(string nugetConfigPath, ILogger logger)
|
630
631
|
{
|
631
632
|
try
|
632
633
|
{
|
@@ -637,8 +638,8 @@ internal static partial class MSBuildHelper
|
|
637
638
|
}
|
638
639
|
catch (NuGetConfigurationException ex)
|
639
640
|
{
|
640
|
-
|
641
|
-
|
641
|
+
logger.Warn("Error while parsing NuGet.config");
|
642
|
+
logger.Warn(ex.Message);
|
642
643
|
|
643
644
|
// Nuget.config is invalid. Won't be able to do anything with specific sources.
|
644
645
|
return null;
|
@@ -651,6 +652,7 @@ internal static partial class MSBuildHelper
|
|
651
652
|
string projectPath,
|
652
653
|
string targetFramework,
|
653
654
|
IReadOnlyCollection<Dependency> packages,
|
655
|
+
ILogger logger,
|
654
656
|
bool usePackageDownload = false)
|
655
657
|
{
|
656
658
|
var projectDirectory = Path.GetDirectoryName(projectPath);
|
@@ -663,7 +665,7 @@ internal static partial class MSBuildHelper
|
|
663
665
|
File.Copy(nugetConfigPath, Path.Combine(tempDir.FullName, "NuGet.Config"));
|
664
666
|
var nugetConfigDir = Path.GetDirectoryName(nugetConfigPath);
|
665
667
|
|
666
|
-
var packageSources = LoadPackageSources(nugetConfigPath);
|
668
|
+
var packageSources = LoadPackageSources(nugetConfigPath, logger);
|
667
669
|
if (packageSources is not null)
|
668
670
|
{
|
669
671
|
// We need to copy local package sources from the NuGet.Config file to the temp directory
|
@@ -747,18 +749,70 @@ internal static partial class MSBuildHelper
|
|
747
749
|
return tempProjectPath;
|
748
750
|
}
|
749
751
|
|
752
|
+
internal static async Task<ImmutableArray<string>> GetTargetFrameworkValuesFromProject(string repoRoot, string projectPath, ILogger logger)
|
753
|
+
{
|
754
|
+
// TODO: once the updater image has all relevant SDKs installed, we won't have to sideline global.json anymore
|
755
|
+
var projectDirectory = Path.GetDirectoryName(projectPath)!;
|
756
|
+
var (exitCode, stdOut, stdErr) = await SidelineGlobalJsonAsync(projectDirectory, repoRoot, async () =>
|
757
|
+
{
|
758
|
+
var targetsHelperPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "TargetFrameworkReporter.targets");
|
759
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", ["build", projectPath, "/t:ReportTargetFramework", $"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={targetsHelperPath};CustomAfterMicrosoftCommonTargets={targetsHelperPath}"], workingDirectory: Path.GetDirectoryName(projectPath));
|
760
|
+
return (exitCode, stdOut, stdErr);
|
761
|
+
});
|
762
|
+
ThrowOnUnauthenticatedFeed(stdOut);
|
763
|
+
if (exitCode != 0)
|
764
|
+
{
|
765
|
+
logger.Warn($"Error determining target frameworks.\nSTDOUT:\n{stdOut}\nSTDERR:\n{stdErr}");
|
766
|
+
}
|
767
|
+
|
768
|
+
// There are 3 return values, all uses slightly differently. Only one will be set, the others will be blank
|
769
|
+
// ProjectData::TargetFrameworkVersion=.NETFramework,Version=v4.5 // non-SDK projects, commonly with `packages.config`
|
770
|
+
// ProjectData::TargetFramework=net7.0 // SDK-style projects
|
771
|
+
// ProjectData::TargetFrameworks=net7.0;net8.0
|
772
|
+
var tfmPatterns = new Regex[]
|
773
|
+
{
|
774
|
+
new Regex("ProjectData::TargetFrameworkVersion=(?<Value>.*)$", RegexOptions.Multiline),
|
775
|
+
new Regex("ProjectData::TargetFramework=(?<Value>.*)$", RegexOptions.Multiline),
|
776
|
+
new Regex("ProjectData::TargetFrameworks=(?<Value>.*)$", RegexOptions.Multiline),
|
777
|
+
};
|
778
|
+
var tfms = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
779
|
+
foreach (var tfmPattern in tfmPatterns)
|
780
|
+
{
|
781
|
+
var candidateTfms = tfmPattern.Matches(stdOut)
|
782
|
+
.Select(m => m.Groups["Value"].Value)
|
783
|
+
.SelectMany(v => v.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
784
|
+
.Where(v => !string.IsNullOrWhiteSpace(v))
|
785
|
+
.Select(v =>
|
786
|
+
{
|
787
|
+
try
|
788
|
+
{
|
789
|
+
var framework = NuGetFramework.Parse(v);
|
790
|
+
return framework.GetShortFolderName();
|
791
|
+
}
|
792
|
+
catch
|
793
|
+
{
|
794
|
+
return string.Empty;
|
795
|
+
}
|
796
|
+
})
|
797
|
+
.Where(tfm => !string.IsNullOrEmpty(tfm));
|
798
|
+
tfms.AddRange(candidateTfms);
|
799
|
+
}
|
800
|
+
|
801
|
+
return tfms.ToImmutableArray();
|
802
|
+
}
|
803
|
+
|
750
804
|
internal static async Task<Dependency[]> GetAllPackageDependenciesAsync(
|
751
805
|
string repoRoot,
|
752
806
|
string projectPath,
|
753
807
|
string targetFramework,
|
754
808
|
IReadOnlyCollection<Dependency> packages,
|
755
|
-
ILogger
|
809
|
+
ILogger logger)
|
756
810
|
{
|
757
811
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-resolution_");
|
758
812
|
try
|
759
813
|
{
|
760
814
|
var topLevelPackagesNames = packages.Select(p => p.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
761
|
-
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
815
|
+
var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, logger);
|
762
816
|
|
763
817
|
var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", ["build", tempProjectPath, "/t:_ReportDependencies"], workingDirectory: tempDirectory.FullName);
|
764
818
|
ThrowOnUnauthenticatedFeed(stdout);
|
@@ -783,7 +837,7 @@ internal static partial class MSBuildHelper
|
|
783
837
|
}
|
784
838
|
else
|
785
839
|
{
|
786
|
-
logger?.
|
840
|
+
logger?.Warn($"dotnet build in {nameof(GetAllPackageDependenciesAsync)} failed. STDOUT: {stdout} STDERR: {stderr}");
|
787
841
|
return [];
|
788
842
|
}
|
789
843
|
}
|
@@ -4,28 +4,12 @@ namespace NuGetUpdater.Core;
|
|
4
4
|
|
5
5
|
internal static class NuGetHelper
|
6
6
|
{
|
7
|
-
internal const string PackagesConfigFileName = "packages.config";
|
8
|
-
|
9
|
-
public static bool TryGetPackagesConfigFile(string projectPath, [NotNullWhen(returnValue: true)] out string? packagesConfigPath)
|
10
|
-
{
|
11
|
-
var projectDirectory = Path.GetDirectoryName(projectPath);
|
12
|
-
|
13
|
-
packagesConfigPath = PathHelper.JoinPath(projectDirectory, PackagesConfigFileName);
|
14
|
-
if (File.Exists(packagesConfigPath))
|
15
|
-
{
|
16
|
-
return true;
|
17
|
-
}
|
18
|
-
|
19
|
-
packagesConfigPath = null;
|
20
|
-
return false;
|
21
|
-
}
|
22
|
-
|
23
7
|
internal static async Task<bool> DownloadNuGetPackagesAsync(string repoRoot, string projectPath, IReadOnlyCollection<Dependency> packages, ILogger logger)
|
24
8
|
{
|
25
9
|
var tempDirectory = Directory.CreateTempSubdirectory("msbuild_sdk_restore_");
|
26
10
|
try
|
27
11
|
{
|
28
|
-
var tempProjectPath = await MSBuildHelper.CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, "netstandard2.0", packages, usePackageDownload: true);
|
12
|
+
var tempProjectPath = await MSBuildHelper.CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, "netstandard2.0", packages, logger, usePackageDownload: true);
|
29
13
|
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", ["restore", tempProjectPath]);
|
30
14
|
|
31
15
|
return exitCode == 0;
|
@@ -0,0 +1,31 @@
|
|
1
|
+
using System.Diagnostics.CodeAnalysis;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Utilities;
|
4
|
+
|
5
|
+
public class PathComparer : IEqualityComparer<string>
|
6
|
+
{
|
7
|
+
public static PathComparer Instance { get; } = new PathComparer();
|
8
|
+
|
9
|
+
public bool Equals(string? x, string? y)
|
10
|
+
{
|
11
|
+
x = x?.NormalizePathToUnix();
|
12
|
+
y = y?.NormalizePathToUnix();
|
13
|
+
|
14
|
+
if (x is null && y is null)
|
15
|
+
{
|
16
|
+
return true;
|
17
|
+
}
|
18
|
+
|
19
|
+
if (x is null || y is null)
|
20
|
+
{
|
21
|
+
return false;
|
22
|
+
}
|
23
|
+
|
24
|
+
return x.Equals(y, StringComparison.OrdinalIgnoreCase);
|
25
|
+
}
|
26
|
+
|
27
|
+
public int GetHashCode([DisallowNull] string obj)
|
28
|
+
{
|
29
|
+
return obj.NormalizePathToUnix().GetHashCode();
|
30
|
+
}
|
31
|
+
}
|
@@ -1,3 +1,6 @@
|
|
1
|
+
using System.Runtime.InteropServices;
|
2
|
+
using System.Text.RegularExpressions;
|
3
|
+
|
1
4
|
namespace NuGetUpdater.Core;
|
2
5
|
|
3
6
|
internal static class PathHelper
|
@@ -63,7 +66,17 @@ internal static class PathHelper
|
|
63
66
|
return result;
|
64
67
|
}
|
65
68
|
|
66
|
-
public static string FullyNormalizedRootedPath(this string path)
|
69
|
+
public static string FullyNormalizedRootedPath(this string path)
|
70
|
+
{
|
71
|
+
var normalizedPath = path.NormalizePathToUnix().NormalizeUnixPathParts();
|
72
|
+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Regex.IsMatch(normalizedPath, @"^[a-z]:", RegexOptions.IgnoreCase))
|
73
|
+
{
|
74
|
+
// Windows path is ready to go
|
75
|
+
return normalizedPath;
|
76
|
+
}
|
77
|
+
|
78
|
+
return normalizedPath.EnsurePrefix("/");
|
79
|
+
}
|
67
80
|
|
68
81
|
public static string GetFullPathFromRelative(string rootPath, string relativePath)
|
69
82
|
=> Path.GetFullPath(JoinPath(rootPath, relativePath.NormalizePathToUnix()));
|
@@ -92,7 +105,7 @@ internal static class PathHelper
|
|
92
105
|
/// </summary>
|
93
106
|
/// <param name="filePath">The file path to resolve.</param>
|
94
107
|
/// <param name="repoRootPath">The root path of the repository.</param>
|
95
|
-
public static string
|
108
|
+
public static List<string>? ResolveCaseInsensitivePathsInsideRepoRoot(string filePath, string repoRootPath)
|
96
109
|
{
|
97
110
|
if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(repoRootPath))
|
98
111
|
{
|
@@ -110,7 +123,7 @@ internal static class PathHelper
|
|
110
123
|
}
|
111
124
|
|
112
125
|
// Start resolving from the root path
|
113
|
-
var
|
126
|
+
var currentPaths = new List<string> { normalizedRepoRoot };
|
114
127
|
var relativePath = normalizedFilePath.Substring(normalizedRepoRoot.Length).TrimStart('/');
|
115
128
|
|
116
129
|
foreach (var part in relativePath.Split('/'))
|
@@ -120,20 +133,28 @@ internal static class PathHelper
|
|
120
133
|
continue;
|
121
134
|
}
|
122
135
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
136
|
+
var nextPaths = new List<string>();
|
137
|
+
|
138
|
+
// Iterate through all current paths to find matches for the current part
|
139
|
+
foreach (var currentPath in currentPaths)
|
140
|
+
{
|
141
|
+
var matches = Directory
|
142
|
+
.EnumerateFileSystemEntries(currentPath)
|
143
|
+
.Where(entry => string.Equals(Path.GetFileName(entry), part, StringComparison.OrdinalIgnoreCase));
|
144
|
+
|
145
|
+
nextPaths.AddRange(matches);
|
146
|
+
}
|
127
147
|
|
128
|
-
if (
|
148
|
+
if (!nextPaths.Any())
|
129
149
|
{
|
130
150
|
return null; // Part of the path does not exist
|
131
151
|
}
|
132
152
|
|
133
|
-
|
153
|
+
currentPaths = nextPaths;
|
134
154
|
}
|
135
155
|
|
136
|
-
|
156
|
+
// Normalize all resulting paths to Unix format
|
157
|
+
return currentPaths.Select(path => path.NormalizePathToUnix()).ToList();
|
137
158
|
}
|
138
159
|
|
139
160
|
/// <summary>
|
@@ -212,4 +233,19 @@ internal static class PathHelper
|
|
212
233
|
|
213
234
|
return false;
|
214
235
|
}
|
236
|
+
|
237
|
+
public static bool IsFileUnderDirectory(DirectoryInfo directory, FileInfo candidateFile)
|
238
|
+
{
|
239
|
+
// n.b., using `DirectoryInfo` and `FileInfo` here to ensure that the callsite doesn't get confused with just strings
|
240
|
+
// the paths are then normalized to make the comparison easier.
|
241
|
+
var directoryPath = directory.FullName.NormalizePathToUnix();
|
242
|
+
if (!directoryPath.EndsWith("/"))
|
243
|
+
{
|
244
|
+
// ensuring a trailing slash means we can do a simple string check later on
|
245
|
+
directoryPath += "/";
|
246
|
+
}
|
247
|
+
var candidateFilePath = candidateFile.FullName.NormalizePathToUnix();
|
248
|
+
|
249
|
+
return candidateFilePath.StartsWith(directoryPath);
|
250
|
+
}
|
215
251
|
}
|
@@ -0,0 +1,96 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
|
3
|
+
using Microsoft.Build.Construction;
|
4
|
+
|
5
|
+
namespace NuGetUpdater.Core.Utilities;
|
6
|
+
|
7
|
+
internal static class ProjectHelper
|
8
|
+
{
|
9
|
+
public const string PackagesConfigFileName = "packages.config";
|
10
|
+
public const string AppConfigFileName = "app.config";
|
11
|
+
public const string WebConfigFileName = "web.config";
|
12
|
+
public const string PackagesLockJsonFileName = "packages.lock.json";
|
13
|
+
|
14
|
+
public enum PathFormat
|
15
|
+
{
|
16
|
+
Relative,
|
17
|
+
Full,
|
18
|
+
}
|
19
|
+
|
20
|
+
public static ImmutableArray<string> GetAllAdditionalFilesFromProject(string fullProjectPath, PathFormat pathFormat)
|
21
|
+
{
|
22
|
+
return GetAdditionalFilesFromProjectContent(fullProjectPath, pathFormat)
|
23
|
+
.AddRange(GetAdditionalFilesFromProjectLocation(fullProjectPath, pathFormat));
|
24
|
+
}
|
25
|
+
|
26
|
+
public static ImmutableArray<string> GetAdditionalFilesFromProjectContent(string fullProjectPath, PathFormat pathFormat)
|
27
|
+
{
|
28
|
+
var projectRootElement = ProjectRootElement.Open(fullProjectPath);
|
29
|
+
var additionalFilesWithFullPaths = new[]
|
30
|
+
{
|
31
|
+
projectRootElement.GetItemPathWithFileName(PackagesConfigFileName),
|
32
|
+
projectRootElement.GetItemPathWithFileName(AppConfigFileName),
|
33
|
+
projectRootElement.GetItemPathWithFileName(WebConfigFileName),
|
34
|
+
}.Where(p => p is not null).Cast<string>().ToImmutableArray();
|
35
|
+
|
36
|
+
var additionalFiles = additionalFilesWithFullPaths
|
37
|
+
.Select(p => MakePathAppropriateFormat(fullProjectPath, p, pathFormat))
|
38
|
+
.ToImmutableArray();
|
39
|
+
return additionalFiles;
|
40
|
+
}
|
41
|
+
|
42
|
+
public static ImmutableArray<string> GetAdditionalFilesFromProjectLocation(string fullProjectPath, PathFormat pathFormat)
|
43
|
+
{
|
44
|
+
var additionalFilesWithFullPaths = new[]
|
45
|
+
{
|
46
|
+
GetPathWithRegardsToProjectFile(fullProjectPath, PackagesLockJsonFileName),
|
47
|
+
}.Where(p => p is not null).Cast<string>().ToImmutableArray();
|
48
|
+
|
49
|
+
var additionalFiles = additionalFilesWithFullPaths
|
50
|
+
.Select(p => MakePathAppropriateFormat(fullProjectPath, p, pathFormat))
|
51
|
+
.ToImmutableArray();
|
52
|
+
return additionalFiles;
|
53
|
+
}
|
54
|
+
|
55
|
+
public static string? GetPackagesConfigPathFromProject(string fullProjectPath, PathFormat pathFormat)
|
56
|
+
{
|
57
|
+
var additionalFiles = GetAdditionalFilesFromProjectContent(fullProjectPath, pathFormat);
|
58
|
+
var packagesConfigFile = additionalFiles.FirstOrDefault(p => Path.GetFileName(p).Equals(PackagesConfigFileName, StringComparison.Ordinal));
|
59
|
+
return packagesConfigFile;
|
60
|
+
}
|
61
|
+
|
62
|
+
private static string MakePathAppropriateFormat(string fullProjectPath, string fullFilePath, PathFormat pathFormat)
|
63
|
+
{
|
64
|
+
var projectDirectory = Path.GetDirectoryName(fullProjectPath)!;
|
65
|
+
var updatedPath = pathFormat switch
|
66
|
+
{
|
67
|
+
PathFormat.Full => fullFilePath,
|
68
|
+
PathFormat.Relative => Path.GetRelativePath(projectDirectory, fullFilePath),
|
69
|
+
_ => throw new NotSupportedException(),
|
70
|
+
};
|
71
|
+
return updatedPath.NormalizePathToUnix();
|
72
|
+
}
|
73
|
+
|
74
|
+
private static string? GetItemPathWithFileName(this ProjectRootElement projectRootElement, string itemFileName)
|
75
|
+
{
|
76
|
+
var projectDirectory = Path.GetDirectoryName(projectRootElement.FullPath)!;
|
77
|
+
var packagesConfigPath = projectRootElement.Items
|
78
|
+
.Where(i => i.ElementName.Equals("None", StringComparison.OrdinalIgnoreCase) ||
|
79
|
+
i.ElementName.Equals("Content", StringComparison.OrdinalIgnoreCase))
|
80
|
+
.Where(i => Path.GetFileName(i.Include).Equals(itemFileName, StringComparison.OrdinalIgnoreCase))
|
81
|
+
.Select(i => Path.GetFullPath(Path.Combine(projectDirectory, i.Include)))
|
82
|
+
.Where(File.Exists)
|
83
|
+
.FirstOrDefault()
|
84
|
+
?.NormalizePathToUnix();
|
85
|
+
return packagesConfigPath;
|
86
|
+
}
|
87
|
+
|
88
|
+
private static string? GetPathWithRegardsToProjectFile(string fullProjectPath, string fileName)
|
89
|
+
{
|
90
|
+
var projectDirectory = Path.GetDirectoryName(fullProjectPath)!;
|
91
|
+
var filePath = Directory.EnumerateFiles(projectDirectory)
|
92
|
+
.Where(p => Path.GetFileName(p).Equals(fileName, StringComparison.Ordinal))
|
93
|
+
.FirstOrDefault();
|
94
|
+
return filePath;
|
95
|
+
}
|
96
|
+
}
|