From 52152db8774aa40a7d71d9c2f61bfbe6b0725531 Mon Sep 17 00:00:00 2001 From: Xavier Decoster Date: Fri, 7 Apr 2017 17:48:39 -0700 Subject: [PATCH] Keep legacy version compliance checks in place for non-SemVer2 versions (#3761) * Keep legacy version compatibility checks in place for non-semver2 versions * Added comment to clarify the reasons behind the legacy version check. * Fix typo * Rename test for clarity * code review feedback --- .../NuGetVersionExtensions.cs | 11 ++++++++ .../Packaging/ManifestValidator.cs | 28 ++++++++++++++++++- .../Packaging/ManifestValidatorFacts.cs | 10 +++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/NuGetGallery.Core/NuGetVersionExtensions.cs b/src/NuGetGallery.Core/NuGetVersionExtensions.cs index 28e6f6047b..5818f1d56c 100644 --- a/src/NuGetGallery.Core/NuGetVersionExtensions.cs +++ b/src/NuGetGallery.Core/NuGetVersionExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Text.RegularExpressions; using NuGet.Versioning; namespace NuGetGallery @@ -22,9 +23,19 @@ public static string Normalize(string version) public static class NuGetVersionExtensions { + private const RegexOptions SemanticVersionRegexFlags = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture; + private static readonly Regex SemanticVersionRegex = new Regex(@"^(?\d+(\s*\.\s*\d+){0,3})(?-[a-z][0-9a-z-]*)?$", SemanticVersionRegexFlags); + public static string ToNormalizedStringSafe(this NuGetVersion self) { return self != null ? self.ToNormalizedString() : String.Empty; } + + public static bool IsValidVersionForLegacyClients(this NuGetVersion self) + { + var match = SemanticVersionRegex.Match(self.ToString().Trim()); + + return match.Success; + } } } \ No newline at end of file diff --git a/src/NuGetGallery.Core/Packaging/ManifestValidator.cs b/src/NuGetGallery.Core/Packaging/ManifestValidator.cs index e7f2481c70..024bdca0fd 100644 --- a/src/NuGetGallery.Core/Packaging/ManifestValidator.cs +++ b/src/NuGetGallery.Core/Packaging/ManifestValidator.cs @@ -76,6 +76,12 @@ private static IEnumerable ValidateCore(PackageMetadata packag version)); } + var versionValidationResult = ValidateVersionForLegacyClients(packageMetadata.Version); + if (versionValidationResult != null) + { + yield return versionValidationResult; + } + // Check framework reference groups var frameworkReferenceGroups = packageMetadata.GetFrameworkReferenceGroups(); if (frameworkReferenceGroups != null) @@ -160,6 +166,26 @@ private static IEnumerable ValidateCore(PackageMetadata packag } } + /// + /// Checks whether the provided version is consumable by legacy 2.x clients, + /// which do not support a `.` in release labels, or release labels starting with numeric characters. + /// See also https://github.com/NuGet/NuGetGallery/issues/3226. + /// + /// The to check for 2.x client compatibility. + /// Returns a when non-compliant; otherwise null. + private static ValidationResult ValidateVersionForLegacyClients(NuGetVersion version) + { + if (!version.IsSemVer2 && !version.IsValidVersionForLegacyClients()) + { + return new ValidationResult(string.Format( + CultureInfo.CurrentCulture, + CoreStrings.Manifest_InvalidVersion, + version)); + } + + return null; + } + private static ValidationResult ValidateDependencyVersion(NuGetVersion version) { if (version.HasMetadata) @@ -170,7 +196,7 @@ private static ValidationResult ValidateDependencyVersion(NuGetVersion version) version.ToFullString())); } - return null; + return ValidateVersionForLegacyClients(version); } private static IEnumerable CheckUrls(params string[] urls) diff --git a/tests/NuGetGallery.Core.Facts/Packaging/ManifestValidatorFacts.cs b/tests/NuGetGallery.Core.Facts/Packaging/ManifestValidatorFacts.cs index 0665cc8f3e..f91753a9c3 100644 --- a/tests/NuGetGallery.Core.Facts/Packaging/ManifestValidatorFacts.cs +++ b/tests/NuGetGallery.Core.Facts/Packaging/ManifestValidatorFacts.cs @@ -440,6 +440,16 @@ public void ReturnsNoErrorIfDependencyVersionIsSemVer200WithoutMetadataPart() Assert.Empty(GetErrors(nuspecStream)); } + [Theory] + [InlineData("1.0.0-10")] + [InlineData("1.0.0--")] + public void ReturnsErrorIfNonSemVer2VersionIsNotCompliantWith2XClients(string version) + { + var nuspecStream = CreateNuspecStream(string.Format(NuSpecPlaceholderVersion, version)); + + Assert.Equal(new[] {String.Format(CoreStrings.Manifest_InvalidVersion, version)}, GetErrors(nuspecStream)); + } + [Fact] public void ReturnsErrorIfDependencyVersionIsSemVer200WithMetadataPart() {