dependabot-nuget 0.290.0 → 0.291.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 (27) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +1 -1
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +3 -0
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +2 -0
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +44 -5
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +2 -2
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/ProjectDiscoveryResult.cs +2 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +19 -11
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ErrorType.cs +1 -0
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +3 -2
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +43 -18
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +1 -1
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +40 -14
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +2 -2
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +45 -7
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +41 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +1 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +1 -1
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +2 -1
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +246 -60
  22. data/lib/dependabot/nuget/file_fetcher.rb +1 -0
  23. data/lib/dependabot/nuget/file_parser.rb +90 -0
  24. data/lib/dependabot/nuget/language.rb +82 -0
  25. data/lib/dependabot/nuget/native_helpers.rb +23 -0
  26. data/lib/dependabot/nuget/package_manager.rb +51 -0
  27. metadata +7 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3ca35ae6f3d02ce8507984f89e7c929eb75cec515b39af94db530d6600f0caa
4
- data.tar.gz: cbd548418a3e25163af5d8543109b520b6c9bd9e2bf5a5869421f8fe838128d1
3
+ metadata.gz: c3d38c911d42c1014432f79bd79e560129291135bb6f5039ff09e2e9229db253
4
+ data.tar.gz: a7417d90f096fb3de7a6a142b2b42c7aac61f299ba57d49ddbe1a1359d4dba3f
5
5
  SHA512:
6
- metadata.gz: 9395fb4eea720fbcba3b0cef278344b41a9ace7315ce62f5cb193bb05af2aa23553130dab3112cb900d39ad12cadd321e64291d72e4e21e4bbee2f2b7610626a
7
- data.tar.gz: d74843dc18cab2fd6a58a31f1df2a4172cb308a3a2e452db7056727666e9f153b611046c25bd78f7c0679abe8be4eb57462886d87c8010ba21ac0a2ee316120e
6
+ metadata.gz: b3cb757cc8d4a2ba7c0e3bc1f22e6d53e06e6de5bae39e460b86f9c697aaef7e95c0f62bf6583a63376c5367a6ec6e820389546f78dc3d7a190a331a1db720c6
7
+ data.tar.gz: f51885f03309f8e8d0f7359fffc41305c98e26f00a3e20af3ac67681f20c7e7d3f018e8093f89fe1591ac22a8f22453b49bb427d5a377aedb0a23f1cdfd1bffc
@@ -382,7 +382,7 @@ public partial class EntryPointTests
382
382
  workingDirectory = Path.Join(workingDirectory, workingDirectoryPath);
383
383
  }
384
384
 
385
- var (exitCode, output, error) = await ProcessEx.RunAsync("dotnet", executableArgs, workingDirectory: workingDirectory);
385
+ var (exitCode, output, error) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(executableArgs, workingDirectory, new ExperimentsManager() { InstallDotnetSdks = false });
386
386
  Assert.True(exitCode == 0, $"Error running update on unsupported SDK.\nSTDOUT:\n{output}\nSTDERR:\n{error}");
387
387
 
388
388
  // verify project update
@@ -142,6 +142,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
142
142
  dependenciesToUpdate,
143
143
  updatedVersion,
144
144
  nugetContext,
145
+ _experimentsManager,
145
146
  _logger,
146
147
  CancellationToken.None);
147
148
  }
@@ -393,6 +394,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
393
394
  ImmutableHashSet<string> packageIds,
394
395
  NuGetVersion updatedVersion,
395
396
  NuGetContext nugetContext,
397
+ ExperimentsManager experimentsManager,
396
398
  ILogger logger,
397
399
  CancellationToken cancellationToken)
398
400
  {
@@ -432,6 +434,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
432
434
  packageIds,
433
435
  updatedVersion,
434
436
  nugetContext,
437
+ experimentsManager,
435
438
  logger,
436
439
  cancellationToken);
437
440
 
@@ -14,6 +14,7 @@ internal static class DependencyFinder
14
14
  ImmutableHashSet<string> packageIds,
15
15
  NuGetVersion version,
16
16
  NuGetContext nugetContext,
17
+ ExperimentsManager experimentsManager,
17
18
  ILogger logger,
18
19
  CancellationToken cancellationToken)
19
20
  {
@@ -30,6 +31,7 @@ internal static class DependencyFinder
30
31
  projectPath,
31
32
  framework.ToString(),
32
33
  packages,
34
+ experimentsManager,
33
35
  logger);
34
36
  var updatedDependencies = new List<Dependency>();
35
37
  foreach (var dependency in dependencies)
@@ -6,6 +6,7 @@ using System.Text.Json.Serialization;
6
6
  using Microsoft.Build.Construction;
7
7
  using Microsoft.Build.Definition;
8
8
  using Microsoft.Build.Evaluation;
9
+ using Microsoft.Build.Exceptions;
9
10
 
10
11
  using NuGetUpdater.Core.Analyze;
11
12
  using NuGetUpdater.Core.Utilities;
@@ -93,13 +94,31 @@ public partial class DiscoveryWorker : IDiscoveryWorker
93
94
  }
94
95
 
95
96
  // this next line should throw or something
96
- projectResults = await RunForDirectoryAsnyc(repoRootPath, workspacePath);
97
+ projectResults = await RunForDirectoryAsync(repoRootPath, workspacePath);
97
98
  }
98
99
  else
99
100
  {
100
101
  _logger.Info($"Workspace path [{workspacePath}] does not exist.");
101
102
  }
102
103
 
104
+ //if any projectResults are not successful, return a failed result
105
+ if (projectResults.Any(p => p.IsSuccess == false))
106
+ {
107
+ var failedProjectResult = projectResults.Where(p => p.IsSuccess == false).First();
108
+ var failedDiscoveryResult = new WorkspaceDiscoveryResult
109
+ {
110
+ Path = initialWorkspacePath,
111
+ DotNetToolsJson = null,
112
+ GlobalJson = null,
113
+ Projects = projectResults.Where(p => p.IsSuccess).OrderBy(p => p.FilePath).ToImmutableArray(),
114
+ ErrorType = failedProjectResult.ErrorType,
115
+ ErrorDetails = failedProjectResult.FilePath,
116
+ IsSuccess = false,
117
+ };
118
+
119
+ return failedDiscoveryResult;
120
+ }
121
+
103
122
  result = new WorkspaceDiscoveryResult
104
123
  {
105
124
  Path = initialWorkspacePath,
@@ -137,14 +156,34 @@ public partial class DiscoveryWorker : IDiscoveryWorker
137
156
 
138
157
  _logger.Info($" Restoring MSBuild SDKs: {string.Join(", ", keys)}");
139
158
 
140
- return await NuGetHelper.DownloadNuGetPackagesAsync(repoRootPath, workspacePath, msbuildSdks, logger);
159
+ return await NuGetHelper.DownloadNuGetPackagesAsync(repoRootPath, workspacePath, msbuildSdks, _experimentsManager, logger);
141
160
  }
142
161
 
143
- private async Task<ImmutableArray<ProjectDiscoveryResult>> RunForDirectoryAsnyc(string repoRootPath, string workspacePath)
162
+ private async Task<ImmutableArray<ProjectDiscoveryResult>> RunForDirectoryAsync(string repoRootPath, string workspacePath)
144
163
  {
145
164
  _logger.Info($" Discovering projects beneath [{Path.GetRelativePath(repoRootPath, workspacePath)}].");
146
165
  var entryPoints = FindEntryPoints(workspacePath);
147
- var projects = ExpandEntryPointsIntoProjects(entryPoints);
166
+ ImmutableArray<string> projects;
167
+ try
168
+ {
169
+ projects = ExpandEntryPointsIntoProjects(entryPoints);
170
+ }
171
+ catch (InvalidProjectFileException e)
172
+ {
173
+ var invalidProjectFile = Path.GetRelativePath(workspacePath, e.ProjectFile).NormalizePathToUnix();
174
+
175
+ _logger.Info("Error encountered during discovery: " + e.Message);
176
+ return [new ProjectDiscoveryResult
177
+ {
178
+ FilePath = invalidProjectFile,
179
+ Dependencies = ImmutableArray<Dependency>.Empty,
180
+ ImportedFiles = ImmutableArray<string>.Empty,
181
+ AdditionalFiles = ImmutableArray<string>.Empty,
182
+ IsSuccess = false,
183
+ ErrorType = ErrorType.DependencyFileNotParseable,
184
+ ErrorDetails = "Failed to parse project file found at " + invalidProjectFile,
185
+ }];
186
+ }
148
187
  if (projects.IsEmpty)
149
188
  {
150
189
  _logger.Info(" No project files found.");
@@ -286,7 +325,7 @@ public partial class DiscoveryWorker : IDiscoveryWorker
286
325
  _processedProjectPaths.Add(actualProjectPath);
287
326
 
288
327
  var relativeProjectPath = Path.GetRelativePath(workspacePath, actualProjectPath).NormalizePathToUnix();
289
- var packagesConfigResult = await PackagesConfigDiscovery.Discover(repoRootPath, workspacePath, actualProjectPath, _logger);
328
+ var packagesConfigResult = await PackagesConfigDiscovery.Discover(repoRootPath, workspacePath, actualProjectPath, _experimentsManager, _logger);
290
329
  var projectResults = await SdkProjectDiscovery.DiscoverAsync(repoRootPath, workspacePath, actualProjectPath, _experimentsManager, _logger);
291
330
 
292
331
  // Determine if there were unrestored MSBuildSdks
@@ -6,7 +6,7 @@ namespace NuGetUpdater.Core.Discover;
6
6
 
7
7
  internal static class PackagesConfigDiscovery
8
8
  {
9
- public static async Task<PackagesConfigDiscoveryResult?> Discover(string repoRootPath, string workspacePath, string projectPath, ILogger logger)
9
+ public static async Task<PackagesConfigDiscoveryResult?> Discover(string repoRootPath, string workspacePath, string projectPath, ExperimentsManager experimentsManager, ILogger logger)
10
10
  {
11
11
  var projectDirectory = Path.GetDirectoryName(projectPath)!;
12
12
  var additionalFiles = ProjectHelper.GetAllAdditionalFilesFromProject(projectPath, ProjectHelper.PathFormat.Full);
@@ -27,7 +27,7 @@ internal static class PackagesConfigDiscovery
27
27
  .ToImmutableArray();
28
28
 
29
29
  // generate `$(TargetFramework)` via MSBuild
30
- var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, projectPath, logger);
30
+ var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, projectPath, experimentsManager, logger);
31
31
 
32
32
  var additionalFilesRelative = additionalFiles.Select(p => Path.GetRelativePath(projectDirectory, p).NormalizePathToUnix()).ToImmutableArray();
33
33
  return new()
@@ -8,6 +8,8 @@ public record ProjectDiscoveryResult : IDiscoveryResultWithDependencies
8
8
  public required string FilePath { get; init; }
9
9
  public required ImmutableArray<Dependency> Dependencies { get; init; }
10
10
  public bool IsSuccess { get; init; } = true;
11
+ public string? ErrorDetails { get; init; }
12
+ public ErrorType? ErrorType { get; init; }
11
13
  public ImmutableArray<Property> Properties { get; init; } = [];
12
14
  public ImmutableArray<string> TargetFrameworks { get; init; } = [];
13
15
  public ImmutableArray<string> ReferencedProjectPaths { get; init; } = [];
@@ -48,15 +48,15 @@ internal static class SdkProjectDiscovery
48
48
  {
49
49
  if (experimentsManager.UseDirectDiscovery)
50
50
  {
51
- return await DiscoverWithBinLogAsync(repoRootPath, workspacePath, startingProjectPath, logger);
51
+ return await DiscoverWithBinLogAsync(repoRootPath, workspacePath, startingProjectPath, experimentsManager, logger);
52
52
  }
53
53
  else
54
54
  {
55
- return await DiscoverWithTempProjectAsync(repoRootPath, workspacePath, startingProjectPath, logger);
55
+ return await DiscoverWithTempProjectAsync(repoRootPath, workspacePath, startingProjectPath, experimentsManager, logger);
56
56
  }
57
57
  }
58
58
 
59
- public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithBinLogAsync(string repoRootPath, string workspacePath, string startingProjectPath, ILogger logger)
59
+ public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithBinLogAsync(string repoRootPath, string workspacePath, string startingProjectPath, ExperimentsManager experimentsManager, ILogger logger)
60
60
  {
61
61
  // N.b., there are many paths used in this function. The MSBuild binary log always reports fully qualified paths, so that's what will be used
62
62
  // throughout until the very end when the appropriate kind of relative path is returned.
@@ -84,7 +84,7 @@ internal static class SdkProjectDiscovery
84
84
  Dictionary<string, HashSet<string>> additionalFiles = new(PathComparer.Instance);
85
85
  // projectPath, additionalFiles
86
86
 
87
- var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, startingProjectPath, logger);
87
+ var tfms = await MSBuildHelper.GetTargetFrameworkValuesFromProject(repoRootPath, startingProjectPath, experimentsManager, logger);
88
88
  foreach (var tfm in tfms)
89
89
  {
90
90
  // create a binlog
@@ -92,7 +92,7 @@ internal static class SdkProjectDiscovery
92
92
  try
93
93
  {
94
94
  // TODO: once the updater image has all relevant SDKs installed, we won't have to sideline global.json anymore
95
- var (exitCode, stdOut, stdErr) = await MSBuildHelper.SidelineGlobalJsonAsync(startingProjectDirectory, repoRootPath, async () =>
95
+ var (exitCode, stdOut, stdErr) = await MSBuildHelper.HandleGlobalJsonAsync(startingProjectDirectory, repoRootPath, experimentsManager, async () =>
96
96
  {
97
97
  // the built-in target `GenerateBuildDependencyFile` forces resolution of all NuGet packages, but doesn't invoke a full build
98
98
  var dependencyDiscoveryTargetsPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "DependencyDiscovery.targets");
@@ -102,10 +102,11 @@ internal static class SdkProjectDiscovery
102
102
  startingProjectPath,
103
103
  "/t:_DiscoverDependencies",
104
104
  $"/p:TargetFramework={tfm}",
105
- $"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={dependencyDiscoveryTargetsPath};CustomAfterMicrosoftCommonTargets={dependencyDiscoveryTargetsPath}",
105
+ $"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={dependencyDiscoveryTargetsPath}",
106
+ $"/p:CustomAfterMicrosoftCommonTargets={dependencyDiscoveryTargetsPath}",
106
107
  $"/bl:{binLogPath}"
107
108
  };
108
- var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", args, workingDirectory: startingProjectDirectory);
109
+ var (exitCode, stdOut, stdErr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(args, startingProjectDirectory, experimentsManager);
109
110
  return (exitCode, stdOut, stdErr);
110
111
  }, logger, retainMSBuildSdks: true);
111
112
  MSBuildHelper.ThrowOnUnauthenticatedFeed(stdOut);
@@ -411,7 +412,7 @@ internal static class SdkProjectDiscovery
411
412
  return property.Value;
412
413
  }
413
414
 
414
- public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithTempProjectAsync(string repoRootPath, string workspacePath, string projectPath, ILogger logger)
415
+ public static async Task<ImmutableArray<ProjectDiscoveryResult>> DiscoverWithTempProjectAsync(string repoRootPath, string workspacePath, string projectPath, ExperimentsManager experimentsManager, ILogger logger)
415
416
  {
416
417
  // Determine which targets and props files contribute to the build.
417
418
  var (buildFiles, projectTargetFrameworks) = await MSBuildHelper.LoadBuildFilesAndTargetFrameworksAsync(repoRootPath, projectPath);
@@ -476,7 +477,7 @@ internal static class SdkProjectDiscovery
476
477
  dependencies = dependencies
477
478
  .Select(d => d with { TargetFrameworks = tfms })
478
479
  .ToImmutableArray();
479
- var transitiveDependencies = await GetTransitiveDependencies(repoRootPath, projectPath, tfms, dependencies, logger);
480
+ var transitiveDependencies = await GetTransitiveDependencies(repoRootPath, projectPath, tfms, dependencies, experimentsManager, logger);
480
481
  ImmutableArray<Dependency> allDependencies = dependencies.Concat(transitiveDependencies).Concat(sdkDependencies)
481
482
  .OrderBy(d => d.Name)
482
483
  .ToImmutableArray();
@@ -514,12 +515,19 @@ internal static class SdkProjectDiscovery
514
515
  return results.ToImmutable();
515
516
  }
516
517
 
517
- private static async Task<ImmutableArray<Dependency>> GetTransitiveDependencies(string repoRootPath, string projectPath, ImmutableArray<string> tfms, ImmutableArray<Dependency> directDependencies, ILogger logger)
518
+ private static async Task<ImmutableArray<Dependency>> GetTransitiveDependencies(
519
+ string repoRootPath,
520
+ string projectPath,
521
+ ImmutableArray<string> tfms,
522
+ ImmutableArray<Dependency> directDependencies,
523
+ ExperimentsManager experimentsManager,
524
+ ILogger logger
525
+ )
518
526
  {
519
527
  Dictionary<string, Dependency> transitiveDependencies = new(StringComparer.OrdinalIgnoreCase);
520
528
  foreach (var tfm in tfms)
521
529
  {
522
- var tfmDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, directDependencies, logger);
530
+ var tfmDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, directDependencies, experimentsManager, logger);
523
531
  foreach (var dependency in tfmDependencies.Where(d => d.IsTransitive))
524
532
  {
525
533
  if (!transitiveDependencies.TryGetValue(dependency.Name, out var existingDependency))
@@ -6,5 +6,6 @@ public enum ErrorType
6
6
  AuthenticationFailure,
7
7
  MissingFile,
8
8
  UpdateNotPossible,
9
+ DependencyFileNotParseable,
9
10
  Unknown,
10
11
  }
@@ -6,6 +6,7 @@ namespace NuGetUpdater.Core;
6
6
 
7
7
  public record ExperimentsManager
8
8
  {
9
+ public bool InstallDotnetSdks { get; init; } = false;
9
10
  public bool UseLegacyDependencySolver { get; init; } = false;
10
11
  public bool UseDirectDiscovery { get; init; } = false;
11
12
 
@@ -13,6 +14,7 @@ public record ExperimentsManager
13
14
  {
14
15
  return new()
15
16
  {
17
+ ["nuget_install_dotnet_sdks"] = InstallDotnetSdks,
16
18
  ["nuget_legacy_dependency_solver"] = UseLegacyDependencySolver,
17
19
  ["nuget_use_direct_discovery"] = UseDirectDiscovery,
18
20
  };
@@ -22,6 +24,7 @@ public record ExperimentsManager
22
24
  {
23
25
  return new ExperimentsManager()
24
26
  {
27
+ InstallDotnetSdks = IsEnabled(experiments, "nuget_install_dotnet_sdks"),
25
28
  UseLegacyDependencySolver = IsEnabled(experiments, "nuget_legacy_dependency_solver"),
26
29
  UseDirectDiscovery = IsEnabled(experiments, "nuget_use_direct_discovery"),
27
30
  };
@@ -5,12 +5,13 @@ internal static class LockFileUpdater
5
5
  public static async Task UpdateLockFileAsync(
6
6
  string repoRootPath,
7
7
  string projectPath,
8
+ ExperimentsManager experimentsManager,
8
9
  ILogger logger)
9
10
  {
10
11
  var projectDirectory = Path.GetDirectoryName(projectPath)!;
11
- await MSBuildHelper.SidelineGlobalJsonAsync(projectDirectory, repoRootPath, async () =>
12
+ await MSBuildHelper.HandleGlobalJsonAsync(projectDirectory, repoRootPath, experimentsManager, async () =>
12
13
  {
13
- var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", ["restore", "--force-evaluate", projectPath], workingDirectory: projectDirectory);
14
+ var (exitCode, stdout, stderr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(["restore", "--force-evaluate", projectPath], projectDirectory, experimentsManager);
14
15
  if (exitCode != 0)
15
16
  {
16
17
  logger.Error($" Lock file update failed.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}");
@@ -37,17 +37,17 @@ internal static class PackageReferenceUpdater
37
37
  // Get the set of all top-level dependencies in the current project
38
38
  var topLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles).ToArray();
39
39
 
40
- if (!await DoesDependencyRequireUpdateAsync(repoRootPath, projectPath, tfms, topLevelDependencies, dependencyName, newDependencyVersion, logger))
40
+ if (!await DoesDependencyRequireUpdateAsync(repoRootPath, projectPath, tfms, topLevelDependencies, dependencyName, newDependencyVersion, experimentsManager, logger))
41
41
  {
42
42
  return;
43
43
  }
44
44
 
45
- var peerDependencies = await GetUpdatedPeerDependenciesAsync(repoRootPath, projectPath, tfms, dependencyName, newDependencyVersion, logger);
45
+ var peerDependencies = await GetUpdatedPeerDependenciesAsync(repoRootPath, projectPath, tfms, dependencyName, newDependencyVersion, experimentsManager, logger);
46
46
  if (experimentsManager.UseLegacyDependencySolver)
47
47
  {
48
48
  if (isTransitive)
49
49
  {
50
- await UpdateTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, buildFiles, logger);
50
+ await UpdateTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, buildFiles, experimentsManager, logger);
51
51
  }
52
52
  else
53
53
  {
@@ -56,7 +56,7 @@ internal static class PackageReferenceUpdater
56
56
  return;
57
57
  }
58
58
 
59
- await UpdateTopLevelDepdendency(repoRootPath, buildFiles, tfms, dependencyName, previousDependencyVersion, newDependencyVersion, peerDependencies, logger);
59
+ await UpdateTopLevelDepdendency(repoRootPath, buildFiles, tfms, dependencyName, previousDependencyVersion, newDependencyVersion, peerDependencies, experimentsManager, logger);
60
60
  }
61
61
  }
62
62
  else
@@ -66,10 +66,10 @@ internal static class PackageReferenceUpdater
66
66
  return;
67
67
  }
68
68
 
69
- await UpdateDependencyWithConflictResolution(repoRootPath, buildFiles, tfms, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive, peerDependencies, logger);
69
+ await UpdateDependencyWithConflictResolution(repoRootPath, buildFiles, tfms, projectPath, dependencyName, previousDependencyVersion, newDependencyVersion, isTransitive, peerDependencies, experimentsManager, logger);
70
70
  }
71
71
 
72
- if (!await AreDependenciesCoherentAsync(repoRootPath, projectPath, dependencyName, logger, buildFiles, tfms))
72
+ if (!await AreDependenciesCoherentAsync(repoRootPath, projectPath, dependencyName, buildFiles, tfms, experimentsManager, logger))
73
73
  {
74
74
  return;
75
75
  }
@@ -87,6 +87,7 @@ internal static class PackageReferenceUpdater
87
87
  string newDependencyVersion,
88
88
  bool isTransitive,
89
89
  IDictionary<string, string> peerDependencies,
90
+ ExperimentsManager experimentsManager,
90
91
  ILogger logger)
91
92
  {
92
93
  var topLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles).ToArray();
@@ -107,7 +108,7 @@ internal static class PackageReferenceUpdater
107
108
  {
108
109
  foreach (var tfm in targetFrameworks)
109
110
  {
110
- var resolvedDependencies = await MSBuildHelper.ResolveDependencyConflicts(repoRootPath, projectFile.Path, tfm, topLevelDependencies, dependenciesToUpdate, logger);
111
+ var resolvedDependencies = await MSBuildHelper.ResolveDependencyConflicts(repoRootPath, projectFile.Path, tfm, topLevelDependencies, dependenciesToUpdate, experimentsManager, logger);
111
112
  if (resolvedDependencies is null)
112
113
  {
113
114
  logger.Warn($" Unable to resolve dependency conflicts for {projectFile.Path}.");
@@ -118,7 +119,7 @@ internal static class PackageReferenceUpdater
118
119
  if (isTransitive && !isDependencyTopLevel && isDependencyInResolutionSet)
119
120
  {
120
121
  // a transitive dependency had to be pinned; add it here
121
- await UpdateTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, buildFiles, logger);
122
+ await UpdateTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, buildFiles, experimentsManager, logger);
122
123
  }
123
124
 
124
125
  // update all resolved dependencies that aren't the initial dependency
@@ -143,6 +144,7 @@ internal static class PackageReferenceUpdater
143
144
  Dependency[] topLevelDependencies,
144
145
  string dependencyName,
145
146
  string newDependencyVersion,
147
+ ExperimentsManager experimentsManager,
146
148
  ILogger logger)
147
149
  {
148
150
  var newDependencyNuGetVersion = NuGetVersion.Parse(newDependencyVersion);
@@ -157,6 +159,7 @@ internal static class PackageReferenceUpdater
157
159
  projectPath,
158
160
  tfm,
159
161
  topLevelDependencies,
162
+ experimentsManager,
160
163
  logger);
161
164
  foreach (var dependency in dependencies)
162
165
  {
@@ -203,7 +206,15 @@ internal static class PackageReferenceUpdater
203
206
  return true;
204
207
  }
205
208
 
206
- private static async Task UpdateTransitiveDependencyAsync(string repoRootPath, string projectPath, string dependencyName, string newDependencyVersion, ImmutableArray<ProjectBuildFile> buildFiles, ILogger logger)
209
+ private static async Task UpdateTransitiveDependencyAsync(
210
+ string repoRootPath,
211
+ string projectPath,
212
+ string dependencyName,
213
+ string newDependencyVersion,
214
+ ImmutableArray<ProjectBuildFile> buildFiles,
215
+ ExperimentsManager experimentsManager,
216
+ ILogger logger
217
+ )
207
218
  {
208
219
  var directoryPackagesWithPinning = buildFiles.OfType<ProjectBuildFile>()
209
220
  .FirstOrDefault(bf => IsCpmTransitivePinningEnabled(bf));
@@ -213,7 +224,7 @@ internal static class PackageReferenceUpdater
213
224
  }
214
225
  else
215
226
  {
216
- await AddTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, logger);
227
+ await AddTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, experimentsManager, logger);
217
228
  }
218
229
  }
219
230
 
@@ -302,15 +313,19 @@ internal static class PackageReferenceUpdater
302
313
  directoryPackages.Update(updatedXml);
303
314
  }
304
315
 
305
- private static async Task AddTransitiveDependencyAsync(string repoRootPath, string projectPath, string dependencyName, string newDependencyVersion, ILogger logger)
316
+ private static async Task AddTransitiveDependencyAsync(string repoRootPath, string projectPath, string dependencyName, string newDependencyVersion, ExperimentsManager experimentsManager, ILogger logger)
306
317
  {
307
318
  var projectDirectory = Path.GetDirectoryName(projectPath)!;
308
- await MSBuildHelper.SidelineGlobalJsonAsync(projectDirectory, repoRootPath, async () =>
319
+ await MSBuildHelper.HandleGlobalJsonAsync(projectDirectory, repoRootPath, experimentsManager, async () =>
309
320
  {
310
321
  logger.Info($" Adding [{dependencyName}/{newDependencyVersion}] as a top-level package reference.");
311
322
 
312
323
  // see https://learn.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli
313
- var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", ["add", projectPath, "package", dependencyName, "--version", newDependencyVersion], workingDirectory: projectDirectory);
324
+ var (exitCode, stdout, stderr) = await ProcessEx.RunDotnetWithoutMSBuildEnvironmentVariablesAsync(
325
+ ["add", projectPath, "package", dependencyName, "--version", newDependencyVersion],
326
+ projectDirectory,
327
+ experimentsManager
328
+ );
314
329
  MSBuildHelper.ThrowOnUnauthenticatedFeed(stdout);
315
330
  if (exitCode != 0)
316
331
  {
@@ -331,13 +346,14 @@ internal static class PackageReferenceUpdater
331
346
  string[] tfms,
332
347
  string dependencyName,
333
348
  string newDependencyVersion,
349
+ ExperimentsManager experimentsManager,
334
350
  ILogger logger)
335
351
  {
336
352
  var newDependency = new[] { new Dependency(dependencyName, newDependencyVersion, DependencyType.Unknown) };
337
353
  var tfmsAndDependencies = new Dictionary<string, Dependency[]>();
338
354
  foreach (var tfm in tfms)
339
355
  {
340
- var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, newDependency, logger);
356
+ var dependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, newDependency, experimentsManager, logger);
341
357
  tfmsAndDependencies[tfm] = dependencies;
342
358
  }
343
359
 
@@ -386,6 +402,7 @@ internal static class PackageReferenceUpdater
386
402
  string previousDependencyVersion,
387
403
  string newDependencyVersion,
388
404
  IDictionary<string, string> peerDependencies,
405
+ ExperimentsManager experimentsManager,
389
406
  ILogger logger)
390
407
  {
391
408
  // update dependencies...
@@ -407,7 +424,7 @@ internal static class PackageReferenceUpdater
407
424
  {
408
425
  foreach (string tfm in targetFrameworks)
409
426
  {
410
- var resolvedDependencies = await MSBuildHelper.ResolveDependencyConflictsWithBruteForce(repoRootPath, projectFile.Path, tfm, updatedTopLevelDependencies, logger);
427
+ var resolvedDependencies = await MSBuildHelper.ResolveDependencyConflictsWithBruteForce(repoRootPath, projectFile.Path, tfm, updatedTopLevelDependencies, experimentsManager, logger);
411
428
  if (resolvedDependencies is null)
412
429
  {
413
430
  logger.Info($" Unable to resolve dependency conflicts for {projectFile.Path}.");
@@ -697,13 +714,21 @@ internal static class PackageReferenceUpdater
697
714
  ?? e.GetAttributeOrSubElementValue("VersionOverride", StringComparison.OrdinalIgnoreCase)) is not null;
698
715
  });
699
716
 
700
- private static async Task<bool> AreDependenciesCoherentAsync(string repoRootPath, string projectPath, string dependencyName, ILogger logger, ImmutableArray<ProjectBuildFile> buildFiles, string[] tfms)
717
+ private static async Task<bool> AreDependenciesCoherentAsync(
718
+ string repoRootPath,
719
+ string projectPath,
720
+ string dependencyName,
721
+ ImmutableArray<ProjectBuildFile> buildFiles,
722
+ string[] tfms,
723
+ ExperimentsManager experimentsManager,
724
+ ILogger logger
725
+ )
701
726
  {
702
727
  var updatedTopLevelDependencies = MSBuildHelper.GetTopLevelPackageDependencyInfos(buildFiles).ToArray();
703
728
  foreach (var tfm in tfms)
704
729
  {
705
- var updatedPackages = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, updatedTopLevelDependencies, logger);
706
- var dependenciesAreCoherent = await MSBuildHelper.DependenciesAreCoherentAsync(repoRootPath, projectPath, tfm, updatedPackages, logger);
730
+ var updatedPackages = await MSBuildHelper.GetAllPackageDependenciesAsync(repoRootPath, projectPath, tfm, updatedTopLevelDependencies, experimentsManager, logger);
731
+ var dependenciesAreCoherent = await MSBuildHelper.DependenciesAreCoherentAsync(repoRootPath, projectPath, tfm, updatedPackages, experimentsManager, logger);
707
732
  if (!dependenciesAreCoherent)
708
733
  {
709
734
  logger.Warn($" Package [{dependencyName}] could not be updated in [{projectPath}] because it would cause a dependency conflict.");
@@ -232,7 +232,7 @@ public class UpdaterWorker : IUpdaterWorker
232
232
  var packagesLockFullPath = additionalFiles.Where(p => Path.GetFileName(p).Equals(ProjectHelper.PackagesLockJsonFileName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
233
233
  if (packagesLockFullPath is not null)
234
234
  {
235
- await LockFileUpdater.UpdateLockFileAsync(repoRootPath, projectPath, _logger);
235
+ await LockFileUpdater.UpdateLockFileAsync(repoRootPath, projectPath, _experimentsManager, _logger);
236
236
  }
237
237
  }
238
238
  }