From 79b57ac8177566c5f06ba595636f64c91583a7b8 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Thu, 16 Jun 2016 09:21:09 +0200 Subject: [PATCH] Prerelease version range are working with ~> again --- RELEASE_NOTES.md | 7 +- src/Paket.Core/DependenciesFile.fs | 80 +++++++++++++++++----- src/Paket.Core/NugetConvert.fs | 2 +- src/Paket.Core/Paket.Core.fsproj | 6 +- src/Paket.Core/SemVer.fs | 105 +++++++++++++++-------------- src/Paket.Core/Utils.fs | 2 +- src/Paket.Core/VersionRange.fs | 6 +- 7 files changed, 130 insertions(+), 78 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index fbc3e3e575..d7e293e08b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,11 +1,14 @@ +#### 3.0.4 - 16.06.2016 +* BUGFIX: Prerelease version range are working with ~> again + #### 3.0.3 - 15.06.2016 * Made Name and Guid in ProjectRefrence optional - https://github.com/fsprojects/Paket/issues/1729 #### 3.0.2 - 15.06.2016 -* Filter empty When conditions - https://github.com/fsprojects/Paket/issues/1727 +* BUGFIX: Filter empty When conditions - https://github.com/fsprojects/Paket/issues/1727 #### 3.0.1 - 15.06.2016 -* Do not garbage collect pacakges with version in path +* BUGFIX: Do not garbage collect pacakges with version in path #### 3.0.0 - 15.06.2016 * Allow to reference git repositories - http://fsprojects.github.io/Paket/git-dependencies.html diff --git a/src/Paket.Core/DependenciesFile.fs b/src/Paket.Core/DependenciesFile.fs index cec981b49e..c1115a65a2 100644 --- a/src/Paket.Core/DependenciesFile.fs +++ b/src/Paket.Core/DependenciesFile.fs @@ -91,21 +91,49 @@ module DependenciesFileParser = let parseVersionRequirement (text : string) : VersionRequirement = try - let inline parsePrerelease (texts : string list) = + let inline parsePrerelease (versions:SemVerInfo list) (texts : string list) = match texts |> List.filter ((<>) "") with - | [] -> PreReleaseStatus.No + | [] -> + versions + |> List.collect (fun version -> + match version.PreRelease with + | Some x -> [x.Name] + | _ -> []) + |> List.distinct + |> fun xs -> + match xs with + | [] -> PreReleaseStatus.No + | _ -> PreReleaseStatus.Concrete xs | [x] when String.equalsIgnoreCase x "prerelease" -> PreReleaseStatus.All | _ -> PreReleaseStatus.Concrete texts if String.IsNullOrWhiteSpace text then VersionRequirement(VersionRange.AtLeast("0"),PreReleaseStatus.No) else match text.Split([|' '|],StringSplitOptions.RemoveEmptyEntries) |> Array.toList with - | ">=" :: v1 :: "<" :: v2 :: rest -> VersionRequirement(VersionRange.Range(VersionRangeBound.Including,SemVer.Parse v1,SemVer.Parse v2,VersionRangeBound.Excluding),parsePrerelease rest) - | ">=" :: v1 :: "<=" :: v2 :: rest -> VersionRequirement(VersionRange.Range(VersionRangeBound.Including,SemVer.Parse v1,SemVer.Parse v2,VersionRangeBound.Including),parsePrerelease rest) - | "~>" :: v1 :: ">=" :: v2 :: rest -> VersionRequirement(VersionRange.Range(VersionRangeBound.Including,SemVer.Parse v2,SemVer.Parse(twiddle v1),VersionRangeBound.Excluding),parsePrerelease rest) - | "~>" :: v1 :: ">" :: v2 :: rest -> VersionRequirement(VersionRange.Range(VersionRangeBound.Excluding,SemVer.Parse v2,SemVer.Parse(twiddle v1),VersionRangeBound.Excluding),parsePrerelease rest) - | ">" :: v1 :: "<" :: v2 :: rest -> VersionRequirement(VersionRange.Range(VersionRangeBound.Excluding,SemVer.Parse v1,SemVer.Parse v2,VersionRangeBound.Excluding),parsePrerelease rest) - | ">" :: v1 :: "<=" :: v2 :: rest -> VersionRequirement(VersionRange.Range(VersionRangeBound.Excluding,SemVer.Parse v1,SemVer.Parse v2,VersionRangeBound.Including),parsePrerelease rest) + | ">=" :: v1 :: "<" :: v2 :: rest -> + let v1 = SemVer.Parse v1 + let v2 = SemVer.Parse v2 + VersionRequirement(VersionRange.Range(VersionRangeBound.Including,v1,v2,VersionRangeBound.Excluding),parsePrerelease [v1; v2] rest) + | ">=" :: v1 :: "<=" :: v2 :: rest -> + let v1 = SemVer.Parse v1 + let v2 = SemVer.Parse v2 + VersionRequirement(VersionRange.Range(VersionRangeBound.Including,v1,v2,VersionRangeBound.Including),parsePrerelease [v1; v2] rest) + | "~>" :: v1 :: ">=" :: v2 :: rest -> + let v1 = SemVer.Parse(twiddle v1) + let v2 = SemVer.Parse v2 + VersionRequirement(VersionRange.Range(VersionRangeBound.Including,v2,v1,VersionRangeBound.Excluding),parsePrerelease [v1; v2] rest) + | "~>" :: v1 :: ">" :: v2 :: rest -> + let v1 = SemVer.Parse(twiddle v1) + let v2 = SemVer.Parse v2 + VersionRequirement(VersionRange.Range(VersionRangeBound.Excluding,v2,v1,VersionRangeBound.Excluding),parsePrerelease [v1; v2] rest) + | ">" :: v1 :: "<" :: v2 :: rest -> + let v1 = SemVer.Parse v1 + let v2 = SemVer.Parse v2 + VersionRequirement(VersionRange.Range(VersionRangeBound.Excluding,v1,v2,VersionRangeBound.Excluding),parsePrerelease [v1; v2] rest) + | ">" :: v1 :: "<=" :: v2 :: rest -> + let v1 = SemVer.Parse v1 + let v2 = SemVer.Parse v2 + VersionRequirement(VersionRange.Range(VersionRangeBound.Excluding,v1,v2,VersionRangeBound.Including),parsePrerelease [v1; v2] rest) | _ -> let splitVersion (text:string) = match VersionRange.BasicOperators |> List.tryFind(text.StartsWith) with @@ -114,13 +142,27 @@ module DependenciesFileParser = match splitVersion text with - | "==", version :: rest -> VersionRequirement(VersionRange.OverrideAll(SemVer.Parse version),parsePrerelease rest) - | ">=", version :: rest -> VersionRequirement(VersionRange.AtLeast(version),parsePrerelease rest) - | ">", version :: rest -> VersionRequirement(VersionRange.GreaterThan(SemVer.Parse version),parsePrerelease rest) - | "<", version :: rest -> VersionRequirement(VersionRange.LessThan(SemVer.Parse version),parsePrerelease rest) - | "<=", version :: rest -> VersionRequirement(VersionRange.Maximum(SemVer.Parse version),parsePrerelease rest) - | "~>", minimum :: rest -> VersionRequirement(VersionRange.Between(minimum,twiddle minimum),parsePrerelease rest) - | _, version :: rest -> VersionRequirement(VersionRange.Exactly(version),parsePrerelease rest) + | "==", version :: rest -> + let v = SemVer.Parse version + VersionRequirement(VersionRange.OverrideAll v,parsePrerelease [v] rest) + | ">=", version :: rest -> + let v = SemVer.Parse version + VersionRequirement(VersionRange.Minimum v,parsePrerelease [v] rest) + | ">", version :: rest -> + let v = SemVer.Parse version + VersionRequirement(VersionRange.GreaterThan v,parsePrerelease [v] rest) + | "<", version :: rest -> + let v = SemVer.Parse version + VersionRequirement(VersionRange.LessThan v,parsePrerelease [v] rest) + | "<=", version :: rest -> + let v = SemVer.Parse version + VersionRequirement(VersionRange.Maximum v,parsePrerelease [v] rest) + | "~>", minimum :: rest -> + let v1 = SemVer.Parse minimum + VersionRequirement(VersionRange.Between(minimum,twiddle minimum),parsePrerelease [v1] rest) + | _, version :: rest -> + let v = SemVer.Parse version + VersionRequirement(VersionRange.Specific v,parsePrerelease [v] rest) | _ -> failwithf "could not parse version range \"%s\"" text with | _ -> failwithf "could not parse version range \"%s\"" text @@ -331,6 +373,10 @@ module DependenciesFileParser = failwithf "Invalid prerelease version %s" prereleases let packageName = PackageName name + + let vr = (version + " " + prereleases).Trim(VersionRange.StrategyOperators |> Array.ofList) + let versionRequirement = parseVersionRequirement vr + { Name = packageName ResolverStrategyForTransitives = if optionsText.Contains "strategy" then @@ -352,7 +398,7 @@ module DependenciesFileParser = Graph = [] Sources = sources Settings = InstallSettings.Parse(optionsText).AdjustWithSpecialCases packageName - VersionRequirement = parseVersionRequirement((version + " " + prereleases).Trim(VersionRange.StrategyOperators |> Array.ofList)) } + VersionRequirement = versionRequirement } let parsePackageLine(sources,parent,line:string) = match line with @@ -474,7 +520,7 @@ module DependenciesFileSerializer = let version = match versionRequirement.Range with - | Minimum x when strategy = None && x = SemVer.Parse "0" -> "" + | Minimum x when strategy = None && x = SemVer.Zero -> "" | Minimum x -> ">= " + x.ToString() | GreaterThan x -> "> " + x.ToString() | Specific x when strategy = None -> x.ToString() diff --git a/src/Paket.Core/NugetConvert.fs b/src/Paket.Core/NugetConvert.fs index 57ad7f1bf0..6fd6cecb81 100644 --- a/src/Paket.Core/NugetConvert.fs +++ b/src/Paket.Core/NugetConvert.fs @@ -212,7 +212,7 @@ let createPackageRequirement sources (packageName, version, restrictions) depend { Name = PackageName packageName VersionRequirement = if version = "" then - VersionRequirement(VersionRange.Minimum <| SemVer.Parse "0", PreReleaseStatus.No) + VersionRequirement(VersionRange.Minimum SemVer.Zero, PreReleaseStatus.No) else VersionRequirement(VersionRange.Exactly version, PreReleaseStatus.No) ResolverStrategyForDirectDependencies = None diff --git a/src/Paket.Core/Paket.Core.fsproj b/src/Paket.Core/Paket.Core.fsproj index 9d7dacdb95..dfe769d3c8 100644 --- a/src/Paket.Core/Paket.Core.fsproj +++ b/src/Paket.Core/Paket.Core.fsproj @@ -87,12 +87,12 @@ - - - + + + diff --git a/src/Paket.Core/SemVer.fs b/src/Paket.Core/SemVer.fs index 2159e90b48..1ab225a2e6 100644 --- a/src/Paket.Core/SemVer.fs +++ b/src/Paket.Core/SemVer.fs @@ -167,60 +167,63 @@ module SemVer = /// parse "1.2.3-alpha2" > parse "1.2.3-alpha" // true /// parse "1.2.3-alpha002" > parse "1.2.3-alpha1" // true /// parse "1.5.0-beta.2" > parse "1.5.0-rc.1" // false - let Parse(version : string) = - try - - /// sanity check to make sure that all of the integers in the string are positive. - /// because we use raw substrings with dashes this is very complex :( - version.Split([|'.'|]) |> Array.iter (fun s -> match Int32.TryParse s with | true, s when s < 0 -> failwith "no negatives!" | _ -> ignore ()) - - if version.Contains("!") then - failwithf "Invalid character found in %s" version - if version.Contains("..") then - failwithf "Empty version part found in %s" version + let Parse = + memoize <| fun (version : string) -> + try + + /// sanity check to make sure that all of the integers in the string are positive. + /// because we use raw substrings with dashes this is very complex :( + version.Split([|'.'|]) |> Array.iter (fun s -> match Int32.TryParse s with | true, s when s < 0 -> failwith "no negatives!" | _ -> ignore ()) + + if version.Contains("!") then + failwithf "Invalid character found in %s" version + if version.Contains("..") then + failwithf "Empty version part found in %s" version - let firstDash = version.IndexOf("-") - let plusIndex = version.IndexOf("+") - - let majorMinorPatch = - let firstSigil = if firstDash > 0 then firstDash else plusIndex - match firstSigil with - | -1 -> version - | n -> version.Substring(0, n) - - let prerelease = - match firstDash, plusIndex with - | -1, _ -> "" - | d, p when p = -1 -> version.Substring(d+1) - | d, p -> version.Substring(d+1, (version.Length - 1 - p) ) + let firstDash = version.IndexOf("-") + let plusIndex = version.IndexOf("+") + + let majorMinorPatch = + let firstSigil = if firstDash > 0 then firstDash else plusIndex + match firstSigil with + | -1 -> version + | n -> version.Substring(0, n) + + let prerelease = + match firstDash, plusIndex with + | -1, _ -> "" + | d, p when p = -1 -> version.Substring(d+1) + | d, p -> version.Substring(d+1, (version.Length - 1 - p) ) - /// there can only be one piece of build metadata, and it is signified by a + and then any number of dot-separated alpha-numeric groups. - /// this just greedily takes the whole remaining string :( - let buildmeta = - match plusIndex with - | -1 -> "" - | n when plusIndex = version.Length - 1 -> "" - | n -> version.Substring(plusIndex + 1) + /// there can only be one piece of build metadata, and it is signified by a + and then any number of dot-separated alpha-numeric groups. + /// this just greedily takes the whole remaining string :( + let buildmeta = + match plusIndex with + | -1 -> "" + | n when plusIndex = version.Length - 1 -> "" + | n -> version.Substring(plusIndex + 1) - let major, minor, patch, build = - match majorMinorPatch.Split([|'.'|]) with - | [|M; m; p; b|] -> uint32 M, uint32 m, uint32 p, b - | [|M; m; p; |] -> uint32 M, uint32 m, uint32 p, "0" - | [|M; m;|] -> uint32 M, uint32 m, 0u, "0" - | [|M;|] -> uint32 M, 0u, 0u, "0" - | _ -> 0u, 0u, 0u, "0" - - { Major = major - Minor = minor - Patch = patch - Build = build - PreRelease = PreRelease.TryParse prerelease - BuildMetaData = buildmeta - Original = Some version } - - with - | exn -> - failwithf "Can't parse \"%s\".%s%s" version Environment.NewLine exn.Message + let major, minor, patch, build = + match majorMinorPatch.Split([|'.'|]) with + | [|M; m; p; b|] -> uint32 M, uint32 m, uint32 p, b + | [|M; m; p; |] -> uint32 M, uint32 m, uint32 p, "0" + | [|M; m;|] -> uint32 M, uint32 m, 0u, "0" + | [|M;|] -> uint32 M, 0u, 0u, "0" + | _ -> 0u, 0u, 0u, "0" + + { Major = major + Minor = minor + Patch = patch + Build = build + PreRelease = PreRelease.TryParse prerelease + BuildMetaData = buildmeta + Original = Some version } + + with + | exn -> + failwithf "Can't parse \"%s\".%s%s" version Environment.NewLine exn.Message + + let Zero = Parse "0" let SortVersions = Array.choose (fun v -> try Some(v,Parse v) with | _ -> None) diff --git a/src/Paket.Core/Utils.fs b/src/Paket.Core/Utils.fs index 24ca25d860..d19713dbe3 100644 --- a/src/Paket.Core/Utils.fs +++ b/src/Paket.Core/Utils.fs @@ -445,7 +445,7 @@ let inline windowsPath (path:string) = path.Replace(Path.DirectorySeparatorChar, /// Gets all files with the given pattern let inline FindAllFiles(folder, pattern) = DirectoryInfo(folder).GetFiles(pattern, SearchOption.AllDirectories) -let getTargetFolder root groupName (packageName:PackageName) (version:SemVerInfo) includeVersionInPath = +let getTargetFolder root groupName (packageName:PackageName) version includeVersionInPath = let packageFolder = string packageName + if includeVersionInPath then "." + string version else "" if groupName = Constants.MainDependencyGroup then Path.Combine(root, Constants.PackagesFolderName, packageFolder) diff --git a/src/Paket.Core/VersionRange.fs b/src/Paket.Core/VersionRange.fs index a392498749..a9d1586194 100644 --- a/src/Paket.Core/VersionRange.fs +++ b/src/Paket.Core/VersionRange.fs @@ -124,8 +124,8 @@ type VersionRequirement = match this with | VersionRequirement(_,prereleases) -> prereleases - static member AllReleases = VersionRequirement(Minimum(SemVer.Parse "0"),PreReleaseStatus.No) - static member NoRestriction = VersionRequirement(Minimum(SemVer.Parse "0"),PreReleaseStatus.All) + static member AllReleases = VersionRequirement(Minimum(SemVer.Zero),PreReleaseStatus.No) + static member NoRestriction = VersionRequirement(Minimum(SemVer.Zero),PreReleaseStatus.All) override this.ToString() = this.Range.ToString() @@ -182,7 +182,7 @@ type VersionRequirement = | VersionRangeBound.Including, VersionRangeBound.Including -> Minimum(versions.[0]) | VersionRangeBound.Including, VersionRangeBound.Excluding -> Minimum(versions.[0]) | _ -> failwithf "unable to parse %s" text - | 0 -> Minimum(SemVer.Parse "0") + | 0 -> Minimum(SemVer.Zero) | _ -> failwithf "unable to parse %s" text match parsed with | Range(fromB, from, _to, _toB) ->