dependabot-nuget 0.267.0 → 0.268.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19fd9d2635d3d1f5737870ebe8bcd155fb5e90557c7eec2b6832233bb0573b29
4
- data.tar.gz: d1bd4ff99ae3fd8319a796cf04ba3a859c084cd465013cd5a1c8b106969a8183
3
+ metadata.gz: 3dbd572d869f156e22c4020848387b9b54611ad236c08be6b3ca4cce3e5e7ebc
4
+ data.tar.gz: f9578fc6352ff07629255fdd1bb2032cda9b0109090507fc39eed9e1b369a68d
5
5
  SHA512:
6
- metadata.gz: 4b1c5c0ed9ca379e3c209c21dbc047e7364a9c3f7eda956ebd11a6f0f44b5a3a3e5a7fe9493ccafe82ac98bad132ab2323a56817c2f234c135814282cd229c30
7
- data.tar.gz: c0f297752cb28d6c32df1261ab10199a5f39e17af23f3c3e46ed76aafd59785e79cd43c81e1a164b8fe92b9f7763f50e3d2c4a8d34c9bb59a4976d0e6eb44be4
6
+ metadata.gz: 8c91cd7ef8d66d4aa48de704d70d41087ad8b6f867946f1cf59038a22f22d06febb5227e637d339fe93ec8fa5c086f8d410e16d00c3f70a4c8c348993de01c28
7
+ data.tar.gz: 161deea8269b8c3fe00013ef83da37e96ddedf9518e9463bdf952034a03ef00be0fac713495b4706ccbcb3d08d072aec700b7921dcbf01506e8e4d432c4fc634
@@ -31,7 +31,7 @@ internal static class SdkPackageUpdater
31
31
 
32
32
  if (isTransitive)
33
33
  {
34
- await UpdateTransitiveDependencyAsnyc(projectPath, dependencyName, newDependencyVersion, buildFiles, logger);
34
+ await UpdateTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, buildFiles, logger);
35
35
  }
36
36
  else
37
37
  {
@@ -123,7 +123,7 @@ internal static class SdkPackageUpdater
123
123
  return true;
124
124
  }
125
125
 
126
- private static async Task UpdateTransitiveDependencyAsnyc(string projectPath, string dependencyName, string newDependencyVersion, ImmutableArray<ProjectBuildFile> buildFiles, Logger logger)
126
+ private static async Task UpdateTransitiveDependencyAsync(string repoRootPath, string projectPath, string dependencyName, string newDependencyVersion, ImmutableArray<ProjectBuildFile> buildFiles, Logger logger)
127
127
  {
128
128
  var directoryPackagesWithPinning = buildFiles.OfType<ProjectBuildFile>()
129
129
  .FirstOrDefault(bf => IsCpmTransitivePinningEnabled(bf));
@@ -133,7 +133,7 @@ internal static class SdkPackageUpdater
133
133
  }
134
134
  else
135
135
  {
136
- await AddTransitiveDependencyAsync(projectPath, dependencyName, newDependencyVersion, logger);
136
+ await AddTransitiveDependencyAsync(repoRootPath, projectPath, dependencyName, newDependencyVersion, logger);
137
137
  }
138
138
  }
139
139
 
@@ -222,17 +222,21 @@ internal static class SdkPackageUpdater
222
222
  directoryPackages.Update(updatedXml);
223
223
  }
224
224
 
225
- private static async Task AddTransitiveDependencyAsync(string projectPath, string dependencyName, string newDependencyVersion, Logger logger)
225
+ private static async Task AddTransitiveDependencyAsync(string repoRootPath, string projectPath, string dependencyName, string newDependencyVersion, Logger logger)
226
226
  {
227
- logger.Log($" Adding [{dependencyName}/{newDependencyVersion}] as a top-level package reference.");
228
-
229
- // see https://learn.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli
230
- var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", $"add {projectPath} package {dependencyName} --version {newDependencyVersion}", workingDirectory: Path.GetDirectoryName(projectPath));
231
- MSBuildHelper.ThrowOnUnauthenticatedFeed(stdout);
232
- if (exitCode != 0)
227
+ var projectDirectory = Path.GetDirectoryName(projectPath)!;
228
+ await MSBuildHelper.SidelineGlobalJsonAsync(projectDirectory, repoRootPath, async () =>
233
229
  {
234
- logger.Log($" Transitive dependency [{dependencyName}/{newDependencyVersion}] was not added.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}");
235
- }
230
+ logger.Log($" Adding [{dependencyName}/{newDependencyVersion}] as a top-level package reference.");
231
+
232
+ // see https://learn.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli
233
+ var (exitCode, stdout, stderr) = await ProcessEx.RunAsync("dotnet", $"add {projectPath} package {dependencyName} --version {newDependencyVersion}", workingDirectory: projectDirectory);
234
+ MSBuildHelper.ThrowOnUnauthenticatedFeed(stdout);
235
+ if (exitCode != 0)
236
+ {
237
+ logger.Log($" Transitive dependency [{dependencyName}/{newDependencyVersion}] was not added.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}");
238
+ }
239
+ }, retainMSBuildSdks: true);
236
240
  }
237
241
 
238
242
  /// <summary>
@@ -31,29 +31,54 @@ internal static partial class MSBuildHelper
31
31
  // Ensure MSBuild types are registered before calling a method that loads the types
32
32
  if (!IsMSBuildRegistered)
33
33
  {
34
- var candidateDirectories = PathHelper.GetAllDirectoriesToRoot(currentDirectory, rootDirectory);
35
- var globalJsonPaths = candidateDirectories.Select(d => Path.Combine(d, "global.json")).Where(File.Exists).Select(p => (p, p + Guid.NewGuid().ToString())).ToArray();
36
- foreach (var (globalJsonPath, tempGlobalJsonPath) in globalJsonPaths)
37
- {
38
- Console.WriteLine($"Temporarily removing `global.json` from `{Path.GetDirectoryName(globalJsonPath)}` for MSBuild detection.");
39
- File.Move(globalJsonPath, tempGlobalJsonPath);
40
- }
41
-
42
- try
34
+ SidelineGlobalJsonAsync(currentDirectory, rootDirectory, () =>
43
35
  {
44
36
  var defaultInstance = MSBuildLocator.QueryVisualStudioInstances().First();
45
37
  MSBuildPath = defaultInstance.MSBuildPath;
46
38
  MSBuildLocator.RegisterInstance(defaultInstance);
47
- }
48
- finally
39
+ return Task.CompletedTask;
40
+ }).Wait();
41
+ }
42
+ }
43
+
44
+ public static async Task SidelineGlobalJsonAsync(string currentDirectory, string rootDirectory, Func<Task> action, bool retainMSBuildSdks = false)
45
+ {
46
+ var candidateDirectories = PathHelper.GetAllDirectoriesToRoot(currentDirectory, rootDirectory);
47
+ var globalJsonPaths = candidateDirectories.Select(d => Path.Combine(d, "global.json")).Where(File.Exists).Select(p => (p, p + Guid.NewGuid().ToString())).ToArray();
48
+ foreach (var (globalJsonPath, tempGlobalJsonPath) in globalJsonPaths)
49
+ {
50
+ Console.WriteLine($"Temporarily removing `global.json` from `{Path.GetDirectoryName(globalJsonPath)}`{(retainMSBuildSdks ? " and retaining MSBuild SDK declarations" : string.Empty)}.");
51
+ File.Move(globalJsonPath, tempGlobalJsonPath);
52
+ if (retainMSBuildSdks)
49
53
  {
50
- foreach (var (globalJsonpath, tempGlobalJsonPath) in globalJsonPaths)
54
+ // custom SDKs might need to be retained for other operations; rebuild `global.json` with only the relevant key
55
+ var originalContent = await File.ReadAllTextAsync(tempGlobalJsonPath);
56
+ var jsonNode = JsonHelper.ParseNode(originalContent);
57
+ if (jsonNode is JsonObject obj &&
58
+ obj.TryGetPropertyValue("msbuild-sdks", out var sdks) &&
59
+ sdks is not null)
51
60
  {
52
- Console.WriteLine($"Restoring `global.json` to `{Path.GetDirectoryName(globalJsonpath)}` after MSBuild discovery.");
53
- File.Move(tempGlobalJsonPath, globalJsonpath);
61
+ var newObj = new JsonObject()
62
+ {
63
+ ["msbuild-sdks"] = sdks.DeepClone(),
64
+ };
65
+ await File.WriteAllTextAsync(globalJsonPath, newObj.ToJsonString());
54
66
  }
55
67
  }
56
68
  }
69
+
70
+ try
71
+ {
72
+ await action();
73
+ }
74
+ finally
75
+ {
76
+ foreach (var (globalJsonpath, tempGlobalJsonPath) in globalJsonPaths)
77
+ {
78
+ Console.WriteLine($"Restoring `global.json` to `{Path.GetDirectoryName(globalJsonpath)}`.");
79
+ File.Move(tempGlobalJsonPath, globalJsonpath, overwrite: retainMSBuildSdks);
80
+ }
81
+ }
57
82
  }
58
83
 
59
84
  public static IEnumerable<string> GetProjectPathsFromSolution(string solutionPath)
@@ -532,6 +532,127 @@ public partial class UpdateWorkerTests
532
532
  );
533
533
  }
534
534
 
535
+ [Fact]
536
+ public async Task TransitiveDependencyCanBeAddedWithMismatchingSdk()
537
+ {
538
+ await TestUpdateForProject("Some.Transitive.Package", "1.0.0", "1.0.1", isTransitive: true,
539
+ packages:
540
+ [
541
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0", [(null, [("Some.Transitive.Package", "1.0.0")])]),
542
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Package", "1.0.0", "net8.0"),
543
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Package", "1.0.1", "net8.0"),
544
+ ],
545
+ projectContents: """
546
+ <Project Sdk="Microsoft.NET.Sdk">
547
+ <PropertyGroup>
548
+ <TargetFramework>net8.0</TargetFramework>
549
+ </PropertyGroup>
550
+ <ItemGroup>
551
+ <PackageReference Include="Some.Package" Version="1.0.0" />
552
+ </ItemGroup>
553
+ </Project>
554
+ """,
555
+ additionalFiles:
556
+ [
557
+ ("global.json", """
558
+ {
559
+ "sdk": {
560
+ "version": "99.99.999" // this version doesn't match anything that's installed
561
+ }
562
+ }
563
+ """)
564
+ ],
565
+ expectedProjectContents: """
566
+ <Project Sdk="Microsoft.NET.Sdk">
567
+ <PropertyGroup>
568
+ <TargetFramework>net8.0</TargetFramework>
569
+ </PropertyGroup>
570
+ <ItemGroup>
571
+ <PackageReference Include="Some.Package" Version="1.0.0" />
572
+ <PackageReference Include="Some.Transitive.Package" Version="1.0.1" />
573
+ </ItemGroup>
574
+ </Project>
575
+ """
576
+ );
577
+ }
578
+
579
+ [Fact]
580
+ public async Task TransitiveDependencyCanBeAddedWithCustomMSBuildSdk()
581
+ {
582
+ await TestUpdateForProject("Some.Transitive.Package", "1.0.0", "1.0.1", isTransitive: true,
583
+ packages:
584
+ [
585
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0", [(null, [("Some.Transitive.Package", "1.0.0")])]),
586
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Package", "1.0.0", "net8.0"),
587
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Package", "1.0.1", "net8.0"),
588
+ MockNuGetPackage.CreateMSBuildSdkPackage("Custom.MSBuild.Sdk", "1.2.3"),
589
+ ],
590
+ projectContents: """
591
+ <Project Sdk="Microsoft.NET.Sdk">
592
+ <PropertyGroup>
593
+ <TargetFramework>net8.0</TargetFramework>
594
+ </PropertyGroup>
595
+ <ItemGroup>
596
+ <PackageReference Include="Some.Package" />
597
+ </ItemGroup>
598
+ </Project>
599
+ """,
600
+ additionalFiles:
601
+ [
602
+ ("Directory.Build.props", """
603
+ <Project>
604
+ <Import Project="Sdk.props" Sdk="Custom.MSBuild.Sdk" />
605
+ </Project>
606
+ """),
607
+ ("Directory.Packages.props", """
608
+ <Project>
609
+ <PropertyGroup>
610
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
611
+ </PropertyGroup>
612
+ <ItemGroup>
613
+ <PackageVersion Include="Some.Package" Version="1.0.0" />
614
+ </ItemGroup>
615
+ </Project>
616
+ """),
617
+ ("global.json", """
618
+ {
619
+ "sdk": {
620
+ "version": "99.99.999" // this version doesn't match anything that's installed
621
+ },
622
+ "msbuild-sdks": {
623
+ "Custom.MSBuild.Sdk": "1.2.3"
624
+ }
625
+ }
626
+ """)
627
+ ],
628
+ expectedProjectContents: """
629
+ <Project Sdk="Microsoft.NET.Sdk">
630
+ <PropertyGroup>
631
+ <TargetFramework>net8.0</TargetFramework>
632
+ </PropertyGroup>
633
+ <ItemGroup>
634
+ <PackageReference Include="Some.Package" />
635
+ <PackageReference Include="Some.Transitive.Package" />
636
+ </ItemGroup>
637
+ </Project>
638
+ """,
639
+ additionalFilesExpected:
640
+ [
641
+ ("Directory.Packages.props", """
642
+ <Project>
643
+ <PropertyGroup>
644
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
645
+ </PropertyGroup>
646
+ <ItemGroup>
647
+ <PackageVersion Include="Some.Package" Version="1.0.0" />
648
+ <PackageVersion Include="Some.Transitive.Package" Version="1.0.1" />
649
+ </ItemGroup>
650
+ </Project>
651
+ """)
652
+ ]
653
+ );
654
+ }
655
+
535
656
  [Fact]
536
657
  public async Task UpdateVersionAttribute_InProjectFile_ForAnalyzerPackageReferenceInclude()
537
658
  {
@@ -31,6 +31,20 @@ module Dependabot
31
31
  ]
32
32
  end
33
33
 
34
+ sig { params(original_content: T.nilable(String), updated_content: String).returns(T::Boolean) }
35
+ def self.differs_in_more_than_blank_lines?(original_content, updated_content)
36
+ # Compare the line counts of the original and updated content, but ignore lines only containing white-space.
37
+ # This prevents false positives when there are trailing empty lines in the original content, for example.
38
+ original_lines = (original_content&.lines || []).map(&:strip).reject(&:empty?)
39
+ updated_lines = updated_content.lines.map(&:strip).reject(&:empty?)
40
+
41
+ # if the line count differs, then something changed
42
+ return true unless original_lines.count == updated_lines.count
43
+
44
+ # check each line pair, ignoring blanks (filtered above)
45
+ original_lines.zip(updated_lines).any? { |pair| pair[0] != pair[1] }
46
+ end
47
+
34
48
  sig { override.returns(T::Array[Dependabot::DependencyFile]) }
35
49
  def updated_dependency_files
36
50
  base_dir = "/"
@@ -45,7 +59,7 @@ module Dependabot
45
59
  normalized_content = normalize_content(f, updated_content)
46
60
  next if normalized_content == f.content
47
61
 
48
- next if only_deleted_lines?(f.content, normalized_content)
62
+ next unless FileUpdater.differs_in_more_than_blank_lines?(f.content, normalized_content)
49
63
 
50
64
  puts "The contents of file [#{f.name}] were updated."
51
65
 
@@ -217,14 +231,6 @@ module Dependabot
217
231
 
218
232
  raise "No project file or packages.config!"
219
233
  end
220
-
221
- sig { params(original_content: T.nilable(String), updated_content: String).returns(T::Boolean) }
222
- def only_deleted_lines?(original_content, updated_content)
223
- original_lines = original_content&.lines || []
224
- updated_lines = updated_content.lines
225
-
226
- original_lines.count > updated_lines.count
227
- end
228
234
  end
229
235
  end
230
236
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-nuget
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.267.0
4
+ version: 0.268.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-25 00:00:00.000000000 Z
11
+ date: 2024-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.267.0
19
+ version: 0.268.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.267.0
26
+ version: 0.268.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubyzip
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -461,7 +461,7 @@ licenses:
461
461
  - MIT
462
462
  metadata:
463
463
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
464
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.267.0
464
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.268.0
465
465
  post_install_message:
466
466
  rdoc_options: []
467
467
  require_paths: