dependabot-nuget 0.258.0 → 0.259.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 +4 -4
- data/helpers/lib/NuGetUpdater/Directory.Packages.props +2 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +2 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +255 -191
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +63 -35
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +107 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +9 -5
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +18 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +6 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +6 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +6 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +11 -21
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +95 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +204 -62
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +64 -45
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +419 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryDirectory.cs +7 -2
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +77 -19
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +120 -91
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +132 -97
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +93 -75
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +45 -42
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +1089 -956
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +1624 -1291
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +296 -293
- data/helpers/lib/NuGetUpdater/global.json +6 -0
- data/lib/dependabot/nuget/file_parser.rb +4 -5
- data/lib/dependabot/nuget/file_updater.rb +1 -1
- data/lib/dependabot/nuget/update_checker/dependency_finder.rb +7 -2
- data/lib/dependabot/nuget/update_checker/property_updater.rb +1 -0
- data/lib/dependabot/nuget/update_checker/version_finder.rb +2 -3
- data/lib/dependabot/nuget/update_checker.rb +1 -0
- metadata +8 -5
@@ -0,0 +1,419 @@
|
|
1
|
+
using System.IO.Compression;
|
2
|
+
using System.Security.Cryptography;
|
3
|
+
using System.Text;
|
4
|
+
using System.Text.Json.Nodes;
|
5
|
+
using System.Text.RegularExpressions;
|
6
|
+
using System.Xml;
|
7
|
+
using System.Xml.Linq;
|
8
|
+
using System.Xml.XPath;
|
9
|
+
|
10
|
+
using Microsoft.CodeAnalysis;
|
11
|
+
using Microsoft.CodeAnalysis.CSharp;
|
12
|
+
using Microsoft.CodeAnalysis.Emit;
|
13
|
+
|
14
|
+
namespace NuGetUpdater.Core.Test
|
15
|
+
{
|
16
|
+
public record MockNuGetPackage(
|
17
|
+
string Id,
|
18
|
+
string Version,
|
19
|
+
XElement[]? AdditionalMetadata = null,
|
20
|
+
(string? TargetFramework, (string Id, string Version)[] Packages)[]? DependencyGroups = null,
|
21
|
+
(string Path, byte[] Content)[]? Files = null)
|
22
|
+
{
|
23
|
+
private static readonly XNamespace Namespace = "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd";
|
24
|
+
private static readonly XmlWriterSettings WriterSettings = new()
|
25
|
+
{
|
26
|
+
Encoding = Encoding.UTF8,
|
27
|
+
Indent = true,
|
28
|
+
};
|
29
|
+
|
30
|
+
private XDocument? _nuspec;
|
31
|
+
private Stream? _stream;
|
32
|
+
|
33
|
+
public void WriteToDirectory(string localPackageSourcePath)
|
34
|
+
{
|
35
|
+
string cachePath = Path.Join(localPackageSourcePath, "_nupkg_cache");
|
36
|
+
string nupkgPath = Path.Join(cachePath, $"{Id}.{Version}.nupkg");
|
37
|
+
Directory.CreateDirectory(cachePath);
|
38
|
+
Stream stream = GetZipStream();
|
39
|
+
using (FileStream fileStream = new(nupkgPath, FileMode.Create))
|
40
|
+
{
|
41
|
+
stream.CopyTo(fileStream);
|
42
|
+
}
|
43
|
+
|
44
|
+
// add the package to the local feed; this is equivalent to running
|
45
|
+
// nuget add <nupkgPath> -source <localPackageSourcePath>
|
46
|
+
// but running that in-process locks the files, so we have to do it manually
|
47
|
+
// the end result is 4 files:
|
48
|
+
// .nupkg.metadata // a JSON object with the package's content hash and some other fields
|
49
|
+
// <id>.<version>.nupkg // the package itself
|
50
|
+
// <id>.<version>.nupkg.sha512 // the SHA512 hash of the package
|
51
|
+
// <id>.nuspec // the package's nuspec file
|
52
|
+
string expandedPath = Path.Join(localPackageSourcePath, Id.ToLowerInvariant(), Version);
|
53
|
+
Directory.CreateDirectory(expandedPath);
|
54
|
+
File.Copy(nupkgPath, Path.Join(expandedPath, $"{Id}.{Version}.nupkg".ToLowerInvariant()));
|
55
|
+
using XmlWriter writer = XmlWriter.Create(Path.Join(expandedPath, $"{Id}.nuspec".ToLowerInvariant()), WriterSettings);
|
56
|
+
GetNuspec().WriteTo(writer);
|
57
|
+
using SHA512 sha512 = SHA512.Create();
|
58
|
+
byte[] hash = sha512.ComputeHash(File.ReadAllBytes(nupkgPath));
|
59
|
+
string hashString = Convert.ToBase64String(hash);
|
60
|
+
File.WriteAllText(Path.Join(expandedPath, $"{Id}.{Version}.nupkg.sha512".ToLowerInvariant()), hashString);
|
61
|
+
JsonObject metadata = new()
|
62
|
+
{
|
63
|
+
["version"] = 2,
|
64
|
+
["contentHash"] = hashString,
|
65
|
+
["source"] = null,
|
66
|
+
};
|
67
|
+
File.WriteAllText(Path.Join(expandedPath, ".nupkg.metadata"), metadata.ToString());
|
68
|
+
}
|
69
|
+
|
70
|
+
/// <summary>
|
71
|
+
/// Creates a mock NuGet package with a single assembly in the appropriate `lib/` directory. The assembly will
|
72
|
+
/// be empty.
|
73
|
+
/// </summary>
|
74
|
+
public static MockNuGetPackage CreateSimplePackage(string id, string version, string targetFramework, (string? TargetFramework, (string Id, string Version)[] Packages)[]? dependencyGroups = null)
|
75
|
+
{
|
76
|
+
return new(
|
77
|
+
id,
|
78
|
+
version,
|
79
|
+
AdditionalMetadata: null,
|
80
|
+
DependencyGroups: dependencyGroups,
|
81
|
+
Files:
|
82
|
+
[
|
83
|
+
($"lib/{targetFramework}/{id}.dll", Array.Empty<byte>())
|
84
|
+
]
|
85
|
+
);
|
86
|
+
}
|
87
|
+
|
88
|
+
/// <summary>
|
89
|
+
/// Creates a mock NuGet package with a single assembly in the appropriate `lib/` directory. The assembly will
|
90
|
+
/// contain the appropriate `AssemblyVersion` attribute and nothing else.
|
91
|
+
/// </summary>
|
92
|
+
public static MockNuGetPackage CreatePackageWithAssembly(string id, string version, string targetFramework, string assemblyVersion, (string? TargetFramework, (string Id, string Version)[] Packages)[]? dependencyGroups = null)
|
93
|
+
{
|
94
|
+
return new(
|
95
|
+
id,
|
96
|
+
version,
|
97
|
+
AdditionalMetadata: null,
|
98
|
+
DependencyGroups: dependencyGroups,
|
99
|
+
Files:
|
100
|
+
[
|
101
|
+
($"lib/{targetFramework}/{id}.dll", CreateAssembly(id, assemblyVersion))
|
102
|
+
]
|
103
|
+
);
|
104
|
+
}
|
105
|
+
|
106
|
+
/// <summary>
|
107
|
+
/// Creates a mock NuGet package with empty analyzer assemblies for both C# and VB.
|
108
|
+
/// </summary>
|
109
|
+
public static MockNuGetPackage CreateAnalyzerPackage(string id, string version, (string? TargetFramework, (string Id, string Version)[] Packages)[]? dependencyGroups = null)
|
110
|
+
{
|
111
|
+
return new(
|
112
|
+
id,
|
113
|
+
version,
|
114
|
+
AdditionalMetadata:
|
115
|
+
[
|
116
|
+
new XElement("developmentDependency", "true"),
|
117
|
+
],
|
118
|
+
DependencyGroups: dependencyGroups,
|
119
|
+
Files:
|
120
|
+
[
|
121
|
+
($"analyzers/dotnet/cs/{id}.dll", Array.Empty<byte>()),
|
122
|
+
($"analyzers/dotnet/vb/{id}.dll", Array.Empty<byte>()),
|
123
|
+
]
|
124
|
+
);
|
125
|
+
}
|
126
|
+
|
127
|
+
public static MockNuGetPackage CreateDotNetToolPackage(string id, string version, string targetFramework)
|
128
|
+
{
|
129
|
+
return new(
|
130
|
+
id,
|
131
|
+
version,
|
132
|
+
AdditionalMetadata:
|
133
|
+
[
|
134
|
+
new XElement("packageTypes",
|
135
|
+
new XElement("packageType",
|
136
|
+
new XAttribute("name", "DotnetTool")
|
137
|
+
)
|
138
|
+
)
|
139
|
+
],
|
140
|
+
Files:
|
141
|
+
[
|
142
|
+
($"tools/{targetFramework}/any/DotnetToolSettings.xml", Encoding.UTF8.GetBytes($"""
|
143
|
+
<DotNetCliTool Version="1">
|
144
|
+
<Commands>
|
145
|
+
<Command Name="{id}" EntryPoint="{id}.dll" Runner="dotnet" />
|
146
|
+
</Commands>
|
147
|
+
</DotNetCliTool>
|
148
|
+
""")),
|
149
|
+
($"tools/{targetFramework}/any/{id}.dll", Array.Empty<byte>()),
|
150
|
+
]
|
151
|
+
);
|
152
|
+
}
|
153
|
+
|
154
|
+
public static MockNuGetPackage CreateMSBuildSdkPackage(string id, string version, string? sdkPropsContent = null, string? sdkTargetsContent = null)
|
155
|
+
{
|
156
|
+
sdkPropsContent ??= """
|
157
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
158
|
+
</Project>
|
159
|
+
""";
|
160
|
+
sdkTargetsContent ??= """
|
161
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
162
|
+
</Project>
|
163
|
+
""";
|
164
|
+
return new(
|
165
|
+
id,
|
166
|
+
version,
|
167
|
+
AdditionalMetadata:
|
168
|
+
[
|
169
|
+
new XElement("packageTypes",
|
170
|
+
new XElement("packageType",
|
171
|
+
new XAttribute("name", "MSBuildSdk")
|
172
|
+
)
|
173
|
+
)
|
174
|
+
],
|
175
|
+
Files:
|
176
|
+
[
|
177
|
+
("Sdk/Sdk.props", Encoding.UTF8.GetBytes(sdkPropsContent)),
|
178
|
+
("Sdk/Sdk.targets", Encoding.UTF8.GetBytes(sdkTargetsContent)),
|
179
|
+
]
|
180
|
+
);
|
181
|
+
}
|
182
|
+
|
183
|
+
private XDocument GetNuspec()
|
184
|
+
{
|
185
|
+
if (_nuspec is null)
|
186
|
+
{
|
187
|
+
_nuspec = new XDocument(
|
188
|
+
new XElement(Namespace + "package",
|
189
|
+
new XElement(Namespace + "metadata",
|
190
|
+
new XElement(Namespace + "id", Id),
|
191
|
+
new XElement(Namespace + "version", Version),
|
192
|
+
new XElement(Namespace + "authors", "MockNuGetPackage"),
|
193
|
+
new XElement(Namespace + "description", "Mock NuGet package"),
|
194
|
+
AdditionalMetadata?.Select(a => WithNamespace(a, Namespace)),
|
195
|
+
new XElement(Namespace + "dependencies",
|
196
|
+
// dependencies with no target framework
|
197
|
+
DependencyGroups?.Where(g => g.TargetFramework is null).SelectMany(g =>
|
198
|
+
g.Packages.Select(p =>
|
199
|
+
new XElement(Namespace + "dependency",
|
200
|
+
new XAttribute("id", p.Id),
|
201
|
+
new XAttribute("version", p.Version)
|
202
|
+
)
|
203
|
+
)
|
204
|
+
),
|
205
|
+
// dependencies with a target framework
|
206
|
+
DependencyGroups?.Where(g => g.TargetFramework is not null).Select(g =>
|
207
|
+
new XElement(Namespace + "group",
|
208
|
+
new XAttribute("targetFramework", g.TargetFramework!),
|
209
|
+
g.Packages.Select(p =>
|
210
|
+
new XElement(Namespace + "dependency",
|
211
|
+
new XAttribute("id", p.Id),
|
212
|
+
new XAttribute("version", p.Version)
|
213
|
+
)
|
214
|
+
)
|
215
|
+
)
|
216
|
+
)
|
217
|
+
)
|
218
|
+
)
|
219
|
+
)
|
220
|
+
);
|
221
|
+
}
|
222
|
+
|
223
|
+
return _nuspec;
|
224
|
+
}
|
225
|
+
|
226
|
+
private static XElement WithNamespace(XElement element, XNamespace ns)
|
227
|
+
{
|
228
|
+
return new XElement(ns + element.Name.LocalName,
|
229
|
+
element.Attributes(),
|
230
|
+
element.Nodes().Select(n =>
|
231
|
+
{
|
232
|
+
if (n is XElement e)
|
233
|
+
{
|
234
|
+
return WithNamespace(e, ns);
|
235
|
+
}
|
236
|
+
|
237
|
+
return n;
|
238
|
+
})
|
239
|
+
);
|
240
|
+
}
|
241
|
+
|
242
|
+
private Stream GetZipStream()
|
243
|
+
{
|
244
|
+
if (_stream is null)
|
245
|
+
{
|
246
|
+
XDocument nuspec = GetNuspec();
|
247
|
+
_stream = new MemoryStream();
|
248
|
+
using ZipArchive zip = new(_stream, ZipArchiveMode.Create, leaveOpen: true);
|
249
|
+
ZipArchiveEntry nuspecEntry = zip.CreateEntry($"{Id}.nuspec");
|
250
|
+
using (Stream contentStream = nuspecEntry.Open())
|
251
|
+
using (XmlWriter writer = XmlWriter.Create(contentStream, WriterSettings))
|
252
|
+
{
|
253
|
+
nuspec.WriteTo(writer);
|
254
|
+
}
|
255
|
+
|
256
|
+
foreach (var file in Files ?? [])
|
257
|
+
{
|
258
|
+
ZipArchiveEntry fileEntry = zip.CreateEntry(file.Path);
|
259
|
+
using Stream contentStream = fileEntry.Open();
|
260
|
+
contentStream.Write(file.Content, 0, file.Content.Length);
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
_stream.Seek(0, SeekOrigin.Begin);
|
265
|
+
return _stream;
|
266
|
+
}
|
267
|
+
|
268
|
+
private static byte[] CreateAssembly(string assemblyName, string assemblyVersion)
|
269
|
+
{
|
270
|
+
CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary);
|
271
|
+
CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, options: compilationOptions)
|
272
|
+
.AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
|
273
|
+
.AddSyntaxTrees(CSharpSyntaxTree.ParseText($"[assembly: System.Reflection.AssemblyVersionAttribute(\"{assemblyVersion}\")]"));
|
274
|
+
MemoryStream assemblyStream = new();
|
275
|
+
EmitResult emitResult = compilation.Emit(assemblyStream);
|
276
|
+
if (!emitResult.Success)
|
277
|
+
{
|
278
|
+
throw new Exception($"Unable to create test assembly:\n\t{string.Join("\n\t", emitResult.Diagnostics.ToString())}");
|
279
|
+
}
|
280
|
+
|
281
|
+
return assemblyStream.ToArray();
|
282
|
+
}
|
283
|
+
|
284
|
+
// some well-known packages
|
285
|
+
public static MockNuGetPackage CentralPackageVersionsPackage =>
|
286
|
+
CreateMSBuildSdkPackage(
|
287
|
+
"Microsoft.Build.CentralPackageVersions",
|
288
|
+
"2.1.3",
|
289
|
+
sdkTargetsContent: """
|
290
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
291
|
+
<!-- this is a simplified version of this package used for testing -->
|
292
|
+
<PropertyGroup>
|
293
|
+
<CentralPackagesFile Condition=" '$(CentralPackagesFile)' == '' ">$([MSBuild]::GetPathOfFileAbove('Packages.props', $(MSBuildProjectDirectory)))</CentralPackagesFile>
|
294
|
+
</PropertyGroup>
|
295
|
+
<Import Project="$(CentralPackagesFile)" Condition="Exists('$(CentralPackagesFile)')" />
|
296
|
+
</Project>
|
297
|
+
"""
|
298
|
+
);
|
299
|
+
|
300
|
+
private static readonly Lazy<string> BundledVersionsPropsPath = new(() =>
|
301
|
+
{
|
302
|
+
// we need to find the file `Microsoft.NETCoreSdk.BundledVersions.props` in the SDK directory
|
303
|
+
|
304
|
+
DirectoryInfo projectDir = Directory.CreateTempSubdirectory("bundled_versions_props_path_discovery_");
|
305
|
+
try
|
306
|
+
{
|
307
|
+
// get the sdk version
|
308
|
+
string projectPath = Path.Combine(projectDir.FullName, "project.csproj");
|
309
|
+
File.WriteAllText(projectPath, """
|
310
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
311
|
+
<Target Name="_ReportCurrentSdkVersion">
|
312
|
+
<Message Text="_CurrentSdkVersion=$(NETCoreSdkVersion)" Importance="High" />
|
313
|
+
</Target>
|
314
|
+
</Project>
|
315
|
+
"""
|
316
|
+
);
|
317
|
+
var (exitCode, stdout, stderr) = ProcessEx.RunAsync("dotnet", $"msbuild {projectPath} /t:_ReportCurrentSdkVersion").Result;
|
318
|
+
if (exitCode != 0)
|
319
|
+
{
|
320
|
+
throw new Exception($"Failed to report the current SDK version:\n{stdout}\n{stderr}");
|
321
|
+
}
|
322
|
+
|
323
|
+
MatchCollection matches = Regex.Matches(stdout, "_CurrentSdkVersion=(?<SdkVersion>.*)$", RegexOptions.Multiline);
|
324
|
+
if (matches.Count == 0)
|
325
|
+
{
|
326
|
+
throw new Exception($"Failed to find the current SDK version in the output:\n{stdout}");
|
327
|
+
}
|
328
|
+
|
329
|
+
string sdkVersionString = matches.First().Groups["SdkVersion"].Value.Trim();
|
330
|
+
|
331
|
+
// find the actual SDK directory
|
332
|
+
string privateCoreLibPath = typeof(object).Assembly.Location; // e.g., C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.4\System.Private.CoreLib.dll
|
333
|
+
string sdkDirectory = Path.Combine(Path.GetDirectoryName(privateCoreLibPath)!, "..", "..", "..", "sdk", sdkVersionString); // e.g., C:\Program Files\dotnet\sdk\8.0.204
|
334
|
+
string bundledVersionsPropsPath = Path.Combine(sdkDirectory, "Microsoft.NETCoreSdk.BundledVersions.props");
|
335
|
+
FileInfo normalizedPath = new(bundledVersionsPropsPath);
|
336
|
+
return normalizedPath.FullName;
|
337
|
+
}
|
338
|
+
finally
|
339
|
+
{
|
340
|
+
projectDir.Delete(recursive: true);
|
341
|
+
}
|
342
|
+
});
|
343
|
+
|
344
|
+
private static readonly Dictionary<string, MockNuGetPackage> WellKnownPackages = new();
|
345
|
+
public static MockNuGetPackage WellKnownReferencePackage(string packageName, string targetFramework, (string Path, byte[] Content)[]? files = null)
|
346
|
+
{
|
347
|
+
string key = $"{packageName}/{targetFramework}";
|
348
|
+
if (!WellKnownPackages.ContainsKey(key))
|
349
|
+
{
|
350
|
+
// for the current SDK, the file `Microsoft.NETCoreSdk.BundledVersions.props` contains the version of the
|
351
|
+
// `Microsoft.WindowsDesktop.App.Ref` package that will be needed to build, so we find it by TFM
|
352
|
+
XDocument propsDocument = XDocument.Load(BundledVersionsPropsPath.Value);
|
353
|
+
XElement? matchingFrameworkElement = propsDocument.XPathSelectElement(
|
354
|
+
$"""
|
355
|
+
/Project/ItemGroup/KnownFrameworkReference
|
356
|
+
[
|
357
|
+
@Include='{packageName}' and
|
358
|
+
@TargetingPackName='{packageName}.Ref' and
|
359
|
+
@TargetFramework='{targetFramework}'
|
360
|
+
]
|
361
|
+
""");
|
362
|
+
if (matchingFrameworkElement is null)
|
363
|
+
{
|
364
|
+
throw new Exception($"Unable to find {packageName}.Ref version for target framework '{targetFramework}'");
|
365
|
+
}
|
366
|
+
|
367
|
+
string expectedVersion = matchingFrameworkElement.Attribute("TargetingPackVersion")!.Value;
|
368
|
+
return new(
|
369
|
+
$"{packageName}.Ref",
|
370
|
+
expectedVersion,
|
371
|
+
AdditionalMetadata:
|
372
|
+
[
|
373
|
+
new XElement("packageTypes",
|
374
|
+
new XElement("packageType",
|
375
|
+
new XAttribute("name", "DotnetPlatform")
|
376
|
+
)
|
377
|
+
)
|
378
|
+
],
|
379
|
+
Files: files
|
380
|
+
);
|
381
|
+
}
|
382
|
+
|
383
|
+
return WellKnownPackages[key];
|
384
|
+
}
|
385
|
+
|
386
|
+
public static MockNuGetPackage[] CommonPackages { get; } =
|
387
|
+
[
|
388
|
+
CreateSimplePackage("NETStandard.Library", "2.0.3", "netstandard2.0"),
|
389
|
+
new MockNuGetPackage("Microsoft.NETFramework.ReferenceAssemblies", "1.0.3"),
|
390
|
+
WellKnownReferencePackage("Microsoft.AspNetCore.App", "net6.0"),
|
391
|
+
WellKnownReferencePackage("Microsoft.AspNetCore.App", "net7.0"),
|
392
|
+
WellKnownReferencePackage("Microsoft.AspNetCore.App", "net8.0"),
|
393
|
+
WellKnownReferencePackage("Microsoft.NETCore.App", "net6.0",
|
394
|
+
[
|
395
|
+
("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
|
396
|
+
<FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="6.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
|
397
|
+
</FileList>
|
398
|
+
"""))
|
399
|
+
]),
|
400
|
+
WellKnownReferencePackage("Microsoft.NETCore.App", "net7.0",
|
401
|
+
[
|
402
|
+
("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
|
403
|
+
<FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="7.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
|
404
|
+
</FileList>
|
405
|
+
"""))
|
406
|
+
]),
|
407
|
+
WellKnownReferencePackage("Microsoft.NETCore.App", "net8.0",
|
408
|
+
[
|
409
|
+
("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
|
410
|
+
<FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="8.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
|
411
|
+
</FileList>
|
412
|
+
"""))
|
413
|
+
]),
|
414
|
+
WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net6.0"),
|
415
|
+
WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net7.0"),
|
416
|
+
WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net8.0"),
|
417
|
+
];
|
418
|
+
}
|
419
|
+
}
|
@@ -12,6 +12,7 @@
|
|
12
12
|
|
13
13
|
<ItemGroup>
|
14
14
|
<PackageReference Include="DiffPlex" />
|
15
|
+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
15
16
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
16
17
|
<PackageReference Include="xunit" />
|
17
18
|
<PackageReference Include="xunit.runner.visualstudio" />
|
@@ -50,9 +50,14 @@ public sealed class TemporaryDirectory : IDisposable
|
|
50
50
|
var parentDirectory = Path.GetDirectoryName(temporaryDirectory.DirectoryPath)!;
|
51
51
|
|
52
52
|
// prevent directory crawling
|
53
|
-
await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Build.props"), "
|
53
|
+
await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Build.props"), """
|
54
|
+
<Project>
|
55
|
+
<PropertyGroup>
|
56
|
+
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
|
57
|
+
</PropertyGroup>
|
58
|
+
</Project>
|
59
|
+
""");
|
54
60
|
await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Build.targets"), "<Project />");
|
55
|
-
await File.WriteAllTextAsync(Path.Combine(parentDirectory, "Directory.Packages.props"), "<Project />");
|
56
61
|
|
57
62
|
foreach (var (path, contents) in fileContents)
|
58
63
|
{
|
@@ -1,8 +1,3 @@
|
|
1
|
-
using System;
|
2
|
-
using System.IO;
|
3
|
-
using System.Linq;
|
4
|
-
using System.Threading.Tasks;
|
5
|
-
|
6
1
|
using Xunit;
|
7
2
|
|
8
3
|
namespace NuGetUpdater.Core.Test.Update;
|
@@ -20,11 +15,12 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
20
15
|
string projectContents,
|
21
16
|
bool isTransitive = false,
|
22
17
|
TestFile[]? additionalFiles = null,
|
18
|
+
MockNuGetPackage[]? packages = null,
|
23
19
|
string projectFilePath = "test-project.csproj")
|
24
20
|
{
|
25
21
|
return useSolution
|
26
|
-
? TestNoChangeforSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], isTransitive, additionalFiles)
|
27
|
-
: TestNoChangeforProject(dependencyName, oldVersion, newVersion, projectContents, isTransitive, additionalFiles, projectFilePath);
|
22
|
+
? TestNoChangeforSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], isTransitive, additionalFiles, packages)
|
23
|
+
: TestNoChangeforProject(dependencyName, oldVersion, newVersion, projectContents, isTransitive, additionalFiles, packages, projectFilePath);
|
28
24
|
}
|
29
25
|
|
30
26
|
protected static Task TestUpdate(
|
@@ -37,11 +33,12 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
37
33
|
bool isTransitive = false,
|
38
34
|
TestFile[]? additionalFiles = null,
|
39
35
|
TestFile[]? additionalFilesExpected = null,
|
36
|
+
MockNuGetPackage[]? packages = null,
|
40
37
|
string projectFilePath = "test-project.csproj")
|
41
38
|
{
|
42
39
|
return useSolution
|
43
|
-
? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], projectFilesExpected: [(projectFilePath, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected)
|
44
|
-
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected);
|
40
|
+
? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], projectFilesExpected: [(projectFilePath, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected, packages)
|
41
|
+
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, packages);
|
45
42
|
}
|
46
43
|
|
47
44
|
protected static Task TestUpdate(
|
@@ -53,11 +50,12 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
53
50
|
string expectedProjectContents,
|
54
51
|
bool isTransitive = false,
|
55
52
|
TestFile[]? additionalFiles = null,
|
56
|
-
TestFile[]? additionalFilesExpected = null
|
53
|
+
TestFile[]? additionalFilesExpected = null,
|
54
|
+
MockNuGetPackage[]? packages = null)
|
57
55
|
{
|
58
56
|
return useSolution
|
59
|
-
? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [projectFile], projectFilesExpected: [(projectFile.Path, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected)
|
60
|
-
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected);
|
57
|
+
? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [projectFile], projectFilesExpected: [(projectFile.Path, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected, packages)
|
58
|
+
: TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, packages);
|
61
59
|
}
|
62
60
|
|
63
61
|
protected static Task TestNoChangeforProject(
|
@@ -67,6 +65,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
67
65
|
string projectContents,
|
68
66
|
bool isTransitive = false,
|
69
67
|
TestFile[]? additionalFiles = null,
|
68
|
+
MockNuGetPackage[]? packages = null,
|
70
69
|
string projectFilePath = "test-project.csproj")
|
71
70
|
=> TestUpdateForProject(
|
72
71
|
dependencyName,
|
@@ -76,7 +75,8 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
76
75
|
expectedProjectContents: projectContents,
|
77
76
|
isTransitive,
|
78
77
|
additionalFiles,
|
79
|
-
additionalFilesExpected: additionalFiles
|
78
|
+
additionalFilesExpected: additionalFiles,
|
79
|
+
packages: packages);
|
80
80
|
|
81
81
|
protected static Task TestUpdateForProject(
|
82
82
|
string dependencyName,
|
@@ -87,6 +87,7 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
87
87
|
bool isTransitive = false,
|
88
88
|
TestFile[]? additionalFiles = null,
|
89
89
|
TestFile[]? additionalFilesExpected = null,
|
90
|
+
MockNuGetPackage[]? packages = null,
|
90
91
|
string projectFilePath = "test-project.csproj")
|
91
92
|
=> TestUpdateForProject(
|
92
93
|
dependencyName,
|
@@ -96,7 +97,8 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
96
97
|
expectedProjectContents,
|
97
98
|
isTransitive,
|
98
99
|
additionalFiles,
|
99
|
-
additionalFilesExpected
|
100
|
+
additionalFilesExpected,
|
101
|
+
packages);
|
100
102
|
|
101
103
|
protected static async Task TestUpdateForProject(
|
102
104
|
string dependencyName,
|
@@ -106,21 +108,36 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
106
108
|
string expectedProjectContents,
|
107
109
|
bool isTransitive = false,
|
108
110
|
TestFile[]? additionalFiles = null,
|
109
|
-
TestFile[]? additionalFilesExpected = null
|
111
|
+
TestFile[]? additionalFilesExpected = null,
|
112
|
+
MockNuGetPackage[]? packages = null)
|
110
113
|
{
|
111
114
|
additionalFiles ??= [];
|
112
115
|
additionalFilesExpected ??= [];
|
113
116
|
|
117
|
+
var placeFilesInSrc = packages is not null;
|
118
|
+
|
114
119
|
var projectFilePath = projectFile.Path;
|
115
120
|
var testFiles = new[] { projectFile }.Concat(additionalFiles).ToArray();
|
121
|
+
if (placeFilesInSrc)
|
122
|
+
{
|
123
|
+
testFiles = testFiles.Select(f => ($"src/{f.Path}", f.Content)).ToArray();
|
124
|
+
}
|
116
125
|
|
117
126
|
var actualResult = await RunUpdate(testFiles, async temporaryDirectory =>
|
118
127
|
{
|
128
|
+
await MockNuGetPackagesInDirectory(packages, temporaryDirectory);
|
129
|
+
|
130
|
+
// run update
|
119
131
|
var worker = new UpdaterWorker(new Logger(verbose: true));
|
120
|
-
|
132
|
+
var projectPath = placeFilesInSrc ? $"src/{projectFilePath}" : projectFilePath;
|
133
|
+
await worker.RunAsync(temporaryDirectory, projectPath, dependencyName, oldVersion, newVersion, isTransitive);
|
121
134
|
});
|
122
135
|
|
123
136
|
var expectedResult = additionalFilesExpected.Prepend((projectFilePath, expectedProjectContents)).ToArray();
|
137
|
+
if (placeFilesInSrc)
|
138
|
+
{
|
139
|
+
expectedResult = expectedResult.Select(er => ($"src/{er.Item1}", er.Item2)).ToArray();
|
140
|
+
}
|
124
141
|
|
125
142
|
AssertContainsFiles(expectedResult, actualResult);
|
126
143
|
}
|
@@ -131,7 +148,8 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
131
148
|
string newVersion,
|
132
149
|
TestFile[] projectFiles,
|
133
150
|
bool isTransitive = false,
|
134
|
-
TestFile[]? additionalFiles = null
|
151
|
+
TestFile[]? additionalFiles = null,
|
152
|
+
MockNuGetPackage[]? packages = null)
|
135
153
|
=> TestUpdateForSolution(
|
136
154
|
dependencyName,
|
137
155
|
oldVersion,
|
@@ -140,7 +158,8 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
140
158
|
projectFilesExpected: projectFiles,
|
141
159
|
isTransitive,
|
142
160
|
additionalFiles,
|
143
|
-
additionalFilesExpected: additionalFiles
|
161
|
+
additionalFilesExpected: additionalFiles,
|
162
|
+
packages: packages);
|
144
163
|
|
145
164
|
protected static async Task TestUpdateForSolution(
|
146
165
|
string dependencyName,
|
@@ -150,7 +169,8 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
150
169
|
TestFile[] projectFilesExpected,
|
151
170
|
bool isTransitive = false,
|
152
171
|
TestFile[]? additionalFiles = null,
|
153
|
-
TestFile[]? additionalFilesExpected = null
|
172
|
+
TestFile[]? additionalFilesExpected = null,
|
173
|
+
MockNuGetPackage[]? packages = null)
|
154
174
|
{
|
155
175
|
additionalFiles ??= [];
|
156
176
|
additionalFilesExpected ??= [];
|
@@ -191,6 +211,8 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
191
211
|
|
192
212
|
var actualResult = await RunUpdate(testFiles, async temporaryDirectory =>
|
193
213
|
{
|
214
|
+
await MockNuGetPackagesInDirectory(packages, temporaryDirectory);
|
215
|
+
|
194
216
|
var slnPath = Path.Combine(temporaryDirectory, slnName);
|
195
217
|
var worker = new UpdaterWorker(new Logger(verbose: true));
|
196
218
|
await worker.RunAsync(temporaryDirectory, slnPath, dependencyName, oldVersion, newVersion, isTransitive);
|
@@ -201,6 +223,42 @@ public abstract class UpdateWorkerTestBase : TestBase
|
|
201
223
|
AssertContainsFiles(expectedResult, actualResult);
|
202
224
|
}
|
203
225
|
|
226
|
+
public static async Task MockNuGetPackagesInDirectory(MockNuGetPackage[]? packages, string temporaryDirectory)
|
227
|
+
{
|
228
|
+
if (packages is not null)
|
229
|
+
{
|
230
|
+
string localFeedPath = Path.Join(temporaryDirectory, "local-feed");
|
231
|
+
Directory.CreateDirectory(localFeedPath);
|
232
|
+
MockNuGetPackage[] allPackages = packages.Concat(MockNuGetPackage.CommonPackages).ToArray();
|
233
|
+
|
234
|
+
// write all packages to disk
|
235
|
+
foreach (MockNuGetPackage package in allPackages)
|
236
|
+
{
|
237
|
+
package.WriteToDirectory(localFeedPath);
|
238
|
+
}
|
239
|
+
|
240
|
+
// override various nuget locations
|
241
|
+
foreach (var envName in new[] { "NUGET_PACKAGES", "NUGET_HTTP_CACHE_PATH", "NUGET_SCRATCH", "NUGET_PLUGINS_CACHE_PATH" })
|
242
|
+
{
|
243
|
+
string dir = Path.Join(temporaryDirectory, envName);
|
244
|
+
Directory.CreateDirectory(dir);
|
245
|
+
Environment.SetEnvironmentVariable(envName, dir);
|
246
|
+
}
|
247
|
+
|
248
|
+
// ensure only the test feed is used
|
249
|
+
await File.WriteAllTextAsync(Path.Join(temporaryDirectory, "NuGet.Config"), $"""
|
250
|
+
<?xml version="1.0" encoding="utf-8"?>
|
251
|
+
<configuration>
|
252
|
+
<packageSources>
|
253
|
+
<clear />
|
254
|
+
<add key="local-feed" value="{localFeedPath}" />
|
255
|
+
</packageSources>
|
256
|
+
</configuration>
|
257
|
+
"""
|
258
|
+
);
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|
204
262
|
protected static async Task<TestFile[]> RunUpdate(TestFile[] files, Func<string, Task> action)
|
205
263
|
{
|
206
264
|
// write initial files
|