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) ->