dependabot-nuget 0.267.0 → 0.268.0

Sign up to get free protection for your applications and to get access to all the features.
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: