diff --git a/src/Paket.Core/Installation/DependencyChangeDetection.fs b/src/Paket.Core/Installation/DependencyChangeDetection.fs
index d63c6764f6..94c6f4a049 100644
--- a/src/Paket.Core/Installation/DependencyChangeDetection.fs
+++ b/src/Paket.Core/Installation/DependencyChangeDetection.fs
@@ -1,5 +1,6 @@
module Paket.DependencyChangeDetection
+open Paket.Domain
open Paket.Requirements
open Paket.PackageResolver
@@ -10,6 +11,8 @@ type DependencyChangeType =
| SettingsChanged
/// The Version in the LockFile doesn't match the spec in the dependencies file.
| VersionNotValid
+ /// The Version in the LockFile is a prerelease, but the dependencies file does not allow prereleases for this package.
+ | PrereleaseVersionNotAllowed
/// Package from dependencies file was not found in lockfile
| PackageNotFoundInLockFile
/// Group from dependencies file was not found in lockfile
@@ -17,6 +20,16 @@ type DependencyChangeType =
/// Package from lock file was not found in dependencies file
| PackageNotFoundInDependenciesFile
+ override this.ToString() =
+ match this with
+ | RestrictionsChanged -> "Framework restrictions have changed"
+ | SettingsChanged -> "Settings have changed"
+ | VersionNotValid -> "Installed version is not valid"
+ | PrereleaseVersionNotAllowed -> "Prerelease version installed, but not allowed"
+ | PackageNotFoundInLockFile -> "Package was not found in lock file"
+ | GroupNotFoundInLockFile -> "Group was not found in lock file"
+ | PackageNotFoundInDependenciesFile -> "Package was not found in dependencies file"
+
let findNuGetChangesInDependenciesFile(dependenciesFile:DependenciesFile,lockFile:LockFile,strict) =
let allTransitives groupName = lockFile.GetTransitiveDependencies groupName
let getChanges groupName transitives (newRequirement:PackageRequirement) (originalPackage:PackageInfo) =
@@ -37,13 +50,19 @@ let findNuGetChangesInDependenciesFile(dependenciesFile:DependenciesFile,lockFil
else []
let requirementOk =
- let isInRange =
+ let requirement =
if strict then
- newRequirement.VersionRequirement.IsInRange originalPackage.Version
+ newRequirement.VersionRequirement
else
- newRequirement.IncludingPrereleases().VersionRequirement.IsInRange originalPackage.Version
+ newRequirement.IncludingPrereleases().VersionRequirement
+
+ let isInRange = requirement.IsInRange originalPackage.Version
+
if not isInRange then
- [VersionNotValid]
+ if originalPackage.Version.PreRelease.IsSome && requirement.PreReleases = No then
+ [PrereleaseVersionNotAllowed]
+ else
+ [VersionNotValid]
else []
requirementOk @ settingsChanged()
@@ -218,6 +237,11 @@ let GetPreferredNuGetVersions (dependenciesFile:DependenciesFile,lockFile:LockFi
| None -> kv.Key, (kv.Value.Version, kv.Value.Source))
|> Map.ofSeq
+type ResolutionTriggeringChange =
+ | NuGetChange of PackageName * DependencyChangeType
+ | RemoteChange of projectName:string * fileName:string
+ | SettingsChange
+
let GetChanges(dependenciesFile,lockFile,strict) =
let nuGetChanges = findNuGetChangesInDependenciesFile(dependenciesFile,lockFile,strict)
let nuGetChangesPerGroup =
@@ -231,37 +255,49 @@ let GetChanges(dependenciesFile,lockFile,strict) =
|> Seq.groupBy fst
|> Map.ofSeq
- let hasNuGetChanges groupName =
+ let getNuGetChanges groupName =
match nuGetChangesPerGroup |> Map.tryFind groupName with
- | None -> false
- | Some x -> Seq.isEmpty x |> not
-
- let hasRemoteFileChanges groupName =
+ | None -> []
+ | Some x ->
+ x
+ |> Seq.collect (fun (_, package, changes) ->
+ changes
+ |> List.map (fun change -> NuGetChange (package, change)))
+ |> Seq.toList
+
+ let getRemoteFileChanges groupName =
match remoteFileChangesPerGroup |> Map.tryFind groupName with
- | None -> false
- | Some x -> Seq.isEmpty x |> not
+ | None -> []
+ | Some x ->
+ x
+ |> Seq.map (fun (_, change) -> RemoteChange (change.Project, change.Name))
+ |> Seq.toList
- let hasChangedSettings groupName =
+ let getChangedSettings groupName =
match dependenciesFile.Groups |> Map.tryFind groupName with
- | None -> true
+ | None -> [ SettingsChange ]
| Some dependenciesFileGroup ->
match lockFile.Groups |> Map.tryFind groupName with
- | None -> true
+ | None -> [ SettingsChange ]
| Some lockFileGroup ->
let lockFileGroupOptions =
if dependenciesFileGroup.Options.Settings.FrameworkRestrictions = AutoDetectFramework then
{ lockFileGroup.Options with Settings = { lockFileGroup.Options.Settings with FrameworkRestrictions = AutoDetectFramework } }
else
lockFileGroup.Options
- dependenciesFileGroup.Options <> lockFileGroupOptions
+
+ if dependenciesFileGroup.Options <> lockFileGroupOptions then
+ [ SettingsChange ]
+ else []
- let hasChanges groupName _ =
- hasChangedSettings groupName || hasNuGetChanges groupName || hasRemoteFileChanges groupName
+ let getChanges groupName _ =
+ [ getChangedSettings groupName; getNuGetChanges groupName; getRemoteFileChanges groupName ]
+ |> List.concat
let hasAnyChanges =
dependenciesFile.Groups
- |> Map.filter hasChanges
+ |> Map.filter (fun groupName group -> getChanges groupName group |> List.isEmpty |> not)
|> Map.isEmpty
|> not
- hasAnyChanges,nuGetChanges,remoteFileChanges,hasChanges
\ No newline at end of file
+ hasAnyChanges,nuGetChanges,remoteFileChanges,getChanges
\ No newline at end of file
diff --git a/src/Paket.Core/Installation/UpdateProcess.fs b/src/Paket.Core/Installation/UpdateProcess.fs
index 2ccdaba262..2514e396f9 100644
--- a/src/Paket.Core/Installation/UpdateProcess.fs
+++ b/src/Paket.Core/Installation/UpdateProcess.fs
@@ -10,6 +10,8 @@ open Chessie.ErrorHandling
open Paket.Logging
open InstallProcess
+type RTC = DependencyChangeDetection.ResolutionTriggeringChange
+
let selectiveUpdate force getSha1 getVersionsF getPackageDetailsF getRuntimeGraphFromPackage (lockFile:LockFile) (dependenciesFile:DependenciesFile) updateMode semVerUpdateMode =
let dependenciesFile =
let processFile createRequirementF =
@@ -42,6 +44,42 @@ let selectiveUpdate force getSha1 getVersionsF getPackageDetailsF getRuntimeGrap
let getPreferredVersionsF,getPackageDetailsF,groupsToUpdate =
let changes,groups =
+ let install groupName =
+ let hasAnyChanges,nuGetChanges,remoteFileChanges,getChanges = DependencyChangeDetection.GetChanges(dependenciesFile,lockFile,true)
+
+ let hasChanges groupName x =
+ match getChanges groupName x with
+ | [] ->
+ tracefn "Skipping resolver for group %O since it is already up-to-date" groupName
+ false
+ | changes ->
+ tracefn "Resolving group %O because of changes:" groupName
+
+ changes
+ |> List.map (function
+ | RTC.NuGetChange (packageName, change) ->
+ sprintf "Package %O: %O" packageName change
+ | RTC.RemoteChange (project, file) ->
+ sprintf "Remote file %s changed in project %s" file project
+ | RTC.SettingsChange -> "Group has settings changes")
+ |> List.iter (tracefn "- %s")
+
+ true
+
+ let groupFilter =
+ match groupName with
+ | Some groupName -> fun g -> g = groupName
+ | None -> fun _ -> true
+
+ let groups =
+ dependenciesFile.Groups
+ |> Map.filter (fun g _ -> groupFilter g)
+ |> Map.filter hasChanges
+
+ nuGetChanges
+ |> Set.map (fun (f,s,_) -> f,s)
+ |> Set.filter (fst >> groupFilter), groups
+
match updateMode with
| UpdateAll ->
let changes =
@@ -78,38 +116,8 @@ let selectiveUpdate force getSha1 getVersionsF getPackageDetailsF getRuntimeGrap
|> Map.filter (fun k _ -> k = groupName || changes |> Seq.exists (fun (g,_) -> g = k))
changes,groups
- | InstallGroup groupName ->
- let hasAnyChanges,nuGetChanges,remoteFileChanges,hasChanges = DependencyChangeDetection.GetChanges(dependenciesFile,lockFile,true)
-
- let hasChanges groupName x =
- let hasChanges = hasChanges groupName x
- if not hasChanges then
- tracefn "Skipping resolver for group %O since it is already up-to-date" groupName
- hasChanges
-
- let groups =
- dependenciesFile.Groups
- |> Map.filter (fun k _ -> k = groupName)
- |> Map.filter hasChanges
-
- nuGetChanges
- |> Set.map (fun (f,s,_) -> f,s)
- |> Set.filter (fun (g,_) -> g = groupName), groups
- | Install ->
- let hasAnyChanges,nuGetChanges,remoteFileChanges,hasChanges = DependencyChangeDetection.GetChanges(dependenciesFile,lockFile,true)
-
- let hasChanges groupName x =
- let hasChanges = hasChanges groupName x
- if not hasChanges then
- tracefn "Skipping resolver for group %O since it is already up-to-date" groupName
- hasChanges
-
- let groups =
- dependenciesFile.Groups
- |> Map.filter hasChanges
-
- nuGetChanges
- |> Set.map (fun (f,s,_) -> f,s), groups
+ | InstallGroup groupName -> install (Some groupName)
+ | Install -> install None
let preferredVersions =
match updateMode with
diff --git a/src/Paket.Core/Paket.Core.fsproj b/src/Paket.Core/Paket.Core.fsproj
index 0d52a9c654..b930ea610d 100644
--- a/src/Paket.Core/Paket.Core.fsproj
+++ b/src/Paket.Core/Paket.Core.fsproj
@@ -23,12 +23,12 @@
..\..\bin
TRACE;DEBUG;USE_WEB_CLIENT_FOR_UPLOAD
3
- update
+ install
Project
paket.exe
- C:\proj\testing\testpaketfailure\
+ D:\Development\Staging\Paket\3008_prerelease_resolution_message\Paket3008\.paket\
true
diff --git a/src/Paket/Paket.fsproj b/src/Paket/Paket.fsproj
index a5154de506..8577694016 100644
--- a/src/Paket/Paket.fsproj
+++ b/src/Paket/Paket.fsproj
@@ -23,7 +23,7 @@
true
false
false
- ..\..\bin\
+ D:\Development\Staging\Paket\3008_prerelease_resolution_message\Paket3008\.paket
DEBUG;TRACE
3
@@ -34,14 +34,14 @@
install
C:\temp\Gu.Reactive
update
- add -g Foo Newtonsoft.Json
+ install
C:\proj\Paket
D:\temp\PaketTargetFrameworkRepro\
D:\code\bookstore
C:\temp\paket-conflict\paket.conflict.app
D:\temp\i3032
C:\code\Paket\integrationtests\scenarios\i003062-external-lock\before
- C:\temp\flip
+ D:\Development\Staging\Paket\3008_prerelease_resolution_message\Paket3008
true
diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs
index 7e3bc771d1..d9144ffe1b 100644
--- a/src/Paket/Program.fs
+++ b/src/Paket/Program.fs
@@ -918,3 +918,5 @@ let main() =
else printError exn
main()
+
+ignore ()