Skip to content

Commit 0aa39ea

Browse files
authored
SemVer 2.0.0 version ranges imply that the package itself is SemVer 2.0.0 (#37)
* SemVer 2.0.0 version ranges imply that the package itself is SemVer 2.0.0 * Fix NuGet/NuGetGallery#3657 for dev
1 parent 929c3f0 commit 0aa39ea

8 files changed

Lines changed: 173 additions & 12 deletions

File tree

src/NuGet.Server.Core/Infrastructure/JsonNetPackagesSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace NuGet.Server.Core.Infrastructure
1313
public class JsonNetPackagesSerializer
1414
: IPackagesSerializer
1515
{
16-
private static readonly SemanticVersion CurrentSchemaVersion = new SemanticVersion("2.0.0");
16+
private static readonly SemanticVersion CurrentSchemaVersion = new SemanticVersion("3.0.0");
1717

1818
private readonly JsonSerializer _serializer = new JsonSerializer
1919
{

src/NuGet.Server.Core/Infrastructure/ServerPackage.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public ServerPackage(
4242
DownloadCount = package.DownloadCount;
4343
Listed = package.Listed;
4444

45+
IsSemVer2 = IsPackageSemVer2(package);
46+
4547
_dependencySets = package.DependencySets.ToList();
4648
Dependencies = DependencySetsAsString(package.DependencySets);
4749

@@ -157,6 +159,8 @@ public IEnumerable<FrameworkName> GetSupportedFrameworks()
157159

158160
public bool Listed { get; set; }
159161

162+
public bool IsSemVer2 { get; set; }
163+
160164
public long PackageSize { get; set; }
161165

162166
public string PackageHash { get; set; }
@@ -249,5 +253,41 @@ private static Tuple<string, IVersionSpec, FrameworkName> ParseDependency(string
249253

250254
return Tuple.Create(id, versionSpec, targetFramework);
251255
}
256+
257+
private static bool IsPackageSemVer2(IPackage package)
258+
{
259+
if (package.Version.IsSemVer2())
260+
{
261+
return true;
262+
}
263+
264+
if (package.DependencySets != null)
265+
{
266+
foreach (var dependencySet in package.DependencySets)
267+
{
268+
foreach (var dependency in dependencySet.Dependencies)
269+
{
270+
var range = dependency.VersionSpec;
271+
if (range == null)
272+
{
273+
continue;
274+
}
275+
276+
if (range.MinVersion != null && range.MinVersion.IsSemVer2())
277+
{
278+
return true;
279+
}
280+
281+
if (range.MaxVersion != null && range.MaxVersion.IsSemVer2())
282+
{
283+
return true;
284+
}
285+
}
286+
}
287+
}
288+
289+
290+
return false;
291+
}
252292
}
253293
}

src/NuGet.Server.Core/Infrastructure/ServerPackageCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private static void UpdateLatestVersions(IEnumerable<ServerPackage> packages)
196196
package.SemVer2IsLatest = false;
197197

198198
// Update the SemVer1 views.
199-
if (!package.Version.IsSemVer2())
199+
if (!package.IsSemVer2)
200200
{
201201
UpdateLatestDictionary(semVer1AbsoluteLatest, package);
202202

src/NuGet.Server.Core/Infrastructure/ServerPackageRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public async Task<IEnumerable<IServerPackage>> GetPackagesAsync(
144144

145145
if (!compatibility.AllowSemVer2)
146146
{
147-
cache = cache.Where(p => !p.Version.IsSemVer2());
147+
cache = cache.Where(p => !p.IsSemVer2);
148148
}
149149

150150
return cache;

test/NuGet.Server.Core.Tests/NuGet.Server.Core.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
<Compile Include="ServerPackageRepositoryTest.cs" />
9696
<Compile Include="ServerPackageCacheTest.cs" />
9797
<Compile Include="ServerPackageStoreTest.cs" />
98+
<Compile Include="ServerPackageTest.cs" />
9899
<Compile Include="TestData.cs" />
99100
</ItemGroup>
100101
<ItemGroup>

test/NuGet.Server.Core.Tests/ServerPackageCacheTest.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class ServerPackageCacheTest
2020
private static readonly SemanticVersion PackageVersion = new SemanticVersion(PackageVersionString);
2121
private static readonly SemanticVersion SemVer2Version = new SemanticVersion(SemVer2VersionString);
2222
private const string MinimalCacheFile =
23-
"{\"SchemaVersion\":\"2.0.0\",\"Packages\":[{\"Id\":\"" + PackageId + "\",\"Version\":\"" + PackageVersionString + "\"}]}";
23+
"{\"SchemaVersion\":\"3.0.0\",\"Packages\":[{\"Id\":\"" + PackageId + "\",\"Version\":\"" + PackageVersionString + "\"}]}";
2424

2525
[Theory]
2626
[InlineData("[")]
@@ -34,9 +34,10 @@ public class ServerPackageCacheTest
3434
[InlineData("[{\"foo\": \"bar\"}]")]
3535
[InlineData("{\"SchemaVersion\":null,\"Packages\":[]}")]
3636
[InlineData("{\"SchemaVersion\":\"1.0.0\",\"Packages\":null}")]
37-
[InlineData("{\"SchemaVersion\":\"3.0.0\",\"Packages\":[]}")]
37+
[InlineData("{\"SchemaVersion\":\"2.0.0\",\"Packages\":null}")]
38+
[InlineData("{\"SchemaVersion\":\"4.0.0\",\"Packages\":[]}")]
3839
[InlineData("{\"Packages\":[]}")]
39-
[InlineData("{\"SchemaVersion\":\"2.0.0\"}")]
40+
[InlineData("{\"SchemaVersion\":\"3.0.0\"}")]
4041
public void Constructor_IgnoresAndDeletesInvalidCacheFile(string content)
4142
{
4243
// Arrange
@@ -57,8 +58,8 @@ public void Constructor_IgnoresAndDeletesInvalidCacheFile(string content)
5758
}
5859

5960
[Theory]
60-
[InlineData("{\"SchemaVersion\":\"2.0.0\",\"Packages\":[]}", 0)]
61-
[InlineData("{\"SchemaVersion\":\"2.0.0\",\"Packages\":[{\"Id\":\"NuGet.Versioning\",\"Version\":\"3.5.0\"}]}", 1)]
61+
[InlineData("{\"SchemaVersion\":\"3.0.0\",\"Packages\":[]}", 0)]
62+
[InlineData("{\"SchemaVersion\":\"3.0.0\",\"Packages\":[{\"Id\":\"NuGet.Versioning\",\"Version\":\"3.5.0\"}]}", 1)]
6263
public void Constructor_LeavesValidCacheFile(string content, int count)
6364
{
6465
// Arrange
@@ -82,7 +83,7 @@ public void Constructor_LeavesValidCacheFile(string content, int count)
8283
public void Constructor_DeserializesSemVer2Version()
8384
{
8485
// Arrange
85-
var cacheFile = "{\"SchemaVersion\":\"2.0.0\",\"Packages\":[{\"Id\":\"" + PackageId + "\",\"Version\":\"" + SemVer2VersionString + "\"}]}";
86+
var cacheFile = "{\"SchemaVersion\":\"3.0.0\",\"Packages\":[{\"Id\":\"" + PackageId + "\",\"Version\":\"" + SemVer2VersionString + "\"}]}";
8687
var fileSystem = new Mock<IFileSystem>();
8788
fileSystem
8889
.Setup(x => x.FileExists(CacheFileName))
@@ -102,6 +103,30 @@ public void Constructor_DeserializesSemVer2Version()
102103
Assert.Equal(SemVer2Version.ToNormalizedString(), package.Version.ToNormalizedString());
103104
}
104105

106+
[Theory]
107+
[InlineData("true", true)]
108+
[InlineData("false", false)]
109+
public void Constructor_DeserializesIsSemVer2(string serialized, bool expected)
110+
{
111+
// Arrange
112+
var cacheFile = "{\"SchemaVersion\":\"3.0.0\",\"Packages\":[{\"Id\":\"" + PackageId + "\",\"Version\":\"" + SemVer2VersionString + "\",\"IsSemVer2\":" + serialized + "}]}";
113+
var fileSystem = new Mock<IFileSystem>();
114+
fileSystem
115+
.Setup(x => x.FileExists(CacheFileName))
116+
.Returns(true);
117+
fileSystem
118+
.Setup(x => x.OpenFile(CacheFileName))
119+
.Returns(() => new MemoryStream(Encoding.UTF8.GetBytes(cacheFile)));
120+
121+
// Act
122+
var actual = new ServerPackageCache(fileSystem.Object, CacheFileName);
123+
124+
// Assert
125+
Assert.Equal(1, actual.GetAll().Count());
126+
var package = actual.GetAll().First();
127+
Assert.Equal(expected, package.IsSemVer2);
128+
}
129+
105130
[Fact]
106131
public void Persist_RetainsSemVer2Version()
107132
{

test/NuGet.Server.Core.Tests/ServerPackageRepositoryTest.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ private async Task<ServerPackageRepository> CreateServerPackageRepositoryWithSem
5151
repository.AddPackage(CreatePackage("test2", "1.0-beta"));
5252
repository.AddPackage(CreatePackage("test3", "1.0-beta.1"));
5353
repository.AddPackage(CreatePackage("test4", "1.0-beta+foo"));
54+
repository.AddPackage(CreatePackage(
55+
"test5",
56+
"1.0-beta",
57+
new PackageDependency(
58+
"SomePackage",
59+
VersionUtility.ParseVersionSpec("1.0.0-beta.1"))));
5460
});
5561
}
5662

@@ -413,7 +419,10 @@ public async Task ServerPackageRepositoryGetPackagesSupportsFilteringOutSemVer2(
413419
var actual = await serverRepository.GetPackagesAsync(ClientCompatibility.Default, Token);
414420

415421
// Assert
416-
Assert.Equal(2, actual.Count());
422+
var packages = actual.OrderBy(p => p.Id).ToList();
423+
Assert.Equal(2, packages.Count);
424+
Assert.Equal("test1", packages[0].Id);
425+
Assert.Equal("test2", packages[1].Id);
417426
}
418427
}
419428

@@ -429,7 +438,13 @@ public async Task ServerPackageRepositoryGetPackagesSupportsIncludingSemVer2()
429438
var actual = await serverRepository.GetPackagesAsync(ClientCompatibility.Max, Token);
430439

431440
// Assert
432-
Assert.Equal(4, actual.Count());
441+
var packages = actual.OrderBy(p => p.Id).ToList();
442+
Assert.Equal(5, packages.Count);
443+
Assert.Equal("test1", packages[0].Id);
444+
Assert.Equal("test2", packages[1].Id);
445+
Assert.Equal("test3", packages[2].Id);
446+
Assert.Equal("test4", packages[3].Id);
447+
Assert.Equal("test5", packages[4].Id);
433448
}
434449
}
435450

@@ -780,7 +795,7 @@ private static IPackage CreateMockPackage(string id, string version)
780795
return package.Object;
781796
}
782797

783-
private IPackage CreatePackage(string id, string version)
798+
private IPackage CreatePackage(string id, string version, PackageDependency packageDependency = null)
784799
{
785800
var parsedVersion = new SemanticVersion(version);
786801
var packageBuilder = new PackageBuilder
@@ -791,6 +806,16 @@ private IPackage CreatePackage(string id, string version)
791806
Authors = { "Test Author" }
792807
};
793808

809+
if (packageDependency != null)
810+
{
811+
packageBuilder.DependencySets.Add(new PackageDependencySet(
812+
new FrameworkName(".NETFramework,Version=v4.5"),
813+
new[]
814+
{
815+
packageDependency
816+
}));
817+
}
818+
794819
var mockFile = new Mock<IPackageFile>();
795820
mockFile.Setup(m => m.Path).Returns("foo");
796821
mockFile.Setup(m => m.GetStream()).Returns(new MemoryStream());
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Linq;
5+
using System.Runtime.Versioning;
6+
using Moq;
7+
using Xunit;
8+
9+
namespace NuGet.Server.Core.Infrastructure.Tests
10+
{
11+
public class ServerPackageTest
12+
{
13+
[Theory]
14+
[InlineData("1.0.0", false)]
15+
[InlineData("1.0.0-alpha", false)]
16+
[InlineData("1.0.0-alpha.1", true)]
17+
[InlineData("1.0.0+githash", true)]
18+
[InlineData("1.0.0-alpha+githash", true)]
19+
[InlineData("1.0.0-alpha.1+githash", true)]
20+
public void IsSemVer2_CanBeDeterminedByPackageVersion(string version, bool isSemVer2)
21+
{
22+
// Arrange
23+
var package = new Mock<IPackage>();
24+
package.Setup(x => x.Version).Returns(new SemanticVersion(version));
25+
var packageDerivedData = new PackageDerivedData();
26+
27+
// Act
28+
var serverPackage = new ServerPackage(package.Object, packageDerivedData);
29+
30+
// Assert
31+
Assert.Equal(isSemVer2, serverPackage.IsSemVer2);
32+
}
33+
34+
[Theory]
35+
[InlineData("1.0.0", false)]
36+
[InlineData("1.0.0-alpha", false)]
37+
[InlineData("1.0.0-alpha.1", true)]
38+
[InlineData("[1.0.0-alpha.1, 2.0.0)", true)]
39+
[InlineData("[1.0.0+githash, 2.0.0)", true)]
40+
[InlineData("[1.0.0-alpha, 2.0.0-alpha.1)", true)]
41+
[InlineData("[1.0.0, 2.0.0+githash)", true)]
42+
[InlineData("[1.0.0-alpha, 2.0.0)", false)]
43+
public void IsSemVer2_CanBeDeterminedByDependencyVersionRange(string versionRange, bool isSemVer2)
44+
{
45+
// Arrange
46+
var package = new Mock<IPackage>();
47+
package
48+
.Setup(x => x.Version)
49+
.Returns(new SemanticVersion("1.0.0"));
50+
package
51+
.Setup(x => x.DependencySets)
52+
.Returns(new[]
53+
{
54+
new PackageDependencySet(
55+
new FrameworkName(".NETFramework,Version=v4.5"),
56+
new[]
57+
{
58+
new PackageDependency("OtherPackage", VersionUtility.ParseVersionSpec(versionRange))
59+
})
60+
}.AsEnumerable());
61+
var packageDerivedData = new PackageDerivedData();
62+
63+
// Act
64+
var serverPackage = new ServerPackage(package.Object, packageDerivedData);
65+
66+
// Assert
67+
Assert.Equal(isSemVer2, serverPackage.IsSemVer2);
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)