dependabot-nuget 0.245.0 → 0.247.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +42 -7
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +164 -90
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +38 -2
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +92 -18
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +27 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +115 -14
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/{UpdateWorker.DirsProj.cs → UpdateWorkerTests.DirsProj.cs} +22 -24
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +66 -0
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +373 -83
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +117 -4
  13. data/lib/dependabot/nuget/cache_manager.rb +9 -3
  14. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +15 -12
  15. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +13 -3
  16. data/lib/dependabot/nuget/file_fetcher.rb +79 -31
  17. data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +10 -2
  18. data/lib/dependabot/nuget/file_parser/global_json_parser.rb +10 -2
  19. data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +11 -2
  20. data/lib/dependabot/nuget/file_parser/project_file_parser.rb +140 -45
  21. data/lib/dependabot/nuget/file_parser/property_value_finder.rb +57 -5
  22. data/lib/dependabot/nuget/file_parser.rb +18 -4
  23. data/lib/dependabot/nuget/file_updater/property_value_updater.rb +25 -8
  24. data/lib/dependabot/nuget/file_updater.rb +74 -38
  25. data/lib/dependabot/nuget/http_response_helpers.rb +19 -0
  26. data/lib/dependabot/nuget/metadata_finder.rb +32 -4
  27. data/lib/dependabot/nuget/nuget_client.rb +31 -13
  28. data/lib/dependabot/nuget/requirement.rb +4 -1
  29. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +26 -15
  30. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +23 -13
  31. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +83 -21
  32. data/lib/dependabot/nuget/update_checker/repository_finder.rb +29 -13
  33. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +2 -2
  34. data/lib/dependabot/nuget/update_checker/version_finder.rb +15 -6
  35. data/lib/dependabot/nuget/update_checker.rb +6 -7
  36. data/lib/dependabot/nuget/version.rb +7 -2
  37. metadata +21 -7
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterTests.cs +0 -317
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e67c27ae4f1d9736ba0db82edf309551b56c5337213f72a71d5dc7502e2a91d
4
- data.tar.gz: f04858bb986a722dbe26aae525f26885dbd7cc0dc514ee099ab5fed628dfbc43
3
+ metadata.gz: 9e8dda5e47b38dec152ba8797986aaaca62fde7dbed194960864b779932d6ff7
4
+ data.tar.gz: 4f1cb76b3dafc332d90ddf7acec0b39c6295d2d9749741e3229af6ad7d7e363d
5
5
  SHA512:
6
- metadata.gz: 9fc5b619a387d372e8b91007cb3a1983e93b891874e87e475286d177e3075a911c98cda226746f7e8bb792ba83da409ba9abaa29402857d3b01e82850bffbbc9
7
- data.tar.gz: '0919b3eb28f2d1c1aa5e3d137eb0ef4d443458f92aaddfca0628353d9b49d2ad6b2ccc6698102f55ada4c04517017c143d5115c1ff0d6ba701c422b6547923f2'
6
+ metadata.gz: c350131e183da643b7caf57a76acc2cb954e9d7f0a4532b340db90a064f0e1b7d735a531d2bea8efea6ee483060b3dbb8efb4a8e1567d2c9d30d88bc907848f2
7
+ data.tar.gz: 9f2a6505e1eca5a2fbe8369e8e21ce0b5eabc4c658bec9d628b5250c16f78f40a7c8b19bc0778b2b7fe6e0c3b215a71b2282407544eb0f6808bdfde3da35d8e0
@@ -48,7 +48,7 @@ internal static class PackagesConfigUpdater
48
48
  var packagesDirectory = PathHelper.JoinPath(projectDirectory, packagesSubDirectory);
49
49
  Directory.CreateDirectory(packagesDirectory);
50
50
 
51
- var args = new List<string>
51
+ var updateArgs = new List<string>
52
52
  {
53
53
  "update",
54
54
  packagesConfigPath,
@@ -61,17 +61,29 @@ internal static class PackagesConfigUpdater
61
61
  "-NonInteractive",
62
62
  };
63
63
 
64
+ var restoreArgs = new List<string>
65
+ {
66
+ "restore",
67
+ projectPath,
68
+ "-PackagesDirectory",
69
+ packagesDirectory,
70
+ "-NonInteractive",
71
+ };
72
+
64
73
  logger.Log(" Finding MSBuild...");
65
74
  var msbuildDirectory = MSBuildHelper.MSBuildPath;
66
75
  if (msbuildDirectory is not null)
67
76
  {
68
- args.Add("-MSBuildPath");
69
- args.Add(msbuildDirectory); // e.g., /usr/share/dotnet/sdk/7.0.203
77
+ foreach (var args in new[] { updateArgs, restoreArgs })
78
+ {
79
+ args.Add("-MSBuildPath");
80
+ args.Add(msbuildDirectory); // e.g., /usr/share/dotnet/sdk/7.0.203
81
+ }
70
82
  }
71
83
 
72
84
  using (new WebApplicationTargetsConditionPatcher(projectPath))
73
85
  {
74
- RunNuget(args, packagesDirectory, logger);
86
+ RunNuget(updateArgs, restoreArgs, packagesDirectory, logger);
75
87
  }
76
88
 
77
89
  projectBuildFile = ProjectBuildFile.Open(repoRootPath, projectPath);
@@ -84,7 +96,7 @@ internal static class PackagesConfigUpdater
84
96
  await projectBuildFile.SaveAsync();
85
97
  }
86
98
 
87
- private static void RunNuget(List<string> args, string packagesDirectory, Logger logger)
99
+ private static void RunNuget(List<string> updateArgs, List<string> restoreArgs, string packagesDirectory, Logger logger)
88
100
  {
89
101
  var outputBuilder = new StringBuilder();
90
102
  var writer = new StringWriter(outputBuilder);
@@ -97,15 +109,38 @@ internal static class PackagesConfigUpdater
97
109
  var currentDir = Environment.CurrentDirectory;
98
110
  try
99
111
  {
100
- logger.Log($" Running NuGet.exe with args: {string.Join(" ", args)}");
101
112
 
102
113
  Environment.CurrentDirectory = packagesDirectory;
103
- var result = Program.Main(args.ToArray());
114
+ var retryingAfterRestore = false;
115
+
116
+ doRestore:
117
+ logger.Log($" Running NuGet.exe with args: {string.Join(" ", updateArgs)}");
118
+ outputBuilder.Clear();
119
+ var result = Program.Main(updateArgs.ToArray());
104
120
  var fullOutput = outputBuilder.ToString();
105
121
  logger.Log($" Result: {result}");
106
122
  logger.Log($" Output:\n{fullOutput}");
107
123
  if (result != 0)
108
124
  {
125
+ // If the `packages.config` file contains a delisted package, the initial `update` operation will fail
126
+ // with the message listed below. The solution is to run `nuget.exe restore ...` and retry.
127
+ if (!retryingAfterRestore &&
128
+ fullOutput.Contains("Existing packages must be restored before performing an install or update."))
129
+ {
130
+ logger.Log($" Running NuGet.exe with args: {string.Join(" ", restoreArgs)}");
131
+ retryingAfterRestore = true;
132
+ outputBuilder.Clear();
133
+ var exitCodeAgain = Program.Main(restoreArgs.ToArray());
134
+ var restoreOutput = outputBuilder.ToString();
135
+
136
+ if (exitCodeAgain != 0)
137
+ {
138
+ throw new Exception($"Unable to restore.\nOutput:\n${restoreOutput}\n");
139
+ }
140
+
141
+ goto doRestore;
142
+ }
143
+
109
144
  throw new Exception(fullOutput);
110
145
  }
111
146
  }
@@ -20,132 +20,124 @@ internal static class SdkPackageUpdater
20
20
  string previousDependencyVersion,
21
21
  string newDependencyVersion,
22
22
  bool isTransitive,
23
- Logger logger
24
- )
23
+ Logger logger)
25
24
  {
26
25
  // SDK-style project, modify the XML directly
27
26
  logger.Log(" Running for SDK-style project");
28
- var buildFiles = await MSBuildHelper.LoadBuildFiles(repoRootPath, projectPath);
29
-
30
- var newDependencyNuGetVersion = NuGetVersion.Parse(newDependencyVersion);
31
27
 
32
- // update all dependencies, including transitive
28
+ var buildFiles = await MSBuildHelper.LoadBuildFiles(repoRootPath, projectPath);
33
29
  var tfms = MSBuildHelper.GetTargetFrameworkMonikers(buildFiles);
34
30
 
35
31
  // Get the set of all top-level dependencies in the current project
36
32
  var topLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles).ToArray();
33
+ if (!await DoesDependencyRequireUpdateAsync(repoRootPath, projectPath, tfms, topLevelDependencies, dependencyName, newDependencyVersion, logger))
34
+ {
35
+ return;
36
+ }
37
37
 
38
- var packageFoundInDependencies = false;
39
- var packageNeedsUpdating = false;
40
-
41
- foreach (var tfm in tfms)
38
+ if (isTransitive)
42
39
  {
43
- var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, topLevelDependencies, logger);
44
- foreach (var (packageName, packageVersion, _, _, _, _) in dependencies)
40
+ await UpdateTransitiveDependencyAsnyc(projectPath, dependencyName, newDependencyVersion, buildFiles, logger);
41
+ }
42
+ else
43
+ {
44
+ var peerDependencies = await GetUpdatedPeerDependenciesAsync(repoRootPath, projectPath, tfms, dependencyName, newDependencyVersion, logger);
45
+ if (peerDependencies is null)
45
46
  {
46
- if (packageName.Equals(dependencyName, StringComparison.OrdinalIgnoreCase))
47
- {
48
- packageFoundInDependencies = true;
49
-
50
- var nugetVersion = NuGetVersion.Parse(packageVersion);
51
- if (nugetVersion < newDependencyNuGetVersion)
52
- {
53
- packageNeedsUpdating = true;
54
- }
55
- }
47
+ return;
56
48
  }
57
- }
58
49
 
59
- // Skip updating the project if the dependency does not exist in the graph
60
- if (!packageFoundInDependencies)
61
- {
62
- logger.Log($" Package [{dependencyName}] Does not exist as a dependency in [{projectPath}].");
63
- return;
50
+ UpdateTopLevelDepdendency(buildFiles, dependencyName, previousDependencyVersion, newDependencyVersion, peerDependencies, logger);
64
51
  }
65
52
 
66
- // Skip updating the project if the dependency version meets or exceeds the newDependencyVersion
67
- if (!packageNeedsUpdating)
53
+ if (!await AreDependenciesCoherentAsync(repoRootPath, projectPath, dependencyName, logger, buildFiles, tfms))
68
54
  {
69
- logger.Log($" Package [{dependencyName}] already meets the requested dependency version in [{projectPath}].");
70
55
  return;
71
56
  }
72
57
 
73
- var newDependency = new[] { new Dependency(dependencyName, newDependencyVersion, DependencyType.Unknown) };
74
- var tfmsAndDependencies = new Dictionary<string, Dependency[]>();
75
- foreach (var tfm in tfms)
76
- {
77
- var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, newDependency, logger);
78
- tfmsAndDependencies[tfm] = dependencies;
79
- }
58
+ await SaveBuildFilesAsync(buildFiles, logger);
59
+ }
80
60
 
81
- // stop update process if we find conflicting package versions
82
- var conflictingPackageVersionsFound = false;
83
- var packagesAndVersions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
84
- foreach (var (_, dependencies) in tfmsAndDependencies)
61
+ /// <summary>
62
+ /// Verifies that the package does not already satisfy the requested dependency version.
63
+ /// </summary>
64
+ /// <returns>Returns false if the package is not found or does not need to be updated.</returns>
65
+ private static async Task<bool> DoesDependencyRequireUpdateAsync(
66
+ string repoRootPath,
67
+ string projectPath,
68
+ string[] tfms,
69
+ Dependency[] topLevelDependencies,
70
+ string dependencyName,
71
+ string newDependencyVersion,
72
+ Logger logger)
73
+ {
74
+ var newDependencyNuGetVersion = NuGetVersion.Parse(newDependencyVersion);
75
+
76
+ bool packageFound = false;
77
+ bool needsUpdate = false;
78
+
79
+ foreach (var tfm in tfms)
85
80
  {
81
+ var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(
82
+ repoRootPath,
83
+ projectPath,
84
+ tfm,
85
+ topLevelDependencies,
86
+ logger);
86
87
  foreach (var (packageName, packageVersion, _, _, _, _) in dependencies)
87
88
  {
88
- if (packagesAndVersions.TryGetValue(packageName, out var existingVersion) &&
89
- existingVersion != packageVersion)
89
+ if (packageVersion is null)
90
90
  {
91
- logger.Log($" Package [{packageName}] tried to update to version [{packageVersion}], but found conflicting package version of [{existingVersion}].");
92
- conflictingPackageVersionsFound = true;
91
+ continue;
93
92
  }
94
- else
93
+
94
+ if (packageName.Equals(dependencyName, StringComparison.OrdinalIgnoreCase))
95
95
  {
96
- packagesAndVersions[packageName] = packageVersion!;
96
+ packageFound = true;
97
+
98
+ var nugetVersion = NuGetVersion.Parse(packageVersion);
99
+ if (nugetVersion < newDependencyNuGetVersion)
100
+ {
101
+ needsUpdate = true;
102
+ break;
103
+ }
97
104
  }
98
105
  }
99
- }
100
106
 
101
- if (conflictingPackageVersionsFound)
102
- {
103
- return;
107
+ if (packageFound && needsUpdate)
108
+ {
109
+ break;
110
+ }
104
111
  }
105
112
 
106
- var unupgradableTfms = tfmsAndDependencies.Where(kvp => !kvp.Value.Any()).Select(kvp => kvp.Key);
107
- if (unupgradableTfms.Any())
113
+ // Skip updating the project if the dependency does not exist in the graph
114
+ if (!packageFound)
108
115
  {
109
- logger.Log($" The following target frameworks could not find packages to upgrade: {string.Join(", ", unupgradableTfms)}");
110
- return;
116
+ logger.Log($" Package [{dependencyName}] Does not exist as a dependency in [{projectPath}].");
117
+ return false;
111
118
  }
112
119
 
113
- if (isTransitive)
114
- {
115
- var directoryPackagesWithPinning = buildFiles.OfType<ProjectBuildFile>()
116
- .FirstOrDefault(bf => IsCpmTransitivePinningEnabled(bf));
117
- if (directoryPackagesWithPinning is not null)
118
- {
119
- PinTransitiveDependency(directoryPackagesWithPinning, dependencyName, newDependencyVersion, logger);
120
- }
121
- else
122
- {
123
- await AddTransitiveDependencyAsync(projectPath, dependencyName, newDependencyVersion, logger);
124
- }
125
- }
126
- else
120
+ // Skip updating the project if the dependency version meets or exceeds the newDependencyVersion
121
+ if (!needsUpdate)
127
122
  {
128
- UpdateTopLevelDepdendency(buildFiles, dependencyName, previousDependencyVersion, newDependencyVersion, packagesAndVersions, logger);
123
+ logger.Log($" Package [{dependencyName}] already meets the requested dependency version in [{projectPath}].");
124
+ return false;
129
125
  }
130
126
 
131
- var updatedTopLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles);
132
- foreach (var tfm in tfms)
127
+ return true;
128
+ }
129
+
130
+ private static async Task UpdateTransitiveDependencyAsnyc(string projectPath, string dependencyName, string newDependencyVersion, ImmutableArray<ProjectBuildFile> buildFiles, Logger logger)
131
+ {
132
+ var directoryPackagesWithPinning = buildFiles.OfType<ProjectBuildFile>()
133
+ .FirstOrDefault(bf => IsCpmTransitivePinningEnabled(bf));
134
+ if (directoryPackagesWithPinning is not null)
133
135
  {
134
- var updatedPackages = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, updatedTopLevelDependencies.ToArray(), logger);
135
- var dependenciesAreCoherent = await MSBuildHelper.DependenciesAreCoherentAsync(repoRootPath, projectPath, tfm, updatedPackages, logger);
136
- if (!dependenciesAreCoherent)
137
- {
138
- logger.Log($" Package [{dependencyName}] could not be updated in [{projectPath}] because it would cause a dependency conflict.");
139
- return;
140
- }
136
+ PinTransitiveDependency(directoryPackagesWithPinning, dependencyName, newDependencyVersion, logger);
141
137
  }
142
-
143
- foreach (var buildFile in buildFiles)
138
+ else
144
139
  {
145
- if (await buildFile.SaveAsync())
146
- {
147
- logger.Log($" Saved [{buildFile.RepoRelativePath}].");
148
- }
140
+ await AddTransitiveDependencyAsync(projectPath, dependencyName, newDependencyVersion, logger);
149
141
  }
150
142
  }
151
143
 
@@ -246,14 +238,68 @@ internal static class SdkPackageUpdater
246
238
  }
247
239
  }
248
240
 
241
+ /// <summary>
242
+ /// Gets the set of peer dependencies that need to be updated.
243
+ /// </summary>
244
+ /// <returns>Returns null if there are conflicting versions.</returns>
245
+ private static async Task<Dictionary<string, string>?> GetUpdatedPeerDependenciesAsync(
246
+ string repoRootPath,
247
+ string projectPath,
248
+ string[] tfms,
249
+ string dependencyName,
250
+ string newDependencyVersion,
251
+ Logger logger)
252
+ {
253
+ var newDependency = new[] { new Dependency(dependencyName, newDependencyVersion, DependencyType.Unknown) };
254
+ var tfmsAndDependencies = new Dictionary<string, Dependency[]>();
255
+ foreach (var tfm in tfms)
256
+ {
257
+ var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, newDependency, logger);
258
+ tfmsAndDependencies[tfm] = dependencies;
259
+ }
260
+
261
+ var unupgradableTfms = tfmsAndDependencies.Where(kvp => !kvp.Value.Any()).Select(kvp => kvp.Key);
262
+ if (unupgradableTfms.Any())
263
+ {
264
+ logger.Log($" The following target frameworks could not find packages to upgrade: {string.Join(", ", unupgradableTfms)}");
265
+ return null;
266
+ }
267
+
268
+ var conflictingPackageVersionsFound = false;
269
+ var packagesAndVersions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
270
+ foreach (var (_, dependencies) in tfmsAndDependencies)
271
+ {
272
+ foreach (var (packageName, packageVersion, _, _, _, _) in dependencies)
273
+ {
274
+ if (packagesAndVersions.TryGetValue(packageName, out var existingVersion) &&
275
+ existingVersion != packageVersion)
276
+ {
277
+ logger.Log($" Package [{packageName}] tried to update to version [{packageVersion}], but found conflicting package version of [{existingVersion}].");
278
+ conflictingPackageVersionsFound = true;
279
+ }
280
+ else
281
+ {
282
+ packagesAndVersions[packageName] = packageVersion!;
283
+ }
284
+ }
285
+ }
286
+
287
+ // stop update process if we find conflicting package versions
288
+ if (conflictingPackageVersionsFound)
289
+ {
290
+ return null;
291
+ }
292
+
293
+ return packagesAndVersions;
294
+ }
295
+
249
296
  private static void UpdateTopLevelDepdendency(
250
297
  ImmutableArray<ProjectBuildFile> buildFiles,
251
298
  string dependencyName,
252
299
  string previousDependencyVersion,
253
300
  string newDependencyVersion,
254
- IDictionary<string, string> packagesAndVersions,
255
- Logger logger
256
- )
301
+ IDictionary<string, string> peerDependencies,
302
+ Logger logger)
257
303
  {
258
304
  var result = TryUpdateDependencyVersion(buildFiles, dependencyName, previousDependencyVersion, newDependencyVersion, logger);
259
305
  if (result == UpdateResult.NotFound)
@@ -262,7 +308,7 @@ internal static class SdkPackageUpdater
262
308
  return;
263
309
  }
264
310
 
265
- foreach (var (packageName, packageVersion) in packagesAndVersions.Where(kvp => string.Compare(kvp.Key, dependencyName, StringComparison.OrdinalIgnoreCase) != 0))
311
+ foreach (var (packageName, packageVersion) in peerDependencies.Where(kvp => string.Compare(kvp.Key, dependencyName, StringComparison.OrdinalIgnoreCase) != 0))
266
312
  {
267
313
  TryUpdateDependencyVersion(buildFiles, packageName, previousDependencyVersion: null, newDependencyVersion: packageVersion, logger);
268
314
  }
@@ -515,4 +561,32 @@ internal static class SdkPackageUpdater
515
561
  packageName,
516
562
  StringComparison.OrdinalIgnoreCase) &&
517
563
  (e.GetAttributeOrSubElementValue("Version", StringComparison.OrdinalIgnoreCase) ?? e.GetAttributeOrSubElementValue("VersionOverride", StringComparison.OrdinalIgnoreCase)) is not null);
564
+
565
+ private static async Task<bool> AreDependenciesCoherentAsync(string repoRootPath, string projectPath, string dependencyName, Logger logger, ImmutableArray<ProjectBuildFile> buildFiles, string[] tfms)
566
+ {
567
+ var updatedTopLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles).ToArray();
568
+ foreach (var tfm in tfms)
569
+ {
570
+ var updatedPackages = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, updatedTopLevelDependencies, logger);
571
+ var dependenciesAreCoherent = await MSBuildHelper.DependenciesAreCoherentAsync(repoRootPath, projectPath, tfm, updatedPackages, logger);
572
+ if (!dependenciesAreCoherent)
573
+ {
574
+ logger.Log($" Package [{dependencyName}] could not be updated in [{projectPath}] because it would cause a dependency conflict.");
575
+ return false;
576
+ }
577
+ }
578
+
579
+ return true;
580
+ }
581
+
582
+ private static async Task SaveBuildFilesAsync(ImmutableArray<ProjectBuildFile> buildFiles, Logger logger)
583
+ {
584
+ foreach (var buildFile in buildFiles)
585
+ {
586
+ if (await buildFile.SaveAsync())
587
+ {
588
+ logger.Log($" Saved [{buildFile.RepoRelativePath}].");
589
+ }
590
+ }
591
+ }
518
592
  }
@@ -1,6 +1,7 @@
1
1
  using System;
2
2
  using System.Collections.Generic;
3
3
  using System.IO;
4
+ using System.Linq;
4
5
  using System.Threading.Tasks;
5
6
 
6
7
  namespace NuGetUpdater.Core;
@@ -9,6 +10,7 @@ public class UpdaterWorker
9
10
  {
10
11
  private readonly Logger _logger;
11
12
  private readonly HashSet<string> _processedGlobalJsonPaths = new(StringComparer.OrdinalIgnoreCase);
13
+ private readonly HashSet<string> _processedProjectPaths = new(StringComparer.OrdinalIgnoreCase);
12
14
 
13
15
  public UpdaterWorker(Logger logger)
14
16
  {
@@ -49,6 +51,7 @@ public class UpdaterWorker
49
51
  }
50
52
 
51
53
  _processedGlobalJsonPaths.Clear();
54
+ _processedProjectPaths.Clear();
52
55
  }
53
56
 
54
57
  private async Task RunForSolutionAsync(
@@ -101,7 +104,40 @@ public class UpdaterWorker
101
104
  string newDependencyVersion,
102
105
  bool isTransitive)
103
106
  {
104
- _logger.Log($"Running for project [{projectPath}]");
107
+ _logger.Log($"Running for project file [{Path.GetRelativePath(repoRootPath, projectPath)}]");
108
+ if (!File.Exists(projectPath))
109
+ {
110
+ _logger.Log($"File [{projectPath}] does not exist.");
111
+ return;
112
+ }
113
+
114
+ var projectFilePaths = MSBuildHelper.GetProjectPathsFromProject(projectPath);
115
+ foreach (var projectFullPath in projectFilePaths.Concat([projectPath]))
116
+ {
117
+ // If there is some MSBuild logic that needs to run to fully resolve the path skip the project
118
+ if (File.Exists(projectFullPath))
119
+ {
120
+ await RunUpdaterAsync(repoRootPath, projectFullPath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
121
+ }
122
+ }
123
+ }
124
+
125
+ private async Task RunUpdaterAsync(
126
+ string repoRootPath,
127
+ string projectPath,
128
+ string dependencyName,
129
+ string previousDependencyVersion,
130
+ string newDependencyVersion,
131
+ bool isTransitive)
132
+ {
133
+ if (_processedProjectPaths.Contains(projectPath))
134
+ {
135
+ return;
136
+ }
137
+
138
+ _processedProjectPaths.Add(projectPath);
139
+
140
+ _logger.Log($"Updating project [{projectPath}]");
105
141
 
106
142
  if (!isTransitive
107
143
  && MSBuildHelper.GetGlobalJsonPath(repoRootPath, projectPath) is { } globalJsonPath
@@ -111,7 +147,7 @@ public class UpdaterWorker
111
147
  await GlobalJsonUpdater.UpdateDependencyAsync(repoRootPath, globalJsonPath, dependencyName, previousDependencyVersion, newDependencyVersion, _logger);
112
148
  }
113
149
 
114
- if (NuGetHelper.HasProjectConfigFile(projectPath))
150
+ if (NuGetHelper.HasPackagesConfigFile(projectPath))
115
151
  {
116
152
  await PackagesConfigUpdater.UpdateDependencyAsync(repoRootPath, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive, _logger);
117
153
  }