dependabot-nuget 0.321.2 → 0.322.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/Directory.Packages.props +22 -22
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation/Model/PackageMapper.cs +9 -0
- data/helpers/lib/NuGetUpdater/DotNetPackageCorrelation.Cli/Program.cs +21 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +19 -11
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/CloneCommand.cs +19 -9
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +21 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/FrameworkCheckCommand.cs +8 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +29 -16
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +20 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +2 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscoveryTargetingPacks.props +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencySolver/IDependencySolver.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencySolver/MSBuildDependencySolver.cs +32 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +10 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +6 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/GlobalJsonBuildFile.cs +5 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/PrivateSourceTimedOutException.cs +12 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/JobErrorBase.cs +4 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/PrivateSourceTimedOut.cs +10 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestTextGenerator.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandler.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/DotNetToolsJsonUpdater.cs +6 -3
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/FileWriterWorker.cs +376 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/IFileWriter.cs +14 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/XmlFileWriter.cs +477 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/GlobalJsonUpdater.cs +9 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationBase.cs +18 -7
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +26 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +15 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/DependencySolver/MSBuildDependencySolverTests.cs +633 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +0 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +0 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +49 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/GlobalJsonBuildFileTests.cs +0 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/EndToEndTests.cs +484 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/HttpApiHandlerTests.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/JobErrorBaseTests.cs +7 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MessageReportTests.cs +11 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestTextTests.cs +21 -22
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +1 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +8 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/DotNetToolsJsonUpdaterTests.cs +181 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterTestsBase.cs +61 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterWorkerTests.cs +917 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterWorkerTests_MiscellaneousTests.cs +154 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/TestFileWriterReturnsConstantResult.cs +20 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests.cs +1620 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests_CreateUpdatedVersionRangeTests.cs +25 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/GlobalJsonUpdaterTests.cs +139 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +1961 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateOperationResultTests.cs +116 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +16 -1043
- data/helpers/lib/NuGetUpdater/global.json +1 -1
- metadata +21 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +0 -375
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +0 -296
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.LockFile.cs +0 -251
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +0 -201
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +0 -3821
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +0 -2706
@@ -1,3 +1,4 @@
|
|
1
|
+
using System.Collections.Immutable;
|
1
2
|
using System.Text.Json.Nodes;
|
2
3
|
|
3
4
|
namespace NuGetUpdater.Core;
|
@@ -12,28 +13,19 @@ internal sealed class GlobalJsonBuildFile : JsonBuildFile
|
|
12
13
|
{
|
13
14
|
}
|
14
15
|
|
15
|
-
public JsonObject? Sdk => Node.Value is JsonObject root ? root["sdk"]?.AsObject() : null;
|
16
|
-
|
17
16
|
public JsonObject? MSBuildSdks => Node.Value is JsonObject root ? root["msbuild-sdks"]?.AsObject() : null;
|
18
17
|
|
19
18
|
public IEnumerable<Dependency> GetDependencies()
|
20
19
|
{
|
21
|
-
List<Dependency> dependencies = [];
|
22
|
-
if (Sdk is not null
|
23
|
-
&& Sdk.TryGetPropertyValue("version", out var version))
|
24
|
-
{
|
25
|
-
dependencies.Add(GetSdkDependency("Microsoft.NET.Sdk", version));
|
26
|
-
}
|
27
|
-
|
28
20
|
if (MSBuildSdks is null)
|
29
21
|
{
|
30
|
-
return
|
22
|
+
return [];
|
31
23
|
}
|
32
24
|
|
33
25
|
var msBuildDependencies = MSBuildSdks
|
34
|
-
.Select(t => GetSdkDependency(t.Key, t.Value))
|
35
|
-
|
36
|
-
return
|
26
|
+
.Select(t => GetSdkDependency(t.Key, t.Value))
|
27
|
+
.ToImmutableArray();
|
28
|
+
return msBuildDependencies;
|
37
29
|
}
|
38
30
|
|
39
31
|
private Dependency GetSdkDependency(string name, JsonNode? version)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
namespace NuGetUpdater.Core;
|
2
|
+
|
3
|
+
internal class PrivateSourceTimedOutException : Exception
|
4
|
+
{
|
5
|
+
public string Url { get; }
|
6
|
+
|
7
|
+
public PrivateSourceTimedOutException(string url)
|
8
|
+
: base($"The request to source {url} has timed out.")
|
9
|
+
{
|
10
|
+
Url = url;
|
11
|
+
}
|
12
|
+
}
|
@@ -70,10 +70,14 @@ public abstract record JobErrorBase : MessageBase
|
|
70
70
|
|
71
71
|
return new UnknownError(ex, jobId);
|
72
72
|
}
|
73
|
+
case InvalidDataException invalidData when invalidData.Message == "Central Directory corrupt.":
|
74
|
+
return new PrivateSourceBadResponse(NuGetContext.GetPackageSourceUrls(currentDirectory));
|
73
75
|
case InvalidProjectFileException invalidProjectFile:
|
74
76
|
return new DependencyFileNotParseable(invalidProjectFile.ProjectFile);
|
75
77
|
case MissingFileException missingFile:
|
76
78
|
return new DependencyFileNotFound(missingFile.FilePath, missingFile.Message);
|
79
|
+
case PrivateSourceTimedOutException timeout:
|
80
|
+
return new PrivateSourceTimedOut(timeout.Url);
|
77
81
|
case UnparseableFileException unparseableFile:
|
78
82
|
return new DependencyFileNotParseable(unparseableFile.FilePath, unparseableFile.Message);
|
79
83
|
case UpdateNotPossibleException updateNotPossible:
|
@@ -126,7 +126,7 @@ public class PullRequestTextGenerator
|
|
126
126
|
|
127
127
|
public static string GetPullRequestBody(Job job, ImmutableArray<UpdateOperationBase> updateOperationsPerformed, string? dependencyGroupName)
|
128
128
|
{
|
129
|
-
var report = UpdateOperationBase.GenerateUpdateOperationReport(updateOperationsPerformed);
|
129
|
+
var report = UpdateOperationBase.GenerateUpdateOperationReport(updateOperationsPerformed, includeFileNames: false);
|
130
130
|
return report;
|
131
131
|
}
|
132
132
|
}
|
@@ -140,7 +140,7 @@ internal class CreateSecurityUpdatePullRequestHandler : IUpdateHandler
|
|
140
140
|
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
141
141
|
foreach (var o in patchedUpdateOperations)
|
142
142
|
{
|
143
|
-
logger.Info($"Update operation performed: {o.GetReport()}");
|
143
|
+
logger.Info($"Update operation performed: {o.GetReport(includeFileNames: true)}");
|
144
144
|
}
|
145
145
|
}
|
146
146
|
}
|
data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs
CHANGED
@@ -143,7 +143,7 @@ internal class GroupUpdateAllVersionsHandler : IUpdateHandler
|
|
143
143
|
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
144
144
|
foreach (var o in patchedUpdateOperations)
|
145
145
|
{
|
146
|
-
logger.Info($"Update operation performed: {o.GetReport()}");
|
146
|
+
logger.Info($"Update operation performed: {o.GetReport(includeFileNames: true)}");
|
147
147
|
}
|
148
148
|
}
|
149
149
|
|
@@ -242,7 +242,7 @@ internal class GroupUpdateAllVersionsHandler : IUpdateHandler
|
|
242
242
|
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
243
243
|
foreach (var o in patchedUpdateOperations)
|
244
244
|
{
|
245
|
-
logger.Info($"Update operation performed: {o.GetReport()}");
|
245
|
+
logger.Info($"Update operation performed: {o.GetReport(includeFileNames: true)}");
|
246
246
|
}
|
247
247
|
}
|
248
248
|
|
@@ -137,7 +137,7 @@ internal class RefreshGroupUpdatePullRequestHandler : IUpdateHandler
|
|
137
137
|
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
138
138
|
foreach (var o in patchedUpdateOperations)
|
139
139
|
{
|
140
|
-
logger.Info($"Update operation performed: {o.GetReport()}");
|
140
|
+
logger.Info($"Update operation performed: {o.GetReport(includeFileNames: true)}");
|
141
141
|
}
|
142
142
|
}
|
143
143
|
}
|
@@ -135,7 +135,7 @@ internal class RefreshSecurityUpdatePullRequestHandler : IUpdateHandler
|
|
135
135
|
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
136
136
|
foreach (var o in patchedUpdateOperations)
|
137
137
|
{
|
138
|
-
logger.Info($"Update operation performed: {o.GetReport()}");
|
138
|
+
logger.Info($"Update operation performed: {o.GetReport(includeFileNames: true)}");
|
139
139
|
}
|
140
140
|
}
|
141
141
|
}
|
@@ -125,7 +125,7 @@ internal class RefreshVersionUpdatePullRequestHandler : IUpdateHandler
|
|
125
125
|
updateOperationsPerformed.AddRange(patchedUpdateOperations);
|
126
126
|
foreach (var o in patchedUpdateOperations)
|
127
127
|
{
|
128
|
-
logger.Info($"Update operation performed: {o.GetReport()}");
|
128
|
+
logger.Info($"Update operation performed: {o.GetReport(includeFileNames: true)}");
|
129
129
|
}
|
130
130
|
}
|
131
131
|
}
|
@@ -2,7 +2,7 @@ namespace NuGetUpdater.Core;
|
|
2
2
|
|
3
3
|
internal static class DotNetToolsJsonUpdater
|
4
4
|
{
|
5
|
-
public static async Task UpdateDependencyAsync(
|
5
|
+
public static async Task<string?> UpdateDependencyAsync(
|
6
6
|
string repoRootPath,
|
7
7
|
string workspacePath,
|
8
8
|
string dependencyName,
|
@@ -13,7 +13,7 @@ internal static class DotNetToolsJsonUpdater
|
|
13
13
|
if (!MSBuildHelper.TryGetDotNetToolsJsonPath(repoRootPath, workspacePath, out var dotnetToolsJsonPath))
|
14
14
|
{
|
15
15
|
logger.Info(" No dotnet-tools.json file found.");
|
16
|
-
return;
|
16
|
+
return null;
|
17
17
|
}
|
18
18
|
|
19
19
|
var dotnetToolsJsonFile = DotNetToolsJsonBuildFile.Open(repoRootPath, dotnetToolsJsonPath, logger);
|
@@ -24,7 +24,7 @@ internal static class DotNetToolsJsonUpdater
|
|
24
24
|
if (!containsDependency)
|
25
25
|
{
|
26
26
|
logger.Info($" Dependency [{dependencyName}] not found.");
|
27
|
-
return;
|
27
|
+
return null;
|
28
28
|
}
|
29
29
|
|
30
30
|
var tool = dotnetToolsJsonFile.Tools
|
@@ -40,7 +40,10 @@ internal static class DotNetToolsJsonUpdater
|
|
40
40
|
if (await dotnetToolsJsonFile.SaveAsync())
|
41
41
|
{
|
42
42
|
logger.Info($" Saved [{dotnetToolsJsonFile.RelativePath}].");
|
43
|
+
return dotnetToolsJsonFile.Path;
|
43
44
|
}
|
44
45
|
}
|
46
|
+
|
47
|
+
return null;
|
45
48
|
}
|
46
49
|
}
|
@@ -0,0 +1,376 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
|
3
|
+
using NuGet.Versioning;
|
4
|
+
|
5
|
+
using NuGetUpdater.Core.DependencySolver;
|
6
|
+
using NuGetUpdater.Core.Discover;
|
7
|
+
using NuGetUpdater.Core.Utilities;
|
8
|
+
|
9
|
+
namespace NuGetUpdater.Core.Updater.FileWriters;
|
10
|
+
|
11
|
+
public class FileWriterWorker
|
12
|
+
{
|
13
|
+
private readonly IDiscoveryWorker _discoveryWorker;
|
14
|
+
private readonly IDependencySolver _dependencySolver;
|
15
|
+
private readonly IFileWriter _fileWriter;
|
16
|
+
private readonly ILogger _logger;
|
17
|
+
|
18
|
+
public FileWriterWorker(IDiscoveryWorker discoveryWorker, IDependencySolver dependencySolver, IFileWriter fileWriter, ILogger logger)
|
19
|
+
{
|
20
|
+
_discoveryWorker = discoveryWorker;
|
21
|
+
_dependencySolver = dependencySolver;
|
22
|
+
_fileWriter = fileWriter;
|
23
|
+
_logger = logger;
|
24
|
+
}
|
25
|
+
|
26
|
+
public async Task<ImmutableArray<UpdateOperationBase>> RunAsync(
|
27
|
+
DirectoryInfo repoContentsPath,
|
28
|
+
FileInfo projectPath,
|
29
|
+
string dependencyName,
|
30
|
+
NuGetVersion oldDependencyVersion,
|
31
|
+
NuGetVersion newDependencyVersion
|
32
|
+
)
|
33
|
+
{
|
34
|
+
var updateOperations = new List<UpdateOperationBase>();
|
35
|
+
var initialProjectDirectory = new DirectoryInfo(Path.GetDirectoryName(projectPath.FullName)!);
|
36
|
+
|
37
|
+
// first try non-project updates
|
38
|
+
var nonProjectUpdates = await ProcessNonProjectUpdatesAsync(repoContentsPath, initialProjectDirectory, dependencyName, oldDependencyVersion, newDependencyVersion);
|
39
|
+
updateOperations.AddRange(nonProjectUpdates);
|
40
|
+
|
41
|
+
// then try packages.config updates
|
42
|
+
var packagesConfigUpdates = await ProcessPackagesConfigUpdatesAsync(repoContentsPath, projectPath, dependencyName, oldDependencyVersion, newDependencyVersion);
|
43
|
+
updateOperations.AddRange(packagesConfigUpdates);
|
44
|
+
|
45
|
+
// then try project updates
|
46
|
+
var packageReferenceUpdates = await ProcessPackageReferenceUpdatesAsync(repoContentsPath, initialProjectDirectory, projectPath, dependencyName, newDependencyVersion);
|
47
|
+
updateOperations.AddRange(packageReferenceUpdates);
|
48
|
+
|
49
|
+
var normalizedUpdateOperations = UpdateOperationBase.NormalizeUpdateOperationCollection(repoContentsPath.FullName, updateOperations);
|
50
|
+
return normalizedUpdateOperations;
|
51
|
+
}
|
52
|
+
|
53
|
+
private async Task<ImmutableArray<UpdateOperationBase>> ProcessNonProjectUpdatesAsync(
|
54
|
+
DirectoryInfo repoContentsPath,
|
55
|
+
DirectoryInfo initialProjectDirectory,
|
56
|
+
string dependencyName,
|
57
|
+
NuGetVersion oldDependencyVersion,
|
58
|
+
NuGetVersion newDependencyVersion
|
59
|
+
)
|
60
|
+
{
|
61
|
+
var updateOperations = new List<UpdateOperationBase>();
|
62
|
+
var updatedDotNetToolsPath = await DotNetToolsJsonUpdater.UpdateDependencyAsync(
|
63
|
+
repoContentsPath.FullName,
|
64
|
+
initialProjectDirectory.FullName,
|
65
|
+
dependencyName,
|
66
|
+
oldDependencyVersion.ToString(),
|
67
|
+
newDependencyVersion.ToString(),
|
68
|
+
_logger
|
69
|
+
);
|
70
|
+
if (updatedDotNetToolsPath is not null)
|
71
|
+
{
|
72
|
+
updateOperations.Add(new DirectUpdate()
|
73
|
+
{
|
74
|
+
DependencyName = dependencyName,
|
75
|
+
OldVersion = oldDependencyVersion,
|
76
|
+
NewVersion = newDependencyVersion,
|
77
|
+
UpdatedFiles = [Path.GetRelativePath(repoContentsPath.FullName, updatedDotNetToolsPath).FullyNormalizedRootedPath()]
|
78
|
+
});
|
79
|
+
}
|
80
|
+
|
81
|
+
var updatedGlobalJsonPath = await GlobalJsonUpdater.UpdateDependencyAsync(
|
82
|
+
repoContentsPath.FullName,
|
83
|
+
initialProjectDirectory.FullName,
|
84
|
+
dependencyName,
|
85
|
+
oldDependencyVersion.ToString(),
|
86
|
+
newDependencyVersion.ToString(),
|
87
|
+
_logger
|
88
|
+
);
|
89
|
+
if (updatedGlobalJsonPath is not null)
|
90
|
+
{
|
91
|
+
updateOperations.Add(new DirectUpdate()
|
92
|
+
{
|
93
|
+
DependencyName = dependencyName,
|
94
|
+
OldVersion = oldDependencyVersion,
|
95
|
+
NewVersion = newDependencyVersion,
|
96
|
+
UpdatedFiles = [Path.GetRelativePath(repoContentsPath.FullName, updatedGlobalJsonPath).FullyNormalizedRootedPath()]
|
97
|
+
});
|
98
|
+
}
|
99
|
+
|
100
|
+
return [.. updateOperations];
|
101
|
+
}
|
102
|
+
|
103
|
+
private async Task<ImmutableArray<UpdateOperationBase>> ProcessPackagesConfigUpdatesAsync(
|
104
|
+
DirectoryInfo repoContentsPath,
|
105
|
+
FileInfo projectPath,
|
106
|
+
string dependencyName,
|
107
|
+
NuGetVersion oldDependencyVersion,
|
108
|
+
NuGetVersion newDependencyVersion
|
109
|
+
)
|
110
|
+
{
|
111
|
+
var additionalFiles = ProjectHelper.GetAllAdditionalFilesFromProject(projectPath.FullName, ProjectHelper.PathFormat.Full);
|
112
|
+
var packagesConfigFullPath = additionalFiles.Where(p => Path.GetFileName(p).Equals(ProjectHelper.PackagesConfigFileName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
113
|
+
if (packagesConfigFullPath is null)
|
114
|
+
{
|
115
|
+
return [];
|
116
|
+
}
|
117
|
+
|
118
|
+
var packagesConfigOperations = await PackagesConfigUpdater.UpdateDependencyAsync(
|
119
|
+
repoContentsPath.FullName,
|
120
|
+
projectPath.FullName,
|
121
|
+
dependencyName,
|
122
|
+
oldDependencyVersion.ToString(),
|
123
|
+
newDependencyVersion.ToString(),
|
124
|
+
packagesConfigFullPath,
|
125
|
+
_logger
|
126
|
+
);
|
127
|
+
var packagesConfigOperationsWithNormalizedPaths = packagesConfigOperations
|
128
|
+
.Select(op => op with { UpdatedFiles = [.. op.UpdatedFiles.Select(f => Path.GetRelativePath(repoContentsPath.FullName, f).FullyNormalizedRootedPath())] })
|
129
|
+
.ToImmutableArray();
|
130
|
+
return packagesConfigOperationsWithNormalizedPaths;
|
131
|
+
}
|
132
|
+
|
133
|
+
private async Task<ImmutableArray<UpdateOperationBase>> ProcessPackageReferenceUpdatesAsync(
|
134
|
+
DirectoryInfo repoContentsPath,
|
135
|
+
DirectoryInfo initialProjectDirectory,
|
136
|
+
FileInfo projectPath,
|
137
|
+
string dependencyName,
|
138
|
+
NuGetVersion newDependencyVersion
|
139
|
+
)
|
140
|
+
{
|
141
|
+
var initialProjectDirectoryRelativeToRepoRoot = Path.GetRelativePath(repoContentsPath.FullName, initialProjectDirectory.FullName).FullyNormalizedRootedPath();
|
142
|
+
var initialDiscoveryResult = await _discoveryWorker.RunAsync(repoContentsPath.FullName, initialProjectDirectoryRelativeToRepoRoot);
|
143
|
+
var initialProjectDiscovery = initialDiscoveryResult.GetProjectDiscoveryFromFullPath(repoContentsPath, projectPath);
|
144
|
+
if (initialProjectDiscovery is null)
|
145
|
+
{
|
146
|
+
_logger.Info($"Unable to find project discovery for project {projectPath}.");
|
147
|
+
return [];
|
148
|
+
}
|
149
|
+
|
150
|
+
var initialRequestedDependency = initialProjectDiscovery.Dependencies
|
151
|
+
.FirstOrDefault(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase));
|
152
|
+
if (initialRequestedDependency is null || initialRequestedDependency.Version is null)
|
153
|
+
{
|
154
|
+
_logger.Info($"Dependency {dependencyName} not found in initial project discovery.");
|
155
|
+
return [];
|
156
|
+
}
|
157
|
+
|
158
|
+
var initialDependencyVersion = NuGetVersion.Parse(initialRequestedDependency.Version);
|
159
|
+
if (initialDependencyVersion >= newDependencyVersion)
|
160
|
+
{
|
161
|
+
_logger.Info($"Dependency {dependencyName} is already at version {initialDependencyVersion}, no update needed.");
|
162
|
+
return [];
|
163
|
+
}
|
164
|
+
|
165
|
+
var initialTopLevelDependencies = initialProjectDiscovery.Dependencies
|
166
|
+
.Where(d => !d.IsTransitive)
|
167
|
+
.ToImmutableArray();
|
168
|
+
var newDependency = new Dependency(dependencyName, newDependencyVersion.ToString(), DependencyType.Unknown);
|
169
|
+
var desiredDependencies = initialTopLevelDependencies.Any(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase))
|
170
|
+
? initialTopLevelDependencies.Select(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase) ? newDependency : d).ToImmutableArray()
|
171
|
+
: initialTopLevelDependencies.Concat([newDependency]).ToImmutableArray();
|
172
|
+
|
173
|
+
var updateOperations = new List<UpdateOperationBase>();
|
174
|
+
foreach (var targetFramework in initialProjectDiscovery.TargetFrameworks)
|
175
|
+
{
|
176
|
+
var resolvedDependencies = await _dependencySolver.SolveAsync(initialTopLevelDependencies, desiredDependencies, targetFramework);
|
177
|
+
if (resolvedDependencies is null)
|
178
|
+
{
|
179
|
+
_logger.Warn($"Unable to solve dependency conflicts for target framework {targetFramework}.");
|
180
|
+
continue;
|
181
|
+
}
|
182
|
+
|
183
|
+
var resolvedRequestedDependency = resolvedDependencies.Value
|
184
|
+
.SingleOrDefault(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase));
|
185
|
+
if (resolvedRequestedDependency is null || resolvedRequestedDependency.Version is null)
|
186
|
+
{
|
187
|
+
_logger.Warn($"Dependency resolution failed to include {dependencyName}.");
|
188
|
+
continue;
|
189
|
+
}
|
190
|
+
|
191
|
+
var resolvedRequestedDependencyVersion = NuGetVersion.Parse(resolvedRequestedDependency.Version);
|
192
|
+
if (resolvedRequestedDependencyVersion != newDependencyVersion)
|
193
|
+
{
|
194
|
+
_logger.Warn($"Requested dependency resolution to include {dependencyName}/{newDependencyVersion} but it was instead resolved to {resolvedRequestedDependencyVersion}.");
|
195
|
+
continue;
|
196
|
+
}
|
197
|
+
|
198
|
+
// process all projects bottom up
|
199
|
+
var orderedProjectDiscovery = GetProjectDiscoveryEvaluationOrder(repoContentsPath, initialDiscoveryResult, projectPath, _logger);
|
200
|
+
|
201
|
+
// track original contents
|
202
|
+
var originalFileContents = await GetOriginalFileContentsAsync(repoContentsPath, initialProjectDirectory, orderedProjectDiscovery);
|
203
|
+
|
204
|
+
var allUpdatedFiles = new List<string>();
|
205
|
+
foreach (var projectDiscovery in orderedProjectDiscovery)
|
206
|
+
{
|
207
|
+
var projectFullPath = Path.Join(repoContentsPath.FullName, initialDiscoveryResult.Path, projectDiscovery.FilePath).FullyNormalizedRootedPath();
|
208
|
+
var updatedFiles = await TryPerformFileWritesAsync(_fileWriter, repoContentsPath, initialProjectDirectory, projectDiscovery, resolvedDependencies.Value);
|
209
|
+
allUpdatedFiles.AddRange(updatedFiles);
|
210
|
+
}
|
211
|
+
|
212
|
+
if (allUpdatedFiles.Count == 0)
|
213
|
+
{
|
214
|
+
_logger.Warn("Failed to write new dependency versions.");
|
215
|
+
await RestoreOriginalFileContentsAsync(originalFileContents);
|
216
|
+
continue;
|
217
|
+
}
|
218
|
+
|
219
|
+
// this final call to discover has the benefit of also updating the lock file if it exists
|
220
|
+
var finalDiscoveryResult = await _discoveryWorker.RunAsync(repoContentsPath.FullName, initialProjectDirectoryRelativeToRepoRoot);
|
221
|
+
var finalProjectDiscovery = finalDiscoveryResult.GetProjectDiscoveryFromFullPath(repoContentsPath, projectPath);
|
222
|
+
if (finalProjectDiscovery is null)
|
223
|
+
{
|
224
|
+
_logger.Warn($"Unable to find final project discovery for project {projectPath}.");
|
225
|
+
await RestoreOriginalFileContentsAsync(originalFileContents);
|
226
|
+
continue;
|
227
|
+
}
|
228
|
+
|
229
|
+
var finalRequestedDependency = finalProjectDiscovery.Dependencies
|
230
|
+
.FirstOrDefault(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase));
|
231
|
+
if (finalRequestedDependency is null || finalRequestedDependency.Version is null)
|
232
|
+
{
|
233
|
+
_logger.Warn($"Dependency {dependencyName} not found in final project discovery.");
|
234
|
+
await RestoreOriginalFileContentsAsync(originalFileContents);
|
235
|
+
continue;
|
236
|
+
}
|
237
|
+
|
238
|
+
var resolvedVersion = NuGetVersion.Parse(finalRequestedDependency.Version);
|
239
|
+
if (resolvedVersion != newDependencyVersion)
|
240
|
+
{
|
241
|
+
_logger.Warn($"Final dependency version for {dependencyName} is {resolvedVersion}, expected {newDependencyVersion}.");
|
242
|
+
await RestoreOriginalFileContentsAsync(originalFileContents);
|
243
|
+
continue;
|
244
|
+
}
|
245
|
+
|
246
|
+
var computedUpdateOperations = await PackageReferenceUpdater.ComputeUpdateOperations(
|
247
|
+
repoContentsPath.FullName,
|
248
|
+
projectPath.FullName,
|
249
|
+
targetFramework,
|
250
|
+
initialTopLevelDependencies,
|
251
|
+
desiredDependencies,
|
252
|
+
resolvedDependencies.Value,
|
253
|
+
new ExperimentsManager() { UseDirectDiscovery = true },
|
254
|
+
_logger);
|
255
|
+
var filteredUpdateOperations = computedUpdateOperations
|
256
|
+
.Where(op =>
|
257
|
+
{
|
258
|
+
var initialDependency = initialProjectDiscovery.Dependencies.FirstOrDefault(d => d.Name.Equals(op.DependencyName, StringComparison.OrdinalIgnoreCase));
|
259
|
+
return initialDependency is not null
|
260
|
+
&& initialDependency.Version is not null
|
261
|
+
&& NuGetVersion.Parse(initialDependency.Version) < op.NewVersion;
|
262
|
+
})
|
263
|
+
.ToImmutableArray();
|
264
|
+
var computedOperationsWithUpdatedFiles = filteredUpdateOperations
|
265
|
+
.Select(op => op with { UpdatedFiles = [.. allUpdatedFiles] })
|
266
|
+
.ToImmutableArray();
|
267
|
+
updateOperations.AddRange(computedOperationsWithUpdatedFiles);
|
268
|
+
}
|
269
|
+
|
270
|
+
return [.. updateOperations];
|
271
|
+
}
|
272
|
+
|
273
|
+
internal static async Task<Dictionary<string, string>> GetOriginalFileContentsAsync(DirectoryInfo repoContentsPath, DirectoryInfo initialStartingDirectory, IEnumerable<ProjectDiscoveryResult> projectDiscoveryResults)
|
274
|
+
{
|
275
|
+
var filesAndContents = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
276
|
+
foreach (var projectDiscoveryResult in projectDiscoveryResults)
|
277
|
+
{
|
278
|
+
var fullProjectPath = Path.Join(initialStartingDirectory.FullName, projectDiscoveryResult.FilePath).FullyNormalizedRootedPath();
|
279
|
+
var projectContents = await File.ReadAllTextAsync(fullProjectPath);
|
280
|
+
filesAndContents[fullProjectPath] = projectContents;
|
281
|
+
|
282
|
+
foreach (var file in projectDiscoveryResult.ImportedFiles.Concat(projectDiscoveryResult.AdditionalFiles))
|
283
|
+
{
|
284
|
+
var filePath = Path.Join(Path.GetDirectoryName(fullProjectPath)!, file).FullyNormalizedRootedPath();
|
285
|
+
var fileContents = await File.ReadAllTextAsync(filePath);
|
286
|
+
filesAndContents[filePath] = fileContents;
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
return filesAndContents;
|
291
|
+
}
|
292
|
+
|
293
|
+
internal static async Task RestoreOriginalFileContentsAsync(Dictionary<string, string> originalFilesAndContents)
|
294
|
+
{
|
295
|
+
foreach (var (path, contents) in originalFilesAndContents)
|
296
|
+
{
|
297
|
+
await File.WriteAllTextAsync(path, contents);
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
301
|
+
internal static ImmutableArray<ProjectDiscoveryResult> GetProjectDiscoveryEvaluationOrder(DirectoryInfo repoContentsPath, WorkspaceDiscoveryResult discoveryResult, FileInfo projectPath, ILogger logger)
|
302
|
+
{
|
303
|
+
var visitedProjectPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
304
|
+
var projectsToProcess = new Queue<ProjectDiscoveryResult>();
|
305
|
+
var startingProjectDiscovery = discoveryResult.GetProjectDiscoveryFromFullPath(repoContentsPath, projectPath);
|
306
|
+
if (startingProjectDiscovery is null)
|
307
|
+
{
|
308
|
+
logger.Warn($"Unable to find project discovery for project {projectPath.FullName} in discovery result.");
|
309
|
+
return [];
|
310
|
+
}
|
311
|
+
|
312
|
+
projectsToProcess.Enqueue(startingProjectDiscovery);
|
313
|
+
|
314
|
+
var reversedProjectDiscoveryOrder = new List<ProjectDiscoveryResult>();
|
315
|
+
while (projectsToProcess.TryDequeue(out var projectDiscovery))
|
316
|
+
{
|
317
|
+
var projectFullPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, projectDiscovery.FilePath).FullyNormalizedRootedPath();
|
318
|
+
if (visitedProjectPaths.Add(projectFullPath))
|
319
|
+
{
|
320
|
+
reversedProjectDiscoveryOrder.Add(projectDiscovery);
|
321
|
+
foreach (var referencedProjectPath in projectDiscovery.ReferencedProjectPaths)
|
322
|
+
{
|
323
|
+
var referencedProjectFullPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, referencedProjectPath).FullyNormalizedRootedPath();
|
324
|
+
var referencedProjectDiscovery = discoveryResult.GetProjectDiscoveryFromFullPath(repoContentsPath, new FileInfo(referencedProjectFullPath));
|
325
|
+
if (referencedProjectDiscovery is not null)
|
326
|
+
{
|
327
|
+
projectsToProcess.Enqueue(referencedProjectDiscovery);
|
328
|
+
}
|
329
|
+
}
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
var projectDiscoveryOrder = ((IEnumerable<ProjectDiscoveryResult>)reversedProjectDiscoveryOrder)
|
334
|
+
.Reverse()
|
335
|
+
.ToImmutableArray();
|
336
|
+
return projectDiscoveryOrder;
|
337
|
+
}
|
338
|
+
|
339
|
+
internal static async Task<ImmutableArray<string>> TryPerformFileWritesAsync(
|
340
|
+
IFileWriter fileWriter,
|
341
|
+
DirectoryInfo repoContentsPath,
|
342
|
+
DirectoryInfo originalDiscoveryDirectory,
|
343
|
+
ProjectDiscoveryResult projectDiscovery,
|
344
|
+
ImmutableArray<Dependency> requiredPackageVersions
|
345
|
+
)
|
346
|
+
{
|
347
|
+
var originalFileContents = await GetOriginalFileContentsAsync(repoContentsPath, originalDiscoveryDirectory, [projectDiscovery]);
|
348
|
+
var relativeFilePaths = originalFileContents.Keys
|
349
|
+
.Select(p => Path.GetRelativePath(repoContentsPath.FullName, p).FullyNormalizedRootedPath())
|
350
|
+
.ToImmutableArray();
|
351
|
+
|
352
|
+
// try update
|
353
|
+
var addPackageReferenceElementForPinnedPackages = !projectDiscovery.CentralPackageTransitivePinningEnabled;
|
354
|
+
var success = await fileWriter.UpdatePackageVersionsAsync(repoContentsPath, relativeFilePaths, projectDiscovery.Dependencies, requiredPackageVersions, addPackageReferenceElementForPinnedPackages);
|
355
|
+
var updatedFiles = new List<string>();
|
356
|
+
foreach (var (filePath, originalContents) in originalFileContents)
|
357
|
+
{
|
358
|
+
var currentContents = await File.ReadAllTextAsync(filePath);
|
359
|
+
var currentContentsNormalized = currentContents.Replace("\r", "");
|
360
|
+
var originalContentsNormalized = originalContents.Replace("\r", "");
|
361
|
+
if (currentContentsNormalized != originalContentsNormalized)
|
362
|
+
{
|
363
|
+
var relativeUpdatedPath = Path.GetRelativePath(repoContentsPath.FullName, filePath).FullyNormalizedRootedPath();
|
364
|
+
updatedFiles.Add(relativeUpdatedPath);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
if (!success)
|
369
|
+
{
|
370
|
+
await RestoreOriginalFileContentsAsync(originalFileContents);
|
371
|
+
}
|
372
|
+
|
373
|
+
var sortedUpdatedFiles = updatedFiles.OrderBy(p => p, StringComparer.Ordinal).ToImmutableArray();
|
374
|
+
return sortedUpdatedFiles;
|
375
|
+
}
|
376
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
using System.Collections.Immutable;
|
2
|
+
|
3
|
+
namespace NuGetUpdater.Core.Updater.FileWriters;
|
4
|
+
|
5
|
+
public interface IFileWriter
|
6
|
+
{
|
7
|
+
Task<bool> UpdatePackageVersionsAsync(
|
8
|
+
DirectoryInfo repoContentsPath,
|
9
|
+
ImmutableArray<string> relativeFilePaths,
|
10
|
+
ImmutableArray<Dependency> originalDependencies,
|
11
|
+
ImmutableArray<Dependency> requiredPackageVersions,
|
12
|
+
bool addPackageReferenceElementForPinnedPackages
|
13
|
+
);
|
14
|
+
}
|