dependabot-nuget 0.245.0 → 0.247.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +42 -7
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +164 -90
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +38 -2
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +92 -18
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +1 -1
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +27 -0
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +115 -14
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/{UpdateWorker.DirsProj.cs → UpdateWorkerTests.DirsProj.cs} +22 -24
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +66 -0
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +373 -83
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +117 -4
  13. data/lib/dependabot/nuget/cache_manager.rb +9 -3
  14. data/lib/dependabot/nuget/file_fetcher/import_paths_finder.rb +15 -12
  15. data/lib/dependabot/nuget/file_fetcher/sln_project_paths_finder.rb +13 -3
  16. data/lib/dependabot/nuget/file_fetcher.rb +79 -31
  17. data/lib/dependabot/nuget/file_parser/dotnet_tools_json_parser.rb +10 -2
  18. data/lib/dependabot/nuget/file_parser/global_json_parser.rb +10 -2
  19. data/lib/dependabot/nuget/file_parser/packages_config_parser.rb +11 -2
  20. data/lib/dependabot/nuget/file_parser/project_file_parser.rb +140 -45
  21. data/lib/dependabot/nuget/file_parser/property_value_finder.rb +57 -5
  22. data/lib/dependabot/nuget/file_parser.rb +18 -4
  23. data/lib/dependabot/nuget/file_updater/property_value_updater.rb +25 -8
  24. data/lib/dependabot/nuget/file_updater.rb +74 -38
  25. data/lib/dependabot/nuget/http_response_helpers.rb +19 -0
  26. data/lib/dependabot/nuget/metadata_finder.rb +32 -4
  27. data/lib/dependabot/nuget/nuget_client.rb +31 -13
  28. data/lib/dependabot/nuget/requirement.rb +4 -1
  29. data/lib/dependabot/nuget/update_checker/compatibility_checker.rb +26 -15
  30. data/lib/dependabot/nuget/update_checker/dependency_finder.rb +23 -13
  31. data/lib/dependabot/nuget/update_checker/nupkg_fetcher.rb +83 -21
  32. data/lib/dependabot/nuget/update_checker/repository_finder.rb +29 -13
  33. data/lib/dependabot/nuget/update_checker/tfm_finder.rb +2 -2
  34. data/lib/dependabot/nuget/update_checker/version_finder.rb +15 -6
  35. data/lib/dependabot/nuget/update_checker.rb +6 -7
  36. data/lib/dependabot/nuget/version.rb +7 -2
  37. metadata +21 -7
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/SdkPackageUpdaterTests.cs +0 -317
@@ -17,10 +17,14 @@ using Microsoft.Build.Exceptions;
17
17
  using Microsoft.Build.Locator;
18
18
  using Microsoft.Extensions.FileSystemGlobbing;
19
19
 
20
+ using NuGet.Configuration;
21
+
20
22
  using NuGetUpdater.Core.Utilities;
21
23
 
22
24
  namespace NuGetUpdater.Core;
23
25
 
26
+ using EvaluationResult = (MSBuildHelper.EvaluationResultType ResultType, string EvaluatedValue, string? ErrorMessage);
27
+
24
28
  internal static partial class MSBuildHelper
25
29
  {
26
30
  public static string MSBuildPath { get; private set; } = string.Empty;
@@ -57,7 +61,10 @@ internal static partial class MSBuildHelper
57
61
  if (property.Name.Equals("TargetFramework", StringComparison.OrdinalIgnoreCase) ||
58
62
  property.Name.Equals("TargetFrameworks", StringComparison.OrdinalIgnoreCase))
59
63
  {
60
- targetFrameworkValues.Add(property.Value);
64
+ foreach (var tfm in property.Value.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
65
+ {
66
+ targetFrameworkValues.Add(tfm);
67
+ }
61
68
  }
62
69
  else if (property.Name.Equals("TargetFrameworkVersion", StringComparison.OrdinalIgnoreCase))
63
70
  {
@@ -75,8 +82,12 @@ internal static partial class MSBuildHelper
75
82
 
76
83
  foreach (var targetFrameworkValue in targetFrameworkValues)
77
84
  {
78
- var tfms = targetFrameworkValue;
79
- tfms = GetRootedValue(tfms, propertyInfo);
85
+ var (resultType, tfms, errorMessage) =
86
+ GetEvaluatedValue(targetFrameworkValue, propertyInfo, propertiesToIgnore: ["TargetFramework", "TargetFrameworks"]);
87
+ if (resultType != EvaluationResultType.Success)
88
+ {
89
+ continue;
90
+ }
80
91
 
81
92
  if (string.IsNullOrEmpty(tfms))
82
93
  {
@@ -101,10 +112,18 @@ internal static partial class MSBuildHelper
101
112
  public static IEnumerable<string> GetProjectPathsFromProject(string projFilePath)
102
113
  {
103
114
  var projectStack = new Stack<(string folderPath, ProjectRootElement)>();
104
- var projectRootElement = ProjectRootElement.Open(projFilePath);
105
115
  var processedProjectFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
116
+ using var projectCollection = new ProjectCollection();
106
117
 
107
- projectStack.Push((Path.GetFullPath(Path.GetDirectoryName(projFilePath)!), projectRootElement));
118
+ try
119
+ {
120
+ var projectRootElement = ProjectRootElement.Open(projFilePath, projectCollection);
121
+ projectStack.Push((Path.GetFullPath(Path.GetDirectoryName(projFilePath)!), projectRootElement));
122
+ }
123
+ catch (InvalidProjectFileException)
124
+ {
125
+ yield break; // Skip invalid project files
126
+ }
108
127
 
109
128
  while (projectStack.Count > 0)
110
129
  {
@@ -137,7 +156,7 @@ internal static partial class MSBuildHelper
137
156
  // If there is some MSBuild logic that needs to run to fully resolve the path skip the project
138
157
  if (File.Exists(file))
139
158
  {
140
- var additionalProjectRootElement = ProjectRootElement.Open(file);
159
+ var additionalProjectRootElement = ProjectRootElement.Open(file, projectCollection);
141
160
  projectStack.Push((Path.GetFullPath(Path.GetDirectoryName(file)!), additionalProjectRootElement));
142
161
  processedProjectFiles.Add(file);
143
162
  }
@@ -222,9 +241,13 @@ internal static partial class MSBuildHelper
222
241
  }
223
242
 
224
243
  // Walk the property replacements until we don't find another one.
225
- packageVersion = GetRootedValue(packageVersion, propertyInfo);
244
+ var evaluationResult = GetEvaluatedValue(packageVersion, propertyInfo);
245
+ if (evaluationResult.ResultType != EvaluationResultType.Success)
246
+ {
247
+ throw new InvalidDataException(evaluationResult.ErrorMessage);
248
+ }
226
249
 
227
- packageVersion = packageVersion.TrimStart('[', '(').TrimEnd(']', ')');
250
+ packageVersion = evaluationResult.EvaluatedValue.TrimStart('[', '(').TrimEnd(']', ')');
228
251
 
229
252
  // We don't know the version for range requirements or wildcard
230
253
  // requirements, so return "" for these.
@@ -237,25 +260,32 @@ internal static partial class MSBuildHelper
237
260
  /// <summary>
238
261
  /// Given an MSBuild string and a set of properties, returns our best guess at the final value MSBuild will evaluate to.
239
262
  /// </summary>
240
- /// <param name="msbuildString"></param>
241
- /// <param name="propertyInfo"></param>
242
- /// <returns></returns>
243
- public static string GetRootedValue(string msbuildString, Dictionary<string, string> propertyInfo)
263
+ public static EvaluationResult GetEvaluatedValue(string msbuildString, Dictionary<string, string> propertyInfo, params string[] propertiesToIgnore)
244
264
  {
265
+ var ignoredProperties = new HashSet<string>(propertiesToIgnore, StringComparer.OrdinalIgnoreCase);
245
266
  var seenProperties = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
267
+
246
268
  while (TryGetPropertyName(msbuildString, out var propertyName))
247
269
  {
270
+ if (ignoredProperties.Contains(propertyName))
271
+ {
272
+ return (EvaluationResultType.PropertyIgnored, msbuildString, $"Property '{propertyName}' is ignored.");
273
+ }
274
+
248
275
  if (!seenProperties.Add(propertyName))
249
276
  {
250
- throw new InvalidDataException($"Property '{propertyName}' has a circular reference.");
277
+ return (EvaluationResultType.CircularReference, msbuildString, $"Property '{propertyName}' has a circular reference.");
251
278
  }
252
279
 
253
- msbuildString = propertyInfo.TryGetValue(propertyName, out var propertyValue)
254
- ? msbuildString.Replace($"$({propertyName})", propertyValue)
255
- : throw new InvalidDataException($"Property '{propertyName}' was not found.");
280
+ if (!propertyInfo.TryGetValue(propertyName, out var propertyValue))
281
+ {
282
+ return (EvaluationResultType.PropertyNotFound, msbuildString, $"Property '{propertyName}' was not found.");
283
+ }
284
+
285
+ msbuildString = msbuildString.Replace($"$({propertyName})", propertyValue);
256
286
  }
257
287
 
258
- return msbuildString;
288
+ return (EvaluationResultType.Success, msbuildString, null);
259
289
  }
260
290
 
261
291
  public static bool TryGetPropertyName(string versionContent, [NotNullWhen(true)] out string? propertyName)
@@ -303,6 +333,25 @@ internal static partial class MSBuildHelper
303
333
  return projectRoot;
304
334
  }
305
335
 
336
+ private static IEnumerable<PackageSource>? LoadPackageSources(string nugetConfigPath)
337
+ {
338
+ try
339
+ {
340
+ var nugetConfigDir = Path.GetDirectoryName(nugetConfigPath);
341
+ var settings = Settings.LoadSpecificSettings(nugetConfigDir, Path.GetFileName(nugetConfigPath));
342
+ var packageSourceProvider = new PackageSourceProvider(settings);
343
+ return packageSourceProvider.LoadPackageSources();
344
+ }
345
+ catch (NuGetConfigurationException ex)
346
+ {
347
+ Console.WriteLine("Error while parsing NuGet.config");
348
+ Console.WriteLine(ex.Message);
349
+
350
+ // Nuget.config is invalid. Won't be able to do anything with specific sources.
351
+ return null;
352
+ }
353
+ }
354
+
306
355
  private static async Task<string> CreateTempProjectAsync(
307
356
  DirectoryInfo tempDir,
308
357
  string repoRoot,
@@ -313,10 +362,27 @@ internal static partial class MSBuildHelper
313
362
  var projectDirectory = Path.GetDirectoryName(projectPath);
314
363
  projectDirectory ??= repoRoot;
315
364
  var topLevelFiles = Directory.GetFiles(repoRoot);
316
- var nugetConfigPath = PathHelper.GetFileInDirectoryOrParent(projectDirectory, repoRoot, "NuGet.Config", caseSensitive: false);
365
+ var nugetConfigPath = PathHelper.GetFileInDirectoryOrParent(projectPath, repoRoot, "NuGet.Config", caseSensitive: false);
317
366
  if (nugetConfigPath is not null)
318
367
  {
368
+ // Copy nuget.config to temp project directory
319
369
  File.Copy(nugetConfigPath, Path.Combine(tempDir.FullName, "NuGet.Config"));
370
+ var nugetConfigDir = Path.GetDirectoryName(nugetConfigPath);
371
+
372
+ var packageSources = LoadPackageSources(nugetConfigPath);
373
+ if (packageSources is not null)
374
+ {
375
+ // We need to copy local package sources from the NuGet.Config file to the temp directory
376
+ foreach (var localSource in packageSources.Where(p => p.IsLocal))
377
+ {
378
+ var subDir = localSource.Source.Split(nugetConfigDir)[1];
379
+ var destPath = Path.Join(tempDir.FullName, subDir);
380
+ if (Directory.Exists(localSource.Source))
381
+ {
382
+ PathHelper.CopyDirectory(localSource.Source, destPath);
383
+ }
384
+ }
385
+ }
320
386
  }
321
387
 
322
388
  var packageReferences = string.Join(
@@ -492,4 +558,12 @@ internal static partial class MSBuildHelper
492
558
 
493
559
  [GeneratedRegex("^\\s*NuGetData::Package=(?<PackageName>[^,]+), Version=(?<PackageVersion>.+)$")]
494
560
  private static partial Regex PackagePattern();
561
+
562
+ internal enum EvaluationResultType
563
+ {
564
+ Success,
565
+ PropertyIgnored,
566
+ CircularReference,
567
+ PropertyNotFound,
568
+ }
495
569
  }
@@ -6,7 +6,7 @@ internal static class NuGetHelper
6
6
  {
7
7
  internal const string PackagesConfigFileName = "packages.config";
8
8
 
9
- public static bool HasProjectConfigFile(string projectPath)
9
+ public static bool HasPackagesConfigFile(string projectPath)
10
10
  {
11
11
  var projectDirectory = Path.GetDirectoryName(projectPath);
12
12
  var packagesConfigPath = PathHelper.JoinPath(projectDirectory, PackagesConfigFileName);
@@ -79,4 +79,31 @@ internal static class PathHelper
79
79
 
80
80
  return null;
81
81
  }
82
+
83
+ public static void CopyDirectory(string sourceDirectory, string destinationDirectory)
84
+ {
85
+ var sourceDirInfo = new DirectoryInfo(sourceDirectory);
86
+ var destinationDirInfo = new DirectoryInfo(destinationDirectory);
87
+
88
+ if (!sourceDirInfo.Exists)
89
+ {
90
+ throw new DirectoryNotFoundException($"Source directory does not exist or could not be found: {sourceDirectory}");
91
+ }
92
+
93
+ if (!destinationDirInfo.Exists)
94
+ {
95
+ destinationDirInfo.Create();
96
+ }
97
+
98
+ foreach (var file in sourceDirInfo.EnumerateFiles())
99
+ {
100
+ file.CopyTo(Path.Combine(destinationDirectory, file.Name), true);
101
+ }
102
+
103
+ foreach (var subDir in sourceDirInfo.EnumerateDirectories())
104
+ {
105
+ var newDestinationDir = Path.Combine(destinationDirectory, subDir.Name);
106
+ CopyDirectory(subDir.FullName, newDestinationDir);
107
+ }
108
+ }
82
109
  }
@@ -6,10 +6,61 @@ using System.Threading.Tasks;
6
6
 
7
7
  using Xunit;
8
8
 
9
+ using TestFile = (string Path, string Content);
10
+ using TestProject = (string Path, string Content, System.Guid ProjectId);
11
+
9
12
  namespace NuGetUpdater.Core.Test.Update;
10
13
 
11
14
  public abstract class UpdateWorkerTestBase
12
15
  {
16
+ protected static Task TestNoChange(
17
+ string dependencyName,
18
+ string oldVersion,
19
+ string newVersion,
20
+ bool useSolution,
21
+ string projectContents,
22
+ bool isTransitive = false,
23
+ (string Path, string Content)[]? additionalFiles = null,
24
+ string projectFilePath = "test-project.csproj")
25
+ {
26
+ return useSolution
27
+ ? TestNoChangeforSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], isTransitive, additionalFiles)
28
+ : TestNoChangeforProject(dependencyName, oldVersion, newVersion, projectContents, isTransitive, additionalFiles, projectFilePath);
29
+ }
30
+
31
+ protected static Task TestUpdate(
32
+ string dependencyName,
33
+ string oldVersion,
34
+ string newVersion,
35
+ bool useSolution,
36
+ string projectContents,
37
+ string expectedProjectContents,
38
+ bool isTransitive = false,
39
+ TestFile[]? additionalFiles = null,
40
+ TestFile[]? additionalFilesExpected = null,
41
+ string projectFilePath = "test-project.csproj")
42
+ {
43
+ return useSolution
44
+ ? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], projectFilesExpected: [(projectFilePath, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected)
45
+ : TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected);
46
+ }
47
+
48
+ protected static Task TestUpdate(
49
+ string dependencyName,
50
+ string oldVersion,
51
+ string newVersion,
52
+ bool useSolution,
53
+ TestFile projectFile,
54
+ string expectedProjectContents,
55
+ bool isTransitive = false,
56
+ TestFile[]? additionalFiles = null,
57
+ TestFile[]? additionalFilesExpected = null)
58
+ {
59
+ return useSolution
60
+ ? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [projectFile], projectFilesExpected: [(projectFile.Path, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected)
61
+ : TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected);
62
+ }
63
+
13
64
  protected static Task TestNoChangeforProject(
14
65
  string dependencyName,
15
66
  string oldVersion,
@@ -35,8 +86,8 @@ public abstract class UpdateWorkerTestBase
35
86
  string projectContents,
36
87
  string expectedProjectContents,
37
88
  bool isTransitive = false,
38
- (string Path, string Content)[]? additionalFiles = null,
39
- (string Path, string Content)[]? additionalFilesExpected = null,
89
+ TestFile[]? additionalFiles = null,
90
+ TestFile[]? additionalFilesExpected = null,
40
91
  string projectFilePath = "test-project.csproj")
41
92
  => TestUpdateForProject(
42
93
  dependencyName,
@@ -52,42 +103,92 @@ public abstract class UpdateWorkerTestBase
52
103
  string dependencyName,
53
104
  string oldVersion,
54
105
  string newVersion,
55
- (string Path, string Content) projectFile,
106
+ TestFile projectFile,
56
107
  string expectedProjectContents,
57
108
  bool isTransitive = false,
58
- (string Path, string Content)[]? additionalFiles = null,
59
- (string Path, string Content)[]? additionalFilesExpected = null)
109
+ TestFile[]? additionalFiles = null,
110
+ TestFile[]? additionalFilesExpected = null)
60
111
  {
61
112
  additionalFiles ??= [];
62
113
  additionalFilesExpected ??= [];
63
114
 
64
115
  var projectFilePath = projectFile.Path;
65
- var projectName = Path.GetFileNameWithoutExtension(projectFilePath);
116
+ var testFiles = new[] { projectFile }.Concat(additionalFiles).ToArray();
117
+
118
+ var actualResult = await RunUpdate(testFiles, async temporaryDirectory =>
119
+ {
120
+ var worker = new UpdaterWorker(new Logger(verbose: true));
121
+ await worker.RunAsync(temporaryDirectory, projectFilePath, dependencyName, oldVersion, newVersion, isTransitive);
122
+ });
123
+
124
+ var expectedResult = additionalFilesExpected.Prepend((projectFilePath, expectedProjectContents)).ToArray();
125
+
126
+ AssertContainsFiles(expectedResult, actualResult);
127
+ }
128
+
129
+ protected static Task TestNoChangeforSolution(
130
+ string dependencyName,
131
+ string oldVersion,
132
+ string newVersion,
133
+ TestFile[] projectFiles,
134
+ bool isTransitive = false,
135
+ TestFile[]? additionalFiles = null)
136
+ => TestUpdateForSolution(
137
+ dependencyName,
138
+ oldVersion,
139
+ newVersion,
140
+ projectFiles,
141
+ projectFilesExpected: projectFiles,
142
+ isTransitive,
143
+ additionalFiles,
144
+ additionalFilesExpected: additionalFiles);
145
+
146
+ protected static async Task TestUpdateForSolution(
147
+ string dependencyName,
148
+ string oldVersion,
149
+ string newVersion,
150
+ TestFile[] projectFiles,
151
+ TestFile[] projectFilesExpected,
152
+ bool isTransitive = false,
153
+ TestFile[]? additionalFiles = null,
154
+ TestFile[]? additionalFilesExpected = null)
155
+ {
156
+ additionalFiles ??= [];
157
+ additionalFilesExpected ??= [];
158
+
159
+ var testProjects = projectFiles.Select(file => new TestProject(file.Path, file.Content, Guid.NewGuid())).ToArray();
160
+ var projectDeclarations = testProjects.Select(project => $$"""
161
+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{Path.GetFileNameWithoutExtension(project.Path)}}", "{{project.Path}}", "{{project.ProjectId}}"
162
+ EndProject
163
+ """);
164
+ var debugConfiguration = testProjects.Select(project => $$"""
165
+ {{project.ProjectId}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
166
+ {{project.ProjectId}}.Debug|Any CPU.Build.0 = Debug|Any CPU
167
+ {{project.ProjectId}}..Release|Any CPU.ActiveCfg = Release|Any CPU
168
+ {{project.ProjectId}}..Release|Any CPU.Build.0 = Release|Any CPU
169
+ """);
170
+
66
171
  var slnName = "test-solution.sln";
67
172
  var slnContent = $$"""
68
173
  Microsoft Visual Studio Solution File, Format Version 12.00
69
174
  # Visual Studio 14
70
175
  VisualStudioVersion = 14.0.22705.0
71
176
  MinimumVisualStudioVersion = 10.0.40219.1
72
- Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{projectName}}", "{{projectFilePath}}", "{782E0C0A-10D3-444D-9640-263D03D2B20C}"
73
- EndProject
177
+ {{string.Join(Environment.NewLine, projectDeclarations)}}
74
178
  Global
75
179
  GlobalSection(SolutionConfigurationPlatforms) = preSolution
76
180
  Debug|Any CPU = Debug|Any CPU
77
181
  Release|Any CPU = Release|Any CPU
78
182
  EndGlobalSection
79
183
  GlobalSection(ProjectConfigurationPlatforms) = postSolution
80
- {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
81
- {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.Build.0 = Debug|Any CPU
82
- {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.ActiveCfg = Release|Any CPU
83
- {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.Build.0 = Release|Any CPU
184
+ {{string.Join(Environment.NewLine, debugConfiguration)}}
84
185
  EndGlobalSection
85
186
  GlobalSection(SolutionProperties) = preSolution
86
187
  HideSolutionNode = FALSE
87
188
  EndGlobalSection
88
189
  EndGlobal
89
190
  """;
90
- var testFiles = new[] { (slnName, slnContent), projectFile }.Concat(additionalFiles).ToArray();
191
+ var testFiles = new[] { (slnName, slnContent) }.Concat(projectFiles).Concat(additionalFiles).ToArray();
91
192
 
92
193
  var actualResult = await RunUpdate(testFiles, async temporaryDirectory =>
93
194
  {
@@ -96,7 +197,7 @@ public abstract class UpdateWorkerTestBase
96
197
  await worker.RunAsync(temporaryDirectory, slnPath, dependencyName, oldVersion, newVersion, isTransitive);
97
198
  });
98
199
 
99
- var expectedResult = additionalFilesExpected.Prepend((projectFilePath, expectedProjectContents)).ToArray();
200
+ var expectedResult = projectFilesExpected.Concat(additionalFilesExpected).ToArray();
100
201
 
101
202
  AssertContainsFiles(expectedResult, actualResult);
102
203
  }
@@ -1,5 +1,3 @@
1
- using System;
2
- using System.Collections.Generic;
3
1
  using System.IO;
4
2
  using System.Linq;
5
3
  using System.Threading.Tasks;
@@ -24,7 +22,7 @@ public partial class UpdateWorkerTests
24
22
  // initial
25
23
  projectContents: """
26
24
  <Project Sdk="Microsoft.Build.NoTargets">
27
-
25
+
28
26
  <ItemGroup>
29
27
  <ProjectReference Include="src/test-project.csproj" />
30
28
  </ItemGroup>
@@ -39,7 +37,7 @@ public partial class UpdateWorkerTests
39
37
  <PropertyGroup>
40
38
  <TargetFramework>netstandard2.0</TargetFramework>
41
39
  </PropertyGroup>
42
-
40
+
43
41
  <ItemGroup>
44
42
  <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
45
43
  </ItemGroup>
@@ -49,7 +47,7 @@ public partial class UpdateWorkerTests
49
47
  // expected
50
48
  expectedProjectContents: """
51
49
  <Project Sdk="Microsoft.Build.NoTargets">
52
-
50
+
53
51
  <ItemGroup>
54
52
  <ProjectReference Include="src/test-project.csproj" />
55
53
  </ItemGroup>
@@ -64,7 +62,7 @@ public partial class UpdateWorkerTests
64
62
  <PropertyGroup>
65
63
  <TargetFramework>netstandard2.0</TargetFramework>
66
64
  </PropertyGroup>
67
-
65
+
68
66
  <ItemGroup>
69
67
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
70
68
  </ItemGroup>
@@ -101,7 +99,7 @@ public partial class UpdateWorkerTests
101
99
  // initial
102
100
  projectContents: """
103
101
  <Project Sdk="Microsoft.Build.NoTargets">
104
-
102
+
105
103
  <ItemGroup>
106
104
  <ProjectReference Include="src/dirs.proj" />
107
105
  </ItemGroup>
@@ -113,7 +111,7 @@ public partial class UpdateWorkerTests
113
111
  ("src/dirs.proj",
114
112
  """
115
113
  <Project Sdk="Microsoft.Build.NoTargets">
116
-
114
+
117
115
  <ItemGroup>
118
116
  <ProjectReference Include="test-project/test-project.csproj" />
119
117
  </ItemGroup>
@@ -126,7 +124,7 @@ public partial class UpdateWorkerTests
126
124
  <PropertyGroup>
127
125
  <TargetFramework>netstandard2.0</TargetFramework>
128
126
  </PropertyGroup>
129
-
127
+
130
128
  <ItemGroup>
131
129
  <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
132
130
  </ItemGroup>
@@ -136,7 +134,7 @@ public partial class UpdateWorkerTests
136
134
  // expected
137
135
  expectedProjectContents: """
138
136
  <Project Sdk="Microsoft.Build.NoTargets">
139
-
137
+
140
138
  <ItemGroup>
141
139
  <ProjectReference Include="src/dirs.proj" />
142
140
  </ItemGroup>
@@ -148,7 +146,7 @@ public partial class UpdateWorkerTests
148
146
  ("src/dirs.proj",
149
147
  """
150
148
  <Project Sdk="Microsoft.Build.NoTargets">
151
-
149
+
152
150
  <ItemGroup>
153
151
  <ProjectReference Include="test-project/test-project.csproj" />
154
152
  </ItemGroup>
@@ -161,7 +159,7 @@ public partial class UpdateWorkerTests
161
159
  <PropertyGroup>
162
160
  <TargetFramework>netstandard2.0</TargetFramework>
163
161
  </PropertyGroup>
164
-
162
+
165
163
  <ItemGroup>
166
164
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
167
165
  </ItemGroup>
@@ -177,7 +175,7 @@ public partial class UpdateWorkerTests
177
175
  // initial
178
176
  projectContents: """
179
177
  <Project Sdk="Microsoft.Build.NoTargets">
180
-
178
+
181
179
  <ItemGroup>
182
180
  <ProjectReference Include="src/*.proj" />
183
181
  </ItemGroup>
@@ -189,7 +187,7 @@ public partial class UpdateWorkerTests
189
187
  ("src/dirs.proj",
190
188
  """
191
189
  <Project Sdk="Microsoft.Build.NoTargets">
192
-
190
+
193
191
  <ItemGroup>
194
192
  <ProjectReference Include="test-project/test-project.csproj" />
195
193
  </ItemGroup>
@@ -202,7 +200,7 @@ public partial class UpdateWorkerTests
202
200
  <PropertyGroup>
203
201
  <TargetFramework>netstandard2.0</TargetFramework>
204
202
  </PropertyGroup>
205
-
203
+
206
204
  <ItemGroup>
207
205
  <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
208
206
  </ItemGroup>
@@ -212,7 +210,7 @@ public partial class UpdateWorkerTests
212
210
  // expected
213
211
  expectedProjectContents: """
214
212
  <Project Sdk="Microsoft.Build.NoTargets">
215
-
213
+
216
214
  <ItemGroup>
217
215
  <ProjectReference Include="src/*.proj" />
218
216
  </ItemGroup>
@@ -224,7 +222,7 @@ public partial class UpdateWorkerTests
224
222
  ("src/dirs.proj",
225
223
  """
226
224
  <Project Sdk="Microsoft.Build.NoTargets">
227
-
225
+
228
226
  <ItemGroup>
229
227
  <ProjectReference Include="test-project/test-project.csproj" />
230
228
  </ItemGroup>
@@ -237,7 +235,7 @@ public partial class UpdateWorkerTests
237
235
  <PropertyGroup>
238
236
  <TargetFramework>netstandard2.0</TargetFramework>
239
237
  </PropertyGroup>
240
-
238
+
241
239
  <ItemGroup>
242
240
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
243
241
  </ItemGroup>
@@ -253,7 +251,7 @@ public partial class UpdateWorkerTests
253
251
  // initial
254
252
  projectContents: """
255
253
  <Project Sdk="Microsoft.Build.NoTargets">
256
-
254
+
257
255
  <ItemGroup>
258
256
  <ProjectReference Include="**/*.proj" />
259
257
  </ItemGroup>
@@ -265,7 +263,7 @@ public partial class UpdateWorkerTests
265
263
  ("src/dirs.proj",
266
264
  """
267
265
  <Project Sdk="Microsoft.Build.NoTargets">
268
-
266
+
269
267
  <ItemGroup>
270
268
  <ProjectReference Include="test-project/test-project.csproj" />
271
269
  </ItemGroup>
@@ -278,7 +276,7 @@ public partial class UpdateWorkerTests
278
276
  <PropertyGroup>
279
277
  <TargetFramework>netstandard2.0</TargetFramework>
280
278
  </PropertyGroup>
281
-
279
+
282
280
  <ItemGroup>
283
281
  <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
284
282
  </ItemGroup>
@@ -288,7 +286,7 @@ public partial class UpdateWorkerTests
288
286
  // expected
289
287
  expectedProjectContents: """
290
288
  <Project Sdk="Microsoft.Build.NoTargets">
291
-
289
+
292
290
  <ItemGroup>
293
291
  <ProjectReference Include="**/*.proj" />
294
292
  </ItemGroup>
@@ -300,7 +298,7 @@ public partial class UpdateWorkerTests
300
298
  ("src/dirs.proj",
301
299
  """
302
300
  <Project Sdk="Microsoft.Build.NoTargets">
303
-
301
+
304
302
  <ItemGroup>
305
303
  <ProjectReference Include="test-project/test-project.csproj" />
306
304
  </ItemGroup>
@@ -313,7 +311,7 @@ public partial class UpdateWorkerTests
313
311
  <PropertyGroup>
314
312
  <TargetFramework>netstandard2.0</TargetFramework>
315
313
  </PropertyGroup>
316
-
314
+
317
315
  <ItemGroup>
318
316
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
319
317
  </ItemGroup>