dependabot-nuget 0.284.0 → 0.286.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) 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 +104 -33
  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 +975 -57
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +168 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +53 -6
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestAnalyzeWorker.cs +37 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestDiscoveryWorker.cs +35 -0
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestUpdaterWorker.cs +39 -0
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackagesConfigUpdaterTests.cs +104 -3
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +51 -13
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +4 -2
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +22 -17
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1 -1
  33. data/lib/dependabot/nuget/file_updater.rb +8 -3
  34. data/lib/dependabot/nuget/native_helpers.rb +11 -12
  35. metadata +12 -6
  36. 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: 0604d43cad05ef88f7471259b903ec56c1cf7d1bcf127b253bf6c0c2af8c66f0
4
- data.tar.gz: 9e4b41b0d72f5989abb57bc18f39116a1a2f5c00f935c7a0c2858e61da6bcb75
3
+ metadata.gz: 01a6eb36ac3591d016d45ddfc4fc9dbb4068bda72e8560b6453461f5019362f7
4
+ data.tar.gz: 4db4968d74f3b9bfac17cbf32a8017635b07cf5338ad0f9db53dd9a16b188874
5
5
  SHA512:
6
- metadata.gz: 6f4b7300174349f5a5c5a5ebdc461a18ea2c08a06b0229043216e2f3b19bc5a5c2523f43735f0aeafd95f0bffea693791f307165dbb22a1d58ab81f19e89496e
7
- data.tar.gz: '0761288866aa1af50029cbd2f61d2423e06f51d090ed8ca4afb3b5afb9a4aa4b5389fa57a1fdad03b0de95895d3b43eb612cbb992660b44ca854bcc8303f1733'
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,15 +61,17 @@ 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
- allDependencyFiles[dependencyFile.Name] = dependencyFile;
73
+ var uniqueKey = Path.GetFullPath(Path.Join(dependencyFile.Directory, dependencyFile.Name)).NormalizePathToUnix().EnsurePrefix("/");
74
+ allDependencyFiles[uniqueKey] = dependencyFile;
67
75
  }
68
76
  }
69
77
 
@@ -101,16 +109,15 @@ public class RunWorker
101
109
  return runResult;
102
110
  }
103
111
 
104
- 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)
105
113
  {
106
- var discoveryWorker = new DiscoveryWorker(_logger);
107
- var discoveryResult = await discoveryWorker.RunAsync(repoContentsPath.FullName, repoDirectory);
114
+ var discoveryResult = await _discoveryWorker.RunAsync(repoContentsPath.FullName, repoDirectory);
108
115
 
109
116
  _logger.Log("Discovery JSON content:");
110
117
  _logger.Log(JsonSerializer.Serialize(discoveryResult, DiscoveryWorker.SerializerOptions));
111
118
 
112
119
  // report dependencies
113
- var discoveredUpdatedDependencies = GetUpdatedDependencyListFromDiscovery(discoveryResult);
120
+ var discoveredUpdatedDependencies = GetUpdatedDependencyListFromDiscovery(discoveryResult, repoContentsPath.FullName);
114
121
  await _apiHandler.UpdateDependencyList(discoveredUpdatedDependencies);
115
122
 
116
123
  // TODO: pull out relevant dependencies, then check each for updates and track the changes
@@ -127,13 +134,31 @@ public class RunWorker
127
134
  });
128
135
 
129
136
  // track original contents for later handling
137
+ async Task TrackOriginalContentsAsync(string directory, string fileName, string? replacementFileName = null)
138
+ {
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))
149
+ {
150
+ return;
151
+ }
152
+
153
+ var content = await File.ReadAllTextAsync(localFullPath);
154
+ originalDependencyFileContents[repoFullPath] = content;
155
+ }
156
+
130
157
  foreach (var project in discoveryResult.Projects)
131
158
  {
159
+ await TrackOriginalContentsAsync(discoveryResult.Path, project.FilePath);
160
+ await TrackOriginalContentsAsync(discoveryResult.Path, project.FilePath, replacementFileName: "packages.config");
132
161
  // TODO: include global.json, etc.
133
- var path = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/");
134
- var localPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, project.FilePath);
135
- var content = await File.ReadAllTextAsync(localPath);
136
- originalDependencyFileContents[path] = content;
137
162
  }
138
163
 
139
164
  // do update
@@ -155,7 +180,6 @@ public class RunWorker
155
180
  continue;
156
181
  }
157
182
 
158
- var analyzeWorker = new AnalyzeWorker(_logger);
159
183
  var dependencyInfo = new DependencyInfo()
160
184
  {
161
185
  Name = dependency.Name,
@@ -164,13 +188,21 @@ public class RunWorker
164
188
  IgnoredVersions = [],
165
189
  Vulnerabilities = [],
166
190
  };
167
- var analysisResult = await analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
191
+ var analysisResult = await _analyzeWorker.RunAsync(repoContentsPath.FullName, discoveryResult, dependencyInfo);
168
192
  // TODO: log analysisResult
169
193
  if (analysisResult.CanUpdate)
170
194
  {
195
+ var dependencyLocation = Path.Join(discoveryResult.Path, project.FilePath);
196
+ if (dependency.Type == DependencyType.PackagesConfig)
197
+ {
198
+ dependencyLocation = Path.Join(Path.GetDirectoryName(dependencyLocation)!, "packages.config");
199
+ }
200
+
201
+ dependencyLocation = dependencyLocation.FullyNormalizedRootedPath();
202
+
171
203
  // TODO: this is inefficient, but not likely causing a bottleneck
172
204
  var previousDependency = discoveredUpdatedDependencies.Dependencies
173
- .Single(d => d.Name == dependency.Name && d.Requirements.Single().File == Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/"));
205
+ .Single(d => d.Name == dependency.Name && d.Requirements.Single().File == dependencyLocation);
174
206
  var updatedDependency = new ReportedDependency()
175
207
  {
176
208
  Name = dependency.Name,
@@ -179,12 +211,12 @@ public class RunWorker
179
211
  [
180
212
  new ReportedRequirement()
181
213
  {
182
- File = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/"),
214
+ File = dependencyLocation,
183
215
  Requirement = analysisResult.UpdatedVersion,
184
216
  Groups = previousDependency.Requirements.Single().Groups,
185
217
  Source = new RequirementSource()
186
218
  {
187
- SourceUrl = analysisResult.UpdatedDependencies.Single(d => d.Name == dependency.Name).InfoUrl,
219
+ SourceUrl = analysisResult.UpdatedDependencies.FirstOrDefault(d => d.Name == dependency.Name)?.InfoUrl,
188
220
  },
189
221
  }
190
222
  ],
@@ -192,12 +224,16 @@ public class RunWorker
192
224
  PreviousRequirements = previousDependency.Requirements,
193
225
  };
194
226
 
195
- var updateWorker = new UpdaterWorker(_logger);
196
- var dependencyFilePath = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix();
197
- 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);
198
229
  // TODO: need to report if anything was actually updated
199
230
  if (updateResult.ErrorType is null || updateResult.ErrorType == ErrorType.None)
200
231
  {
232
+ if (dependencyLocation != dependencyFilePath)
233
+ {
234
+ updatedDependency.Requirements.All(r => r.File == dependencyFilePath);
235
+ }
236
+
201
237
  actualUpdatedDependencies.Add(updatedDependency);
202
238
  }
203
239
  }
@@ -206,23 +242,41 @@ public class RunWorker
206
242
 
207
243
  // create PR - we need to manually check file contents; we can't easily use `git status` in tests
208
244
  var updatedDependencyFiles = new List<DependencyFile>();
209
- foreach (var project in discoveryResult.Projects)
245
+ async Task AddUpdatedFileIfDifferentAsync(string directory, string fileName, string? replacementFileName = null)
210
246
  {
211
- var path = Path.Join(discoveryResult.Path, project.FilePath).NormalizePathToUnix().EnsurePrefix("/");
212
- var localPath = Path.Join(repoContentsPath.FullName, discoveryResult.Path, project.FilePath);
213
- var updatedContent = await File.ReadAllTextAsync(localPath);
214
- var originalContent = originalDependencyFileContents[path];
247
+ var repoFullPath = Path.Join(directory, fileName);
248
+ if (replacementFileName is not null)
249
+ {
250
+ repoFullPath = Path.Join(Path.GetDirectoryName(repoFullPath)!, replacementFileName);
251
+ }
252
+
253
+ repoFullPath = repoFullPath.FullyNormalizedRootedPath();
254
+ var localFullPath = Path.Join(repoContentsPath.FullName, repoFullPath);
255
+
256
+ if (!File.Exists(localFullPath))
257
+ {
258
+ return;
259
+ }
260
+
261
+ var originalContent = originalDependencyFileContents[repoFullPath];
262
+ var updatedContent = await File.ReadAllTextAsync(localFullPath);
215
263
  if (updatedContent != originalContent)
216
264
  {
217
265
  updatedDependencyFiles.Add(new DependencyFile()
218
266
  {
219
- Name = project.FilePath,
267
+ Name = Path.GetFileName(repoFullPath),
268
+ Directory = Path.GetDirectoryName(repoFullPath)!.NormalizePathToUnix(),
220
269
  Content = updatedContent,
221
- Directory = discoveryResult.Path,
222
270
  });
223
271
  }
224
272
  }
225
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
+
226
280
  if (updatedDependencyFiles.Count > 0)
227
281
  {
228
282
  var createPullRequest = new CreatePullRequest()
@@ -249,23 +303,27 @@ public class RunWorker
249
303
 
250
304
  var result = new RunResult()
251
305
  {
252
- Base64DependencyFiles = originalDependencyFileContents.Select(kvp => new DependencyFile()
306
+ Base64DependencyFiles = originalDependencyFileContents.Select(kvp =>
253
307
  {
254
- Name = Path.GetFileName(kvp.Key),
255
- Content = Convert.ToBase64String(Encoding.UTF8.GetBytes(kvp.Value)),
256
- Directory = 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
+ };
257
315
  }).ToArray(),
258
316
  BaseCommitSha = baseCommitSha,
259
317
  };
260
318
  return result;
261
319
  }
262
320
 
263
- internal static UpdatedDependencyList GetUpdatedDependencyListFromDiscovery(WorkspaceDiscoveryResult discoveryResult)
321
+ internal static UpdatedDependencyList GetUpdatedDependencyListFromDiscovery(WorkspaceDiscoveryResult discoveryResult, string pathToContents)
264
322
  {
265
323
  string GetFullRepoPath(string path)
266
324
  {
267
325
  // ensures `path\to\file` is `/path/to/file`
268
- return Path.Join(discoveryResult.Path, path).NormalizePathToUnix().NormalizeUnixPathParts().EnsurePrefix("/");
326
+ return Path.Join(discoveryResult.Path, path).FullyNormalizedRootedPath();
269
327
  }
270
328
 
271
329
  var auxiliaryFiles = new List<string>();
@@ -282,6 +340,17 @@ public class RunWorker
282
340
  auxiliaryFiles.Add(GetFullRepoPath(discoveryResult.DirectoryPackagesProps.FilePath));
283
341
  }
284
342
 
343
+ foreach (var project in discoveryResult.Projects)
344
+ {
345
+ var projectDirectory = Path.GetDirectoryName(project.FilePath);
346
+ var pathToPackagesConfig = Path.Join(pathToContents, discoveryResult.Path, projectDirectory, "packages.config");
347
+
348
+ if (File.Exists(pathToPackagesConfig))
349
+ {
350
+ auxiliaryFiles.Add(GetFullRepoPath(Path.Join(projectDirectory, "packages.config")));
351
+ }
352
+ }
353
+
285
354
  var updatedDependencyList = new UpdatedDependencyList()
286
355
  {
287
356
  Dependencies = discoveryResult.Projects.SelectMany(p =>
@@ -292,7 +361,9 @@ public class RunWorker
292
361
  Name = d.Name,
293
362
  Requirements = d.IsTransitive ? [] : [new ReportedRequirement()
294
363
  {
295
- File = GetFullRepoPath(p.FilePath),
364
+ File = d.Type == DependencyType.PackagesConfig
365
+ ? Path.Join(Path.GetDirectoryName(GetFullRepoPath(p.FilePath))!, "packages.config").FullyNormalizedRootedPath()
366
+ : GetFullRepoPath(p.FilePath),
296
367
  Requirement = d.Version!,
297
368
  Groups = ["dependencies"],
298
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
  {