dependabot-nuget 0.285.0 → 0.286.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetProjects/Directory.Build.props +5 -1
  3. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.CommandLine/NuGet.CommandLine.csproj +1 -0
  4. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Configuration/NuGet.Configuration.csproj +1 -0
  5. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.LibraryModel/NuGet.LibraryModel.csproj +1 -0
  6. data/helpers/lib/NuGetUpdater/NuGetProjects/NuGet.Packaging/NuGet.Packaging.csproj +1 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/RunCommand.cs +8 -1
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +7 -3
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +11 -0
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +1 -1
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +2 -2
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +52 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/IAnalyzeWorker.cs +9 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/IDiscoveryWorker.cs +8 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/IUpdaterWorker.cs +9 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +78 -61
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +6 -5
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +37 -5
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +5 -3
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +0 -5
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +2 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +329 -45
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +168 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestAnalyzeWorker.cs +37 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestDiscoveryWorker.cs +35 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestUpdaterWorker.cs +39 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +104 -3
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +51 -13
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +4 -2
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +22 -17
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
  32. data/lib/dependabot/nuget/file_updater.rb +8 -3
  33. data/lib/dependabot/nuget/native_helpers.rb +11 -12
  34. metadata +12 -6
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/DependencySolverEnvironment.cs +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8dd6e625e132b28270ffbff6c1af11b0173e3a786a1f6518080c20adc028ac2
4
- data.tar.gz: 7afe9afdd9b8ab5ae40372ac51fb292efce75ed4d4b5ba7fee96468e00e835bc
3
+ metadata.gz: 01a6eb36ac3591d016d45ddfc4fc9dbb4068bda72e8560b6453461f5019362f7
4
+ data.tar.gz: 4db4968d74f3b9bfac17cbf32a8017635b07cf5338ad0f9db53dd9a16b188874
5
5
  SHA512:
6
- metadata.gz: 0d9b4fdc7ba52be531cb199699324e7be1a68ae6a698619e961535f0cdb993833cc06e6e4f0df7a88f5b12e3a8bb06627a5ba2233e24bcafa4ade1badcf6a2bf
7
- data.tar.gz: e9619a91fc865a8aa45a812a923f089a10e67f0be0c8588908206726e4e2b6d95ee1626cc0897d3dad5c5aca1a2e89f1c657e25a9137d4f186e05a7813b3e34c
6
+ metadata.gz: 1fce16345ed91813776f2b83b802212e466e15cf5784fcd239c8907ec3af683f0727b7a8e00df7fcb6b97035802c68023ddeb2481a28acce479db6fdfdb6674b
7
+ data.tar.gz: 59d4ac62296d157fbeb3870bcfc18313df3deac4e3f86c0c040ea0c2d2d3c73c1c8d0e84f05d32d83a9129583e6b6e38a1f5314e2cbd0df833c1657c5eb2d7f9
@@ -3,7 +3,11 @@
3
3
  <PropertyGroup>
4
4
  <DefineConstants>$(DefineConstants);IS_CORECLR</DefineConstants>
5
5
  <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
6
- <NoWarn>$(NoWarn);NU1701</NoWarn>
6
+ <NoWarn>$(NoWarn);CA1305</NoWarn><!-- behavior of StringBuilder could vary based on user's locale -->
7
+ <NoWarn>$(NoWarn);CA2022</NoWarn><!-- avoid inexact Stream.Read() -->
8
+ <NoWarn>$(NoWarn);NU1701</NoWarn><!-- package target framework may not be compatible -->
9
+ <NoWarn>$(NoWarn);NU1903</NoWarn><!-- package has a known high severity vulnerability -->
10
+ <NoWarn>$(NoWarn);SYSLIB0014</NoWarn><!-- obsolete -->
7
11
  <NuGetSourceLocation>$(MSBuildThisFileDirectory)..\..\NuGet.Client</NuGetSourceLocation>
8
12
  <SharedDirectory>$(NuGetSourceLocation)\build\Shared</SharedDirectory>
9
13
  <Version>6.8.0</Version>
@@ -3,6 +3,7 @@
3
3
  <PropertyGroup>
4
4
  <TargetFramework>$(CommonTargetFramework)</TargetFramework>
5
5
  <NoWarn>$(NoWarn);CA1416</NoWarn>
6
+ <NoWarn>$(NoWarn);SYSLIB0018</NoWarn><!-- ReflectionOnly loading is not supported -->
6
7
  </PropertyGroup>
7
8
 
8
9
  <ItemGroup>
@@ -3,6 +3,7 @@
3
3
  <PropertyGroup>
4
4
  <TargetFramework>$(CommonTargetFramework)</TargetFramework>
5
5
  <NoWarn>$(NoWarn);CS1591;RS0041</NoWarn>
6
+ <Nullable>enable</Nullable>
6
7
  </PropertyGroup>
7
8
 
8
9
  <ItemGroup>
@@ -3,6 +3,7 @@
3
3
  <PropertyGroup>
4
4
  <TargetFramework>$(CommonTargetFramework)</TargetFramework>
5
5
  <NoWarn>$(NoWarn);CS1591;RS0041</NoWarn>
6
+ <Nullable>enable</Nullable>
6
7
  </PropertyGroup>
7
8
 
8
9
  <ItemGroup>
@@ -3,7 +3,7 @@
3
3
  <PropertyGroup>
4
4
  <TargetFramework>$(CommonTargetFramework)</TargetFramework>
5
5
  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6
- <NoWarn>$(NoWarn);CS0414;CS1591;CS1574;CS1573;CS1572;RS0041</NoWarn>
6
+ <NoWarn>$(NoWarn);CA1305;CS0414;CS1591;CS1574;CS1573;CS1572;RS0041</NoWarn>
7
7
  </PropertyGroup>
8
8
 
9
9
  <ItemGroup>
@@ -1,6 +1,8 @@
1
1
  using System.CommandLine;
2
2
 
3
3
  using NuGetUpdater.Core;
4
+ using NuGetUpdater.Core.Analyze;
5
+ using NuGetUpdater.Core.Discover;
4
6
  using NuGetUpdater.Core.Run;
5
7
 
6
8
  namespace NuGetUpdater.Cli.Commands;
@@ -31,7 +33,12 @@ internal static class RunCommand
31
33
  command.SetHandler(async (jobPath, repoContentsPath, apiUrl, jobId, outputPath, baseCommitSha) =>
32
34
  {
33
35
  var apiHandler = new HttpApiHandler(apiUrl.ToString(), jobId);
34
- var worker = new RunWorker(apiHandler, new ConsoleLogger());
36
+ var logger = new ConsoleLogger();
37
+ var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
38
+ var discoverWorker = new DiscoveryWorker(logger);
39
+ var analyzeWorker = new AnalyzeWorker(logger);
40
+ var updateWorker = new UpdaterWorker(experimentsManager, logger);
41
+ var worker = new RunWorker(apiHandler, discoverWorker, analyzeWorker, updateWorker, logger);
35
42
  await worker.RunAsync(jobPath, repoContentsPath, baseCommitSha, outputPath);
36
43
  }, JobPathOption, RepoContentsPathOption, ApiUrlOption, JobIdOption, OutputPathOption, BaseCommitShaOption);
37
44
 
@@ -6,6 +6,7 @@ namespace NuGetUpdater.Cli.Commands;
6
6
 
7
7
  internal static class UpdateCommand
8
8
  {
9
+ internal static readonly Option<FileInfo> JobPathOption = new("--job-path") { IsRequired = true };
9
10
  internal static readonly Option<DirectoryInfo> RepoRootOption = new("--repo-root", () => new DirectoryInfo(Environment.CurrentDirectory)) { IsRequired = false };
10
11
  internal static readonly Option<FileInfo> SolutionOrProjectFileOption = new("--solution-or-project") { IsRequired = true };
11
12
  internal static readonly Option<string> DependencyNameOption = new("--dependency") { IsRequired = true };
@@ -18,6 +19,7 @@ internal static class UpdateCommand
18
19
  {
19
20
  Command command = new("update", "Applies the changes from an analysis report to update a dependency.")
20
21
  {
22
+ JobPathOption,
21
23
  RepoRootOption,
22
24
  SolutionOrProjectFileOption,
23
25
  DependencyNameOption,
@@ -29,12 +31,14 @@ internal static class UpdateCommand
29
31
 
30
32
  command.TreatUnmatchedTokensAsErrors = true;
31
33
 
32
- command.SetHandler(async (repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, resultOutputPath) =>
34
+ command.SetHandler(async (jobPath, repoRoot, solutionOrProjectFile, dependencyName, newVersion, previousVersion, isTransitive, resultOutputPath) =>
33
35
  {
34
- var worker = new UpdaterWorker(new ConsoleLogger());
36
+ var logger = new ConsoleLogger();
37
+ var experimentsManager = await ExperimentsManager.FromJobFileAsync(jobPath.FullName, logger);
38
+ var worker = new UpdaterWorker(experimentsManager, logger);
35
39
  await worker.RunAsync(repoRoot.FullName, solutionOrProjectFile.FullName, dependencyName, previousVersion, newVersion, isTransitive, resultOutputPath);
36
40
  setExitCode(0);
37
- }, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, ResultOutputPathOption);
41
+ }, JobPathOption, RepoRootOption, SolutionOrProjectFileOption, DependencyNameOption, NewVersionOption, PreviousVersionOption, IsTransitiveOption, ResultOutputPathOption);
38
42
 
39
43
  return command;
40
44
  }
@@ -1,3 +1,4 @@
1
+ using System.IO;
1
2
  using System.Text;
2
3
 
3
4
  using NuGetUpdater.Core;
@@ -18,6 +19,8 @@ public partial class EntryPointTests
18
19
  await Run(path =>
19
20
  [
20
21
  "update",
22
+ "--job-path",
23
+ Path.Combine(path, "job.json"),
21
24
  "--repo-root",
22
25
  path,
23
26
  "--solution-or-project",
@@ -119,6 +122,8 @@ public partial class EntryPointTests
119
122
  await Run(path =>
120
123
  [
121
124
  "update",
125
+ "--job-path",
126
+ Path.Combine(path, "job.json"),
122
127
  "--repo-root",
123
128
  path,
124
129
  "--solution-or-project",
@@ -197,6 +202,8 @@ public partial class EntryPointTests
197
202
  await Run(path =>
198
203
  [
199
204
  "update",
205
+ "--job-path",
206
+ Path.Combine(path, "job.json"),
200
207
  "--repo-root",
201
208
  path,
202
209
  "--solution-or-project",
@@ -325,6 +332,7 @@ public partial class EntryPointTests
325
332
  MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"),
326
333
  ];
327
334
  await MockNuGetPackagesInDirectory(testPackages, tempDir.DirectoryPath);
335
+ await MockJobFileInDirectory(tempDir.DirectoryPath);
328
336
 
329
337
  var globalJsonPath = Path.Join(tempDir.DirectoryPath, "global.json");
330
338
  var srcGlobalJsonPath = Path.Join(tempDir.DirectoryPath, "src", "global.json");
@@ -353,6 +361,8 @@ public partial class EntryPointTests
353
361
  IEnumerable<string> executableArgs = [
354
362
  executableName,
355
363
  "update",
364
+ "--job-path",
365
+ Path.Combine(tempDir.DirectoryPath, "job.json"),
356
366
  "--repo-root",
357
367
  tempDir.DirectoryPath,
358
368
  "--solution-or-project",
@@ -402,6 +412,7 @@ public partial class EntryPointTests
402
412
 
403
413
  try
404
414
  {
415
+ await MockJobFileInDirectory(path);
405
416
  await MockNuGetPackagesInDirectory(packages, path);
406
417
 
407
418
  var args = getArgs(path);
@@ -12,7 +12,7 @@ namespace NuGetUpdater.Core.Analyze;
12
12
 
13
13
  using MultiDependency = (string PropertyName, ImmutableArray<string> TargetFrameworks, ImmutableHashSet<string> DependencyNames);
14
14
 
15
- public partial class AnalyzeWorker
15
+ public partial class AnalyzeWorker : IAnalyzeWorker
16
16
  {
17
17
  public const string AnalysisDirectoryName = "./.dependabot/analysis";
18
18
 
@@ -12,7 +12,7 @@ using NuGetUpdater.Core.Utilities;
12
12
 
13
13
  namespace NuGetUpdater.Core.Discover;
14
14
 
15
- public partial class DiscoveryWorker
15
+ public partial class DiscoveryWorker : IDiscoveryWorker
16
16
  {
17
17
  public const string DiscoveryResultFileName = "./.dependabot/discovery.json";
18
18
 
@@ -58,7 +58,7 @@ public partial class DiscoveryWorker
58
58
  return result;
59
59
  }
60
60
 
61
- internal async Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath)
61
+ public async Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath)
62
62
  {
63
63
  MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, repoRootPath);
64
64
 
@@ -0,0 +1,52 @@
1
+ using System.Text.Json;
2
+
3
+ using NuGetUpdater.Core.Run;
4
+
5
+ namespace NuGetUpdater.Core;
6
+
7
+ public record ExperimentsManager
8
+ {
9
+ public bool UseLegacyDependencySolver { get; init; } = false;
10
+
11
+ public static ExperimentsManager GetExperimentsManager(Dictionary<string, object>? experiments)
12
+ {
13
+ return new ExperimentsManager()
14
+ {
15
+ UseLegacyDependencySolver = IsEnabled(experiments, "nuget_legacy_dependency_solver"),
16
+ };
17
+ }
18
+
19
+ public static async Task<ExperimentsManager> FromJobFileAsync(string jobFilePath, ILogger logger)
20
+ {
21
+ var jobFileContent = await File.ReadAllTextAsync(jobFilePath);
22
+ try
23
+ {
24
+ var jobWrapper = RunWorker.Deserialize(jobFileContent);
25
+ return GetExperimentsManager(jobWrapper.Job.Experiments);
26
+ }
27
+ catch (JsonException ex)
28
+ {
29
+ // the following message has been specifically designed to match the format of `Dependabot.logger.info(...)` from Ruby
30
+ logger.Log($"{DateTime.UtcNow:yyyy/MM/dd HH:mm:ss} INFO Error deserializing job file: {ex.ToString()}: {jobFileContent}");
31
+ return new ExperimentsManager();
32
+ }
33
+ }
34
+
35
+ private static bool IsEnabled(Dictionary<string, object>? experiments, string experimentName)
36
+ {
37
+ if (experiments is null)
38
+ {
39
+ return false;
40
+ }
41
+
42
+ if (experiments.TryGetValue(experimentName, out var value))
43
+ {
44
+ if ((value?.ToString() ?? "").Equals("true", StringComparison.OrdinalIgnoreCase))
45
+ {
46
+ return true;
47
+ }
48
+ }
49
+
50
+ return false;
51
+ }
52
+ }
@@ -0,0 +1,9 @@
1
+ using NuGetUpdater.Core.Analyze;
2
+ using NuGetUpdater.Core.Discover;
3
+
4
+ namespace NuGetUpdater.Core;
5
+
6
+ public interface IAnalyzeWorker
7
+ {
8
+ Task<AnalysisResult> RunAsync(string repoRoot, WorkspaceDiscoveryResult discovery, DependencyInfo dependencyInfo);
9
+ }
@@ -0,0 +1,8 @@
1
+ using NuGetUpdater.Core.Discover;
2
+
3
+ namespace NuGetUpdater.Core;
4
+
5
+ public interface IDiscoveryWorker
6
+ {
7
+ Task<WorkspaceDiscoveryResult> RunAsync(string repoRootPath, string workspacePath);
8
+ }
@@ -0,0 +1,9 @@
1
+
2
+ using NuGetUpdater.Core.Updater;
3
+
4
+ namespace NuGetUpdater.Core;
5
+
6
+ public interface IUpdaterWorker
7
+ {
8
+ Task<UpdateOperationResult> RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive);
9
+ }
@@ -13,6 +13,9 @@ public class RunWorker
13
13
  {
14
14
  private readonly IApiHandler _apiHandler;
15
15
  private readonly ILogger _logger;
16
+ private readonly IDiscoveryWorker _discoveryWorker;
17
+ private readonly IAnalyzeWorker _analyzeWorker;
18
+ private readonly IUpdaterWorker _updaterWorker;
16
19
 
17
20
  internal static readonly JsonSerializerOptions SerializerOptions = new()
18
21
  {
@@ -21,10 +24,13 @@ public class RunWorker
21
24
  Converters = { new JsonStringEnumConverter() },
22
25
  };
23
26
 
24
- public RunWorker(IApiHandler apiHandler, ILogger logger)
27
+ public RunWorker(IApiHandler apiHandler, IDiscoveryWorker discoverWorker, IAnalyzeWorker analyzeWorker, IUpdaterWorker updateWorker, ILogger logger)
25
28
  {
26
29
  _apiHandler = apiHandler;
27
30
  _logger = logger;
31
+ _discoveryWorker = discoverWorker;
32
+ _analyzeWorker = analyzeWorker;
33
+ _updaterWorker = updateWorker;
28
34
  }
29
35
 
30
36
  public async Task RunAsync(FileInfo jobFilePath, DirectoryInfo repoContentsPath, string baseCommitSha, FileInfo outputFilePath)
@@ -55,12 +61,13 @@ public class RunWorker
55
61
  {
56
62
  MSBuildHelper.RegisterMSBuild(repoContentsPath.FullName, repoContentsPath.FullName);
57
63
 
64
+ var experimentsManager = ExperimentsManager.GetExperimentsManager(job.Experiments);
58
65
  var allDependencyFiles = new Dictionary<string, DependencyFile>();
59
66
  foreach (var directory in job.GetAllDirectories())
60
67
  {
61
68
  var localPath = PathHelper.JoinPath(repoContentsPath.FullName, directory);
62
69
  lastUsedPackageSourceUrls = NuGetContext.GetPackageSourceUrls(localPath);
63
- var result = await RunForDirectory(job, repoContentsPath, directory, baseCommitSha);
70
+ var result = await RunForDirectory(job, repoContentsPath, directory, baseCommitSha, experimentsManager);
64
71
  foreach (var dependencyFile in result.Base64DependencyFiles)
65
72
  {
66
73
  var uniqueKey = Path.GetFullPath(Path.Join(dependencyFile.Directory, dependencyFile.Name)).NormalizePathToUnix().EnsurePrefix("/");
@@ -102,10 +109,9 @@ public class RunWorker
102
109
  return runResult;
103
110
  }
104
111
 
105
- private async Task<RunResult> RunForDirectory(Job job, DirectoryInfo repoContentsPath, string repoDirectory, string baseCommitSha)
112
+ private async Task<RunResult> RunForDirectory(Job job, DirectoryInfo repoContentsPath, string repoDirectory, string baseCommitSha, ExperimentsManager experimentsManager)
106
113
  {
107
- var discoveryWorker = new DiscoveryWorker(_logger);
108
- var discoveryResult = await discoveryWorker.RunAsync(repoContentsPath.FullName, repoDirectory);
114
+ var discoveryResult = await _discoveryWorker.RunAsync(repoContentsPath.FullName, repoDirectory);
109
115
 
110
116
  _logger.Log("Discovery JSON content:");
111
117
  _logger.Log(JsonSerializer.Serialize(discoveryResult, DiscoveryWorker.SerializerOptions));
@@ -128,23 +134,31 @@ public class RunWorker
128
134
  });
129
135
 
130
136
  // track original contents for later handling
131
- foreach (var project in discoveryResult.Projects)
137
+ async Task TrackOriginalContentsAsync(string directory, string fileName, string? replacementFileName = null)
132
138
  {
133
- // TODO: include global.json, etc.
134
- var path = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/");
135
- var localPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, project.FilePath);
136
- var content = await File.ReadAllTextAsync(localPath);
137
- originalDependencyFileContents[path] = content;
138
-
139
- // track packages.config if it exists
140
- var projectDirectory = Path.GetDirectoryName(project.FilePath);
141
- var packagesConfigPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, projectDirectory, "packages.config");
142
- var normalizedPackagesConfigPath = Path.Join(discoveryResult.Path, projectDirectory, "packages.config").NormalizePathToUnix().EnsurePrefix("/");
143
- if (File.Exists(packagesConfigPath))
139
+ var repoFullPath = Path.Join(directory, fileName);
140
+ if (replacementFileName is not null)
141
+ {
142
+ repoFullPath = Path.Join(Path.GetDirectoryName(repoFullPath)!, replacementFileName);
143
+ }
144
+
145
+ repoFullPath = repoFullPath.FullyNormalizedRootedPath();
146
+ var localFullPath = Path.Join(repoContentsPath.FullName, repoFullPath);
147
+
148
+ if (!File.Exists(localFullPath))
144
149
  {
145
- var packagesConfigContent = await File.ReadAllTextAsync(packagesConfigPath);
146
- originalDependencyFileContents[normalizedPackagesConfigPath] = packagesConfigContent;
150
+ return;
147
151
  }
152
+
153
+ var content = await File.ReadAllTextAsync(localFullPath);
154
+ originalDependencyFileContents[repoFullPath] = content;
155
+ }
156
+
157
+ foreach (var project in discoveryResult.Projects)
158
+ {
159
+ await TrackOriginalContentsAsync(discoveryResult.Path, project.FilePath);
160
+ await TrackOriginalContentsAsync(discoveryResult.Path, project.FilePath, replacementFileName: "packages.config");
161
+ // TODO: include global.json, etc.
148
162
  }
149
163
 
150
164
  // do update
@@ -166,7 +180,6 @@ public class RunWorker
166
180
  continue;
167
181
  }
168
182
 
169
- var analyzeWorker = new AnalyzeWorker(_logger);
170
183
  var dependencyInfo = new DependencyInfo()
171
184
  {
172
185
  Name = dependency.Name,
@@ -175,16 +188,18 @@ public class RunWorker
175
188
  IgnoredVersions = [],
176
189
  Vulnerabilities = [],
177
190
  };
178
- var analysisResult = await analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
191
+ var analysisResult = await _analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
179
192
  // TODO: log analysisResult
180
193
  if (analysisResult.CanUpdate)
181
194
  {
182
- var dependencyLocation = Path.GetFullPath(Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/"));
195
+ var dependencyLocation = Path.Join(discoveryResult.Path, project.FilePath);
183
196
  if (dependency.Type == DependencyType.PackagesConfig)
184
197
  {
185
- dependencyLocation = Path.Combine(Path.GetDirectoryName(dependencyLocation)!, "packages.config");
198
+ dependencyLocation = Path.Join(Path.GetDirectoryName(dependencyLocation)!, "packages.config");
186
199
  }
187
200
 
201
+ dependencyLocation = dependencyLocation.FullyNormalizedRootedPath();
202
+
188
203
  // TODO: this is inefficient, but not likely causing a bottleneck
189
204
  var previousDependency = discoveredUpdatedDependencies.Dependencies
190
205
  .Single(d => d.Name == dependency.Name && d.Requirements.Single().File == dependencyLocation);
@@ -201,7 +216,7 @@ public class RunWorker
201
216
  Groups = previousDependency.Requirements.Single().Groups,
202
217
  Source = new RequirementSource()
203
218
  {
204
- SourceUrl = analysisResult.UpdatedDependencies.Single(d => d.Name == dependency.Name).InfoUrl,
219
+ SourceUrl = analysisResult.UpdatedDependencies.FirstOrDefault(d => d.Name == dependency.Name)?.InfoUrl,
205
220
  },
206
221
  }
207
222
  ],
@@ -209,9 +224,8 @@ public class RunWorker
209
224
  PreviousRequirements = previousDependency.Requirements,
210
225
  };
211
226
 
212
- var updateWorker = new UpdaterWorker(_logger);
213
- var dependencyFilePath = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix();
214
- var updateResult = await updateWorker.RunAsync(repoContentsPath.FullName, dependencyFilePath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, isTransitive: false);
227
+ var dependencyFilePath = Path.Join(discoveryResult.Path, project.FilePath).FullyNormalizedRootedPath();
228
+ var updateResult = await _updaterWorker.RunAsync(repoContentsPath.FullName, dependencyFilePath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, isTransitive: false);
215
229
  // TODO: need to report if anything was actually updated
216
230
  if (updateResult.ErrorType is null || updateResult.ErrorType == ErrorType.None)
217
231
  {
@@ -228,44 +242,41 @@ public class RunWorker
228
242
 
229
243
  // create PR - we need to manually check file contents; we can't easily use `git status` in tests
230
244
  var updatedDependencyFiles = new List<DependencyFile>();
231
- foreach (var project in discoveryResult.Projects)
245
+ async Task AddUpdatedFileIfDifferentAsync(string directory, string fileName, string? replacementFileName = null)
232
246
  {
233
- var projectPath = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/");
234
- var localProjectPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, project.FilePath);
235
- var updatedProjectContent = await File.ReadAllTextAsync(localProjectPath);
236
- var originalProjectContent = originalDependencyFileContents[projectPath];
237
-
238
- if (updatedProjectContent != originalProjectContent)
247
+ var repoFullPath = Path.Join(directory, fileName);
248
+ if (replacementFileName is not null)
239
249
  {
240
- updatedDependencyFiles.Add(new DependencyFile()
241
- {
242
- Name = project.FilePath,
243
- Content = updatedProjectContent,
244
- Directory = Path.GetDirectoryName(projectPath)!.NormalizeUnixPathParts(),
245
- });
250
+ repoFullPath = Path.Join(Path.GetDirectoryName(repoFullPath)!, replacementFileName);
246
251
  }
247
252
 
248
- var projectDirectory = Path.GetDirectoryName(project.FilePath);
249
- var packagesConfigPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, projectDirectory, "packages.config");
250
- var normalizedPackagesConfigPath = Path.Join(discoveryResult.Path, projectDirectory, "packages.config").NormalizePathToUnix().EnsurePrefix("/");
253
+ repoFullPath = repoFullPath.FullyNormalizedRootedPath();
254
+ var localFullPath = Path.Join(repoContentsPath.FullName, repoFullPath);
251
255
 
252
- if (File.Exists(packagesConfigPath))
256
+ if (!File.Exists(localFullPath))
253
257
  {
254
- var updatedPackagesConfigContent = await File.ReadAllTextAsync(packagesConfigPath);
255
- var originalPackagesConfigContent = originalDependencyFileContents[normalizedPackagesConfigPath];
258
+ return;
259
+ }
256
260
 
257
- if (updatedPackagesConfigContent != originalPackagesConfigContent)
261
+ var originalContent = originalDependencyFileContents[repoFullPath];
262
+ var updatedContent = await File.ReadAllTextAsync(localFullPath);
263
+ if (updatedContent != originalContent)
264
+ {
265
+ updatedDependencyFiles.Add(new DependencyFile()
258
266
  {
259
- updatedDependencyFiles.Add(new DependencyFile()
260
- {
261
- Name = Path.Join(projectDirectory!, "packages.config"),
262
- Content = updatedPackagesConfigContent,
263
- Directory = Path.GetDirectoryName(normalizedPackagesConfigPath)!.NormalizeUnixPathParts(),
264
- });
265
- }
267
+ Name = Path.GetFileName(repoFullPath),
268
+ Directory = Path.GetDirectoryName(repoFullPath)!.NormalizePathToUnix(),
269
+ Content = updatedContent,
270
+ });
266
271
  }
267
272
  }
268
273
 
274
+ foreach (var project in discoveryResult.Projects)
275
+ {
276
+ await AddUpdatedFileIfDifferentAsync(discoveryResult.Path, project.FilePath);
277
+ await AddUpdatedFileIfDifferentAsync(discoveryResult.Path, project.FilePath, replacementFileName: "packages.config");
278
+ }
279
+
269
280
  if (updatedDependencyFiles.Count > 0)
270
281
  {
271
282
  var createPullRequest = new CreatePullRequest()
@@ -292,11 +303,15 @@ public class RunWorker
292
303
 
293
304
  var result = new RunResult()
294
305
  {
295
- Base64DependencyFiles = originalDependencyFileContents.Select(kvp => new DependencyFile()
306
+ Base64DependencyFiles = originalDependencyFileContents.Select(kvp =>
296
307
  {
297
- Name = Path.GetFileName(kvp.Key),
298
- Content = Convert.ToBase64String(Encoding.UTF8.GetBytes(kvp.Value)),
299
- Directory = Path.GetFullPath(Path.GetDirectoryName(kvp.Key)!).NormalizePathToUnix(),
308
+ var fullPath = kvp.Key.FullyNormalizedRootedPath();
309
+ return new DependencyFile()
310
+ {
311
+ Name = Path.GetFileName(fullPath),
312
+ Content = Convert.ToBase64String(Encoding.UTF8.GetBytes(kvp.Value)),
313
+ Directory = Path.GetDirectoryName(fullPath)!.NormalizePathToUnix(),
314
+ };
300
315
  }).ToArray(),
301
316
  BaseCommitSha = baseCommitSha,
302
317
  };
@@ -308,7 +323,7 @@ public class RunWorker
308
323
  string GetFullRepoPath(string path)
309
324
  {
310
325
  // ensures `path\to\file` is `/path/to/file`
311
- return Path.Join(discoveryResult.Path, path).NormalizePathToUnix().NormalizeUnixPathParts().EnsurePrefix("/");
326
+ return Path.Join(discoveryResult.Path, path).FullyNormalizedRootedPath();
312
327
  }
313
328
 
314
329
  var auxiliaryFiles = new List<string>();
@@ -328,7 +343,7 @@ public class RunWorker
328
343
  foreach (var project in discoveryResult.Projects)
329
344
  {
330
345
  var projectDirectory = Path.GetDirectoryName(project.FilePath);
331
- var pathToPackagesConfig = Path.Join(pathToContents, discoveryResult.Path, projectDirectory, "packages.config").NormalizePathToUnix().EnsurePrefix("/");
346
+ var pathToPackagesConfig = Path.Join(pathToContents, discoveryResult.Path, projectDirectory, "packages.config");
332
347
 
333
348
  if (File.Exists(pathToPackagesConfig))
334
349
  {
@@ -346,7 +361,9 @@ public class RunWorker
346
361
  Name = d.Name,
347
362
  Requirements = d.IsTransitive ? [] : [new ReportedRequirement()
348
363
  {
349
- File = d.Type == DependencyType.PackagesConfig ? Path.Combine(Path.GetDirectoryName(GetFullRepoPath(p.FilePath))!, "packages.config"): GetFullRepoPath(p.FilePath),
364
+ File = d.Type == DependencyType.PackagesConfig
365
+ ? Path.Join(Path.GetDirectoryName(GetFullRepoPath(p.FilePath))!, "packages.config").FullyNormalizedRootedPath()
366
+ : GetFullRepoPath(p.FilePath),
350
367
  Requirement = d.Version!,
351
368
  Groups = ["dependencies"],
352
369
  }],
@@ -26,6 +26,7 @@ internal static class PackageReferenceUpdater
26
26
  string previousDependencyVersion,
27
27
  string newDependencyVersion,
28
28
  bool isTransitive,
29
+ ExperimentsManager experimentsManager,
29
30
  ILogger logger)
30
31
  {
31
32
  // PackageReference project; modify the XML directly
@@ -42,11 +43,7 @@ internal static class PackageReferenceUpdater
42
43
  }
43
44
 
44
45
  var peerDependencies = await GetUpdatedPeerDependenciesAsync(repoRootPath, projectPath, tfms, dependencyName, newDependencyVersion, logger);
45
- if (MSBuildHelper.UseNewDependencySolver())
46
- {
47
- await UpdateDependencyWithConflictResolution(repoRootPath, buildFiles, tfms, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive, peerDependencies, logger);
48
- }
49
- else
46
+ if (experimentsManager.UseLegacyDependencySolver)
50
47
  {
51
48
  if (isTransitive)
52
49
  {
@@ -62,6 +59,10 @@ internal static class PackageReferenceUpdater
62
59
  await UpdateTopLevelDepdendency(repoRootPath, buildFiles, tfms, dependencyName, previousDependencyVersion, newDependencyVersion, peerDependencies, logger);
63
60
  }
64
61
  }
62
+ else
63
+ {
64
+ await UpdateDependencyWithConflictResolution(repoRootPath, buildFiles, tfms, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive, peerDependencies, logger);
65
+ }
65
66
 
66
67
  if (!await AreDependenciesCoherentAsync(repoRootPath, projectPath, dependencyName, logger, buildFiles, tfms))
67
68
  {