dependabot-nuget 0.267.0 → 0.270.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/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +1 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +6 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +16 -13
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +8 -1
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +33 -14
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +689 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +226 -23
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +84 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +14 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/TemporaryEnvironment.cs +23 -0
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +164 -55
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +186 -10
- data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +785 -1
- data/lib/dependabot/nuget/file_updater.rb +44 -22
- data/lib/dependabot/nuget/native_helpers.rb +6 -1
- metadata +7 -5
@@ -13,9 +13,12 @@ using Microsoft.Build.Exceptions;
|
|
13
13
|
using Microsoft.Build.Locator;
|
14
14
|
using Microsoft.Extensions.FileSystemGlobbing;
|
15
15
|
|
16
|
+
using NuGet;
|
16
17
|
using NuGet.Configuration;
|
18
|
+
using NuGet.Frameworks;
|
17
19
|
using NuGet.Versioning;
|
18
20
|
|
21
|
+
using NuGetUpdater.Core.Analyze;
|
19
22
|
using NuGetUpdater.Core.Utilities;
|
20
23
|
|
21
24
|
namespace NuGetUpdater.Core;
|
@@ -31,29 +34,54 @@ internal static partial class MSBuildHelper
|
|
31
34
|
// Ensure MSBuild types are registered before calling a method that loads the types
|
32
35
|
if (!IsMSBuildRegistered)
|
33
36
|
{
|
34
|
-
|
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
|
37
|
+
SidelineGlobalJsonAsync(currentDirectory, rootDirectory, () =>
|
43
38
|
{
|
44
39
|
var defaultInstance = MSBuildLocator.QueryVisualStudioInstances().First();
|
45
40
|
MSBuildPath = defaultInstance.MSBuildPath;
|
46
41
|
MSBuildLocator.RegisterInstance(defaultInstance);
|
47
|
-
|
48
|
-
|
42
|
+
return Task.CompletedTask;
|
43
|
+
}).Wait();
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
public static async Task SidelineGlobalJsonAsync(string currentDirectory, string rootDirectory, Func<Task> action, bool retainMSBuildSdks = false)
|
48
|
+
{
|
49
|
+
var candidateDirectories = PathHelper.GetAllDirectoriesToRoot(currentDirectory, rootDirectory);
|
50
|
+
var globalJsonPaths = candidateDirectories.Select(d => Path.Combine(d, "global.json")).Where(File.Exists).Select(p => (p, p + Guid.NewGuid().ToString())).ToArray();
|
51
|
+
foreach (var (globalJsonPath, tempGlobalJsonPath) in globalJsonPaths)
|
52
|
+
{
|
53
|
+
Console.WriteLine($"Temporarily removing `global.json` from `{Path.GetDirectoryName(globalJsonPath)}`{(retainMSBuildSdks ? " and retaining MSBuild SDK declarations" : string.Empty)}.");
|
54
|
+
File.Move(globalJsonPath, tempGlobalJsonPath);
|
55
|
+
if (retainMSBuildSdks)
|
49
56
|
{
|
50
|
-
|
57
|
+
// custom SDKs might need to be retained for other operations; rebuild `global.json` with only the relevant key
|
58
|
+
var originalContent = await File.ReadAllTextAsync(tempGlobalJsonPath);
|
59
|
+
var jsonNode = JsonHelper.ParseNode(originalContent);
|
60
|
+
if (jsonNode is JsonObject obj &&
|
61
|
+
obj.TryGetPropertyValue("msbuild-sdks", out var sdks) &&
|
62
|
+
sdks is not null)
|
51
63
|
{
|
52
|
-
|
53
|
-
|
64
|
+
var newObj = new JsonObject()
|
65
|
+
{
|
66
|
+
["msbuild-sdks"] = sdks.DeepClone(),
|
67
|
+
};
|
68
|
+
await File.WriteAllTextAsync(globalJsonPath, newObj.ToJsonString());
|
54
69
|
}
|
55
70
|
}
|
56
71
|
}
|
72
|
+
|
73
|
+
try
|
74
|
+
{
|
75
|
+
await action();
|
76
|
+
}
|
77
|
+
finally
|
78
|
+
{
|
79
|
+
foreach (var (globalJsonpath, tempGlobalJsonPath) in globalJsonPaths)
|
80
|
+
{
|
81
|
+
Console.WriteLine($"Restoring `global.json` to `{Path.GetDirectoryName(globalJsonpath)}`.");
|
82
|
+
File.Move(tempGlobalJsonPath, globalJsonpath, overwrite: retainMSBuildSdks);
|
83
|
+
}
|
84
|
+
}
|
57
85
|
}
|
58
86
|
|
59
87
|
public static IEnumerable<string> GetProjectPathsFromSolution(string solutionPath)
|
@@ -306,7 +334,182 @@ internal static partial class MSBuildHelper
|
|
306
334
|
}
|
307
335
|
}
|
308
336
|
|
309
|
-
internal static
|
337
|
+
internal static bool UseNewDependencySolver()
|
338
|
+
{
|
339
|
+
return Environment.GetEnvironmentVariable("UseNewNugetPackageResolver") == "true";
|
340
|
+
}
|
341
|
+
|
342
|
+
internal static async Task<Dependency[]?> ResolveDependencyConflicts(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Dependency[] update, Logger logger)
|
343
|
+
{
|
344
|
+
if (UseNewDependencySolver())
|
345
|
+
{
|
346
|
+
return await ResolveDependencyConflictsNew(repoRoot, projectPath, targetFramework, packages, update, logger);
|
347
|
+
}
|
348
|
+
else
|
349
|
+
{
|
350
|
+
return await ResolveDependencyConflictsOld(repoRoot, projectPath, targetFramework, packages, logger);
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
354
|
+
internal static async Task<Dependency[]?> ResolveDependencyConflictsNew(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Dependency[] update, Logger logger)
|
355
|
+
{
|
356
|
+
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
357
|
+
PackageManager packageManager = new PackageManager(repoRoot, projectPath);
|
358
|
+
|
359
|
+
try
|
360
|
+
{
|
361
|
+
string tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages);
|
362
|
+
var (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"restore \"{tempProjectPath}\"", workingDirectory: tempDirectory.FullName);
|
363
|
+
|
364
|
+
// Add Dependency[] packages to List<PackageToUpdate> existingPackages
|
365
|
+
List<PackageToUpdate> existingPackages = packages
|
366
|
+
.Select(existingPackage => new PackageToUpdate
|
367
|
+
{
|
368
|
+
PackageName = existingPackage.Name,
|
369
|
+
CurrentVersion = existingPackage.Version
|
370
|
+
})
|
371
|
+
.ToList();
|
372
|
+
|
373
|
+
// Add Dependency[] update to List<PackageToUpdate> packagesToUpdate
|
374
|
+
List<PackageToUpdate> packagesToUpdate = update
|
375
|
+
.Where(package => package.Version != null)
|
376
|
+
.Select(package => new PackageToUpdate
|
377
|
+
{
|
378
|
+
PackageName = package.Name,
|
379
|
+
NewVersion = package.Version.ToString()
|
380
|
+
})
|
381
|
+
.ToList();
|
382
|
+
|
383
|
+
foreach (PackageToUpdate existing in existingPackages)
|
384
|
+
{
|
385
|
+
var foundPackage = packagesToUpdate.Where(p => string.Equals(p.PackageName, existing.PackageName, StringComparison.OrdinalIgnoreCase));
|
386
|
+
if (!foundPackage.Any())
|
387
|
+
{
|
388
|
+
existing.NewVersion = existing.CurrentVersion;
|
389
|
+
}
|
390
|
+
}
|
391
|
+
|
392
|
+
// Create a duplicate set of existingPackages for flexible package reference addition and removal
|
393
|
+
List<PackageToUpdate> existingDuplicate = new List<PackageToUpdate>(existingPackages);
|
394
|
+
|
395
|
+
// Bool to keep track of if anything was added to the existingDuplicate list
|
396
|
+
bool added = false;
|
397
|
+
|
398
|
+
// If package 'isnt there, add it to the existingDuplicate list
|
399
|
+
foreach (PackageToUpdate package in packagesToUpdate)
|
400
|
+
{
|
401
|
+
if (!existingDuplicate.Any(p => string.Equals(p.PackageName, package.PackageName, StringComparison.OrdinalIgnoreCase)))
|
402
|
+
{
|
403
|
+
existingDuplicate.Add(package);
|
404
|
+
added = true;
|
405
|
+
}
|
406
|
+
}
|
407
|
+
|
408
|
+
// If you have to use the existingDuplicate list
|
409
|
+
if (added == true)
|
410
|
+
{
|
411
|
+
// Add existing versions to existing list
|
412
|
+
packageManager.UpdateExistingPackagesWithNewVersions(existingDuplicate, packagesToUpdate);
|
413
|
+
|
414
|
+
// Make relationships
|
415
|
+
await packageManager.PopulatePackageDependenciesAsync(existingDuplicate, targetFramework, Path.GetDirectoryName(projectPath));
|
416
|
+
|
417
|
+
// Update all to new versions
|
418
|
+
foreach (var package in existingDuplicate)
|
419
|
+
{
|
420
|
+
string updateResult = await packageManager.UpdateVersion(existingDuplicate, package, targetFramework, Path.GetDirectoryName(projectPath));
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
// Editing existing list because nothing was added to existingDuplicate
|
425
|
+
else
|
426
|
+
{
|
427
|
+
// Add existing versions to existing list
|
428
|
+
packageManager.UpdateExistingPackagesWithNewVersions(existingPackages, packagesToUpdate);
|
429
|
+
|
430
|
+
// Make relationships
|
431
|
+
await packageManager.PopulatePackageDependenciesAsync(existingPackages, targetFramework, Path.GetDirectoryName(projectPath));
|
432
|
+
|
433
|
+
// Update all to new versions
|
434
|
+
foreach (var package in existingPackages)
|
435
|
+
{
|
436
|
+
string updateResult = await packageManager.UpdateVersion(existingPackages, package, targetFramework, Path.GetDirectoryName(projectPath));
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
440
|
+
// Make new list to remove and differentiate between existingDuplicate and existingPackages lists
|
441
|
+
List<PackageToUpdate> packagesToRemove = existingDuplicate
|
442
|
+
.Where(existingPackageDupe => !existingPackages.Contains(existingPackageDupe) && existingPackageDupe.IsSpecific == true)
|
443
|
+
.ToList();
|
444
|
+
|
445
|
+
foreach (PackageToUpdate package in packagesToRemove)
|
446
|
+
{
|
447
|
+
existingDuplicate.Remove(package);
|
448
|
+
}
|
449
|
+
|
450
|
+
if (existingDuplicate != null)
|
451
|
+
{
|
452
|
+
existingPackages = existingDuplicate;
|
453
|
+
}
|
454
|
+
|
455
|
+
// Convert back to Dependency [], use NewVersion if available, otherwise use CurrentVersion
|
456
|
+
List<Dependency> candidatePackages = existingPackages
|
457
|
+
.Select(package => new Dependency(
|
458
|
+
package.PackageName,
|
459
|
+
package.NewVersion ?? package.CurrentVersion,
|
460
|
+
DependencyType.Unknown,
|
461
|
+
null,
|
462
|
+
null,
|
463
|
+
false,
|
464
|
+
false,
|
465
|
+
false,
|
466
|
+
false,
|
467
|
+
false
|
468
|
+
))
|
469
|
+
.ToList();
|
470
|
+
|
471
|
+
// Return as array
|
472
|
+
Dependency[] candidatePackagesArray = candidatePackages.ToArray();
|
473
|
+
|
474
|
+
var targetFrameworks = new NuGetFramework[] { NuGetFramework.Parse(targetFramework) };
|
475
|
+
|
476
|
+
var resolveProjectPath = projectPath;
|
477
|
+
|
478
|
+
if (!Path.IsPathRooted(resolveProjectPath) || !File.Exists(resolveProjectPath))
|
479
|
+
{
|
480
|
+
resolveProjectPath = Path.GetFullPath(Path.Join(repoRoot, resolveProjectPath));
|
481
|
+
}
|
482
|
+
|
483
|
+
NuGetContext nugetContext = new NuGetContext(Path.GetDirectoryName(resolveProjectPath));
|
484
|
+
|
485
|
+
// Target framework compatibility check
|
486
|
+
foreach (var package in candidatePackages)
|
487
|
+
{
|
488
|
+
if (!NuGetVersion.TryParse(package.Version, out var nuGetVersion))
|
489
|
+
{
|
490
|
+
// If version is not valid, return original packages and revert
|
491
|
+
return packages;
|
492
|
+
}
|
493
|
+
|
494
|
+
var packageIdentity = new NuGet.Packaging.Core.PackageIdentity(package.Name, nuGetVersion);
|
495
|
+
|
496
|
+
bool isNewPackageCompatible = await CompatibilityChecker.CheckAsync(packageIdentity, targetFrameworks.ToImmutableArray(), nugetContext, logger, CancellationToken.None);
|
497
|
+
if (!isNewPackageCompatible)
|
498
|
+
{
|
499
|
+
// If the package target framework is not compatible, return original packages and revert
|
500
|
+
return packages;
|
501
|
+
}
|
502
|
+
}
|
503
|
+
|
504
|
+
return candidatePackagesArray;
|
505
|
+
}
|
506
|
+
finally
|
507
|
+
{
|
508
|
+
tempDirectory.Delete(recursive: true);
|
509
|
+
}
|
510
|
+
}
|
511
|
+
|
512
|
+
internal static async Task<Dependency[]?> ResolveDependencyConflictsOld(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Logger logger)
|
310
513
|
{
|
311
514
|
var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
|
312
515
|
try
|
@@ -334,22 +537,22 @@ internal static partial class MSBuildHelper
|
|
334
537
|
Dictionary<string, HashSet<NuGetVersion>> badPackagesAndCandidateVersionsDictionary = new(StringComparer.OrdinalIgnoreCase);
|
335
538
|
|
336
539
|
// and for each of those packages, find all versions greater than the one that's currently installed
|
337
|
-
foreach ((string
|
540
|
+
foreach ((string PackageName, NuGetVersion packageVersion) in badPackagesAndVersions)
|
338
541
|
{
|
339
542
|
// this command dumps a JSON object with all versions of the specified package from all package sources
|
340
|
-
(exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"package search {
|
543
|
+
(exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"package search {PackageName} --exact-match --format json", workingDirectory: tempDirectory.FullName);
|
341
544
|
if (exitCode != 0)
|
342
545
|
{
|
343
546
|
continue;
|
344
547
|
}
|
345
548
|
|
346
549
|
// ensure collection exists
|
347
|
-
if (!badPackagesAndCandidateVersionsDictionary.ContainsKey(
|
550
|
+
if (!badPackagesAndCandidateVersionsDictionary.ContainsKey(PackageName))
|
348
551
|
{
|
349
|
-
badPackagesAndCandidateVersionsDictionary.Add(
|
552
|
+
badPackagesAndCandidateVersionsDictionary.Add(PackageName, new HashSet<NuGetVersion>());
|
350
553
|
}
|
351
554
|
|
352
|
-
HashSet<NuGetVersion> foundVersions = badPackagesAndCandidateVersionsDictionary[
|
555
|
+
HashSet<NuGetVersion> foundVersions = badPackagesAndCandidateVersionsDictionary[PackageName];
|
353
556
|
|
354
557
|
var json = JsonHelper.ParseNode(stdOut);
|
355
558
|
if (json?["searchResult"] is JsonArray searchResults)
|
@@ -580,9 +783,9 @@ internal static partial class MSBuildHelper
|
|
580
783
|
.Where(match => match.Success)
|
581
784
|
.Select(match =>
|
582
785
|
{
|
583
|
-
var
|
584
|
-
var isTransitive = !topLevelPackagesNames.Contains(
|
585
|
-
return new Dependency(
|
786
|
+
var PackageName = match.Groups["PackageName"].Value;
|
787
|
+
var isTransitive = !topLevelPackagesNames.Contains(PackageName);
|
788
|
+
return new Dependency(PackageName, match.Groups["PackageVersion"].Value, DependencyType.Unknown, TargetFrameworks: tfms, IsTransitive: isTransitive);
|
586
789
|
})
|
587
790
|
.ToArray();
|
588
791
|
|
@@ -264,6 +264,46 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
264
264
|
|
265
265
|
[Fact]
|
266
266
|
public async Task ReturnsUpToDate_ForMissingDependency()
|
267
|
+
{
|
268
|
+
await TestAnalyzeAsync(
|
269
|
+
packages:
|
270
|
+
[
|
271
|
+
// no packages listed
|
272
|
+
],
|
273
|
+
discovery: new()
|
274
|
+
{
|
275
|
+
Path = "/",
|
276
|
+
Projects = [
|
277
|
+
new()
|
278
|
+
{
|
279
|
+
FilePath = "./project.csproj",
|
280
|
+
TargetFrameworks = ["net8.0"],
|
281
|
+
Dependencies = [
|
282
|
+
new("Some.Package", "1.0.0", DependencyType.PackageReference), // this was found in the source, but doesn't exist in any feed
|
283
|
+
],
|
284
|
+
},
|
285
|
+
],
|
286
|
+
},
|
287
|
+
dependencyInfo: new()
|
288
|
+
{
|
289
|
+
Name = "Some.Package",
|
290
|
+
Version = "1.0.0",
|
291
|
+
IgnoredVersions = [],
|
292
|
+
IsVulnerable = false,
|
293
|
+
Vulnerabilities = [],
|
294
|
+
},
|
295
|
+
expectedResult: new()
|
296
|
+
{
|
297
|
+
UpdatedVersion = "1.0.0",
|
298
|
+
CanUpdate = false,
|
299
|
+
VersionComesFromMultiDependencyProperty = false,
|
300
|
+
UpdatedDependencies = [],
|
301
|
+
}
|
302
|
+
);
|
303
|
+
}
|
304
|
+
|
305
|
+
[Fact]
|
306
|
+
public async Task ReturnsUpToDate_ForIgnoredRequirements()
|
267
307
|
{
|
268
308
|
await TestAnalyzeAsync(
|
269
309
|
packages:
|
@@ -307,6 +347,50 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
|
|
307
347
|
);
|
308
348
|
}
|
309
349
|
|
350
|
+
[Fact]
|
351
|
+
public async Task IgnoredVersionsCanHandleWildcardSpecification()
|
352
|
+
{
|
353
|
+
await TestAnalyzeAsync(
|
354
|
+
packages:
|
355
|
+
[
|
356
|
+
MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"), // initially this
|
357
|
+
MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0"), // should update to this
|
358
|
+
MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.0", "net8.0"), // `IgnoredVersions` should prevent this from being selected
|
359
|
+
],
|
360
|
+
discovery: new()
|
361
|
+
{
|
362
|
+
Path = "/",
|
363
|
+
Projects = [
|
364
|
+
new()
|
365
|
+
{
|
366
|
+
FilePath = "./project.csproj",
|
367
|
+
TargetFrameworks = ["net8.0"],
|
368
|
+
Dependencies = [
|
369
|
+
new("Some.Package", "1.0.0", DependencyType.PackageReference),
|
370
|
+
],
|
371
|
+
},
|
372
|
+
],
|
373
|
+
},
|
374
|
+
dependencyInfo: new()
|
375
|
+
{
|
376
|
+
Name = "Some.Package",
|
377
|
+
Version = "1.0.0",
|
378
|
+
IgnoredVersions = [Requirement.Parse("> 1.1.*")],
|
379
|
+
IsVulnerable = false,
|
380
|
+
Vulnerabilities = [],
|
381
|
+
},
|
382
|
+
expectedResult: new()
|
383
|
+
{
|
384
|
+
UpdatedVersion = "1.1.0",
|
385
|
+
CanUpdate = true,
|
386
|
+
VersionComesFromMultiDependencyProperty = false,
|
387
|
+
UpdatedDependencies = [
|
388
|
+
new("Some.Package", "1.1.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
|
389
|
+
],
|
390
|
+
}
|
391
|
+
);
|
392
|
+
}
|
393
|
+
|
310
394
|
[Fact]
|
311
395
|
public async Task VersionFinderCanHandle404FromPackageSource_V2()
|
312
396
|
{
|
@@ -33,6 +33,8 @@ public class RequirementTests
|
|
33
33
|
[InlineData("1", "~> 1", true)]
|
34
34
|
[InlineData("2", "~> 1", false)]
|
35
35
|
[InlineData("5.3.8", "< 6, > 5.2.4", true)]
|
36
|
+
[InlineData("1.0-preview", ">= 1.x", false)] // wildcards
|
37
|
+
[InlineData("1.1-preview", ">= 1.x", true)]
|
36
38
|
public void IsSatisfiedBy(string versionString, string requirementString, bool expected)
|
37
39
|
{
|
38
40
|
var version = NuGetVersion.Parse(versionString);
|
@@ -43,6 +45,18 @@ public class RequirementTests
|
|
43
45
|
Assert.Equal(expected, actual);
|
44
46
|
}
|
45
47
|
|
48
|
+
[Theory]
|
49
|
+
[InlineData("> 1.*", "> 1.0")] // standard wildcard, single digit
|
50
|
+
[InlineData("> 1.2.*", "> 1.2.0")] // standard wildcard, multiple digit
|
51
|
+
[InlineData("> 1.a", "> 1.0")] // alternate wildcard, single digit
|
52
|
+
[InlineData("> 1.2.a", "> 1.2.0")] // alternate wildcard, multiple digit
|
53
|
+
public void Parse_ConvertsWildcardInVersion(string givenRequirementString, string expectedRequirementString)
|
54
|
+
{
|
55
|
+
var parsedRequirement = Requirement.Parse(givenRequirementString);
|
56
|
+
var actualRequirementString = parsedRequirement.ToString();
|
57
|
+
Assert.Equal(expectedRequirementString, actualRequirementString);
|
58
|
+
}
|
59
|
+
|
46
60
|
[Theory]
|
47
61
|
[InlineData("> = 1.0.0")] // Invalid format
|
48
62
|
[InlineData("<>= 1.0.0")] // Invalid Operator
|
@@ -0,0 +1,23 @@
|
|
1
|
+
namespace NuGetUpdater.Core.Test;
|
2
|
+
|
3
|
+
public class TemporaryEnvironment : IDisposable
|
4
|
+
{
|
5
|
+
private readonly List<(string Name, string? Value)> _originalVariables = new();
|
6
|
+
|
7
|
+
public TemporaryEnvironment((string Name, string Value)[] variables)
|
8
|
+
{
|
9
|
+
foreach (var (name, value) in variables)
|
10
|
+
{
|
11
|
+
_originalVariables.Add((name, Environment.GetEnvironmentVariable(name)));
|
12
|
+
Environment.SetEnvironmentVariable(name, value);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
public void Dispose()
|
17
|
+
{
|
18
|
+
foreach (var (name, value) in _originalVariables)
|
19
|
+
{
|
20
|
+
Environment.SetEnvironmentVariable(name, value);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|