dependabot-nuget 0.285.0 → 0.286.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.
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
  {