dependabot-nuget 0.268.0 → 0.271.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;
@@ -331,7 +334,182 @@ internal static partial class MSBuildHelper
331
334
  }
332
335
  }
333
336
 
334
- internal static async Task<Dependency[]?> ResolveDependencyConflicts(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Logger logger)
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)
335
513
  {
336
514
  var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
337
515
  try
@@ -359,22 +537,22 @@ internal static partial class MSBuildHelper
359
537
  Dictionary<string, HashSet<NuGetVersion>> badPackagesAndCandidateVersionsDictionary = new(StringComparer.OrdinalIgnoreCase);
360
538
 
361
539
  // and for each of those packages, find all versions greater than the one that's currently installed
362
- foreach ((string packageName, NuGetVersion packageVersion) in badPackagesAndVersions)
540
+ foreach ((string PackageName, NuGetVersion packageVersion) in badPackagesAndVersions)
363
541
  {
364
542
  // this command dumps a JSON object with all versions of the specified package from all package sources
365
- (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"package search {packageName} --exact-match --format json", workingDirectory: tempDirectory.FullName);
543
+ (exitCode, stdOut, stdErr) = await ProcessEx.RunAsync("dotnet", $"package search {PackageName} --exact-match --format json", workingDirectory: tempDirectory.FullName);
366
544
  if (exitCode != 0)
367
545
  {
368
546
  continue;
369
547
  }
370
548
 
371
549
  // ensure collection exists
372
- if (!badPackagesAndCandidateVersionsDictionary.ContainsKey(packageName))
550
+ if (!badPackagesAndCandidateVersionsDictionary.ContainsKey(PackageName))
373
551
  {
374
- badPackagesAndCandidateVersionsDictionary.Add(packageName, new HashSet<NuGetVersion>());
552
+ badPackagesAndCandidateVersionsDictionary.Add(PackageName, new HashSet<NuGetVersion>());
375
553
  }
376
554
 
377
- HashSet<NuGetVersion> foundVersions = badPackagesAndCandidateVersionsDictionary[packageName];
555
+ HashSet<NuGetVersion> foundVersions = badPackagesAndCandidateVersionsDictionary[PackageName];
378
556
 
379
557
  var json = JsonHelper.ParseNode(stdOut);
380
558
  if (json?["searchResult"] is JsonArray searchResults)
@@ -605,9 +783,9 @@ internal static partial class MSBuildHelper
605
783
  .Where(match => match.Success)
606
784
  .Select(match =>
607
785
  {
608
- var packageName = match.Groups["PackageName"].Value;
609
- var isTransitive = !topLevelPackagesNames.Contains(packageName);
610
- return new Dependency(packageName, match.Groups["PackageVersion"].Value, DependencyType.Unknown, TargetFrameworks: tfms, IsTransitive: isTransitive);
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);
611
789
  })
612
790
  .ToArray();
613
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
+ }
@@ -1,6 +1,9 @@
1
1
  using System.Collections.Immutable;
2
+ using System.Text;
2
3
  using System.Text.Json;
3
4
 
5
+ using NuGet;
6
+
4
7
  using NuGetUpdater.Core.Updater;
5
8
 
6
9
  using Xunit;
@@ -1663,67 +1666,173 @@ public partial class UpdateWorkerTests
1663
1666
  [Fact]
1664
1667
  public async Task PackageCanBeUpdatedWhenAnotherInstalledPackageHasBeenDelisted()
1665
1668
  {
1666
- // updating one package (Newtonsoft.Json) when another installed package (FSharp.Core/5.0.3-beta.21369.4) has been delisted
1667
- await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1",
1669
+ // updating one package (Some.Package) when another installed package (Delisted.Package/5.0.0) has been delisted
1670
+ // this test can't be faked with a local package source and requires an HTTP endpoint; the important part is
1671
+ // the `"listed": false` in the registration index
1672
+ static (int, byte[]) TestHttpHandler(string uriString)
1673
+ {
1674
+ var uri = new Uri(uriString, UriKind.Absolute);
1675
+ var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
1676
+ return uri.PathAndQuery switch
1677
+ {
1678
+ "/index.json" => (200, Encoding.UTF8.GetBytes($$"""
1679
+ {
1680
+ "version": "3.0.0",
1681
+ "resources": [
1682
+ {
1683
+ "@id": "{{baseUrl}}/download",
1684
+ "@type": "PackageBaseAddress/3.0.0"
1685
+ },
1686
+ {
1687
+ "@id": "{{baseUrl}}/query",
1688
+ "@type": "SearchQueryService"
1689
+ },
1690
+ {
1691
+ "@id": "{{baseUrl}}/registrations",
1692
+ "@type": "RegistrationsBaseUrl"
1693
+ }
1694
+ ]
1695
+ }
1696
+ """)),
1697
+ "/registrations/delisted.package/index.json" => (200, Encoding.UTF8.GetBytes($$"""
1698
+ {
1699
+ "count": 1,
1700
+ "items": [
1701
+ {
1702
+ "lower": "5.0.0",
1703
+ "upper": "5.0.0",
1704
+ "items": [
1705
+ {
1706
+ "catalogEntry": {
1707
+ "id": "Delisted.Package",
1708
+ "listed": false,
1709
+ "version": "5.0.0"
1710
+ },
1711
+ "packageContent": "{{baseUrl}}/download/delisted.package/5.0.0/delisted.package.5.0.0.nupkg",
1712
+ }
1713
+ ]
1714
+ }
1715
+ ]
1716
+ }
1717
+ """)),
1718
+ "/registrations/some.package/index.json" => (200, Encoding.UTF8.GetBytes($$"""
1719
+ {
1720
+ "count": 1,
1721
+ "items": [
1722
+ {
1723
+ "lower": "1.0.0",
1724
+ "upper": "2.0.0",
1725
+ "items": [
1726
+ {
1727
+ "catalogEntry": {
1728
+ "id": "Some.Package",
1729
+ "listed": true,
1730
+ "version": "1.0.0"
1731
+ },
1732
+ "packageContent": "{{baseUrl}}/download/some.package/1.0.0/some.package.1.0.0.nupkg",
1733
+ },
1734
+ {
1735
+ "catalogEntry": {
1736
+ "id": "Some.Package",
1737
+ "listed": true,
1738
+ "version": "2.0.0"
1739
+ },
1740
+ "packageContent": "{{baseUrl}}/download/some.package/2.0.0/some.package.2.0.0.nupkg",
1741
+ }
1742
+ ]
1743
+ }
1744
+ ]
1745
+ }
1746
+ """)),
1747
+ "/download/delisted.package/5.0.0/delisted.package.5.0.0.nupkg" =>
1748
+ (200, MockNuGetPackage.CreateSimplePackage("Delisted.Package", "5.0.0", "net45").GetZipStream().ReadAllBytes()),
1749
+ "/download/some.package/1.0.0/some.package.1.0.0.nupkg" =>
1750
+ (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net45").GetZipStream().ReadAllBytes()),
1751
+ "/download/some.package/2.0.0/some.package.2.0.0.nupkg" =>
1752
+ (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "2.0.0", "net45").GetZipStream().ReadAllBytes()),
1753
+ _ => (404, Encoding.UTF8.GetBytes("{}")), // everything is missing
1754
+ };
1755
+ }
1756
+ using var cache = new TemporaryDirectory();
1757
+ using var env = new TemporaryEnvironment([
1758
+ ("NUGET_PACKAGES", Path.Join(cache.DirectoryPath, "NUGET_PACKAGES")),
1759
+ ("NUGET_HTTP_CACHE_PATH", Path.Join(cache.DirectoryPath, "NUGET_HTTP_CACHE_PATH")),
1760
+ ("NUGET_SCRATCH", Path.Join(cache.DirectoryPath, "NUGET_SCRATCH")),
1761
+ ("NUGET_PLUGINS_CACHE_PATH", Path.Join(cache.DirectoryPath, "NUGET_PLUGINS_CACHE_PATH")),
1762
+ ]);
1763
+ using var http = TestHttpServer.CreateTestServer(TestHttpHandler);
1764
+ await TestUpdateForProject("Some.Package", "1.0.0", "2.0.0",
1668
1765
  // existing
1669
1766
  projectContents: """
1670
- <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
1671
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1672
- <PropertyGroup>
1673
- <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
1674
- </PropertyGroup>
1675
- <ItemGroup>
1676
- <None Include="packages.config" />
1677
- </ItemGroup>
1678
- <ItemGroup>
1679
- <Reference Include="FSharp.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
1680
- <HintPath>packages\FSharp.Core.5.0.3-beta.21369.4\lib\netstandard2.0\FSharp.Core.dll</HintPath>
1681
- <Private>True</Private>
1682
- </Reference>
1683
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
1684
- <HintPath>packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
1685
- <Private>True</Private>
1686
- </Reference>
1687
- </ItemGroup>
1688
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1689
- </Project>
1690
- """,
1767
+ <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
1768
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1769
+ <PropertyGroup>
1770
+ <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
1771
+ </PropertyGroup>
1772
+ <ItemGroup>
1773
+ <None Include="packages.config" />
1774
+ </ItemGroup>
1775
+ <ItemGroup>
1776
+ <Reference Include="Delisted.Package">
1777
+ <HintPath>packages\Delisted.Package.5.0.0\lib\net45\Delisted.Package.dll</HintPath>
1778
+ <Private>True</Private>
1779
+ </Reference>
1780
+ <Reference Include="Some.Package">
1781
+ <HintPath>packages\Some.Package.1.0.0\lib\net45\Some.Package.dll</HintPath>
1782
+ <Private>True</Private>
1783
+ </Reference>
1784
+ </ItemGroup>
1785
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1786
+ </Project>
1787
+ """,
1691
1788
  packagesConfigContents: """
1692
- <packages>
1693
- <package id="FSharp.Core" version="5.0.3-beta.21369.4" targetFramework="net462" />
1694
- <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net462" />
1695
- </packages>
1696
- """,
1789
+ <packages>
1790
+ <package id="Delisted.Package" version="5.0.0" targetFramework="net462" />
1791
+ <package id="Some.Package" version="1.0.0" targetFramework="net462" />
1792
+ </packages>
1793
+ """,
1794
+ additionalFiles:
1795
+ [
1796
+ ("NuGet.Config", $"""
1797
+ <configuration>
1798
+ <packageSources>
1799
+ <clear />
1800
+ <add key="private_feed" value="{http.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
1801
+ </packageSources>
1802
+ </configuration>
1803
+ """)
1804
+ ],
1697
1805
  // expected
1698
1806
  expectedProjectContents: """
1699
- <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
1700
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1701
- <PropertyGroup>
1702
- <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
1703
- </PropertyGroup>
1704
- <ItemGroup>
1705
- <None Include="packages.config" />
1706
- </ItemGroup>
1707
- <ItemGroup>
1708
- <Reference Include="FSharp.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
1709
- <HintPath>packages\FSharp.Core.5.0.3-beta.21369.4\lib\netstandard2.0\FSharp.Core.dll</HintPath>
1710
- <Private>True</Private>
1711
- </Reference>
1712
- <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
1713
- <HintPath>packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
1714
- <Private>True</Private>
1715
- </Reference>
1716
- </ItemGroup>
1717
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1718
- </Project>
1719
- """,
1807
+ <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
1808
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1809
+ <PropertyGroup>
1810
+ <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
1811
+ </PropertyGroup>
1812
+ <ItemGroup>
1813
+ <None Include="packages.config" />
1814
+ </ItemGroup>
1815
+ <ItemGroup>
1816
+ <Reference Include="Delisted.Package">
1817
+ <HintPath>packages\Delisted.Package.5.0.0\lib\net45\Delisted.Package.dll</HintPath>
1818
+ <Private>True</Private>
1819
+ </Reference>
1820
+ <Reference Include="Some.Package">
1821
+ <HintPath>packages\Some.Package.2.0.0\lib\net45\Some.Package.dll</HintPath>
1822
+ <Private>True</Private>
1823
+ </Reference>
1824
+ </ItemGroup>
1825
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1826
+ </Project>
1827
+ """,
1720
1828
  expectedPackagesConfigContents: """
1721
- <?xml version="1.0" encoding="utf-8"?>
1722
- <packages>
1723
- <package id="FSharp.Core" version="5.0.3-beta.21369.4" targetFramework="net462" />
1724
- <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net462" />
1725
- </packages>
1726
- """);
1829
+ <?xml version="1.0" encoding="utf-8"?>
1830
+ <packages>
1831
+ <package id="Delisted.Package" version="5.0.0" targetFramework="net462" />
1832
+ <package id="Some.Package" version="2.0.0" targetFramework="net462" />
1833
+ </packages>
1834
+ """
1835
+ );
1727
1836
  }
1728
1837
 
1729
1838
  [Fact]