dependabot-nuget 0.372.0 → 0.374.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Build.props +1 -0
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +7 -7
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +1 -1
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Dependency.cs +3 -12
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +12 -5
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackageManagementKind.cs +23 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +1 -1
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +13 -7
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/PackagesConfigBuildFile.cs +1 -2
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Files/ProjectBuildFile.cs +1 -4
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/IUpdaterWorker.cs +1 -1
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +2 -2
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandler.cs +1 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs +2 -2
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandler.cs +1 -1
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandler.cs +1 -1
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandler.cs +1 -1
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/FileWriterWorker.cs +3 -4
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/IFileWriter.cs +3 -1
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/XmlFileWriter.cs +8 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +1 -1
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +5 -5
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +5 -12
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +15 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +1 -2
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +9 -9
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +4 -5
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +2 -2
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +2 -2
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +84 -24
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +34 -36
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +21 -21
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/PackagesConfigBuildFileTests.cs +1 -1
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Files/ProjectBuildFileTests.cs +2 -2
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +1 -1
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/ApiModel/JobTests.cs +16 -16
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandlerTests.cs +3 -3
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/GroupUpdateAllVersionsHandlerTests.cs +10 -10
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandlerTests.cs +5 -5
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandlerTests.cs +7 -7
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandlerTests.cs +5 -5
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdatedDependencyListTests.cs +1 -1
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/StringLogger.cs +13 -0
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TestUpdaterWorker.cs +5 -5
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterTestsBase.cs +5 -6
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/TestFileWriterReturnsConstantResult.cs +2 -1
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests.cs +3 -2
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +19 -19
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +60 -60
  51. metadata +6 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a058182c9ce909abc8398d444a3cba984f43528a7655fd5ee96cc8c607bbfd76
4
- data.tar.gz: ffd8f02946da91739938e89ca13e3beb4e6b3ef157bb23083251df98cf45930f
3
+ metadata.gz: 44fba281ef6f7ae5edcc476e8c7776c0eb7f67f34c0fc88fd97a5b2bb0fd9ecd
4
+ data.tar.gz: 58769e2284c8cc3c71fa27ad89f5121985d5050afa2d8354359246507049025e
5
5
  SHA512:
6
- metadata.gz: 4d9d90b837aa4ebd014a46c1dc0a89ae29689f30bbe84fc49c16deec4c260625e263aa731f100d0ef909ad2da00a48c131e9086393866f54e83e48e6678a77f8
7
- data.tar.gz: d8c27b9ff9c1837c191ce89ae005e3071f5fc5cd09d76d8c1e0ecc3ea1bd511ed1cd544bac6bdd0ea17aef43dc49747b2c87cc8cbe0f3e3645f6977582ec3394
6
+ metadata.gz: 0343710df6bb80e64d5e19c48d02bbc78b930338516e5951e3909e622ea2bd692ece05dd89b884103ef86467d8cb29bd7dfdb5e4b17127c264040950e3ebf81e
7
+ data.tar.gz: de4e648b06eb7bd4a13a17fe544600bc7d4e5ea3477935e06941e378668fccdc60efceabe6b6c78e9c13da9fec8a69109eec00068a922559b92b8b5b1f9b472d
@@ -6,6 +6,7 @@
6
6
  <Nullable>enable</Nullable>
7
7
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
8
8
  <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
9
+ <NuGetAudit>false</NuGetAudit>
9
10
  </PropertyGroup>
10
11
 
11
12
  <Import Project="Directory.Common.props" />
@@ -84,7 +84,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
84
84
  .Select(NuGetFramework.Parse)
85
85
  .ToImmutableArray();
86
86
  var propertyBasedDependencies = discovery.Projects.SelectMany(p
87
- => p.Dependencies.Where(d => !d.IsTransitive &&
87
+ => p.Dependencies.Where(d => d.IsTopLevel &&
88
88
  d.EvaluationResult?.RootPropertyName is not null)
89
89
  ).ToImmutableArray();
90
90
  var dotnetToolsHasDependency = discovery.DotNetToolsJson?.Dependencies.Any(d => d.Name.Equals(dependencyInfo.Name, StringComparison.OrdinalIgnoreCase)) == true;
@@ -149,12 +149,12 @@ public partial class AnalyzeWorker : IAnalyzeWorker
149
149
  else if (dotnetToolsHasDependency)
150
150
  {
151
151
  var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
152
- updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, IsDirect: true, InfoUrl: infoUrl)];
152
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.DotNetTool, InfoUrl: infoUrl)];
153
153
  }
154
154
  else if (globalJsonHasDependency)
155
155
  {
156
156
  var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependencyInfo.Name, updatedVersion.ToNormalizedString(), CancellationToken.None);
157
- updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, IsDirect: true, InfoUrl: infoUrl)];
157
+ updatedDependencies = [new Dependency(dependencyInfo.Name, updatedVersion.ToNormalizedString(), DependencyType.MSBuildSdk, InfoUrl: infoUrl)];
158
158
  }
159
159
  else
160
160
  {
@@ -193,11 +193,11 @@ public partial class AnalyzeWorker : IAnalyzeWorker
193
193
  return true;
194
194
  }
195
195
 
196
- // Since the dependency is not vulnerable, we only need to update if it is not transitive.
196
+ // Since the dependency is not vulnerable, we only need to update if it is a top-level dependency.
197
197
  return projectsWithDependency.Any(p =>
198
198
  p.Dependencies.Any(d =>
199
199
  d.Name.Equals(dependencyInfo.Name, StringComparison.OrdinalIgnoreCase) &&
200
- !d.IsTransitive));
200
+ d.IsTopLevel));
201
201
  }
202
202
 
203
203
  private static Task<WorkspaceDiscoveryResult> DeserializeWorkspaceDiscoveryResultFileAsync(string path)
@@ -392,7 +392,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
392
392
  // When updating peer dependencies, we only need to consider top-level dependencies.
393
393
  var projectDependencyNames = projectsWithDependency
394
394
  .SelectMany(p => p.Dependencies)
395
- .Where(d => !d.IsTransitive)
395
+ .Where(d => d.IsTopLevel)
396
396
  .Select(d => d.Name)
397
397
  .ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
398
398
 
@@ -427,7 +427,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
427
427
  {
428
428
  var packageDeclarationsUsingProperty = discovery.Projects
429
429
  .SelectMany(p =>
430
- p.Dependencies.Where(d => !d.IsTransitive &&
430
+ p.Dependencies.Where(d => d.IsTopLevel &&
431
431
  d.Name.Equals(packageId, StringComparison.OrdinalIgnoreCase) &&
432
432
  d.EvaluationResult?.RootPropertyName is not null)
433
433
  ).ToImmutableArray();
@@ -34,7 +34,7 @@ internal static class DependencyFinder
34
34
  foreach (var dependency in dependencies)
35
35
  {
36
36
  var infoUrl = await nugetContext.GetPackageInfoUrlAsync(dependency.Name, dependency.Version!, cancellationToken);
37
- var updatedDependency = dependency with { IsTransitive = false, InfoUrl = infoUrl };
37
+ var updatedDependency = dependency with { IsTopLevel = true, InfoUrl = infoUrl };
38
38
  updatedDependencies.Add(updatedDependency);
39
39
  }
40
40
 
@@ -10,10 +10,7 @@ public sealed record Dependency(
10
10
  DependencyType Type,
11
11
  EvaluationResult? EvaluationResult = null,
12
12
  ImmutableArray<string>? TargetFrameworks = null,
13
- bool IsDevDependency = false,
14
- bool IsDirect = false,
15
- bool IsTransitive = false,
16
- bool IsOverride = false,
13
+ bool IsTopLevel = true,
17
14
  bool IsUpdate = false,
18
15
  string? InfoUrl = null) : IEquatable<Dependency>
19
16
  {
@@ -34,10 +31,7 @@ public sealed record Dependency(
34
31
  Type == other.Type &&
35
32
  EvaluationResult == other.EvaluationResult &&
36
33
  TargetFrameworks.SequenceEqual(other.TargetFrameworks) &&
37
- IsDevDependency == other.IsDevDependency &&
38
- IsDirect == other.IsDirect &&
39
- IsTransitive == other.IsTransitive &&
40
- IsOverride == other.IsOverride &&
34
+ IsTopLevel == other.IsTopLevel &&
41
35
  IsUpdate == other.IsUpdate &&
42
36
  InfoUrl == other.InfoUrl;
43
37
  }
@@ -50,10 +44,7 @@ public sealed record Dependency(
50
44
  hash.Add(Type);
51
45
  hash.Add(EvaluationResult);
52
46
  hash.Add(TargetFrameworks);
53
- hash.Add(IsDevDependency);
54
- hash.Add(IsDirect);
55
- hash.Add(IsTransitive);
56
- hash.Add(IsOverride);
47
+ hash.Add(IsTopLevel);
57
48
  hash.Add(IsUpdate);
58
49
  hash.Add(InfoUrl);
59
50
  return hash.ToHashCode();
@@ -171,10 +171,11 @@ public partial class DiscoveryWorker : IDiscoveryWorker
171
171
  {
172
172
  _logger.Info($" Discovering projects beneath [{Path.GetRelativePath(repoRootPath, workspacePath)}].");
173
173
  var entryPoints = FindEntryPoints(workspacePath);
174
+ _logger.Info($" Entry points found: {string.Join(", ", entryPoints)}");
174
175
  ImmutableArray<string> projects;
175
176
  try
176
177
  {
177
- projects = await ExpandEntryPointsIntoProjectsAsync(entryPoints, _experimentsManager);
178
+ projects = await ExpandEntryPointsIntoProjectsAsync(entryPoints, _experimentsManager, _logger);
178
179
  }
179
180
  catch (InvalidProjectFileException e)
180
181
  {
@@ -193,7 +194,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
193
194
  }
194
195
  if (projects.IsEmpty)
195
196
  {
196
- _logger.Info(" No project files found.");
197
+ _logger.Info(" No project files found.");
197
198
  return [];
198
199
  }
199
200
 
@@ -222,7 +223,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
222
223
  .ToImmutableArray();
223
224
  }
224
225
 
225
- internal async static Task<ImmutableArray<string>> ExpandEntryPointsIntoProjectsAsync(IEnumerable<string> entryPoints, ExperimentsManager experimentsManager)
226
+ internal async static Task<ImmutableArray<string>> ExpandEntryPointsIntoProjectsAsync(IEnumerable<string> entryPoints, ExperimentsManager experimentsManager, ILogger logger)
226
227
  {
227
228
  HashSet<string> expandedProjects = new(PathComparer.Instance);
228
229
  HashSet<string> seenProjects = new(PathComparer.Instance);
@@ -235,28 +236,34 @@ public partial class DiscoveryWorker : IDiscoveryWorker
235
236
  string extension = Path.GetExtension(candidateEntryPoint).ToLowerInvariant();
236
237
  if (extension == ".sln")
237
238
  {
239
+ logger.Info($" Expanding solution: {candidateEntryPoint}:");
238
240
  SolutionFile solution = SolutionFile.Parse(candidateEntryPoint);
239
241
  foreach (ProjectInSolution project in solution.ProjectsInOrder)
240
242
  {
243
+ logger.Info($" Expanded project: {project.AbsolutePath}");
241
244
  filesToExpand.Push(project.AbsolutePath);
242
245
  }
243
246
  }
244
247
  else if (extension == ".slnx")
245
248
  {
249
+ logger.Info($" Expanding solution: {candidateEntryPoint}:");
246
250
  SolutionModel solution = await SolutionSerializers.SlnXml.OpenAsync(candidateEntryPoint, CancellationToken.None);
247
251
  string solutionPath = Path.GetDirectoryName(candidateEntryPoint) ?? string.Empty;
248
252
 
249
253
  foreach (SolutionProjectModel project in solution.SolutionProjects)
250
254
  {
251
255
  string projectPath = Path.Combine(solutionPath, project.FilePath);
256
+ logger.Info($" Expanded project: {projectPath}");
252
257
  filesToExpand.Push(projectPath);
253
258
  }
254
259
  }
255
260
  else if (extension == ".proj")
256
261
  {
262
+ logger.Info($" Expanding file: {candidateEntryPoint}:");
257
263
  var foundProjects = ExpandItemGroupFilesFromProject(candidateEntryPoint, "ProjectFile", "ProjectReference");
258
264
  foreach (var foundProject in foundProjects)
259
265
  {
266
+ logger.Info($" Expanded project: {foundProject}");
260
267
  filesToExpand.Push(foundProject);
261
268
  }
262
269
  }
@@ -337,7 +344,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
337
344
  try
338
345
  {
339
346
  // get all packages.config results first
340
- var expandedProjects = await ExpandEntryPointsIntoProjectsAsync(normalizedProjectPaths, _experimentsManager);
347
+ var expandedProjects = await ExpandEntryPointsIntoProjectsAsync(normalizedProjectPaths, _experimentsManager, _logger);
341
348
  foreach (var expandedProject in expandedProjects)
342
349
  {
343
350
  var packagesConfigResult = await PackagesConfigDiscovery.Discover(repoRootPath, workspacePath, expandedProject, _logger);
@@ -463,7 +470,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
463
470
  ReferencedProjectPaths = mergedReferencedProjects,
464
471
  ImportedFiles = mergedImportedFiles,
465
472
  AdditionalFiles = mergedAdditionalFiles,
466
- CentralPackageTransitivePinningEnabled = result1.CentralPackageTransitivePinningEnabled || result2.CentralPackageTransitivePinningEnabled,
473
+ PackageManagementKind = (PackageManagementKind)Math.Max((int)result1.PackageManagementKind, (int)result2.PackageManagementKind),
467
474
  };
468
475
  return mergedResult;
469
476
  }
@@ -0,0 +1,23 @@
1
+ namespace NuGetUpdater.Core.Discover;
2
+
3
+ public enum PackageManagementKind
4
+ {
5
+ /// <summary>
6
+ /// The default for SDK-style projects, e.g., <code>&lt;PackageReference Include="Some.Package" Version="1.0.0" /&gt;</code>
7
+ /// </summary>
8
+ Default,
9
+
10
+ /// <summary>
11
+ /// Separate <code>&lt;PackageReference&gt;</code> and <code>&lt;PackageVersion&gt;</code> elements. Set by the
12
+ /// user by adding the property <code>&lt;ManagePackageVersionsCentrally&gt;true&lt;/ManagePackageVersionsCentrally&gt;</code>
13
+ /// and commonly using the file <code>Directory.Packages.props</code>
14
+ /// </summary>
15
+ CentralPackageManagement,
16
+
17
+ /// <summary>
18
+ /// Similar to <see cref="CentralPackageManagement"/> but with the additional property
19
+ /// <code>&lt;CentralPackageTransitivePinningEnabled&gt;true&lt;/CentralPackageTransitivePinningEnabled&gt;</code> which applies
20
+ /// <code>&lt;PackageVersion&gt;</code> elements for all transitive dependencies as well.
21
+ /// </summary>
22
+ CentralPackageManagementWithTransitivePinning,
23
+ }
@@ -14,5 +14,5 @@ public record ProjectDiscoveryResult : IDiscoveryResultWithDependencies
14
14
  public ImmutableArray<string> ReferencedProjectPaths { get; init; } = [];
15
15
  public required ImmutableArray<string> ImportedFiles { get; init; }
16
16
  public required ImmutableArray<string> AdditionalFiles { get; init; }
17
- public bool CentralPackageTransitivePinningEnabled { get; init; } = false;
17
+ public PackageManagementKind PackageManagementKind { get; init; } = PackageManagementKind.Default;
18
18
  }
@@ -144,7 +144,7 @@ internal static class SdkProjectDiscovery
144
144
  try
145
145
  {
146
146
  // when using single restore, we can directly invoke the relevant targets...
147
- var args = new List<string>() { "msbuild", startingProjectPath };
147
+ var args = new List<string>() { startingProjectPath };
148
148
 
149
149
  // ...but determining what the relevant targets are can be complicated
150
150
 
@@ -195,7 +195,7 @@ internal static class SdkProjectDiscovery
195
195
  args.Add("/p:MSBuildTreatWarningsAsErrors=false");
196
196
  args.Add($"/bl:{binLogPath}");
197
197
 
198
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, startingProjectDirectory);
198
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync(args, startingProjectDirectory);
199
199
  if (exitCode != 0 && stdOut.Contains("error : Object reference not set to an instance of an object."))
200
200
  {
201
201
  // https://github.com/NuGet/Home/issues/11761#issuecomment-1105218996
@@ -203,7 +203,7 @@ internal static class SdkProjectDiscovery
203
203
  // but this argument can't always be added; it can cause problems in other instances, so we're taking the approach of not using it
204
204
  // unless we have to.
205
205
  args.Add("/RestoreProperty:__Unused__=__Unused__");
206
- (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, startingProjectDirectory);
206
+ (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync(args, startingProjectDirectory);
207
207
  }
208
208
 
209
209
  MSBuildHelper.ThrowOnError(stdOut);
@@ -621,7 +621,7 @@ internal static class SdkProjectDiscovery
621
621
  }
622
622
 
623
623
  var normalizedTfms = combinedTfms.OrderBy(t => t).ToImmutableArray();
624
- groupedDependencies[package.Key] = new Dependency(packageName, packageVersion, dependencyType, TargetFrameworks: normalizedTfms, IsDirect: isTopLevel, IsTransitive: !isTopLevel);
624
+ groupedDependencies[package.Key] = new Dependency(packageName, packageVersion, dependencyType, TargetFrameworks: normalizedTfms, IsTopLevel: isTopLevel);
625
625
  }
626
626
  }
627
627
 
@@ -643,13 +643,19 @@ internal static class SdkProjectDiscovery
643
643
  .Select(p => p.NormalizePathToUnix())
644
644
  .OrderBy(p => p)
645
645
  .ToImmutableArray();
646
- var useCpmTransitivePinning =
646
+ var projectLevelCpm =
647
647
  projectProperties.TryGetValue("ManagePackageVersionsCentrally", out var useCpmString) &&
648
648
  bool.TryParse(useCpmString, out var useCpm) &&
649
- useCpm &&
649
+ useCpm;
650
+ var projectLevelCpmWithPinning =
651
+ projectLevelCpm &&
650
652
  projectProperties.TryGetValue("CentralPackageTransitivePinningEnabled", out var useTransitivePinningString) &&
651
653
  bool.TryParse(useTransitivePinningString, out var useTransitivePinning) &&
652
654
  useTransitivePinning;
655
+ var packageManagementKind =
656
+ projectLevelCpmWithPinning ? PackageManagementKind.CentralPackageManagementWithTransitivePinning :
657
+ projectLevelCpm ? PackageManagementKind.CentralPackageManagement :
658
+ PackageManagementKind.Default;
653
659
 
654
660
  var projectDiscoveryResult = new ProjectDiscoveryResult()
655
661
  {
@@ -659,7 +665,7 @@ internal static class SdkProjectDiscovery
659
665
  ReferencedProjectPaths = referenced,
660
666
  ImportedFiles = imported,
661
667
  AdditionalFiles = additional,
662
- CentralPackageTransitivePinningEnabled = useCpmTransitivePinning,
668
+ PackageManagementKind = packageManagementKind,
663
669
  };
664
670
  projectDiscoveryResults.Add(projectDiscoveryResult);
665
671
  }
@@ -26,6 +26,5 @@ internal sealed class PackagesConfigBuildFile : XmlBuildFile
26
26
  .Select(p => new Dependency(
27
27
  p.GetAttributeValue("id", StringComparison.OrdinalIgnoreCase),
28
28
  p.GetAttributeValue("version", StringComparison.OrdinalIgnoreCase),
29
- DependencyType.PackagesConfig,
30
- IsDevDependency: (p.GetAttribute("developmentDependency", StringComparison.OrdinalIgnoreCase)?.Value ?? "false").Equals(true.ToString(), StringComparison.OrdinalIgnoreCase)));
29
+ DependencyType.PackagesConfig));
31
30
  }
@@ -108,12 +108,10 @@ internal sealed class ProjectBuildFile : XmlBuildFile
108
108
  return null;
109
109
  }
110
110
 
111
- var isVersionOverride = false;
112
111
  var version = element.GetAttributeOrSubElementValue("Version", StringComparison.OrdinalIgnoreCase);
113
112
  if (version is null)
114
113
  {
115
114
  version = element.GetAttributeOrSubElementValue("VersionOverride", StringComparison.OrdinalIgnoreCase);
116
- isVersionOverride = version is not null;
117
115
  }
118
116
 
119
117
  dependencies.AddRange(
@@ -122,8 +120,7 @@ internal sealed class ProjectBuildFile : XmlBuildFile
122
120
  Name: dep.Trim(),
123
121
  Version: string.IsNullOrEmpty(version) ? null : version,
124
122
  Type: GetDependencyType(element.Name),
125
- IsUpdate: isUpdate,
126
- IsOverride: isVersionOverride))
123
+ IsUpdate: isUpdate))
127
124
  );
128
125
 
129
126
 
@@ -5,5 +5,5 @@ namespace NuGetUpdater.Core;
5
5
 
6
6
  public interface IUpdaterWorker
7
7
  {
8
- Task<UpdateOperationResult> RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive);
8
+ Task<UpdateOperationResult> RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTopLevel);
9
9
  }
@@ -210,8 +210,8 @@ public sealed record Job
210
210
  return true;
211
211
  }
212
212
 
213
- // ...no specific update being performed, do it if it's not transitive
214
- return !dependency.IsTransitive;
213
+ // ...no specific update being performed, do it if it's a top-level dependency
214
+ return dependency.IsTopLevel;
215
215
  }
216
216
  }
217
217
 
@@ -111,7 +111,7 @@ internal class CreateSecurityUpdatePullRequestHandler : IUpdateHandler
111
111
 
112
112
  logger.Info($"Attempting update of {dependency.Name} from {dependency.Version} to {analysisResult.UpdatedVersion} for {projectPath}.");
113
113
  var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(projectPath);
114
- var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTransitive);
114
+ var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTopLevel);
115
115
  if (updaterResult.Error is not null)
116
116
  {
117
117
  logger.Error($"Error updating {dependency.Name} in {projectPath}: {updaterResult.Error.GetReport()}");
@@ -117,7 +117,7 @@ internal class GroupUpdateAllVersionsHandler : IUpdateHandler
117
117
  }
118
118
 
119
119
  var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(projectPath);
120
- var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTransitive);
120
+ var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTopLevel);
121
121
  if (updaterResult.Error is not null)
122
122
  {
123
123
  logger.Error($"Error updating {dependency.Name} in {projectPath}: {updaterResult.Error.GetReport()}");
@@ -236,7 +236,7 @@ internal class GroupUpdateAllVersionsHandler : IUpdateHandler
236
236
  }
237
237
 
238
238
  var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(projectPath);
239
- var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTransitive);
239
+ var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTopLevel);
240
240
  if (updaterResult.Error is not null)
241
241
  {
242
242
  await apiHandler.RecordUpdateJobError(updaterResult.Error, logger);
@@ -117,7 +117,7 @@ internal class RefreshGroupUpdatePullRequestHandler : IUpdateHandler
117
117
 
118
118
  logger.Info($"Attempting update of {dependency.Name} from {dependency.Version} to {analysisResult.UpdatedVersion} for {projectPath}.");
119
119
  var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(projectPath);
120
- var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTransitive);
120
+ var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTopLevel);
121
121
  if (updaterResult.Error is not null)
122
122
  {
123
123
  logger.Error($"Error updating {dependency.Name} in {projectPath}: {updaterResult.Error.GetReport()}");
@@ -112,7 +112,7 @@ internal class RefreshSecurityUpdatePullRequestHandler : IUpdateHandler
112
112
 
113
113
  logger.Info($"Attempting update of {dependency.Name} from {dependency.Version} to {analysisResult.UpdatedVersion} for {projectPath}.");
114
114
  var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(projectPath);
115
- var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTransitive);
115
+ var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTopLevel);
116
116
  if (updaterResult.Error is not null)
117
117
  {
118
118
  logger.Error($"Error updating {dependency.Name} in {projectPath}: {updaterResult.Error.GetReport()}");
@@ -102,7 +102,7 @@ internal class RefreshVersionUpdatePullRequestHandler : IUpdateHandler
102
102
 
103
103
  logger.Info($"Attempting update of {dependency.Name} from {dependency.Version} to {analysisResult.UpdatedVersion} for {projectPath}.");
104
104
  var projectDiscovery = discoveryResult.GetProjectDiscoveryFromPath(projectPath);
105
- var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTransitive);
105
+ var updaterResult = await updaterWorker.RunAsync(repoContentsPath.FullName, projectPath, dependency.Name, dependency.Version!, analysisResult.UpdatedVersion, dependency.IsTopLevel);
106
106
  if (updaterResult.Error is not null)
107
107
  {
108
108
  logger.Error($"Error updating {dependency.Name} in {projectPath}: {updaterResult.Error.GetReport()}");
@@ -167,7 +167,7 @@ public class FileWriterWorker
167
167
  }
168
168
 
169
169
  var initialTopLevelDependencies = initialProjectDiscovery.Dependencies
170
- .Where(d => !d.IsTransitive)
170
+ .Where(d => d.IsTopLevel)
171
171
  .ToImmutableArray();
172
172
  var newDependency = new Dependency(dependencyName, newDependencyVersion.ToString(), DependencyType.Unknown);
173
173
  var desiredDependencies = initialTopLevelDependencies.Any(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase))
@@ -243,7 +243,7 @@ public class FileWriterWorker
243
243
  }
244
244
 
245
245
  var rerunTopLevelDependencies = rerunProjectDiscovery.Dependencies
246
- .Where(d => !d.IsTransitive)
246
+ .Where(d => d.IsTopLevel)
247
247
  .ToImmutableArray();
248
248
  var rerunDesiredDependencies = rerunTopLevelDependencies.Any(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase))
249
249
  ? rerunTopLevelDependencies.Select(d => d.Name.Equals(dependencyName, StringComparison.OrdinalIgnoreCase) ? newDependency : d).ToImmutableArray()
@@ -408,8 +408,7 @@ public class FileWriterWorker
408
408
  .ToImmutableArray();
409
409
 
410
410
  // try update
411
- var addPackageReferenceElementForPinnedPackages = !projectDiscovery.CentralPackageTransitivePinningEnabled;
412
- var success = await fileWriter.UpdatePackageVersionsAsync(repoContentsPath, relativeFilePaths, projectDiscovery.Dependencies, requiredPackageVersions, addPackageReferenceElementForPinnedPackages);
411
+ var success = await fileWriter.UpdatePackageVersionsAsync(repoContentsPath, relativeFilePaths, projectDiscovery.Dependencies, requiredPackageVersions, projectDiscovery.PackageManagementKind);
413
412
  var updatedFiles = new List<string>();
414
413
  foreach (var (filePath, originalContents) in originalFileContents)
415
414
  {
@@ -1,5 +1,7 @@
1
1
  using System.Collections.Immutable;
2
2
 
3
+ using NuGetUpdater.Core.Discover;
4
+
3
5
  namespace NuGetUpdater.Core.Updater.FileWriters;
4
6
 
5
7
  public interface IFileWriter
@@ -9,6 +11,6 @@ public interface IFileWriter
9
11
  ImmutableArray<string> relativeFilePaths,
10
12
  ImmutableArray<Dependency> originalDependencies,
11
13
  ImmutableArray<Dependency> requiredPackageVersions,
12
- bool addPackageReferenceElementForPinnedPackages
14
+ PackageManagementKind packageManagementKind
13
15
  );
14
16
  }
@@ -5,6 +5,7 @@ using Microsoft.Language.Xml;
5
5
 
6
6
  using NuGet.Versioning;
7
7
 
8
+ using NuGetUpdater.Core.Discover;
8
9
  using NuGetUpdater.Core.Utilities;
9
10
 
10
11
  namespace NuGetUpdater.Core.Updater.FileWriters;
@@ -51,7 +52,7 @@ public class XmlFileWriter : IFileWriter
51
52
  ImmutableArray<string> relativeFilePaths,
52
53
  ImmutableArray<Dependency> originalDependencies,
53
54
  ImmutableArray<Dependency> requiredPackageVersions,
54
- bool addPackageReferenceElementForPinnedPackages
55
+ PackageManagementKind packageManagementKind
55
56
  )
56
57
  {
57
58
  if (relativeFilePaths.IsDefaultOrEmpty)
@@ -185,6 +186,12 @@ public class XmlFileWriter : IFileWriter
185
186
  .WithAttribute(IncludeAttributeName, requiredPackageVersion.Name);
186
187
 
187
188
  // ...add the `<PackageReference>` element if and where appropriate...
189
+ var addPackageReferenceElementForPinnedPackages =
190
+ packageManagementKind switch
191
+ {
192
+ PackageManagementKind.CentralPackageManagementWithTransitivePinning => false,
193
+ _ => true,
194
+ };
188
195
  if (addPackageReferenceElementForPinnedPackages)
189
196
  {
190
197
  addItemGroup();
@@ -118,7 +118,7 @@ internal static class PackageReferenceUpdater
118
118
  // generate project.assets.json
119
119
  var parsedTargetFramework = NuGetFramework.Parse(targetFramework);
120
120
  var tempProject = await MSBuildHelper.CreateTempProjectAsync(tempDir, repoRoot, projectPath, targetFramework, topLevelDependencies, logger, importDependencyTargets: true);
121
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["msbuild", tempProject, "/t:Restore,GenerateBuildDependencyFile"], tempDir.FullName);
121
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync([tempProject, "/t:Restore,GenerateBuildDependencyFile"], tempDir.FullName);
122
122
  var assetsJsonPath = Path.Join(tempDir.FullName, "obj", "project.assets.json");
123
123
  var assetsJsonContent = await File.ReadAllTextAsync(assetsJsonPath);
124
124
 
@@ -32,9 +32,9 @@ public class UpdaterWorker : IUpdaterWorker
32
32
  _logger = logger;
33
33
  }
34
34
 
35
- public async Task RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive, string? resultOutputPath = null)
35
+ public async Task RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTopLevel, string? resultOutputPath = null)
36
36
  {
37
- var result = await RunWithErrorHandlingAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
37
+ var result = await RunWithErrorHandlingAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTopLevel);
38
38
  if (resultOutputPath is { })
39
39
  {
40
40
  await WriteResultFile(result, resultOutputPath, _logger);
@@ -42,11 +42,11 @@ public class UpdaterWorker : IUpdaterWorker
42
42
  }
43
43
 
44
44
  // this is a convenient method for tests
45
- internal async Task<UpdateOperationResult> RunWithErrorHandlingAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive)
45
+ internal async Task<UpdateOperationResult> RunWithErrorHandlingAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTopLevel)
46
46
  {
47
47
  try
48
48
  {
49
- var result = await RunAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive);
49
+ var result = await RunAsync(repoRootPath, workspacePath, dependencyName, previousDependencyVersion, newDependencyVersion, isTopLevel);
50
50
  return result;
51
51
  }
52
52
  catch (Exception ex)
@@ -66,7 +66,7 @@ public class UpdaterWorker : IUpdaterWorker
66
66
  }
67
67
  }
68
68
 
69
- public async Task<UpdateOperationResult> RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTransitive)
69
+ public async Task<UpdateOperationResult> RunAsync(string repoRootPath, string workspacePath, string dependencyName, string previousDependencyVersion, string newDependencyVersion, bool isTopLevel)
70
70
  {
71
71
  MSBuildHelper.RegisterMSBuild(Environment.CurrentDirectory, repoRootPath, _logger);
72
72
 
@@ -197,10 +197,7 @@ internal static partial class MSBuildHelper
197
197
  DependencyType.Unknown,
198
198
  null,
199
199
  null,
200
- false,
201
- false,
202
- false,
203
- false,
200
+ true,
204
201
  false
205
202
  ))
206
203
  .ToList();
@@ -409,9 +406,8 @@ internal static partial class MSBuildHelper
409
406
  var (exitCode, stdOut, stdErr) = await HandleGlobalJsonAsync(projectDirectory, repoRoot, async () =>
410
407
  {
411
408
  var targetsHelperPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "TargetFrameworkReporter.targets");
412
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(
409
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync(
413
410
  [
414
- "msbuild",
415
411
  projectPath,
416
412
  "/t:ReportTargetFramework",
417
413
  $"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={targetsHelperPath}",
@@ -527,11 +523,10 @@ internal static partial class MSBuildHelper
527
523
  var projectDirectory = Path.GetDirectoryName(projectPath)!;
528
524
  var args = new[]
529
525
  {
530
- "msbuild",
531
526
  projectPath,
532
527
  "-targets"
533
528
  };
534
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, projectDirectory);
529
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync(args, projectDirectory);
535
530
  if (exitCode != 0)
536
531
  {
537
532
  logger.Warn($"Unable to determine targets for project [{projectPath}]:\nSTDOUT:\n{stdOut}\nSTDERR:\n{stdErr}\n");
@@ -558,12 +553,11 @@ internal static partial class MSBuildHelper
558
553
  var projectDirectory = Path.GetDirectoryName(projectPath)!;
559
554
  var args = new[]
560
555
  {
561
- "msbuild",
562
556
  projectPath,
563
557
  $"-getProperty:{propertyName}"
564
558
  };
565
559
 
566
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, projectDirectory);
560
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync(args, projectDirectory);
567
561
  if (exitCode != 0)
568
562
  {
569
563
  if (stdOut.Contains("error MSB1001: Unknown switch."))
@@ -583,12 +577,11 @@ internal static partial class MSBuildHelper
583
577
 
584
578
  // do it
585
579
  args = [
586
- "msbuild",
587
580
  projectPath,
588
581
  $"/p:CustomAfterMicrosoftCommonTargets={tempTargetsPath}",
589
582
  "/t:_Dependabot_GetProperty",
590
583
  ];
591
- (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, projectDirectory);
584
+ (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetMSBuildSafelyAsync(args, projectDirectory);
592
585
  if (exitCode == 0)
593
586
  {
594
587
  var match = Regex.Match(stdOut, "__PROPERTY_VALUE:(?<PropertyValue>[^$]*)$", RegexOptions.Multiline);
@@ -5,6 +5,21 @@ namespace NuGetUpdater.Core;
5
5
 
6
6
  public static class ProcessEx
7
7
  {
8
+ /// <summary>
9
+ /// Run `dotnet msbuild` with the given additional arguments. The argument `-noAutoResponse` is always appended to
10
+ /// suppress `Directory.Build.rsp` inclusion. This new set of arguments is then passed to the function
11
+ /// `RunDotnetWithoutMSBuildEnvironmentVariablesAsync` to prevent MSBuild from inheriting certain environment
12
+ /// variables.
13
+ /// </summary>
14
+ public static Task<(int ExitCode, string Output, string Error)> RunDotnetMSBuildSafelyAsync(
15
+ IEnumerable<string> arguments,
16
+ string workingDirectory,
17
+ IEnumerable<(string Name, string? Value)>? extraEnvironmentVariables = null
18
+ )
19
+ {
20
+ return RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["msbuild", .. arguments, "-noAutoResponse"], workingDirectory, extraEnvironmentVariables);
21
+ }
22
+
8
23
  /// <summary>
9
24
  /// Run the `dotnet` command with the given values. This will exclude all `MSBuild*` environment variables from the execution.
10
25
  /// </summary>