diff --git a/Distribution/Client/BuildReports/Anonymous.hs b/Distribution/Client/BuildReports/Anonymous.hs
--- a/Distribution/Client/BuildReports/Anonymous.hs
+++ b/Distribution/Client/BuildReports/Anonymous.hs
@@ -146,17 +146,17 @@
       Left  (BR.BuildFailed     _) -> BuildFailed
       Left  (BR.TestsFailed     _) -> TestsFailed
       Left  (BR.InstallFailed   _) -> InstallFailed
-      Right (BR.BuildOk       _ _) -> InstallOk
+      Right (BR.BuildOk       _ _ _) -> InstallOk
     convertDocsOutcome = case result of
       Left _                                -> NotTried
-      Right (BR.BuildOk BR.DocsNotTried _)  -> NotTried
-      Right (BR.BuildOk BR.DocsFailed _)    -> Failed
-      Right (BR.BuildOk BR.DocsOk _)        -> Ok
+      Right (BR.BuildOk BR.DocsNotTried _ _)  -> NotTried
+      Right (BR.BuildOk BR.DocsFailed _ _)    -> Failed
+      Right (BR.BuildOk BR.DocsOk _ _)        -> Ok
     convertTestsOutcome = case result of
       Left  (BR.TestsFailed _)              -> Failed
       Left _                                -> NotTried
-      Right (BR.BuildOk _ BR.TestsNotTried) -> NotTried
-      Right (BR.BuildOk _ BR.TestsOk)       -> Ok
+      Right (BR.BuildOk _ BR.TestsNotTried _) -> NotTried
+      Right (BR.BuildOk _ BR.TestsOk _)       -> Ok
 
 cabalInstallID :: PackageIdentifier
 cabalInstallID =
diff --git a/Distribution/Client/BuildReports/Storage.hs b/Distribution/Client/BuildReports/Storage.hs
--- a/Distribution/Client/BuildReports/Storage.hs
+++ b/Distribution/Client/BuildReports/Storage.hs
@@ -117,9 +117,10 @@
                 -> Maybe (BuildReport, Repo)
 fromPlanPackage (Platform arch os) comp planPackage = case planPackage of
 
-  InstallPlan.Installed pkg@(ConfiguredPackage (SourcePackage {
+  InstallPlan.Installed pkg@(ReadyPackage (SourcePackage {
                           packageSource = RepoTarballPackage repo _ _ }) _ _ _) result
-    -> Just $ (BuildReport.new os arch comp pkg (Right result), repo)
+    -> Just $ (BuildReport.new os arch comp
+               (readyPackageToConfiguredPackage pkg) (Right result), repo)
 
   InstallPlan.Failed pkg@(ConfiguredPackage (SourcePackage {
                        packageSource = RepoTarballPackage repo _ _ }) _ _ _) result
diff --git a/Distribution/Client/Compat/Environment.hs b/Distribution/Client/Compat/Environment.hs
--- a/Distribution/Client/Compat/Environment.hs
+++ b/Distribution/Client/Compat/Environment.hs
@@ -54,7 +54,7 @@
   | otherwise  = setEnv_ key value
   where
     -- NOTE: Anything that follows NUL is ignored on both POSIX and Windows. We
-    -- still strip it manually so that the null check above succeds if a value
+    -- still strip it manually so that the null check above succeeds if a value
     -- starts with NUL.
     value = takeWhile (/= '\NUL') value_
 
diff --git a/Distribution/Client/Compat/ExecutablePath.hs b/Distribution/Client/Compat/ExecutablePath.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/Client/Compat/ExecutablePath.hs
@@ -0,0 +1,183 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE CPP #-}
+
+-- Copied verbatim from base-4.6.0.0. We can't simply import
+-- System.Environment.getExecutablePath because we need compatibility with older
+-- GHCs.
+
+module Distribution.Client.Compat.ExecutablePath ( getExecutablePath ) where
+
+-- The imports are purposely kept completely disjoint to prevent edits
+-- to one OS implementation from breaking another.
+
+#if defined(darwin_HOST_OS)
+import Data.Word
+import Foreign.C
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+import Foreign.Storable
+import System.Posix.Internals
+#elif defined(linux_HOST_OS)
+import Foreign.C
+import Foreign.Marshal.Array
+import System.Posix.Internals
+#elif defined(mingw32_HOST_OS)
+import Data.Word
+import Foreign.C
+import Foreign.Marshal.Array
+import Foreign.Ptr
+import System.Posix.Internals
+#else
+import Foreign.C
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+import Foreign.Storable
+import System.Posix.Internals
+#endif
+
+-- GHC 7.0.* compatibility. 'System.Posix.Internals' in base-4.3.* doesn't
+-- provide 'peekFilePath' and 'peekFilePathLen'.
+#if !MIN_VERSION_base(4,4,0)
+#ifdef mingw32_HOST_OS
+
+peekFilePath :: CWString -> IO FilePath
+peekFilePath = peekCWString
+
+#else
+
+peekFilePath :: CString -> IO FilePath
+peekFilePath = peekCString
+
+peekFilePathLen :: CStringLen -> IO FilePath
+peekFilePathLen = peekCStringLen
+
+#endif
+#endif
+
+-- The exported function is defined outside any if-guard to make sure
+-- every OS implements it with the same type.
+
+-- | Returns the absolute pathname of the current executable.
+--
+-- Note that for scripts and interactive sessions, this is the path to
+-- the interpreter (e.g. ghci.)
+--
+-- /Since: 4.6.0.0/
+getExecutablePath :: IO FilePath
+
+--------------------------------------------------------------------------------
+-- Mac OS X
+
+#if defined(darwin_HOST_OS)
+
+type UInt32 = Word32
+
+foreign import ccall unsafe "mach-o/dyld.h _NSGetExecutablePath"
+    c__NSGetExecutablePath :: CString -> Ptr UInt32 -> IO CInt
+
+-- | Returns the path of the main executable. The path may be a
+-- symbolic link and not the real file.
+--
+-- See dyld(3)
+_NSGetExecutablePath :: IO FilePath
+_NSGetExecutablePath =
+    allocaBytes 1024 $ \ buf ->  -- PATH_MAX is 1024 on OS X
+    alloca $ \ bufsize -> do
+        poke bufsize 1024
+        status <- c__NSGetExecutablePath buf bufsize
+        if status == 0
+            then peekFilePath buf
+            else do reqBufsize <- fromIntegral `fmap` peek bufsize
+                    allocaBytes reqBufsize $ \ newBuf -> do
+                        status2 <- c__NSGetExecutablePath newBuf bufsize
+                        if status2 == 0
+                             then peekFilePath newBuf
+                             else error "_NSGetExecutablePath: buffer too small"
+
+foreign import ccall unsafe "stdlib.h realpath"
+    c_realpath :: CString -> CString -> IO CString
+
+-- | Resolves all symbolic links, extra \/ characters, and references
+-- to \/.\/ and \/..\/. Returns an absolute pathname.
+--
+-- See realpath(3)
+realpath :: FilePath -> IO FilePath
+realpath path =
+    withFilePath path $ \ fileName ->
+    allocaBytes 1024 $ \ resolvedName -> do
+        _ <- throwErrnoIfNull "realpath" $ c_realpath fileName resolvedName
+        peekFilePath resolvedName
+
+getExecutablePath = _NSGetExecutablePath >>= realpath
+
+--------------------------------------------------------------------------------
+-- Linux
+
+#elif defined(linux_HOST_OS)
+
+foreign import ccall unsafe "readlink"
+    c_readlink :: CString -> CString -> CSize -> IO CInt
+
+-- | Reads the @FilePath@ pointed to by the symbolic link and returns
+-- it.
+--
+-- See readlink(2)
+readSymbolicLink :: FilePath -> IO FilePath
+readSymbolicLink file =
+    allocaArray0 4096 $ \buf -> do
+        withFilePath file $ \s -> do
+            len <- throwErrnoPathIfMinus1 "readSymbolicLink" file $
+                   c_readlink s buf 4096
+            peekFilePathLen (buf,fromIntegral len)
+
+getExecutablePath = readSymbolicLink $ "/proc/self/exe"
+
+--------------------------------------------------------------------------------
+-- Windows
+
+#elif defined(mingw32_HOST_OS)
+
+# if defined(i386_HOST_ARCH)
+#  define WINDOWS_CCONV stdcall
+# elif defined(x86_64_HOST_ARCH)
+#  define WINDOWS_CCONV ccall
+# else
+#  error Unknown mingw32 arch
+# endif
+
+foreign import WINDOWS_CCONV unsafe "windows.h GetModuleFileNameW"
+    c_GetModuleFileName :: Ptr () -> CWString -> Word32 -> IO Word32
+
+getExecutablePath = go 2048  -- plenty, PATH_MAX is 512 under Win32
+  where
+    go size = allocaArray (fromIntegral size) $ \ buf -> do
+        ret <- c_GetModuleFileName nullPtr buf size
+        case ret of
+            0 -> error "getExecutablePath: GetModuleFileNameW returned an error"
+            _ | ret < size -> peekFilePath buf
+              | otherwise  -> go (size * 2)
+
+--------------------------------------------------------------------------------
+-- Fallback to argv[0]
+
+#else
+
+foreign import ccall unsafe "getFullProgArgv"
+    c_getFullProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
+
+getExecutablePath =
+    alloca $ \ p_argc ->
+    alloca $ \ p_argv -> do
+        c_getFullProgArgv p_argc p_argv
+        argc <- peek p_argc
+        if argc > 0
+            -- If argc > 0 then argv[0] is guaranteed by the standard
+            -- to be a pointer to a null-terminated string.
+            then peek p_argv >>= peek >>= peekFilePath
+            else error $ "getExecutablePath: " ++ msg
+  where msg = "no OS specific implementation and program name couldn't be " ++
+              "found in argv"
+
+--------------------------------------------------------------------------------
+
+#endif
diff --git a/Distribution/Client/Compat/Process.hs b/Distribution/Client/Compat/Process.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/Client/Compat/Process.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE CPP #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Distribution.Client.Compat.Process
+-- Copyright   :  (c) 2013 Liu Hao, Brent Yorgey
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  cabal-devel@haskell.org
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Cross-platform utilities for invoking processes.
+--
+-----------------------------------------------------------------------------
+
+module Distribution.Client.Compat.Process (
+  readProcessWithExitCode
+) where
+
+#if !MIN_VERSION_base(4,6,0)
+import           Prelude           hiding (catch)
+#endif
+
+import           Control.Exception (catch, throw)
+import           System.Exit       (ExitCode (ExitFailure))
+import           System.IO.Error   (isDoesNotExistError)
+import qualified System.Process    as P
+
+-- | @readProcessWithExitCode@ creates an external process, reads its
+--   standard output and standard error strictly, waits until the
+--   process terminates, and then returns the @ExitCode@ of the
+--   process, the standard output, and the standard error.
+--
+--   See the documentation of the version from @System.Process@ for
+--   more information.
+--
+--   The version from @System.Process@ behaves inconsistently across
+--   platforms when an executable with the given name is not found: in
+--   some cases it returns an @ExitFailure@, in others it throws an
+--   exception.  This variant catches \"does not exist\" exceptions and
+--   turns them into @ExitFailure@s.
+readProcessWithExitCode :: FilePath -> [String] -> String -> IO (ExitCode, String, String)
+readProcessWithExitCode cmd args input =
+  P.readProcessWithExitCode cmd args input
+    `catch` \e -> if isDoesNotExistError e
+                    then return (ExitFailure 127, "", "")
+                    else throw e
diff --git a/Distribution/Client/Config.hs b/Distribution/Client/Config.hs
--- a/Distribution/Client/Config.hs
+++ b/Distribution/Client/Config.hs
@@ -30,16 +30,18 @@
     commentSavedConfig,
     initialSavedConfig,
     configFieldDescriptions,
-    installDirsFields
+    haddockFlagsFields,
+    installDirsFields,
+    withProgramsFields,
+    withProgramOptionsFields
   ) where
 
-
 import Distribution.Client.Types
          ( RemoteRepo(..), Username(..), Password(..) )
 import Distribution.Client.BuildReports.Types
          ( ReportLevel(..) )
 import Distribution.Client.Setup
-         ( GlobalFlags(..), globalCommand
+         ( GlobalFlags(..), globalCommand, defaultGlobalFlags
          , ConfigExFlags(..), configureExOptions, defaultConfigExFlags
          , InstallFlags(..), installOptions, defaultInstallFlags
          , UploadFlags(..), uploadCommand
@@ -50,6 +52,7 @@
          ( OptimisationLevel(..) )
 import Distribution.Simple.Setup
          ( ConfigFlags(..), configureOptions, defaultConfigFlags
+         , HaddockFlags(..), haddockOptions, defaultHaddockFlags
          , installDirsOptions
          , programConfigurationPaths', programConfigurationOptions
          , Flag(..), toFlag, flagToMaybe, fromFlagOrDefault )
@@ -119,7 +122,8 @@
     savedUserInstallDirs   :: InstallDirs (Flag PathTemplate),
     savedGlobalInstallDirs :: InstallDirs (Flag PathTemplate),
     savedUploadFlags       :: UploadFlags,
-    savedReportFlags       :: ReportFlags
+    savedReportFlags       :: ReportFlags,
+    savedHaddockFlags      :: HaddockFlags
   }
 
 instance Monoid SavedConfig where
@@ -131,182 +135,21 @@
     savedUserInstallDirs   = mempty,
     savedGlobalInstallDirs = mempty,
     savedUploadFlags       = mempty,
-    savedReportFlags       = mempty
+    savedReportFlags       = mempty,
+    savedHaddockFlags      = mempty
   }
   mappend a b = SavedConfig {
-    savedGlobalFlags       = combinedSavedGlobalFlags,
-    savedInstallFlags      = combinedSavedInstallFlags,
-    savedConfigureFlags    = combinedSavedConfigureFlags,
-    savedConfigureExFlags  = combinedSavedConfigureExFlags,
-    savedUserInstallDirs   = combinedSavedUserInstallDirs,
-    savedGlobalInstallDirs = combinedSavedGlobalInstallDirs,
-    savedUploadFlags       = combinedSavedUploadFlags,
-    savedReportFlags       = combinedSavedReportFlags
+    savedGlobalFlags       = combine savedGlobalFlags,
+    savedInstallFlags      = combine savedInstallFlags,
+    savedConfigureFlags    = combine savedConfigureFlags,
+    savedConfigureExFlags  = combine savedConfigureExFlags,
+    savedUserInstallDirs   = combine savedUserInstallDirs,
+    savedGlobalInstallDirs = combine savedGlobalInstallDirs,
+    savedUploadFlags       = combine savedUploadFlags,
+    savedReportFlags       = combine savedReportFlags,
+    savedHaddockFlags      = combine savedHaddockFlags
   }
-    where
-      -- This is ugly, but necessary. If we're mappending two config files, we
-      -- want the values of the *non-empty* list fields from the second one to
-      -- *override* the corresponding values from the first one. Default
-      -- behaviour (concatenation) is confusing and makes some use cases (see
-      -- #1884) impossible.
-      --
-      -- However, we also want to allow specifying multiple values for a list
-      -- field in a *single* config file. For example, we want the following to
-      -- continue to work:
-      --
-      -- remote-repo: hackage.haskell.org:http://hackage.haskell.org/
-      -- remote-repo: private-collection:http://hackage.local/
-      --
-      -- So we can't just wrap the list fields inside Flags; we have to do some
-      -- special-casing just for SavedConfig.
-
-      -- NB: the signature prevents us from using 'combine' on lists.
-      combine' :: (SavedConfig -> flags) -> (flags -> Flag a) -> Flag a
-      combine'        field subfield =
-        (subfield . field $ a) `mappend` (subfield . field $ b)
-
-      lastNonEmpty' :: (SavedConfig -> flags) -> (flags -> [a]) -> [a]
-      lastNonEmpty'   field subfield =
-        let a' = subfield . field $ a
-            b' = subfield . field $ b
-        in case b' of [] -> a'
-                      _  -> b'
-
-      lastNonEmptyNL' :: (SavedConfig -> flags) -> (flags -> [a])
-                      -> [a]
-      lastNonEmptyNL' field subfield =
-        let a' = subfield . field $ a
-            b' = subfield . field $ b
-        in case b' of [] -> a'
-                      _  -> b'
-
-      combinedSavedGlobalFlags = GlobalFlags {
-        globalVersion           = combine globalVersion,
-        globalNumericVersion    = combine globalNumericVersion,
-        globalConfigFile        = combine globalConfigFile,
-        globalSandboxConfigFile = combine globalSandboxConfigFile,
-        globalRemoteRepos       = lastNonEmptyNL globalRemoteRepos,
-        globalCacheDir          = combine globalCacheDir,
-        globalLocalRepos        = lastNonEmptyNL globalLocalRepos,
-        globalLogsDir           = combine globalLogsDir,
-        globalWorldFile         = combine globalWorldFile
-        }
-        where
-          combine        = combine'        savedGlobalFlags
-          lastNonEmptyNL = lastNonEmptyNL' savedGlobalFlags
-
-      combinedSavedInstallFlags = InstallFlags {
-        installDocumentation         = combine installDocumentation,
-        installHaddockIndex          = combine installHaddockIndex,
-        installDryRun                = combine installDryRun,
-        installMaxBackjumps          = combine installMaxBackjumps,
-        installReorderGoals          = combine installReorderGoals,
-        installIndependentGoals      = combine installIndependentGoals,
-        installShadowPkgs            = combine installShadowPkgs,
-        installStrongFlags           = combine installStrongFlags,
-        installReinstall             = combine installReinstall,
-        installAvoidReinstalls       = combine installAvoidReinstalls,
-        installOverrideReinstall     = combine installOverrideReinstall,
-        installUpgradeDeps           = combine installUpgradeDeps,
-        installOnly                  = combine installOnly,
-        installOnlyDeps              = combine installOnlyDeps,
-        installRootCmd               = combine installRootCmd,
-        installSummaryFile           = lastNonEmptyNL installSummaryFile,
-        installLogFile               = combine installLogFile,
-        installBuildReports          = combine installBuildReports,
-        installSymlinkBinDir         = combine installSymlinkBinDir,
-        installOneShot               = combine installOneShot,
-        installNumJobs               = combine installNumJobs
-        }
-        where
-          combine        = combine'        savedInstallFlags
-          lastNonEmptyNL = lastNonEmptyNL' savedInstallFlags
-
-      combinedSavedConfigureFlags = ConfigFlags {
-        configPrograms            = configPrograms . savedConfigureFlags $ b,
-        -- TODO: NubListify
-        configProgramPaths        = lastNonEmpty configProgramPaths,
-        -- TODO: NubListify
-        configProgramArgs         = lastNonEmpty configProgramArgs,
-        configProgramPathExtra    = lastNonEmptyNL configProgramPathExtra,
-        configHcFlavor            = combine configHcFlavor,
-        configHcPath              = combine configHcPath,
-        configHcPkg               = combine configHcPkg,
-        configVanillaLib          = combine configVanillaLib,
-        configProfLib             = combine configProfLib,
-        configSharedLib           = combine configSharedLib,
-        configDynExe              = combine configDynExe,
-        configProfExe             = combine configProfExe,
-        -- TODO: NubListify
-        configConfigureArgs       = lastNonEmpty configConfigureArgs,
-        configOptimization        = combine configOptimization,
-        configProgPrefix          = combine configProgPrefix,
-        configProgSuffix          = combine configProgSuffix,
-        -- Parametrised by (Flag PathTemplate), so safe to use 'mappend'.
-        configInstallDirs         =
-          (configInstallDirs . savedConfigureFlags $ a)
-          `mappend` (configInstallDirs . savedConfigureFlags $ b),
-        configScratchDir          = combine configScratchDir,
-        -- TODO: NubListify
-        configExtraLibDirs        = lastNonEmpty configExtraLibDirs,
-        -- TODO: NubListify
-        configExtraIncludeDirs    = lastNonEmpty configExtraIncludeDirs,
-        configDistPref            = combine configDistPref,
-        configVerbosity           = combine configVerbosity,
-        configUserInstall         = combine configUserInstall,
-        -- TODO: NubListify
-        configPackageDBs          = lastNonEmpty configPackageDBs,
-        configGHCiLib             = combine configGHCiLib,
-        configSplitObjs           = combine configSplitObjs,
-        configStripExes           = combine configStripExes,
-        configConstraints         = lastNonEmpty configConstraints,
-        configConfigurationsFlags = lastNonEmpty configConfigurationsFlags,
-        configTests               = combine configTests,
-        configBenchmarks          = combine configBenchmarks,
-        configLibCoverage         = combine configLibCoverage
-        }
-        where
-          combine        = combine'        savedConfigureFlags
-          lastNonEmpty   = lastNonEmpty'   savedConfigureFlags
-          lastNonEmptyNL = lastNonEmptyNL' savedConfigureFlags
-
-      combinedSavedConfigureExFlags = ConfigExFlags {
-        configCabalVersion  = combine configCabalVersion,
-        -- TODO: NubListify
-        configExConstraints = lastNonEmpty configExConstraints,
-        -- TODO: NubListify
-        configPreferences   = lastNonEmpty configPreferences,
-        configSolver        = combine configSolver
-        }
-        where
-          combine      = combine' savedConfigureExFlags
-          lastNonEmpty = lastNonEmpty' savedConfigureExFlags
-
-      -- Parametrised by (Flag PathTemplate), so safe to use 'mappend'.
-      combinedSavedUserInstallDirs = savedUserInstallDirs a
-                                     `mappend` savedUserInstallDirs b
-
-      -- Parametrised by (Flag PathTemplate), so safe to use 'mappend'.
-      combinedSavedGlobalInstallDirs = savedGlobalInstallDirs a
-                                       `mappend` savedGlobalInstallDirs b
-
-      combinedSavedUploadFlags = UploadFlags {
-        uploadCheck     = combine uploadCheck,
-        uploadUsername  = combine uploadUsername,
-        uploadPassword  = combine uploadPassword,
-        uploadVerbosity = combine uploadVerbosity
-        }
-        where
-          combine = combine' savedUploadFlags
-
-      combinedSavedReportFlags = ReportFlags {
-        reportUsername  = combine reportUsername,
-        reportPassword  = combine reportPassword,
-        reportVerbosity = combine reportVerbosity
-        }
-        where
-          combine = combine' savedReportFlags
-
+    where combine field = field a `mappend` field b
 
 updateInstallDirs :: Flag Bool -> SavedConfig -> SavedConfig
 updateInstallDirs userInstallFlag
@@ -511,7 +354,7 @@
   userInstallDirs   <- defaultInstallDirs defaultCompiler True True
   globalInstallDirs <- defaultInstallDirs defaultCompiler False True
   return SavedConfig {
-    savedGlobalFlags       = commandDefaultFlags globalCommand,
+    savedGlobalFlags       = defaultGlobalFlags,
     savedInstallFlags      = defaultInstallFlags,
     savedConfigureExFlags  = defaultConfigExFlags,
     savedConfigureFlags    = (defaultConfigFlags defaultProgramConfiguration) {
@@ -520,7 +363,8 @@
     savedUserInstallDirs   = fmap toFlag userInstallDirs,
     savedGlobalInstallDirs = fmap toFlag globalInstallDirs,
     savedUploadFlags       = commandDefaultFlags uploadCommand,
-    savedReportFlags       = commandDefaultFlags reportCommand
+    savedReportFlags       = commandDefaultFlags reportCommand,
+    savedHaddockFlags      = defaultHaddockFlags
   }
 
 -- | All config file fields.
@@ -534,7 +378,8 @@
 
   ++ toSavedConfig liftConfigFlag
        (configureOptions ParseArgs)
-       (["builddir", "configure-option", "constraint"] ++ map fieldName installDirsFields)
+       (["builddir", "configure-option", "constraint", "dependency"]
+        ++ map fieldName installDirsFields)
 
         --FIXME: this is only here because viewAsFieldDescr gives us a parser
         -- that only recognises 'ghc' etc, the case-sensitive flag names, not
@@ -584,7 +429,7 @@
   ++ toSavedConfig liftReportFlag
        (commandOptions reportCommand ParseArgs)
        ["verbose", "username", "password"] []
-       --FIXME: this is a hack, hiding the username and password.
+       --FIXME: this is a hack, hiding the user name and password.
        -- But otherwise it masks the upload ones. Either need to
        -- share the options or make then distinct. In any case
        -- they should probably be per-server.
@@ -670,18 +515,25 @@
   config <- parse others
   let user0   = savedUserInstallDirs config
       global0 = savedGlobalInstallDirs config
-  (user, global, paths, args) <-
-    foldM parseSections (user0, global0, [], []) knownSections
+  (haddockFlags, user, global, paths, args) <-
+    foldM parseSections
+          (savedHaddockFlags config, user0, global0, [], [])
+          knownSections
   return config {
     savedConfigureFlags    = (savedConfigureFlags config) {
        configProgramPaths  = paths,
        configProgramArgs   = args
        },
+    savedHaddockFlags      = haddockFlags {
+       haddockProgramPaths = paths,
+       haddockProgramArgs  = args
+       },
     savedUserInstallDirs   = user,
     savedGlobalInstallDirs = global
   }
 
   where
+    isKnownSection (ParseUtils.Section _ "haddock" _ _)                 = True
     isKnownSection (ParseUtils.Section _ "install-dirs" _ _)            = True
     isKnownSection (ParseUtils.Section _ "program-locations" _ _)       = True
     isKnownSection (ParseUtils.Section _ "program-default-options" _ _) = True
@@ -690,26 +542,34 @@
     parse = parseFields (configFieldDescriptions
                       ++ deprecatedFieldDescriptions) initial
 
-    parseSections accum@(u,g,p,a) (ParseUtils.Section _ "install-dirs" name fs)
+    parseSections accum@(h,u,g,p,a)
+                 (ParseUtils.Section _ "haddock" name fs)
+      | name == ""        = do h' <- parseFields haddockFlagsFields h fs
+                               return (h', u, g, p, a)
+      | otherwise         = do
+          warning "The 'haddock' section should be unnamed"
+          return accum
+    parseSections accum@(h,u,g,p,a)
+                  (ParseUtils.Section _ "install-dirs" name fs)
       | name' == "user"   = do u' <- parseFields installDirsFields u fs
-                               return (u', g, p, a)
+                               return (h, u', g, p, a)
       | name' == "global" = do g' <- parseFields installDirsFields g fs
-                               return (u, g', p, a)
+                               return (h, u, g', p, a)
       | otherwise         = do
-          warning "The install-paths section should be for 'user' or 'global'"
+          warning "The 'install-paths' section should be for 'user' or 'global'"
           return accum
       where name' = lowercase name
-    parseSections accum@(u,g,p,a)
+    parseSections accum@(h,u,g,p,a)
                  (ParseUtils.Section _ "program-locations" name fs)
       | name == ""        = do p' <- parseFields withProgramsFields p fs
-                               return (u, g, p', a)
+                               return (h, u, g, p', a)
       | otherwise         = do
           warning "The 'program-locations' section should be unnamed"
           return accum
-    parseSections accum@(u, g, p, a)
+    parseSections accum@(h, u, g, p, a)
                   (ParseUtils.Section _ "program-default-options" name fs)
       | name == ""        = do a' <- parseFields withProgramOptionsFields a fs
-                               return (u, g, p, a')
+                               return (h, u, g, p, a')
       | otherwise         = do
           warning "The 'program-default-options' section should be unnamed"
           return accum
@@ -724,6 +584,9 @@
 showConfigWithComments comment vals = Disp.render $
       ppFields configFieldDescriptions mcomment vals
   $+$ Disp.text ""
+  $+$ ppSection "haddock" "" haddockFlagsFields
+                (fmap savedHaddockFlags mcomment) (savedHaddockFlags vals)
+  $+$ Disp.text ""
   $+$ installDirsSection "user"   savedUserInstallDirs
   $+$ Disp.text ""
   $+$ installDirsSection "global" savedGlobalInstallDirs
@@ -743,9 +606,19 @@
                (fmap (field . savedConfigureFlags) mcomment)
                ((field . savedConfigureFlags) vals)
 
-
+-- | Fields for the 'install-dirs' sections.
 installDirsFields :: [FieldDescr (InstallDirs (Flag PathTemplate))]
 installDirsFields = map viewAsFieldDescr installDirsOptions
+
+-- | Fields for the 'haddock' section.
+haddockFlagsFields :: [FieldDescr HaddockFlags]
+haddockFlagsFields = [ field
+                     | opt <- haddockOptions ParseArgs
+                     , let field = viewAsFieldDescr opt
+                           name  = fieldName field
+                     , name `notElem` exclusions ]
+  where
+    exclusions = ["verbose", "builddir"]
 
 -- | Fields for the 'program-locations' section.
 withProgramsFields :: [FieldDescr [(String, FilePath)]]
diff --git a/Distribution/Client/Configure.hs b/Distribution/Client/Configure.hs
--- a/Distribution/Client/Configure.hs
+++ b/Distribution/Client/Configure.hs
@@ -12,9 +12,11 @@
 -----------------------------------------------------------------------------
 module Distribution.Client.Configure (
     configure,
+    chooseCabalVersion,
   ) where
 
 import Distribution.Client.Dependency
+import Distribution.Client.Dependency.Types (AllowNewer(..), isAllowNewer)
 import qualified Distribution.Client.InstallPlan as InstallPlan
 import Distribution.Client.InstallPlan (InstallPlan)
 import Distribution.Client.IndexUtils as IndexUtils
@@ -36,6 +38,7 @@
 import Distribution.Simple.PackageIndex (PackageIndex)
 import Distribution.Simple.Utils
          ( defaultPackageDesc )
+import qualified Distribution.InstalledPackageInfo as Installed
 import Distribution.Package
          ( Package(..), packageName, Dependency(..), thisPackageVersion )
 import Distribution.PackageDescription.Parse
@@ -45,14 +48,29 @@
 import Distribution.Version
          ( anyVersion, thisVersion )
 import Distribution.Simple.Utils as Utils
-         ( notice, info, debug, die )
+         ( notice, debug, die )
 import Distribution.System
          ( Platform )
 import Distribution.Verbosity as Verbosity
          ( Verbosity )
+import Distribution.Version
+         ( Version(..), VersionRange, orLaterVersion )
 
 import Data.Monoid (Monoid(..))
 
+-- | Choose the Cabal version such that the setup scripts compiled against this
+-- version will support the given command-line flags.
+chooseCabalVersion :: ConfigExFlags -> Maybe Version -> VersionRange
+chooseCabalVersion configExFlags maybeVersion =
+  maybe defaultVersionRange thisVersion maybeVersion
+  where
+    allowNewer = fromFlagOrDefault False $
+                 fmap isAllowNewer (configAllowNewer configExFlags)
+
+    defaultVersionRange = if allowNewer
+                          then orLaterVersion (Version [1,19,2] [])
+                          else anyVersion
+
 -- | Configure the package found in the local directory
 configure :: Verbosity
           -> PackageDBStack
@@ -77,13 +95,10 @@
   maybePlan <- foldProgress logMsg (return . Left) (return . Right)
                             progress
   case maybePlan of
-    Left message -> do
-      info verbosity message
-      setupWrapper verbosity (setupScriptOptions installedPkgIndex) Nothing
-        configureCommand (const configFlags) extraArgs
+    Left message -> die message
 
     Right installPlan -> case InstallPlan.ready installPlan of
-      [pkg@(ConfiguredPackage (SourcePackage _ _ (LocalUnpackedPackage _) _) _ _ _)] ->
+      [pkg@(ReadyPackage (SourcePackage _ _ (LocalUnpackedPackage _) _) _ _ _)] ->
         configurePackage verbosity
           (InstallPlan.planPlatform installPlan)
           (InstallPlan.planCompiler installPlan)
@@ -95,7 +110,7 @@
 
   where
     setupScriptOptions index = SetupScriptOptions {
-      useCabalVersion  = maybe anyVersion thisVersion
+      useCabalVersion  = chooseCabalVersion configExFlags
                          (flagToMaybe (configCabalVersion configExFlags)),
       useCompiler      = Just comp,
       usePlatform      = Just platform,
@@ -150,16 +165,18 @@
         fromFlagOrDefault False $ configBenchmarks configFlags
 
       resolverParams =
+          removeUpperBounds (fromFlagOrDefault AllowNewerNone $
+                             configAllowNewer configExFlags)
 
-          addPreferences
+        . addPreferences
             -- preferences from the config file or command line
             [ PackageVersionPreference name ver
             | Dependency name ver <- configPreferences configExFlags ]
 
         . addConstraints
             -- version constraints from the config file or command line
-            -- TODO: should warn or error on constraints that are not on direct deps
-            -- or flag constraints not on the package in question.
+            -- TODO: should warn or error on constraints that are not on direct
+            -- deps or flag constraints not on the package in question.
             (map userToPackageConstraint (configExConstraints configExFlags))
 
         . addConstraints
@@ -184,20 +201,22 @@
 
 
 -- | Call an installer for an 'SourcePackage' but override the configure
--- flags with the ones given by the 'ConfiguredPackage'. In particular the
--- 'ConfiguredPackage' specifies an exact 'FlagAssignment' and exactly
+-- flags with the ones given by the 'ReadyPackage'. In particular the
+-- 'ReadyPackage' specifies an exact 'FlagAssignment' and exactly
 -- versioned package dependencies. So we ignore any previous partial flag
 -- assignment or dependency constraints and use the new ones.
 --
+-- NB: when updating this function, don't forget to also update
+-- 'installReadyPackage' in D.C.Install.
 configurePackage :: Verbosity
                  -> Platform -> CompilerId
                  -> SetupScriptOptions
                  -> ConfigFlags
-                 -> ConfiguredPackage
+                 -> ReadyPackage
                  -> [String]
                  -> IO ()
 configurePackage verbosity platform comp scriptOptions configFlags
-  (ConfiguredPackage (SourcePackage _ gpkg _ _) flags stanzas deps) extraArgs =
+  (ReadyPackage (SourcePackage _ gpkg _ _) flags stanzas deps) extraArgs =
 
   setupWrapper verbosity
     scriptOptions (Just pkg) configureCommand configureFlags extraArgs
@@ -205,14 +224,23 @@
   where
     configureFlags   = filterConfigureFlags configFlags {
       configConfigurationsFlags = flags,
-      configConstraints         = map thisPackageVersion deps,
-      configVerbosity           = toFlag verbosity,
-      configBenchmarks          = toFlag (BenchStanzas `elem` stanzas),
-      configTests               = toFlag (TestStanzas `elem` stanzas)
+      -- We generate the legacy constraints as well as the new style precise
+      -- deps.  In the end only one set gets passed to Setup.hs configure,
+      -- depending on the Cabal version we are talking to.
+      configConstraints  = [ thisPackageVersion (packageId deppkg)
+                           | deppkg <- deps ],
+      configDependencies = [ (packageName (Installed.sourcePackageId deppkg),
+                              Installed.installedPackageId deppkg)
+                           | deppkg <- deps ],
+      -- Use '--exact-configuration' if supported.
+      configExactConfiguration = toFlag True,
+      configVerbosity          = toFlag verbosity,
+      configBenchmarks         = toFlag (BenchStanzas `elem` stanzas),
+      configTests              = toFlag (TestStanzas `elem` stanzas)
     }
 
     pkg = case finalizePackageDescription flags
            (const True)
            platform comp [] (enableStanzas stanzas gpkg) of
-      Left _ -> error "finalizePackageDescription ConfiguredPackage failed"
+      Left _ -> error "finalizePackageDescription ReadyPackage failed"
       Right (desc, _) -> desc
diff --git a/Distribution/Client/Dependency.hs b/Distribution/Client/Dependency.hs
--- a/Distribution/Client/Dependency.hs
+++ b/Distribution/Client/Dependency.hs
@@ -37,7 +37,7 @@
     applySandboxInstallPolicy,
 
     -- ** Extra policy options
-    dontUpgradeBasePackage,
+    dontUpgradeNonUpgradeablePackages,
     hideBrokenInstalledPackages,
     upgradeDependencies,
     reinstallTargets,
@@ -50,12 +50,12 @@
     setIndependentGoals,
     setAvoidReinstalls,
     setShadowPkgs,
-    setStrongFlags,
     setMaxBackjumps,
     addSourcePackages,
     hideInstalledPackagesSpecificByInstalledPackageId,
     hideInstalledPackagesSpecificBySourcePackageId,
     hideInstalledPackagesAllVersions,
+    removeUpperBounds
   ) where
 
 import Distribution.Client.Dependency.TopDown
@@ -71,7 +71,7 @@
          , SourcePackage(..) )
 import Distribution.Client.Dependency.Types
          ( PreSolver(..), Solver(..), DependencyResolver, PackageConstraint(..)
-         , PackagePreferences(..), InstalledPreference(..)
+         , AllowNewer(..), PackagePreferences(..), InstalledPreference(..)
          , PackagesPreferenceDefault(..)
          , Progress(..), foldProgress )
 import Distribution.Client.Sandbox.Types
@@ -81,9 +81,14 @@
 import Distribution.Package
          ( PackageName(..), PackageId, Package(..), packageName, packageVersion
          , InstalledPackageId, Dependency(Dependency))
+import qualified Distribution.PackageDescription as PD
+         ( PackageDescription(..), GenericPackageDescription(..)
+         , Library(..), Executable(..), TestSuite(..), Benchmark(..), CondTree)
+import Distribution.PackageDescription (BuildInfo(targetBuildDepends))
+import Distribution.PackageDescription.Configuration (mapCondTree)
 import Distribution.Version
          ( Version(..), VersionRange, anyVersion, thisVersion, withinRange
-         , simplifyVersionRange )
+         , removeUpperBound, simplifyVersionRange )
 import Distribution.Compiler
          ( CompilerId(..), CompilerFlavor(..) )
 import Distribution.System
@@ -120,7 +125,6 @@
        depResolverIndependentGoals  :: Bool,
        depResolverAvoidReinstalls   :: Bool,
        depResolverShadowPkgs        :: Bool,
-       depResolverStrongFlags       :: Bool,
        depResolverMaxBackjumps      :: Maybe Int
      }
 
@@ -154,7 +158,6 @@
        depResolverIndependentGoals  = False,
        depResolverAvoidReinstalls   = False,
        depResolverShadowPkgs        = False,
-       depResolverStrongFlags       = False,
        depResolverMaxBackjumps      = Nothing
      }
 
@@ -212,30 +215,27 @@
       depResolverShadowPkgs = b
     }
 
-setStrongFlags :: Bool -> DepResolverParams -> DepResolverParams
-setStrongFlags b params =
-    params {
-      depResolverStrongFlags = b
-    }
-
 setMaxBackjumps :: Maybe Int -> DepResolverParams -> DepResolverParams
 setMaxBackjumps n params =
     params {
       depResolverMaxBackjumps = n
     }
 
-dontUpgradeBasePackage :: DepResolverParams -> DepResolverParams
-dontUpgradeBasePackage params =
+-- | Some packages are specific to a given compiler version and should never be
+-- upgraded.
+dontUpgradeNonUpgradeablePackages :: DepResolverParams -> DepResolverParams
+dontUpgradeNonUpgradeablePackages params =
     addConstraints extraConstraints params
   where
     extraConstraints =
       [ PackageConstraintInstalled pkgname
       | all (/=PackageName "base") (depResolverTargets params)
-      , pkgname <-  [ PackageName "base", PackageName "ghc-prim" ]
+      , pkgname <- map PackageName [ "base", "ghc-prim", "integer-gmp"
+                                   , "integer-simple", "template-haskell" ]
       , isInstalled pkgname ]
     -- TODO: the top down resolver chokes on the base constraints
     -- below when there are no targets and thus no dep on base.
-    -- Need to refactor contraints separate from needing packages.
+    -- Need to refactor constraints separate from needing packages.
     isInstalled = not . null
                 . InstalledPackageIndex.lookupPackageName
                                  (depResolverInstalledPkgIndex params)
@@ -293,7 +293,89 @@
            . InstalledPackageIndex.brokenPackages
            $ depResolverInstalledPkgIndex params
 
+-- | Remove upper bounds in dependencies using the policy specified by the
+-- 'AllowNewer' argument (all/some/none).
+removeUpperBounds :: AllowNewer -> DepResolverParams -> DepResolverParams
+removeUpperBounds allowNewer params =
+    params {
+      -- NB: It's important to apply 'removeUpperBounds' after
+      -- 'addSourcePackages'. Otherwise, the packages inserted by
+      -- 'addSourcePackages' won't have upper bounds in dependencies relaxed.
 
+      depResolverSourcePkgIndex = sourcePkgIndex'
+    }
+  where
+    sourcePkgIndex  = depResolverSourcePkgIndex params
+    sourcePkgIndex' = case allowNewer of
+      AllowNewerNone      -> sourcePkgIndex
+      AllowNewerAll       -> fmap relaxAllPackageDeps         sourcePkgIndex
+      AllowNewerSome pkgs -> fmap (relaxSomePackageDeps pkgs) sourcePkgIndex
+
+    relaxAllPackageDeps :: SourcePackage -> SourcePackage
+    relaxAllPackageDeps = onAllBuildDepends doRelax
+      where
+        doRelax (Dependency pkgName verRange) =
+          Dependency pkgName (removeUpperBound verRange)
+
+    relaxSomePackageDeps :: [PackageName] -> SourcePackage -> SourcePackage
+    relaxSomePackageDeps pkgNames = onAllBuildDepends doRelax
+      where
+        doRelax d@(Dependency pkgName verRange)
+          | pkgName `elem` pkgNames = Dependency pkgName
+                                      (removeUpperBound verRange)
+          | otherwise               = d
+
+    -- Walk a 'GenericPackageDescription' and apply 'f' to all 'build-depends'
+    -- fields.
+    onAllBuildDepends :: (Dependency -> Dependency)
+                      -> SourcePackage -> SourcePackage
+    onAllBuildDepends f srcPkg = srcPkg'
+      where
+        gpd        = packageDescription srcPkg
+        pd         = PD.packageDescription gpd
+        condLib    = PD.condLibrary        gpd
+        condExes   = PD.condExecutables    gpd
+        condTests  = PD.condTestSuites     gpd
+        condBenchs = PD.condBenchmarks     gpd
+
+        f' = onBuildInfo f
+        onBuildInfo g bi = bi
+          { targetBuildDepends = map g (targetBuildDepends bi) }
+
+        onLibrary    lib  = lib { PD.libBuildInfo  = f' $ PD.libBuildInfo  lib }
+        onExecutable exe  = exe { PD.buildInfo     = f' $ PD.buildInfo     exe }
+        onTestSuite  tst  = tst { PD.testBuildInfo = f' $ PD.testBuildInfo tst }
+        onBenchmark  bmk  = bmk { PD.benchmarkBuildInfo =
+                                     f' $ PD.benchmarkBuildInfo bmk }
+
+        srcPkg' = srcPkg { packageDescription = gpd' }
+        gpd'    = gpd {
+          PD.packageDescription = pd',
+          PD.condLibrary        = condLib',
+          PD.condExecutables    = condExes',
+          PD.condTestSuites     = condTests',
+          PD.condBenchmarks     = condBenchs'
+          }
+        pd' = pd {
+          PD.buildDepends = map  f            (PD.buildDepends pd),
+          PD.library      = fmap onLibrary    (PD.library pd),
+          PD.executables  = map  onExecutable (PD.executables pd),
+          PD.testSuites   = map  onTestSuite  (PD.testSuites pd),
+          PD.benchmarks   = map  onBenchmark  (PD.benchmarks pd)
+          }
+        condLib'    = fmap (onCondTree onLibrary)             condLib
+        condExes'   = map  (mapSnd $ onCondTree onExecutable) condExes
+        condTests'  = map  (mapSnd $ onCondTree onTestSuite)  condTests
+        condBenchs' = map  (mapSnd $ onCondTree onBenchmark)  condBenchs
+
+        mapSnd :: (a -> b) -> (c,a) -> (c,b)
+        mapSnd = fmap
+
+        onCondTree :: (a -> b) -> PD.CondTree v [Dependency] a
+                   -> PD.CondTree v [Dependency] b
+        onCondTree g = mapCondTree g (map f) id
+
+
 upgradeDependencies :: DepResolverParams -> DepResolverParams
 upgradeDependencies = setPreferenceDefault PreferAllLatest
 
@@ -384,7 +466,7 @@
   return chosenSolver
 
 runSolver :: Solver -> SolverConfig -> DependencyResolver
-runSolver TopDown = const topDownResolver -- TODO: warn about unsuported options
+runSolver TopDown = const topDownResolver -- TODO: warn about unsupported options
 runSolver Modular = modularResolver
 
 -- | Run the dependency solver.
@@ -399,7 +481,7 @@
                     -> DepResolverParams
                     -> Progress String String InstallPlan
 
-    --TODO: is this needed here? see dontUpgradeBasePackage
+    --TODO: is this needed here? see dontUpgradeNonUpgradeablePackages
 resolveDependencies platform comp _solver params
   | null (depResolverTargets params)
   = return (mkInstallPlan platform comp [])
@@ -408,7 +490,7 @@
 
     fmap (mkInstallPlan platform comp)
   $ runSolver solver (SolverConfig reorderGoals indGoals noReinstalls
-                      shadowing strFlags maxBkjumps)
+                      shadowing maxBkjumps)
                      platform comp installedPkgIndex sourcePkgIndex
                      preferences constraints targets
   where
@@ -421,13 +503,12 @@
       indGoals
       noReinstalls
       shadowing
-      strFlags
-      maxBkjumps      = dontUpgradeBasePackage
+      maxBkjumps      = dontUpgradeNonUpgradeablePackages
                       -- TODO:
                       -- The modular solver can properly deal with broken
                       -- packages and won't select them. So the
                       -- 'hideBrokenInstalledPackages' function should be moved
-                      -- into a module that is specific to the Topdown solver.
+                      -- into a module that is specific to the top-down solver.
                       . (if solver /= Modular then hideBrokenInstalledPackages
                                               else id)
                       $ params
@@ -435,7 +516,6 @@
     preferences = interpretPackagesPreference
                     (Set.fromList targets) defpref prefs
 
-
 -- | Make an install plan from the output of the dep resolver.
 -- It checks that the plan is valid, or it's an error in the dep resolver.
 --
@@ -497,7 +577,7 @@
 -- It is suitable for tasks such as selecting packages to download for user
 -- inspection. It is not suitable for selecting packages to install.
 --
--- Note: if no installed package index is available, it is ok to pass 'mempty'.
+-- Note: if no installed package index is available, it is OK to pass 'mempty'.
 -- It simply means preferences for installed packages will be ignored.
 --
 resolveWithoutDependencies :: DepResolverParams
@@ -505,7 +585,7 @@
 resolveWithoutDependencies (DepResolverParams targets constraints
                               prefs defpref installedPkgIndex sourcePkgIndex
                               _reorderGoals _indGoals _avoidReinstalls
-                              _shadowing _strFlags _maxBjumps) =
+                              _shadowing _maxBjumps) =
     collectEithers (map selectPackage targets)
   where
     selectPackage :: PackageName -> Either ResolveNoDepsError SourcePackage
diff --git a/Distribution/Client/Dependency/Modular.hs b/Distribution/Client/Dependency/Modular.hs
--- a/Distribution/Client/Dependency/Modular.hs
+++ b/Distribution/Client/Dependency/Modular.hs
@@ -41,7 +41,7 @@
   solve sc idx pprefs gcs pns
     where
       -- Indices have to be converted into solver-specific uniform index.
-      idx    = convPIs os arch cid (shadowPkgs sc) (strongFlags sc) iidx sidx
+      idx    = convPIs os arch cid (shadowPkgs sc) iidx sidx
       -- Constraints have to be converted into a finite map indexed by PN.
       gcs    = M.fromListWith (++) (map (\ pc -> (pcName pc, [pc])) pcs)
 
diff --git a/Distribution/Client/Dependency/Modular/Builder.hs b/Distribution/Client/Dependency/Modular/Builder.hs
--- a/Distribution/Client/Dependency/Modular/Builder.hs
+++ b/Distribution/Client/Dependency/Modular/Builder.hs
@@ -46,9 +46,6 @@
     go :: RevDepMap -> PSQ OpenGoal () -> [OpenGoal] -> BuildState
     go g o []                                             = s { rdeps = g, open = o }
     go g o (ng@(OpenGoal (Flagged _ _ _ _)    _gr) : ngs) = go g (cons ng () o) ngs
-      -- Note: for 'Flagged' goals, we always insert, so later additions win.
-      -- This is important, because in general, if a goal is inserted twice,
-      -- the later addition will have better dependency information.
     go g o (ng@(OpenGoal (Stanza  _   _  )    _gr) : ngs) = go g (cons ng () o) ngs
     go g o (ng@(OpenGoal (Simple (Dep qpn _)) _gr) : ngs)
       | qpn == qpn'                                       = go                       g              o  ngs
@@ -72,34 +69,11 @@
 scopedExtendOpen qpn i gr fdeps fdefs s = extendOpen qpn gs s
   where
     sc     = scope s
-    -- Qualify all package names
     qfdeps = L.map (fmap (qualify sc)) fdeps -- qualify all the package names
-    -- Introduce all package flags
     qfdefs = L.map (\ (fn, b) -> Flagged (FN (PI qpn i) fn) b [] []) $ M.toList fdefs
-    -- Combine new package and flag goals
-    gs     = L.map (flip OpenGoal gr) (qfdefs ++ qfdeps)
-    -- NOTE:
-    --
-    -- In the expression @qfdefs ++ qfdeps@ above, flags occur potentially
-    -- multiple times, both via the flag declaration and via dependencies.
-    -- The order is potentially important, because the occurrences via
-    -- dependencies may record flag-dependency information. After a number
-    -- of bugs involving computing this information incorrectly, however,
-    -- we're currently not using carefully computed inter-flag dependencies
-    -- anymore, but instead use 'simplifyVar' when computing conflict sets
-    -- to map all flags of one package to a single flag for conflict set
-    -- purposes, thereby treating them all as interdependent.
-    --
-    -- If we ever move to a more clever algorithm again, then the line above
-    -- needs to be looked at very carefully, and probably be replaced by
-    -- more systematically computed flag dependency information.
+    gs     = L.map (flip OpenGoal gr) (qfdeps ++ qfdefs)
 
--- | Datatype that encodes what to build next
-data BuildType =
-    Goals                                  -- ^ build a goal choice node
-  | OneGoal OpenGoal                       -- ^ build a node for this goal
-  | Instance QPN I PInfo QGoalReasonChain  -- ^ build a tree for a concrete instance
-  deriving Show
+data BuildType = Goals | OneGoal OpenGoal | Instance QPN I PInfo QGoalReasonChain
 
 build :: BuildState -> Tree (QGoalReasonChain, Scope)
 build = ana go
@@ -131,8 +105,8 @@
     -- that is indicated by the flag default.
     --
     -- TODO: Should we include the flag default in the tree?
-    go bs@(BS { scope = sc, next = OneGoal (OpenGoal (Flagged qfn@(FN (PI qpn _) _) (FInfo b m w) t f) gr) }) =
-      FChoiceF qfn (gr, sc) (w || trivial) m (P.fromList (reorder b
+    go bs@(BS { scope = sc, next = OneGoal (OpenGoal (Flagged qfn@(FN (PI qpn _) _) (FInfo b m) t f) gr) }) =
+      FChoiceF qfn (gr, sc) trivial m (P.fromList (reorder b
         [(True,  (extendOpen qpn (L.map (flip OpenGoal (FDependency qfn True  : gr)) t) bs) { next = Goals }),
          (False, (extendOpen qpn (L.map (flip OpenGoal (FDependency qfn False : gr)) f) bs) { next = Goals })]))
       where
diff --git a/Distribution/Client/Dependency/Modular/Dependency.hs b/Distribution/Client/Dependency/Modular/Dependency.hs
--- a/Distribution/Client/Dependency/Modular/Dependency.hs
+++ b/Distribution/Client/Dependency/Modular/Dependency.hs
@@ -21,16 +21,6 @@
 data Var qpn = P qpn | F (FN qpn) | S (SN qpn)
   deriving (Eq, Ord, Show)
 
--- | For computing conflict sets, we map flag choice vars to a
--- single flag choice. This means that all flag choices are treated
--- as interdependent. So if one flag of a package ends up in a
--- conflict set, then all flags are being treated as being part of
--- the conflict set.
-simplifyVar :: Var qpn -> Var qpn
-simplifyVar (P qpn)       = P qpn
-simplifyVar (F (FN pi _)) = F (FN pi (mkFlag "flag"))
-simplifyVar (S qsn)       = S qsn
-
 showVar :: Var QPN -> String
 showVar (P qpn) = showQPN qpn
 showVar (F qfn) = showQFN qfn
@@ -185,7 +175,7 @@
 goalReasonToVars :: GoalReason qpn -> ConflictSet qpn
 goalReasonToVars UserGoal                 = S.empty
 goalReasonToVars (PDependency (PI qpn _)) = S.singleton (P qpn)
-goalReasonToVars (FDependency qfn _)      = S.singleton (simplifyVar (F qfn))
+goalReasonToVars (FDependency qfn _)      = S.singleton (F qfn)
 goalReasonToVars (SDependency qsn)        = S.singleton (S qsn)
 
 goalReasonChainToVars :: Ord qpn => GoalReasonChain qpn -> ConflictSet qpn
@@ -204,4 +194,4 @@
 -- | Compute a conflic set from a goal. The conflict set contains the
 -- closure of goal reasons as well as the variable of the goal itself.
 toConflictSet :: Ord qpn => Goal qpn -> ConflictSet qpn
-toConflictSet (Goal g grs) = S.insert (simplifyVar g) (goalReasonChainToVars grs)
+toConflictSet (Goal g grs) = S.insert g (goalReasonChainToVars grs)
diff --git a/Distribution/Client/Dependency/Modular/Explore.hs b/Distribution/Client/Dependency/Modular/Explore.hs
--- a/Distribution/Client/Dependency/Modular/Explore.hs
+++ b/Distribution/Client/Dependency/Modular/Explore.hs
@@ -66,9 +66,9 @@
 combine _   []                      c = (Just c, [])
 combine var ((k, (     d, v)) : xs) c = (\ ~(e, ys) -> (e, (k, v) : ys)) $
                                         case d of
-                                          Just e | not (simplifyVar var `S.member` e) -> (Just e, [])
-                                                 | otherwise                          -> combine var xs (e `S.union` c)
-                                          Nothing                                     -> (Nothing, snd $ combine var xs S.empty)
+                                          Just e | not (var `S.member` e) -> (Just e, [])
+                                                 | otherwise              -> combine var xs (e `S.union` c)
+                                          Nothing                         -> (Nothing, snd $ combine var xs S.empty)
 
 -- | Naive backtracking exploration of the search tree. This will yield correct
 -- assignments only once the tree itself is validated.
diff --git a/Distribution/Client/Dependency/Modular/Flag.hs b/Distribution/Client/Dependency/Modular/Flag.hs
--- a/Distribution/Client/Dependency/Modular/Flag.hs
+++ b/Distribution/Client/Dependency/Modular/Flag.hs
@@ -25,13 +25,9 @@
 unFlag :: Flag -> String
 unFlag (FlagName fn) = fn
 
-mkFlag :: String -> Flag
-mkFlag fn = FlagName fn
-
--- | Flag info. Default value, whether the flag is manual, and
--- whether the flag is weak. Manual flags can only be set explicitly.
--- Weak flags are typically deferred by the solver.
-data FInfo = FInfo { fdefault :: Bool, fmanual :: Bool, fweak :: Bool }
+-- | Flag info. Default value, and whether the flag is manual.
+-- Manual flags can only be set explicitly.
+data FInfo = FInfo { fdefault :: Bool, fmanual :: Bool }
   deriving (Eq, Ord, Show)
 
 -- | Flag defaults.
diff --git a/Distribution/Client/Dependency/Modular/IndexConversion.hs b/Distribution/Client/Dependency/Modular/IndexConversion.hs
--- a/Distribution/Client/Dependency/Modular/IndexConversion.hs
+++ b/Distribution/Client/Dependency/Modular/IndexConversion.hs
@@ -32,16 +32,16 @@
 -- resolving these situations. However, the right thing to do is to
 -- fix the problem there, so for now, shadowing is only activated if
 -- explicitly requested.
-convPIs :: OS -> Arch -> CompilerId -> Bool -> Bool ->
+convPIs :: OS -> Arch -> CompilerId -> Bool ->
            SI.PackageIndex -> CI.PackageIndex SourcePackage -> Index
-convPIs os arch cid sip strfl iidx sidx =
-  mkIndex (convIPI' sip iidx ++ convSPI' os arch cid strfl sidx)
+convPIs os arch cid sip iidx sidx =
+  mkIndex (convIPI' sip iidx ++ convSPI' os arch cid sidx)
 
 -- | Convert a Cabal installed package index to the simpler,
 -- more uniform index format of the solver.
 convIPI' :: Bool -> SI.PackageIndex -> [(PN, I, PInfo)]
 convIPI' sip idx =
-    -- apply shadowing whenever there are multple installed packages with
+    -- apply shadowing whenever there are multiple installed packages with
     -- the same version
     [ maybeShadow (convIP idx pkg)
     | (_pkgid, pkgs) <- SI.allPackagesBySourcePackageId idx
@@ -82,19 +82,19 @@
 
 -- | Convert a cabal-install source package index to the simpler,
 -- more uniform index format of the solver.
-convSPI' :: OS -> Arch -> CompilerId -> Bool ->
+convSPI' :: OS -> Arch -> CompilerId ->
             CI.PackageIndex SourcePackage -> [(PN, I, PInfo)]
-convSPI' os arch cid strfl = L.map (convSP os arch cid strfl) . CI.allPackages
+convSPI' os arch cid = L.map (convSP os arch cid) . CI.allPackages
 
-convSPI :: OS -> Arch -> CompilerId -> Bool ->
+convSPI :: OS -> Arch -> CompilerId ->
            CI.PackageIndex SourcePackage -> Index
-convSPI os arch cid strfl = mkIndex . convSPI' os arch cid strfl
+convSPI os arch cid = mkIndex . convSPI' os arch cid
 
 -- | Convert a single source package into the solver-specific format.
-convSP :: OS -> Arch -> CompilerId -> Bool -> SourcePackage -> (PN, I, PInfo)
-convSP os arch cid strfl (SourcePackage (PackageIdentifier pn pv) gpd _ _pl) =
+convSP :: OS -> Arch -> CompilerId -> SourcePackage -> (PN, I, PInfo)
+convSP os arch cid (SourcePackage (PackageIdentifier pn pv) gpd _ _pl) =
   let i = I pv InRepo
-  in  (pn, i, convGPD os arch cid strfl (PI pn i) gpd)
+  in  (pn, i, convGPD os arch cid (PI pn i) gpd)
 
 -- We do not use 'flattenPackageDescription' or 'finalizePackageDescription'
 -- from 'Distribution.PackageDescription.Configuration' here, because we
@@ -104,12 +104,12 @@
 --
 -- TODO: We currently just take all dependencies from all specified library,
 -- executable and test components. This does not quite seem fair.
-convGPD :: OS -> Arch -> CompilerId -> Bool ->
+convGPD :: OS -> Arch -> CompilerId ->
            PI PN -> GenericPackageDescription -> PInfo
-convGPD os arch cid strfl pi
+convGPD os arch cid pi
         (GenericPackageDescription _ flags libs exes tests benchs) =
   let
-    fds = flagInfo strfl flags
+    fds = flagInfo flags
   in
     PInfo
       (maybe []    (convCondTree os arch cid pi fds (const True)          ) libs    ++
@@ -126,10 +126,9 @@
 prefix _ []  = []
 prefix f fds = [f (concat fds)]
 
--- | Convert flag information. Automatic flags are now considered weak
--- unless strong flags have been selected explicitly.
-flagInfo :: Bool -> [PD.Flag] -> FlagInfo
-flagInfo strfl = M.fromList . L.map (\ (MkFlag fn _ b m) -> (fn, FInfo b m (not (strfl || m))))
+-- | Convert flag information.
+flagInfo :: [PD.Flag] -> FlagInfo
+flagInfo = M.fromList . L.map (\ (MkFlag fn _ b m) -> (fn, FInfo b m))
 
 -- | Convert condition trees to flagged dependencies.
 convCondTree :: OS -> Arch -> CompilerId -> PI PN -> FlagInfo ->
@@ -165,7 +164,7 @@
     go (CNot c)    t f = go c f t
     go (CAnd c d)  t f = go c (go d t f) f
     go (COr  c d)  t f = go c t (go d t f)
-    go (Var (Flag fn)) t f = extractCommon t f ++ [Flagged (FN pi fn) (fds ! fn) t f]
+    go (Var (Flag fn)) t f = [Flagged (FN pi fn) (fds ! fn) t f]
     go (Var (OS os')) t f
       | os == os'      = t
       | otherwise      = f
@@ -175,14 +174,6 @@
     go (Var (Impl cf' cvr')) t f
       | cf == cf' && checkVR cvr' cv = t
       | otherwise      = f
-
-    -- If both branches contain the same package as a simple dep, we lift it to
-    -- the next higher-level, but without constraints. This heuristic together
-    -- with deferring flag choices will then usually first resolve this package,
-    -- and try an already installed version before imposing a default flag choice
-    -- that might not be what we want.
-    extractCommon :: FlaggedDeps PN -> FlaggedDeps PN -> FlaggedDeps PN
-    extractCommon ps ps' = [ D.Simple (Dep pn (Constrained [])) | D.Simple (Dep pn _) <- ps, D.Simple (Dep pn' _) <- ps', pn == pn' ]
 
 -- | Convert a Cabal dependency to a solver-specific dependency.
 convDep :: PN -> Dependency -> Dep PN
diff --git a/Distribution/Client/Dependency/Modular/PSQ.hs b/Distribution/Client/Dependency/Modular/PSQ.hs
--- a/Distribution/Client/Dependency/Modular/PSQ.hs
+++ b/Distribution/Client/Dependency/Modular/PSQ.hs
@@ -2,7 +2,7 @@
 
 -- Priority search queues.
 --
--- I am not yet sure what exactly is needed. But we need a datastructure with
+-- I am not yet sure what exactly is needed. But we need a data structure with
 -- key-based lookup that can be sorted. We're using a sequence right now with
 -- (inefficiently implemented) lookup, because I think that queue-based
 -- operations and sorting turn out to be more efficiency-critical in practice.
diff --git a/Distribution/Client/Dependency/Modular/Preference.hs b/Distribution/Client/Dependency/Modular/Preference.hs
--- a/Distribution/Client/Dependency/Modular/Preference.hs
+++ b/Distribution/Client/Dependency/Modular/Preference.hs
@@ -138,7 +138,7 @@
     go (FChoiceF qfn gr tr True ts) = FChoiceF qfn gr tr True $
       let c = toConflictSet (Goal (F qfn) gr)
       in  case span isDisabled (P.toList ts) of
-            (xs, [])     -> P.fromList xs -- everything's already disabled, leave everything as is
+            (_ , [])     -> P.fromList []
             (xs, y : ys) -> P.fromList (xs ++ y : L.map (\ (b, _) -> (b, Fail c ManualFlag)) ys)
       where
         isDisabled (_, Fail _ _) = True
@@ -241,11 +241,10 @@
     go (GoalChoiceF xs) = GoalChoiceF (P.sortBy (comparing choices) xs)
     go x                = x
 
--- | Transformation that tries to avoid making weak flag choices early.
--- Weak flags are trivial flags (not influencing dependencies) or such
--- flags that are explicitly declared to be weak in the index.
-deferWeakFlagChoices :: Tree a -> Tree a
-deferWeakFlagChoices = trav go
+-- | Transformation that tries to avoid making inconsequential
+-- flag choices early.
+deferDefaultFlagChoices :: Tree a -> Tree a
+deferDefaultFlagChoices = trav go
   where
     go (GoalChoiceF xs) = GoalChoiceF (P.sortBy defer xs)
     go x                = x
diff --git a/Distribution/Client/Dependency/Modular/Solver.hs b/Distribution/Client/Dependency/Modular/Solver.hs
--- a/Distribution/Client/Dependency/Modular/Solver.hs
+++ b/Distribution/Client/Dependency/Modular/Solver.hs
@@ -21,7 +21,6 @@
   independentGoals      :: Bool,
   avoidReinstalls       :: Bool,
   shadowPkgs            :: Bool,
-  strongFlags           :: Bool,
   maxBackjumps          :: Maybe Int
 }
 
@@ -41,17 +40,19 @@
   where
     explorePhase     = exploreTreeLog . backjump
     heuristicsPhase  = P.firstGoal . -- after doing goal-choice heuristics, commit to the first choice (saves space)
-                       P.deferWeakFlagChoices .
-                       P.preferBaseGoalChoice .
                        if preferEasyGoalChoices sc
-                         then P.lpreferEasyGoalChoices
-                         else id
+                         then P.preferBaseGoalChoice . P.deferDefaultFlagChoices . P.lpreferEasyGoalChoices
+                         else P.preferBaseGoalChoice
     preferencesPhase = P.preferPackagePreferences userPrefs
     validationPhase  = P.enforceManualFlags . -- can only be done after user constraints
                        P.enforcePackageConstraints userConstraints .
                        validateTree idx
     prunePhase       = (if avoidReinstalls sc then P.avoidReinstalls (const True) else id) .
                        -- packages that can never be "upgraded":
-                       P.requireInstalled (`elem` [PackageName "base",
-                                                   PackageName "ghc-prim"])
+                       P.requireInstalled (`elem` [ PackageName "base"
+                                                  , PackageName "ghc-prim"
+                                                  , PackageName "integer-gmp"
+                                                  , PackageName "integer-simple"
+                                                  , PackageName "template-haskell"
+                                                  ])
     buildPhase       = buildTree idx (independentGoals sc) userGoals
diff --git a/Distribution/Client/Dependency/Modular/Tree.hs b/Distribution/Client/Dependency/Modular/Tree.hs
--- a/Distribution/Client/Dependency/Modular/Tree.hs
+++ b/Distribution/Client/Dependency/Modular/Tree.hs
@@ -15,7 +15,7 @@
 -- | Type of the search tree. Inlining the choice nodes for now.
 data Tree a =
     PChoice     QPN a           (PSQ I        (Tree a))
-  | FChoice     QFN a Bool Bool (PSQ Bool     (Tree a)) -- Bool indicates whether it's weak/trivial, second Bool whether it's manual
+  | FChoice     QFN a Bool Bool (PSQ Bool     (Tree a)) -- Bool indicates whether it's trivial, second Bool whether it's manual
   | SChoice     QSN a Bool      (PSQ Bool     (Tree a)) -- Bool indicates whether it's trivial
   | GoalChoice                  (PSQ OpenGoal (Tree a)) -- PSQ should never be empty
   | Done        RevDepMap
@@ -24,11 +24,6 @@
   -- Above, a choice is called trivial if it clearly does not matter. The
   -- special case of triviality we actually consider is if there are no new
   -- dependencies introduced by this node.
-  --
-  -- A (flag) choice is called weak if we do want to defer it. This is the
-  -- case for flags that should be implied by what's currently installed on
-  -- the system, as opposed to flags that are used to explicitly enable or
-  -- disable some functionality.
 
 instance Functor Tree where
   fmap  f (PChoice qpn i     xs) = PChoice qpn (f i)     (fmap (fmap f) xs)
diff --git a/Distribution/Client/Dependency/Modular/Validate.hs b/Distribution/Client/Dependency/Modular/Validate.hs
--- a/Distribution/Client/Dependency/Modular/Validate.hs
+++ b/Distribution/Client/Dependency/Modular/Validate.hs
@@ -23,7 +23,7 @@
 
 -- In practice, most constraints are implication constraints (IF we have made
 -- a number of choices, THEN we also have to ensure that). We call constraints
--- that for which the precondiditions are fulfilled ACTIVE. We maintain a set
+-- that for which the preconditions are fulfilled ACTIVE. We maintain a set
 -- of currently active constraints that we pass down the node.
 --
 -- We aim at detecting inconsistent states as early as possible.
diff --git a/Distribution/Client/Dependency/Modular/Version.hs b/Distribution/Client/Dependency/Modular/Version.hs
--- a/Distribution/Client/Dependency/Modular/Version.hs
+++ b/Distribution/Client/Dependency/Modular/Version.hs
@@ -40,4 +40,3 @@
 -- | Make a version number.
 mkV :: [Int] -> Ver
 mkV xs = CV.Version xs []
-
diff --git a/Distribution/Client/Dependency/Types.hs b/Distribution/Client/Dependency/Types.hs
--- a/Distribution/Client/Dependency/Types.hs
+++ b/Distribution/Client/Dependency/Types.hs
@@ -17,6 +17,7 @@
     Solver(..),
     DependencyResolver,
 
+    AllowNewer(..), isAllowNewer,
     PackageConstraint(..),
     PackagePreferences(..),
     InstalledPreference(..),
@@ -129,7 +130,7 @@
 -- | A per-package preference on the version. It is a soft constraint that the
 -- 'DependencyResolver' should try to respect where possible. It consists of
 -- a 'InstalledPreference' which says if we prefer versions of packages
--- that are already installed. It also hase a 'PackageVersionPreference' which
+-- that are already installed. It also has a 'PackageVersionPreference' which
 -- is a suggested constraint on the version number. The resolver should try to
 -- use package versions that satisfy the suggested version constraint.
 --
@@ -167,9 +168,31 @@
      --
    | PreferLatestForSelected
 
+-- | Policy for relaxing upper bounds in dependencies. For example, given
+-- 'build-depends: array >= 0.3 && < 0.5', are we allowed to relax the upper
+-- bound and choose a version of 'array' that is greater or equal to 0.5? By
+-- default the upper bounds are always strictly honored.
+data AllowNewer =
+
+  -- | Default: honor the upper bounds in all dependencies, never choose
+  -- versions newer than allowed.
+  AllowNewerNone
+
+  -- | Ignore upper bounds in dependencies on the given packages.
+  | AllowNewerSome [PackageName]
+
+  -- | Ignore upper bounds in dependencies on all packages.
+  | AllowNewerAll
+
+-- | Convert 'AllowNewer' to a boolean.
+isAllowNewer :: AllowNewer -> Bool
+isAllowNewer AllowNewerNone     = False
+isAllowNewer (AllowNewerSome _) = True
+isAllowNewer AllowNewerAll      = True
+
 -- | A type to represent the unfolding of an expensive long running
 -- calculation that may fail. We may get intermediate steps before the final
--- retult which may be used to indicate progress and\/or logging messages.
+-- result which may be used to indicate progress and\/or logging messages.
 --
 data Progress step fail done = Step step (Progress step fail done)
                              | Fail fail
diff --git a/Distribution/Client/Fetch.hs b/Distribution/Client/Fetch.hs
--- a/Distribution/Client/Fetch.hs
+++ b/Distribution/Client/Fetch.hs
@@ -154,8 +154,6 @@
 
       . setShadowPkgs shadowPkgs
 
-      . setStrongFlags strongFlags
-
         -- Reinstall the targets given on the command line so that the dep
         -- resolver will decide that they need fetching, even if they're
         -- already installed. Since we want to get the source packages of
@@ -170,7 +168,6 @@
     reorderGoals     = fromFlag (fetchReorderGoals     fetchFlags)
     independentGoals = fromFlag (fetchIndependentGoals fetchFlags)
     shadowPkgs       = fromFlag (fetchShadowPkgs       fetchFlags)
-    strongFlags      = fromFlag (fetchStrongFlags      fetchFlags)
     maxBackjumps     = fromFlag (fetchMaxBackjumps     fetchFlags)
 
 
diff --git a/Distribution/Client/Freeze.hs b/Distribution/Client/Freeze.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/Client/Freeze.hs
@@ -0,0 +1,215 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Distribution.Client.Freeze
+-- Copyright   :  (c) David Himmelstrup 2005
+--                    Duncan Coutts 2011
+-- License     :  BSD-like
+--
+-- Maintainer  :  cabal-devel@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- The cabal freeze command
+-----------------------------------------------------------------------------
+module Distribution.Client.Freeze (
+    freeze,
+  ) where
+
+import Distribution.Client.Config ( SavedConfig(..) )
+import Distribution.Client.Types
+import Distribution.Client.Targets
+import Distribution.Client.Dependency hiding ( addConstraints )
+import Distribution.Client.IndexUtils as IndexUtils
+         ( getSourcePackages, getInstalledPackages )
+import Distribution.Client.InstallPlan
+         ( PlanPackage )
+import qualified Distribution.Client.InstallPlan as InstallPlan
+import Distribution.Client.Setup
+         ( GlobalFlags(..), FreezeFlags(..), ConfigExFlags(..) )
+import Distribution.Client.Sandbox.PackageEnvironment
+         ( loadUserConfig, pkgEnvSavedConfig, showPackageEnvironment,
+           userPackageEnvironmentFile )
+import Distribution.Client.Sandbox.Types
+         ( SandboxPackageInfo(..) )
+
+import Distribution.Package
+         ( Package, PackageIdentifier, packageId, packageName, packageVersion )
+import Distribution.Simple.Compiler
+         ( Compiler(compilerId), PackageDBStack )
+import Distribution.Simple.PackageIndex (PackageIndex)
+import qualified Distribution.Client.PackageIndex as PackageIndex
+import Distribution.Simple.Program
+         ( ProgramConfiguration )
+import Distribution.Simple.Setup
+         ( fromFlag )
+import Distribution.Simple.Utils
+         ( die, notice, debug, writeFileAtomic )
+import Distribution.System
+         ( Platform )
+import Distribution.Text
+         ( display )
+import Distribution.Verbosity
+         ( Verbosity )
+
+import Control.Monad
+         ( when )
+import qualified Data.ByteString.Lazy.Char8 as BS.Char8
+import Data.Monoid
+         ( mempty )
+import Data.Version
+         ( showVersion )
+import Distribution.Version
+         ( thisVersion )
+
+-- ------------------------------------------------------------
+-- * The freeze command
+-- ------------------------------------------------------------
+
+--TODO:
+-- * Don't overwrite all of `cabal.config`, just the constraints section.
+-- * Should the package represented by `UserTargetLocalDir "."` be
+--   constrained too? What about `base`?
+
+
+-- | Freeze all of the dependencies by writing a constraints section
+-- constraining each dependency to an exact version.
+--
+freeze :: Verbosity
+      -> PackageDBStack
+      -> [Repo]
+      -> Compiler
+      -> Platform
+      -> ProgramConfiguration
+      -> Maybe SandboxPackageInfo
+      -> GlobalFlags
+      -> FreezeFlags
+      -> IO ()
+freeze verbosity packageDBs repos comp platform conf mSandboxPkgInfo
+      globalFlags freezeFlags = do
+
+    installedPkgIndex <- getInstalledPackages verbosity comp packageDBs conf
+    sourcePkgDb       <- getSourcePackages    verbosity repos
+
+    pkgSpecifiers <- resolveUserTargets verbosity
+                       (fromFlag $ globalWorldFile globalFlags)
+                       (packageIndex sourcePkgDb)
+                       [UserTargetLocalDir "."]
+
+    sanityCheck pkgSpecifiers
+    pkgs  <- planPackages
+               verbosity comp platform mSandboxPkgInfo freezeFlags
+               installedPkgIndex sourcePkgDb pkgSpecifiers
+
+    if null pkgs
+      then notice verbosity $ "No packages to be frozen. "
+                           ++ "As this package has no dependencies."
+      else if dryRun
+             then notice verbosity $ unlines $
+                     "The following packages would be frozen:"
+                   : formatPkgs pkgs
+
+             else freezePackages verbosity pkgs
+
+  where
+    dryRun = fromFlag (freezeDryRun freezeFlags)
+
+    sanityCheck pkgSpecifiers =
+      when (not . null $ [n | n@(NamedPackage _ _) <- pkgSpecifiers]) $
+        die $ "internal error: 'resolveUserTargets' returned "
+           ++ "unexpected named package specifiers!"
+
+planPackages :: Verbosity
+             -> Compiler
+             -> Platform
+             -> Maybe SandboxPackageInfo
+             -> FreezeFlags
+             -> PackageIndex
+             -> SourcePackageDb
+             -> [PackageSpecifier SourcePackage]
+             -> IO [PlanPackage]
+planPackages verbosity comp platform mSandboxPkgInfo freezeFlags
+             installedPkgIndex sourcePkgDb pkgSpecifiers = do
+
+  solver <- chooseSolver verbosity
+            (fromFlag (freezeSolver freezeFlags)) (compilerId comp)
+  notice verbosity "Resolving dependencies..."
+
+  installPlan <- foldProgress logMsg die return $
+                   resolveDependencies
+                     platform (compilerId comp)
+                     solver
+                     resolverParams
+
+  return $ either id
+                  (error "planPackages: installPlan contains broken packages")
+                  (pruneInstallPlan installPlan pkgSpecifiers)
+
+  where
+    resolverParams =
+
+        setMaxBackjumps (if maxBackjumps < 0 then Nothing
+                                             else Just maxBackjumps)
+
+      . setIndependentGoals independentGoals
+
+      . setReorderGoals reorderGoals
+
+      . setShadowPkgs shadowPkgs
+
+      . maybe id applySandboxInstallPolicy mSandboxPkgInfo
+
+      $ standardInstallPolicy installedPkgIndex sourcePkgDb pkgSpecifiers
+
+    logMsg message rest = debug verbosity message >> rest
+
+    reorderGoals     = fromFlag (freezeReorderGoals     freezeFlags)
+    independentGoals = fromFlag (freezeIndependentGoals freezeFlags)
+    shadowPkgs       = fromFlag (freezeShadowPkgs       freezeFlags)
+    maxBackjumps     = fromFlag (freezeMaxBackjumps     freezeFlags)
+
+
+-- | Remove all unneeded packages from an install plan.
+--
+-- A package is unneeded if it is not a dependency (directly or
+-- transitively) of any of the 'PackageSpecifier SourcePackage's.  This is
+-- useful for removing previously installed packages which are no longer
+-- required from the install plan.
+pruneInstallPlan :: InstallPlan.InstallPlan
+                 -> [PackageSpecifier SourcePackage]
+                 -> Either [PlanPackage] [(PlanPackage, [PackageIdentifier])]
+pruneInstallPlan installPlan pkgSpecifiers =
+    mapLeft PackageIndex.allPackages $
+    PackageIndex.dependencyClosure pkgIdx pkgIds
+  where
+    pkgIdx = PackageIndex.fromList $ InstallPlan.toList installPlan
+    pkgIds = [ packageId pkg | SpecificSourcePackage pkg <- pkgSpecifiers ]
+    mapLeft f (Left v)  = Left $ f v
+    mapLeft _ (Right v) = Right v
+
+
+freezePackages :: Package pkg => Verbosity -> [pkg] -> IO ()
+freezePackages verbosity pkgs = do
+    pkgEnv <- fmap (createPkgEnv . addConstraints) $ loadUserConfig verbosity ""
+    writeFileAtomic userPackageEnvironmentFile $ showPkgEnv pkgEnv
+  where
+    addConstraints config =
+        config {
+            savedConfigureExFlags = (savedConfigureExFlags config) {
+                configExConstraints = constraints pkgs
+            }
+        }
+    constraints = map $ pkgIdToConstraint . packageId
+      where
+        pkgIdToConstraint pkg =
+            UserConstraintVersion (packageName pkg)
+                                  (thisVersion $ packageVersion pkg)
+    createPkgEnv config = mempty { pkgEnvSavedConfig = config }
+    showPkgEnv = BS.Char8.pack . showPackageEnvironment
+
+
+formatPkgs :: Package pkg => [pkg] -> [String]
+formatPkgs = map $ showPkg . packageId
+  where
+    showPkg pid = name pid ++ " == " ++ version pid
+    name = display . packageName
+    version = showVersion . packageVersion
diff --git a/Distribution/Client/Get.hs b/Distribution/Client/Get.hs
--- a/Distribution/Client/Get.hs
+++ b/Distribution/Client/Get.hs
@@ -37,6 +37,8 @@
 import qualified Distribution.Client.Tar as Tar (extractTarGzFile)
 import Distribution.Client.IndexUtils as IndexUtils
         ( getSourcePackages )
+import Distribution.Client.Compat.Process
+        ( readProcessWithExitCode )
 import Distribution.Compat.Exception
         ( catchIO )
 
@@ -62,7 +64,7 @@
 import System.FilePath
          ( (</>), (<.>), addTrailingPathSeparator )
 import System.Process
-         ( rawSystem, readProcessWithExitCode )
+         ( rawSystem )
 
 
 -- | Entry point for the 'cabal get' command.
@@ -103,7 +105,7 @@
 
   where
     resolverParams sourcePkgDb pkgSpecifiers =
-        --TODO: add commandline constraint and preference args for unpack
+        --TODO: add command-line constraint and preference args for unpack
         standardInstallPolicy mempty sourcePkgDb pkgSpecifiers
 
     prefix = fromFlagOrDefault "" (getDestDir getFlags)
@@ -212,7 +214,7 @@
     return (Data.Map.fromList pairs)
 
 -- | Fork a single package from a remote source repository to the local
--- filesystem.
+-- file system.
 forkPackage :: Verbosity
             -> Data.Map.Map PD.RepoType Brancher
                -- ^ Branchers supported by the local machine.
diff --git a/Distribution/Client/Haddock.hs b/Distribution/Client/Haddock.hs
--- a/Distribution/Client/Haddock.hs
+++ b/Distribution/Client/Haddock.hs
@@ -16,31 +16,29 @@
     )
     where
 
-import Data.Maybe (listToMaybe)
 import Data.List (maximumBy)
-import Control.Monad (guard)
-import System.Directory (createDirectoryIfMissing, doesFileExist,
-                         renameFile)
-import System.FilePath ((</>), splitFileName, isAbsolute)
+import System.Directory (createDirectoryIfMissing, renameFile)
+import System.FilePath ((</>), splitFileName)
 import Distribution.Package
-         ( Package(..), packageVersion )
+         ( packageVersion )
+import Distribution.Simple.Haddock (haddockPackagePaths)
 import Distribution.Simple.Program (haddockProgram, ProgramConfiguration
                                    , rawSystemProgram, requireProgramVersion)
 import Distribution.Version (Version(Version), orLaterVersion)
 import Distribution.Verbosity (Verbosity)
-import Distribution.Text (display)
 import Distribution.Simple.PackageIndex
          ( PackageIndex, allPackagesByName )
 import Distribution.Simple.Utils
-         ( comparing, intercalate, debug
-         , installDirectoryContents, withTempDirectory )
+         ( comparing, debug, installDirectoryContents, withTempDirectory )
 import Distribution.InstalledPackageInfo as InstalledPackageInfo
-         ( InstalledPackageInfo
-         , InstalledPackageInfo_(haddockHTMLs, haddockInterfaces, exposed) )
+         ( InstalledPackageInfo_(exposed) )
 
-regenerateHaddockIndex :: Verbosity -> PackageIndex -> ProgramConfiguration -> FilePath -> IO ()
+regenerateHaddockIndex :: Verbosity
+                       -> PackageIndex -> ProgramConfiguration -> FilePath
+                       -> IO ()
 regenerateHaddockIndex verbosity pkgs conf index = do
-      (paths,warns) <- haddockPackagePaths pkgs'
+      (paths, warns) <- haddockPackagePaths pkgs' Nothing
+      let paths' = [ (interface, html) | (interface, Just html) <- paths]
       case warns of
         Nothing -> return ()
         Just m  -> debug verbosity m
@@ -58,7 +56,7 @@
                     , "--odir=" ++ tempDir
                     , "--title=Haskell modules on this system" ]
                  ++ [ "--read-interface=" ++ html ++ "," ++ interface
-                    | (interface, html) <- paths ]
+                    | (interface, html) <- paths' ]
         rawSystemProgram verbosity confHaddock flags
         renameFile (tempDir </> "index.html") (tempDir </> destFile)
         installDirectoryContents verbosity tempDir destDir
@@ -69,41 +67,3 @@
             | (_pname, pkgvers) <- allPackagesByName pkgs
             , let pkgvers' = filter exposed pkgvers
             , not (null pkgvers') ]
-
-haddockPackagePaths :: [InstalledPackageInfo]
-                       -> IO ([(FilePath, FilePath)], Maybe String)
-haddockPackagePaths pkgs = do
-  interfaces <- sequence
-    [ case interfaceAndHtmlPath pkg of
-        Just (interface, html) -> do
-          exists <- doesFileExist interface
-          if exists
-            then return (pkgid, Just (interface, html))
-            else return (pkgid, Nothing)
-        Nothing -> return (pkgid, Nothing)
-    | pkg <- pkgs, let pkgid = packageId pkg ]
-
-  let missing = [ pkgid | (pkgid, Nothing) <- interfaces ]
-
-      warning = "The documentation for the following packages are not "
-             ++ "installed. No links will be generated to these packages: "
-             ++ intercalate ", " (map display missing)
-
-      flags = [ x | (_, Just x) <- interfaces ]
-
-  return (flags, if null missing then Nothing else Just warning)
-
-  where
-    interfaceAndHtmlPath pkg = do
-      interface <- listToMaybe (InstalledPackageInfo.haddockInterfaces pkg)
-      html <- fmap fixFileUrl
-                   (listToMaybe (InstalledPackageInfo.haddockHTMLs pkg))
-      guard (not . null $ html)
-      return (interface, html)
-    
-    -- the 'haddock-html' field in the hc-pkg output is often set as a
-    -- native path, but we need it as a URL.
-    -- See https://github.com/haskell/cabal/issues/1064
-    fixFileUrl f | isAbsolute f = "file://" ++ f
-                 | otherwise    = f
-
diff --git a/Distribution/Client/HttpUtils.hs b/Distribution/Client/HttpUtils.hs
--- a/Distribution/Client/HttpUtils.hs
+++ b/Distribution/Client/HttpUtils.hs
@@ -17,8 +17,8 @@
 import Network.URI
          ( URI (..), URIAuth (..) )
 import Network.Browser
-         ( BrowserAction, browse, setAllowBasicAuth, setAuthorityGen
-         , setOutHandler, setErrHandler, setProxy, request)
+         ( BrowserAction, browse
+         , setOutHandler, setErrHandler, setProxy, setAuthorityGen, request)
 import Network.Stream
          ( Result, ConnError(..) )
 import Control.Monad
@@ -43,7 +43,7 @@
 
 data DownloadResult = FileAlreadyInCache | FileDownloaded FilePath deriving (Eq)
 
--- Trime
+-- Trim
 trim :: String -> String
 trim = f . f
       where f = reverse . dropWhile isSpace
@@ -76,10 +76,10 @@
         -> Maybe String -- ^ Optional etag to check if we already have the latest file.
         -> IO (Result (Response ByteString))
 getHTTP verbosity uri etag = liftM (\(_, resp) -> Right resp) $
-                                   cabalBrowse verbosity Nothing (request (mkRequest uri etag))
+                                   cabalBrowse verbosity (return ()) (request (mkRequest uri etag))
 
 cabalBrowse :: Verbosity
-            -> Maybe (String, String)
+            -> BrowserAction s ()
             -> BrowserAction s a
             -> IO a
 cabalBrowse verbosity auth act = do
@@ -88,8 +88,8 @@
         setProxy p
         setErrHandler (warn verbosity . ("http error: "++))
         setOutHandler (debug verbosity)
-        setAllowBasicAuth False
-        setAuthorityGen (\_ _ -> return auth)
+        auth
+        setAuthorityGen (\_ _ -> return Nothing)
         act
 
 downloadURI :: Verbosity
diff --git a/Distribution/Client/IndexUtils.hs b/Distribution/Client/IndexUtils.hs
--- a/Distribution/Client/IndexUtils.hs
+++ b/Distribution/Client/IndexUtils.hs
@@ -55,7 +55,7 @@
 import Distribution.Verbosity
          ( Verbosity, normal, lessVerbose )
 import Distribution.Simple.Utils
-         ( die, warn, info, fromUTF8, findPackageDesc )
+         ( die, warn, info, fromUTF8, tryFindPackageDesc )
 
 import Data.Char   (isAlphaNum)
 import Data.Maybe  (mapMaybe, fromMaybe)
@@ -71,7 +71,7 @@
 import Distribution.Client.GZipUtils (maybeDecompress)
 import Distribution.Client.Utils (byteStringToFilePath)
 import Distribution.Compat.Exception (catchIO)
-import Distribution.Client.Compat.Time
+import Distribution.Client.Compat.Time (getFileAge, getModTime)
 import System.Directory (doesFileExist)
 import System.FilePath ((</>), takeExtension, splitDirectories, normalise)
 import System.FilePath.Posix as FilePath.Posix
@@ -93,7 +93,7 @@
 convert :: InstalledPackageIndex.PackageIndex -> PackageIndex InstalledPackage
 convert index' = PackageIndex.fromList
     -- There can be multiple installed instances of each package version,
-    -- like when the same package is installed in the global & user dbs.
+    -- like when the same package is installed in the global & user DBs.
     -- InstalledPackageIndex.allPackagesBySourcePackageId gives us the
     -- installed packages with the most preferred instances first, so by
     -- picking the first we should get the user one. This is almost but not
@@ -109,7 +109,7 @@
     -- other packages that do not exist then we have a problem we cannot find
     -- the original source package id. Instead we make up a bogus package id.
     -- This should have the same effect since it should be a dependency on a
-    -- non-existant package.
+    -- nonexistent package.
     sourceDeps index ipkg =
       [ maybe (brokenPackageId depid) packageId mdep
       | let depids = InstalledPackageInfo.depends ipkg
@@ -281,7 +281,7 @@
 -- | Read a compressed \"00-index.tar.gz\" file into a 'PackageIndex'.
 --
 -- This is supposed to be an \"all in one\" way to easily get at the info in
--- the hackage package index.
+-- the Hackage package index.
 --
 -- It takes a function to map a 'GenericPackageDescription' into any more
 -- specific instance of 'Package' that you might want to use. In the simple
@@ -351,7 +351,7 @@
     | Tar.isBuildTreeRefTypeCode typeCode ->
       Just $ do
         let path   = byteStringToFilePath content
-        cabalFile <- findPackageDesc path
+        cabalFile <- tryFindPackageDesc path
         descr     <- PackageDesc.Parse.readPackageDescription normal cabalFile
         return $ BuildTreeRef (refTypeFromTypeCode typeCode) (packageId descr)
                               descr path blockNo
@@ -452,7 +452,7 @@
       -- package id for build tree references - the user might edit the .cabal
       -- file after the reference was added to the index.
       path <- liftM byteStringToFilePath . getEntryContent $ blockno
-      pkg  <- do cabalFile <- findPackageDesc path
+      pkg  <- do cabalFile <- tryFindPackageDesc path
                  PackageDesc.Parse.readPackageDescription normal cabalFile
       let srcpkg = mkPkg (BuildTreeRef refType (packageId pkg) pkg path blockno)
       accum (srcpkg:srcpkgs) prefs entries
diff --git a/Distribution/Client/Init.hs b/Distribution/Client/Init.hs
--- a/Distribution/Client/Init.hs
+++ b/Distribution/Client/Init.hs
@@ -36,7 +36,7 @@
 import Data.List
   ( intercalate, nub, groupBy, (\\) )
 import Data.Maybe
-  ( fromMaybe, isJust, catMaybes )
+  ( fromMaybe, isJust, catMaybes, listToMaybe )
 import Data.Function
   ( on )
 import qualified Data.Map as M
@@ -67,9 +67,10 @@
 import Distribution.Client.Init.Types
   ( InitFlags(..), PackageType(..), Category(..) )
 import Distribution.Client.Init.Licenses
-  ( bsd3, gplv2, gplv3, lgpl2, lgpl3, agplv3, apache20 )
+  ( bsd2, bsd3, gplv2, gplv3, lgpl21, lgpl3, agplv3, apache20, mit, mpl20 )
 import Distribution.Client.Init.Heuristics
-  ( guessPackageName, guessAuthorNameMail, SourceFileEntry(..),
+  ( guessPackageName, guessAuthorNameMail, guessMainFileCandidates,
+    SourceFileEntry(..),
     scanForModules, neededBuildPrograms )
 
 import Distribution.License
@@ -154,7 +155,7 @@
               ?>> Just `fmap` (getCurrentDirectory >>= guessPackageName)
 
   pkgName' <-     return (flagToMaybe $ packageName flags)
-              ?>> maybePrompt flags (promptStr "Package name" guess)
+              ?>> maybePrompt flags (prompt "Package name" guess)
               ?>> return guess
 
   return $ flags { packageName = maybeToFlag pkgName' }
@@ -266,9 +267,29 @@
                                    [Library, Executable]
                                    Nothing display False)
            ?>> return (Just Library)
+  mainFile <- if isLib /= Just Executable then return Nothing else
+                    getMainFile flags
 
-  return $ flags { packageType = maybeToFlag isLib }
+  return $ flags { packageType = maybeToFlag isLib
+                 , mainIs = maybeToFlag mainFile
+                 }
 
+-- | Try to guess the main file of the executable, and prompt the user to choose
+-- one of them. Top-level modules including the word 'Main' in the file name
+-- will be candidates, and shorter filenames will be preferred.
+getMainFile :: InitFlags -> IO (Maybe FilePath)
+getMainFile flags =
+  return (flagToMaybe $ mainIs flags)
+  ?>> do
+    candidates <- guessMainFileCandidates flags
+    let showCandidate = either (++" (does not yet exist)") id
+        defaultFile = listToMaybe candidates
+    maybePrompt flags (either id (either id id) `fmap`
+                       promptList "What is the main module of the executable"
+                       candidates
+                       defaultFile showCandidate True)
+      ?>> return (fmap (either id id) defaultFile)
+
 -- | Ask for the base language of the package.
 getLanguage :: InitFlags -> IO InitFlags
 getLanguage flags = do
@@ -534,23 +555,24 @@
 writeLicense :: InitFlags -> IO ()
 writeLicense flags = do
   message flags "\nGenerating LICENSE..."
-  year <- getYear
+  year <- show <$> getYear
+  let authors = fromMaybe "???" . flagToMaybe . author $ flags
   let licenseFile =
         case license flags of
-          Flag BSD3 -> Just $ bsd3 (fromMaybe "???"
-                                  . flagToMaybe
-                                  . author
-                                  $ flags)
-                              (show year)
+          Flag BSD2
+            -> Just $ bsd2 authors year
 
+          Flag BSD3
+            -> Just $ bsd3 authors year
+
           Flag (GPL (Just (Version {versionBranch = [2]})))
             -> Just gplv2
 
           Flag (GPL (Just (Version {versionBranch = [3]})))
             -> Just gplv3
 
-          Flag (LGPL (Just (Version {versionBranch = [2]})))
-            -> Just lgpl2
+          Flag (LGPL (Just (Version {versionBranch = [2, 1]})))
+            -> Just lgpl21
 
           Flag (LGPL (Just (Version {versionBranch = [3]})))
             -> Just lgpl3
@@ -561,6 +583,12 @@
           Flag (Apache (Just (Version {versionBranch = [2, 0]})))
             -> Just apache20
 
+          Flag MIT
+            -> Just $ mit authors year
+
+          Flag (MPL (Version {versionBranch = [2, 0]}))
+            -> Just mpl20
+
           _ -> Nothing
 
   case licenseFile of
@@ -590,7 +618,7 @@
   message flags "Error: no package name provided."
   return False
 writeCabalFile flags@(InitFlags{packageName = Flag p}) = do
-  let cabalFileName = p ++ ".cabal"
+  let cabalFileName = display p ++ ".cabal"
   message flags $ "Generating " ++ cabalFileName ++ "..."
   writeFileSafe flags cabalFileName (generateCabalFile cabalFileName flags)
   return True
@@ -640,7 +668,7 @@
          $$ text ""
     else empty)
   $$
-  vcat [ fieldS "name"          (packageName   c)
+  vcat [ field  "name"          (packageName   c)
                 (Just "The name of the package.")
                 True
 
@@ -705,8 +733,10 @@
 
        , case packageType c of
            Flag Executable ->
-             text "\nexecutable" <+> text (fromMaybe "" . flagToMaybe $ packageName c) $$ nest 2 (vcat
-             [ fieldS "main-is" NoFlag (Just ".hs or .lhs file containing the Main module.") True
+             text "\nexecutable" <+>
+             text (maybe "" display . flagToMaybe $ packageName c) $$
+             nest 2 (vcat
+             [ fieldS "main-is" (mainIs c) (Just ".hs or .lhs file containing the Main module.") True
 
              , generateBuildInfo Executable c
              ])
diff --git a/Distribution/Client/Init/Heuristics.hs b/Distribution/Client/Init/Heuristics.hs
--- a/Distribution/Client/Init/Heuristics.hs
+++ b/Distribution/Client/Init/Heuristics.hs
@@ -15,15 +15,17 @@
     guessPackageName,
     scanForModules,     SourceFileEntry(..),
     neededBuildPrograms,
+    guessMainFileCandidates,
     guessAuthorNameMail,
     knownCategories,
 ) where
 import Distribution.Text         (simpleParse)
-import Distribution.Simple.Setup (Flag(..))
+import Distribution.Simple.Setup (Flag(..), flagToMaybe)
 import Distribution.ModuleName
     ( ModuleName, toFilePath )
 import Distribution.Client.PackageIndex
     ( allPackagesByName )
+import qualified Distribution.Package as P
 import qualified Distribution.PackageDescription as PD
     ( category, packageDescription )
 import Distribution.Simple.Utils
@@ -34,25 +36,74 @@
 
 import Distribution.Client.Types ( packageDescription, SourcePackageDb(..) )
 import Control.Applicative ( pure, (<$>), (<*>) )
+import Control.Arrow ( first )
 import Control.Monad ( liftM )
-import Data.Char   ( isUpper, isLower, isSpace )
+import Data.Char   ( isAlphaNum, isNumber, isUpper, isLower, isSpace )
 import Data.Either ( partitionEithers )
-import Data.List   ( isPrefixOf )
+import Data.List   ( isInfixOf, isPrefixOf, isSuffixOf, sortBy )
 import Data.Maybe  ( mapMaybe, catMaybes, maybeToList )
-import Data.Monoid ( mempty, mconcat )
+import Data.Monoid ( mempty, mappend, mconcat, )
+import Data.Ord    ( comparing )
 import qualified Data.Set as Set ( fromList, toList )
-import System.Directory ( getDirectoryContents,
+import System.Directory ( getCurrentDirectory, getDirectoryContents,
                           doesDirectoryExist, doesFileExist, getHomeDirectory, )
 import Distribution.Compat.Environment ( getEnvironment )
 import System.FilePath ( takeExtension, takeBaseName, dropExtension,
                          (</>), (<.>), splitDirectories, makeRelative )
-import System.Process ( readProcessWithExitCode )
+
+import Distribution.Client.Init.Types     ( InitFlags(..) )
+import Distribution.Client.Compat.Process ( readProcessWithExitCode )
 import System.Exit ( ExitCode(..) )
 
--- |Guess the package name based on the given root directory
-guessPackageName :: FilePath -> IO String
-guessPackageName = liftM (last . splitDirectories) . tryCanonicalizePath
+-- | Return a list of candidate main files for this executable: top-level
+-- modules including the word 'Main' in the file name. The list is sorted in
+-- order of preference, shorter file names are preferred. 'Right's are existing
+-- candidates and 'Left's are those that do not yet exist.
+guessMainFileCandidates :: InitFlags -> IO [Either FilePath FilePath]
+guessMainFileCandidates flags = do
+  dir <-
+    maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)
+  files <- getDirectoryContents dir
+  let existingCandidates = filter isMain files
+      -- We always want to give the user at least one default choice.  If either
+      -- Main.hs or Main.lhs has already been created, then we don't want to
+      -- suggest the other; however, if neither has been created, then we
+      -- suggest both.
+      newCandidates =
+        if any (`elem` existingCandidates) ["Main.hs", "Main.lhs"]
+        then []
+        else ["Main.hs", "Main.lhs"]
+      candidates =
+        sortBy (\x y -> comparing (length . either id id) x y
+                        `mappend` compare x y)
+               (map Left newCandidates ++ map Right existingCandidates)
+  return candidates
 
+  where
+    isMain f =    (isInfixOf "Main" f || isInfixOf  "main" f)
+               && (isSuffixOf ".hs" f || isSuffixOf ".lhs" f)
+
+-- | Guess the package name based on the given root directory.
+guessPackageName :: FilePath -> IO P.PackageName
+guessPackageName = liftM (P.PackageName . repair . last . splitDirectories)
+                 . tryCanonicalizePath
+  where
+    -- Treat each span of non-alphanumeric characters as a hyphen. Each
+    -- hyphenated component of a package name must contain at least one
+    -- alphabetic character. An arbitrary character ('x') will be prepended if
+    -- this is not the case for the first component, and subsequent components
+    -- will simply be run together. For example, "1+2_foo-3" will become
+    -- "x12-foo3".
+    repair = repair' ('x' :) id
+    repair' invalid valid x = case dropWhile (not . isAlphaNum) x of
+        "" -> repairComponent ""
+        x' -> let (c, r) = first repairComponent $ break (not . isAlphaNum) x'
+              in c ++ repairRest r
+      where
+        repairComponent c | all isNumber c = invalid c
+                          | otherwise      = valid c
+    repairRest = repair' id ('-' :)
+
 -- |Data type of source files found in the working directory
 data SourceFileEntry = SourceFileEntry
     { relativeSourcePath :: FilePath
@@ -67,7 +118,7 @@
   = projectRoot </> relPath </> toFilePath m <.> ext
 
 -- |Search for source files in the given directory
--- and return pairs of guessed haskell source path and
+-- and return pairs of guessed Haskell source path and
 -- module names.
 scanForModules :: FilePath -> IO [SourceFileEntry]
 scanForModules rootDir = scanForModulesIn rootDir rootDir
@@ -232,18 +283,18 @@
 darcsEnv = maybe mempty nameAndMail . lookup "DARCS_EMAIL"
 
 gitEnv :: Enviro -> AuthorGuess
-gitEnv env = (name, email)
+gitEnv env = (name, mail)
   where
-    name  = maybeFlag "GIT_AUTHOR_NAME" env
-    email = maybeFlag "GIT_AUTHOR_EMAIL" env
+    name = maybeFlag "GIT_AUTHOR_NAME" env
+    mail = maybeFlag "GIT_AUTHOR_EMAIL" env
 
 darcsCfg :: Maybe String -> AuthorGuess
 darcsCfg = maybe mempty nameAndMail
 
 emailEnv :: Enviro -> AuthorGuess
-emailEnv env = (mempty, email)
+emailEnv env = (mempty, mail)
   where
-    email = maybeFlag "EMAIL" env
+    mail = maybeFlag "EMAIL" env
 
 gitCfg :: GitLoc -> IO AuthorGuess
 gitCfg which = do
@@ -278,7 +329,7 @@
         then fmap Just $ readFile f
         else return Nothing
 
--- |Get list of categories used in hackage. NOTE: Very slow, needs to be cached
+-- |Get list of categories used in Hackage. NOTE: Very slow, needs to be cached
 knownCategories :: SourcePackageDb -> [String]
 knownCategories (SourcePackageDb sourcePkgIndex _) = nubSet
     [ cat | pkg <- map head (allPackagesByName sourcePkgIndex)
@@ -291,17 +342,17 @@
 nameAndMail str
   | all isSpace nameOrEmail = mempty
   | null erest = (mempty, Flag $ trim nameOrEmail)
-  | otherwise  = (Flag $ trim nameOrEmail, Flag email)
+  | otherwise  = (Flag $ trim nameOrEmail, Flag mail)
   where
     (nameOrEmail,erest) = break (== '<') str
-    (email,_)           = break (== '>') (tail erest)
+    (mail,_)            = break (== '>') (tail erest)
 
 trim :: String -> String
 trim = removeLeadingSpace . reverse . removeLeadingSpace . reverse
   where
     removeLeadingSpace  = dropWhile isSpace
 
--- split string at given character, and remove whitespaces
+-- split string at given character, and remove whitespace
 splitString :: Char -> String -> [String]
 splitString sep str = go str where
     go s = if null s' then [] else tok : go rest where
diff --git a/Distribution/Client/Init/Licenses.hs b/Distribution/Client/Init/Licenses.hs
--- a/Distribution/Client/Init/Licenses.hs
+++ b/Distribution/Client/Init/Licenses.hs
@@ -1,17 +1,50 @@
 module Distribution.Client.Init.Licenses
   ( License
+  , bsd2
   , bsd3
   , gplv2
   , gplv3
-  , lgpl2
+  , lgpl21
   , lgpl3
   , agplv3
   , apache20
+  , mit
+  , mpl20
 
   ) where
 
 type License = String
 
+bsd2 :: String -> String -> License
+bsd2 authors year = unlines
+    [ "Copyright (c) " ++ year ++ ", " ++ authors
+    , "All rights reserved."
+    , ""
+    , "Redistribution and use in source and binary forms, with or without"
+    , "modification, are permitted provided that the following conditions are"
+    , "met:"
+    , ""
+    , "1. Redistributions of source code must retain the above copyright"
+    , "   notice, this list of conditions and the following disclaimer."
+    , ""
+    , "2. Redistributions in binary form must reproduce the above copyright"
+    , "   notice, this list of conditions and the following disclaimer in the"
+    , "   documentation and/or other materials provided with the"
+    , "   distribution."
+    , ""
+    , "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"
+    , "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"
+    , "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"
+    , "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"
+    , "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"
+    , "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"
+    , "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"
+    , "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"
+    , "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"
+    , "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"
+    , "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+    ]
+
 bsd3 :: String -> String -> License
 bsd3 authors year = unlines
     [ "Copyright (c) " ++ year ++ ", " ++ authors
@@ -469,7 +502,7 @@
     , ""
     , "  \"Copyright\" also means copyright-like laws that apply to other kinds of"
     , "works, such as semiconductor masks."
-    , " "
+    , ""
     , "  \"The Program\" refers to any copyrightable work licensed under this"
     , "License.  Each licensee is addressed as \"you\".  \"Licensees\" and"
     , "\"recipients\" may be individuals or organizations."
@@ -902,7 +935,7 @@
     , "covered work in a country, or your recipient's use of the covered work"
     , "in a country, would infringe one or more identifiable patents in that"
     , "country that you have reason to believe are valid."
-    , "  "
+    , ""
     , "  If, pursuant to or in connection with a single transaction or"
     , "arrangement, you convey, or propagate by procuring conveyance of, a"
     , "covered work, and grant a patent license to some of the parties"
@@ -1065,7 +1098,6 @@
     , "the library.  If this is what you want to do, use the GNU Lesser General"
     , "Public License instead of this License.  But first, please read"
     , "<http://www.gnu.org/philosophy/why-not-lgpl.html>."
-    , ""
     ]
 
 agplv3 :: License
@@ -1733,117 +1765,130 @@
     , "<http://www.gnu.org/licenses/>."
     ]
 
-lgpl2 :: License
-lgpl2 = unlines
-    [ "           GNU LIBRARY GENERAL PUBLIC LICENSE"
-    , "                 Version 2, June 1991"
+lgpl21 :: License
+lgpl21 = unlines
+    [ "                  GNU LESSER GENERAL PUBLIC LICENSE"
+    , "                       Version 2.1, February 1999"
     , ""
-    , " Copyright (C) 1991 Free Software Foundation, Inc."
+    , " Copyright (C) 1991, 1999 Free Software Foundation, Inc."
     , " 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA"
     , " Everyone is permitted to copy and distribute verbatim copies"
     , " of this license document, but changing it is not allowed."
     , ""
-    , "[This is the first released version of the library GPL.  It is"
-    , " numbered 2 because it goes with version 2 of the ordinary GPL.]"
+    , "[This is the first released version of the Lesser GPL.  It also counts"
+    , " as the successor of the GNU Library Public License, version 2, hence"
+    , " the version number 2.1.]"
     , ""
-    , "                     Preamble"
+    , "                            Preamble"
     , ""
     , "  The licenses for most software are designed to take away your"
     , "freedom to share and change it.  By contrast, the GNU General Public"
     , "Licenses are intended to guarantee your freedom to share and change"
     , "free software--to make sure the software is free for all its users."
     , ""
-    , "  This license, the Library General Public License, applies to some"
-    , "specially designated Free Software Foundation software, and to any"
-    , "other libraries whose authors decide to use it.  You can use it for"
-    , "your libraries, too."
+    , "  This license, the Lesser General Public License, applies to some"
+    , "specially designated software packages--typically libraries--of the"
+    , "Free Software Foundation and other authors who decide to use it.  You"
+    , "can use it too, but we suggest you first think carefully about whether"
+    , "this license or the ordinary General Public License is the better"
+    , "strategy to use in any particular case, based on the explanations below."
     , ""
-    , "  When we speak of free software, we are referring to freedom, not"
-    , "price.  Our General Public Licenses are designed to make sure that you"
-    , "have the freedom to distribute copies of free software (and charge for"
-    , "this service if you wish), that you receive source code or can get it"
-    , "if you want it, that you can change the software or use pieces of it"
-    , "in new free programs; and that you know you can do these things."
+    , "  When we speak of free software, we are referring to freedom of use,"
+    , "not price.  Our General Public Licenses are designed to make sure that"
+    , "you have the freedom to distribute copies of free software (and charge"
+    , "for this service if you wish); that you receive source code or can get"
+    , "it if you want it; that you can change the software and use pieces of"
+    , "it in new free programs; and that you are informed that you can do"
+    , "these things."
     , ""
     , "  To protect your rights, we need to make restrictions that forbid"
-    , "anyone to deny you these rights or to ask you to surrender the rights."
-    , "These restrictions translate to certain responsibilities for you if"
-    , "you distribute copies of the library, or if you modify it."
+    , "distributors to deny you these rights or to ask you to surrender these"
+    , "rights.  These restrictions translate to certain responsibilities for"
+    , "you if you distribute copies of the library or if you modify it."
     , ""
     , "  For example, if you distribute copies of the library, whether gratis"
     , "or for a fee, you must give the recipients all the rights that we gave"
     , "you.  You must make sure that they, too, receive or can get the source"
-    , "code.  If you link a program with the library, you must provide"
-    , "complete object files to the recipients so that they can relink them"
-    , "with the library, after making changes to the library and recompiling"
+    , "code.  If you link other code with the library, you must provide"
+    , "complete object files to the recipients, so that they can relink them"
+    , "with the library after making changes to the library and recompiling"
     , "it.  And you must show them these terms so they know their rights."
     , ""
-    , "  Our method of protecting your rights has two steps: (1) copyright"
-    , "the library, and (2) offer you this license which gives you legal"
+    , "  We protect your rights with a two-step method: (1) we copyright the"
+    , "library, and (2) we offer you this license, which gives you legal"
     , "permission to copy, distribute and/or modify the library."
     , ""
-    , "  Also, for each distributor's protection, we want to make certain"
-    , "that everyone understands that there is no warranty for this free"
-    , "library.  If the library is modified by someone else and passed on, we"
-    , "want its recipients to know that what they have is not the original"
-    , "version, so that any problems introduced by others will not reflect on"
-    , "the original authors' reputations."
+    , "  To protect each distributor, we want to make it very clear that"
+    , "there is no warranty for the free library.  Also, if the library is"
+    , "modified by someone else and passed on, the recipients should know"
+    , "that what they have is not the original version, so that the original"
+    , "author's reputation will not be affected by problems that might be"
+    , "introduced by others."
     , ""
-    , "  Finally, any free program is threatened constantly by software"
-    , "patents.  We wish to avoid the danger that companies distributing free"
-    , "software will individually obtain patent licenses, thus in effect"
-    , "transforming the program into proprietary software.  To prevent this,"
-    , "we have made it clear that any patent must be licensed for everyone's"
-    , "free use or not licensed at all."
+    , "  Finally, software patents pose a constant threat to the existence of"
+    , "any free program.  We wish to make sure that a company cannot"
+    , "effectively restrict the users of a free program by obtaining a"
+    , "restrictive license from a patent holder.  Therefore, we insist that"
+    , "any patent license obtained for a version of the library must be"
+    , "consistent with the full freedom of use specified in this license."
     , ""
-    , "  Most GNU software, including some libraries, is covered by the ordinary"
-    , "GNU General Public License, which was designed for utility programs.  This"
-    , "license, the GNU Library General Public License, applies to certain"
-    , "designated libraries.  This license is quite different from the ordinary"
-    , "one; be sure to read it in full, and don't assume that anything in it is"
-    , "the same as in the ordinary license."
+    , "  Most GNU software, including some libraries, is covered by the"
+    , "ordinary GNU General Public License.  This license, the GNU Lesser"
+    , "General Public License, applies to certain designated libraries, and"
+    , "is quite different from the ordinary General Public License.  We use"
+    , "this license for certain libraries in order to permit linking those"
+    , "libraries into non-free programs."
     , ""
-    , "  The reason we have a separate public license for some libraries is that"
-    , "they blur the distinction we usually make between modifying or adding to a"
-    , "program and simply using it.  Linking a program with a library, without"
-    , "changing the library, is in some sense simply using the library, and is"
-    , "analogous to running a utility program or application program.  However, in"
-    , "a textual and legal sense, the linked executable is a combined work, a"
-    , "derivative of the original library, and the ordinary General Public License"
-    , "treats it as such."
+    , "  When a program is linked with a library, whether statically or using"
+    , "a shared library, the combination of the two is legally speaking a"
+    , "combined work, a derivative of the original library.  The ordinary"
+    , "General Public License therefore permits such linking only if the"
+    , "entire combination fits its criteria of freedom.  The Lesser General"
+    , "Public License permits more lax criteria for linking other code with"
+    , "the library."
     , ""
-    , "  Because of this blurred distinction, using the ordinary General"
-    , "Public License for libraries did not effectively promote software"
-    , "sharing, because most developers did not use the libraries.  We"
-    , "concluded that weaker conditions might promote sharing better."
+    , "  We call this license the \"Lesser\" General Public License because it"
+    , "does Less to protect the user's freedom than the ordinary General"
+    , "Public License.  It also provides other free software developers Less"
+    , "of an advantage over competing non-free programs.  These disadvantages"
+    , "are the reason we use the ordinary General Public License for many"
+    , "libraries.  However, the Lesser license provides advantages in certain"
+    , "special circumstances."
     , ""
-    , "  However, unrestricted linking of non-free programs would deprive the"
-    , "users of those programs of all benefit from the free status of the"
-    , "libraries themselves.  This Library General Public License is intended to"
-    , "permit developers of non-free programs to use free libraries, while"
-    , "preserving your freedom as a user of such programs to change the free"
-    , "libraries that are incorporated in them.  (We have not seen how to achieve"
-    , "this as regards changes in header files, but we have achieved it as regards"
-    , "changes in the actual functions of the Library.)  The hope is that this"
-    , "will lead to faster development of free libraries."
+    , "  For example, on rare occasions, there may be a special need to"
+    , "encourage the widest possible use of a certain library, so that it becomes"
+    , "a de-facto standard.  To achieve this, non-free programs must be"
+    , "allowed to use the library.  A more frequent case is that a free"
+    , "library does the same job as widely used non-free libraries.  In this"
+    , "case, there is little to gain by limiting the free library to free"
+    , "software only, so we use the Lesser General Public License."
     , ""
+    , "  In other cases, permission to use a particular library in non-free"
+    , "programs enables a greater number of people to use a large body of"
+    , "free software.  For example, permission to use the GNU C Library in"
+    , "non-free programs enables many more people to use the whole GNU"
+    , "operating system, as well as its variant, the GNU/Linux operating"
+    , "system."
+    , ""
+    , "  Although the Lesser General Public License is Less protective of the"
+    , "users' freedom, it does ensure that the user of a program that is"
+    , "linked with the Library has the freedom and the wherewithal to run"
+    , "that program using a modified version of the Library."
+    , ""
     , "  The precise terms and conditions for copying, distribution and"
     , "modification follow.  Pay close attention to the difference between a"
     , "\"work based on the library\" and a \"work that uses the library\".  The"
-    , "former contains code derived from the library, while the latter only"
-    , "works together with the library."
-    , ""
-    , "  Note that it is possible for a library to be covered by the ordinary"
-    , "General Public License rather than by this special one."
+    , "former contains code derived from the library, whereas the latter must"
+    , "be combined with the library in order to run."
     , ""
-    , "              GNU LIBRARY GENERAL PUBLIC LICENSE"
+    , "                  GNU LESSER GENERAL PUBLIC LICENSE"
     , "   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION"
     , ""
-    , "  0. This License Agreement applies to any software library which"
-    , "contains a notice placed by the copyright holder or other authorized"
-    , "party saying it may be distributed under the terms of this Library"
-    , "General Public License (also called \"this License\").  Each licensee is"
-    , "addressed as \"you\"."
+    , "  0. This License Agreement applies to any software library or other"
+    , "program which contains a notice placed by the copyright holder or"
+    , "other authorized party saying it may be distributed under the terms of"
+    , "this Lesser General Public License (also called \"this License\")."
+    , "Each licensee is addressed as \"you\"."
     , ""
     , "  A \"library\" means a collection of software functions and/or data"
     , "prepared so as to be conveniently linked with application programs"
@@ -1870,7 +1915,7 @@
     , "on the Library (independent of the use of the Library in a tool for"
     , "writing it).  Whether that is true depends on what the Library does"
     , "and what the program that uses the Library does."
-    , "  "
+    , ""
     , "  1. You may copy and distribute verbatim copies of the Library's"
     , "complete source code as you receive it, in any medium, provided that"
     , "you conspicuously and appropriately publish on each copy an"
@@ -1992,7 +2037,7 @@
     , "Any executables containing that work also fall under Section 6,"
     , "whether or not they are linked directly with the Library itself."
     , ""
-    , "  6. As an exception to the Sections above, you may also compile or"
+    , "  6. As an exception to the Sections above, you may also combine or"
     , "link a \"work that uses the Library\" with the Library to produce a"
     , "work containing portions of the Library, and distribute that work"
     , "under terms of your choice, provided that the terms permit"
@@ -2019,23 +2064,31 @@
     , "    Library will not necessarily be able to recompile the application"
     , "    to use the modified definitions.)"
     , ""
-    , "    b) Accompany the work with a written offer, valid for at"
+    , "    b) Use a suitable shared library mechanism for linking with the"
+    , "    Library.  A suitable mechanism is one that (1) uses at run time a"
+    , "    copy of the library already present on the user's computer system,"
+    , "    rather than copying library functions into the executable, and (2)"
+    , "    will operate properly with a modified version of the library, if"
+    , "    the user installs one, as long as the modified version is"
+    , "    interface-compatible with the version that the work was made with."
+    , ""
+    , "    c) Accompany the work with a written offer, valid for at"
     , "    least three years, to give the same user the materials"
     , "    specified in Subsection 6a, above, for a charge no more"
     , "    than the cost of performing this distribution."
     , ""
-    , "    c) If distribution of the work is made by offering access to copy"
+    , "    d) If distribution of the work is made by offering access to copy"
     , "    from a designated place, offer equivalent access to copy the above"
     , "    specified materials from the same place."
     , ""
-    , "    d) Verify that the user has already received a copy of these"
+    , "    e) Verify that the user has already received a copy of these"
     , "    materials or that you have already sent this user a copy."
     , ""
     , "  For an executable, the required form of the \"work that uses the"
     , "Library\" must include any data and utility programs needed for"
     , "reproducing the executable from it.  However, as a special exception,"
-    , "the source code distributed need not include anything that is normally"
-    , "distributed (in either source or binary form) with the major"
+    , "the materials to be distributed need not include anything that is"
+    , "normally distributed (in either source or binary form) with the major"
     , "components (compiler, kernel, and so on) of the operating system on"
     , "which the executable runs, unless that component itself accompanies"
     , "the executable."
@@ -2084,7 +2137,7 @@
     , "original licensor to copy, distribute, link with or modify the Library"
     , "subject to these terms and conditions.  You may not impose any further"
     , "restrictions on the recipients' exercise of the rights granted herein."
-    , "You are not responsible for enforcing compliance by third parties to"
+    , "You are not responsible for enforcing compliance by third parties with"
     , "this License."
     , ""
     , "  11. If, as a consequence of a court judgment or allegation of patent"
@@ -2127,7 +2180,7 @@
     , "written in the body of this License."
     , ""
     , "  13. The Free Software Foundation may publish revised and/or new"
-    , "versions of the Library General Public License from time to time."
+    , "versions of the Lesser General Public License from time to time."
     , "Such new versions will be similar in spirit to the present version,"
     , "but may differ in detail to address new problems or concerns."
     , ""
@@ -2148,7 +2201,7 @@
     , "of all derivatives of our free software and of promoting the sharing"
     , "and reuse of software generally."
     , ""
-    , "                     NO WARRANTY"
+    , "                            NO WARRANTY"
     , ""
     , "  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO"
     , "WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW."
@@ -2171,7 +2224,7 @@
     , "SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH"
     , "DAMAGES."
     , ""
-    , "              END OF TERMS AND CONDITIONS"
+    , "                     END OF TERMS AND CONDITIONS"
     , ""
     , "           How to Apply These Terms to Your New Libraries"
     , ""
@@ -2190,17 +2243,17 @@
     , "    Copyright (C) <year>  <name of author>"
     , ""
     , "    This library is free software; you can redistribute it and/or"
-    , "    modify it under the terms of the GNU Library General Public"
+    , "    modify it under the terms of the GNU Lesser General Public"
     , "    License as published by the Free Software Foundation; either"
-    , "    version 2 of the License, or (at your option) any later version."
+    , "    version 2.1 of the License, or (at your option) any later version."
     , ""
     , "    This library is distributed in the hope that it will be useful,"
     , "    but WITHOUT ANY WARRANTY; without even the implied warranty of"
     , "    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU"
-    , "    Library General Public License for more details."
+    , "    Lesser General Public License for more details."
     , ""
-    , "    You should have received a copy of the GNU Library General Public"
-    , "    License along with this library; if not, write to the Free"
+    , "    You should have received a copy of the GNU Lesser General Public"
+    , "    License along with this library; if not, write to the Free Software"
     , "    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA"
     , ""
     , "Also add information on how to contact you by electronic and paper mail."
@@ -2232,7 +2285,7 @@
     , "the terms and conditions of version 3 of the GNU General Public"
     , "License, supplemented by the additional permissions listed below."
     , ""
-    , "  0. Additional Definitions. "
+    , "  0. Additional Definitions."
     , ""
     , "  As used herein, \"this License\" refers to version 3 of the GNU Lesser"
     , "General Public License, and the \"GNU GPL\" refers to version 3 of the GNU"
@@ -2333,7 +2386,7 @@
     , "       a copy of the Library already present on the user's computer"
     , "       system, and (b) will operate properly with a modified version"
     , "       of the Library that is interface-compatible with the Linked"
-    , "       Version. "
+    , "       Version."
     , ""
     , "   e) Provide Installation Information, but only if you would otherwise"
     , "   be required to provide such information under section 6 of the"
@@ -2591,4 +2644,405 @@
     , "   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."
     , "   See the License for the specific language governing permissions and"
     , "   limitations under the License."
+    ]
+
+mit :: String -> String -> License
+mit authors year = unlines
+    [ "Copyright (c) " ++ year ++ " " ++ authors
+    , ""
+    , "Permission is hereby granted, free of charge, to any person obtaining"
+    , "a copy of this software and associated documentation files (the"
+    , "\"Software\"), to deal in the Software without restriction, including"
+    , "without limitation the rights to use, copy, modify, merge, publish,"
+    , "distribute, sublicense, and/or sell copies of the Software, and to"
+    , "permit persons to whom the Software is furnished to do so, subject to"
+    , "the following conditions:"
+    , ""
+    , "The above copyright notice and this permission notice shall be included"
+    , "in all copies or substantial portions of the Software."
+    , ""
+    , "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,"
+    , "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF"
+    , "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT."
+    , "IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY"
+    , "CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,"
+    , "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE"
+    , "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
+    ]
+
+mpl20 :: License
+mpl20 = unlines
+    [ "Mozilla Public License Version 2.0"
+    , "=================================="
+    , ""
+    , "1. Definitions"
+    , "--------------"
+    , ""
+    , "1.1. \"Contributor\""
+    , "    means each individual or legal entity that creates, contributes to"
+    , "    the creation of, or owns Covered Software."
+    , ""
+    , "1.2. \"Contributor Version\""
+    , "    means the combination of the Contributions of others (if any) used"
+    , "    by a Contributor and that particular Contributor's Contribution."
+    , ""
+    , "1.3. \"Contribution\""
+    , "    means Covered Software of a particular Contributor."
+    , ""
+    , "1.4. \"Covered Software\""
+    , "    means Source Code Form to which the initial Contributor has attached"
+    , "    the notice in Exhibit A, the Executable Form of such Source Code"
+    , "    Form, and Modifications of such Source Code Form, in each case"
+    , "    including portions thereof."
+    , ""
+    , "1.5. \"Incompatible With Secondary Licenses\""
+    , "    means"
+    , ""
+    , "    (a) that the initial Contributor has attached the notice described"
+    , "        in Exhibit B to the Covered Software; or"
+    , ""
+    , "    (b) that the Covered Software was made available under the terms of"
+    , "        version 1.1 or earlier of the License, but not also under the"
+    , "        terms of a Secondary License."
+    , ""
+    , "1.6. \"Executable Form\""
+    , "    means any form of the work other than Source Code Form."
+    , ""
+    , "1.7. \"Larger Work\""
+    , "    means a work that combines Covered Software with other material, in"
+    , "    a separate file or files, that is not Covered Software."
+    , ""
+    , "1.8. \"License\""
+    , "    means this document."
+    , ""
+    , "1.9. \"Licensable\""
+    , "    means having the right to grant, to the maximum extent possible,"
+    , "    whether at the time of the initial grant or subsequently, any and"
+    , "    all of the rights conveyed by this License."
+    , ""
+    , "1.10. \"Modifications\""
+    , "    means any of the following:"
+    , ""
+    , "    (a) any file in Source Code Form that results from an addition to,"
+    , "        deletion from, or modification of the contents of Covered"
+    , "        Software; or"
+    , ""
+    , "    (b) any new file in Source Code Form that contains any Covered"
+    , "        Software."
+    , ""
+    , "1.11. \"Patent Claims\" of a Contributor"
+    , "    means any patent claim(s), including without limitation, method,"
+    , "    process, and apparatus claims, in any patent Licensable by such"
+    , "    Contributor that would be infringed, but for the grant of the"
+    , "    License, by the making, using, selling, offering for sale, having"
+    , "    made, import, or transfer of either its Contributions or its"
+    , "    Contributor Version."
+    , ""
+    , "1.12. \"Secondary License\""
+    , "    means either the GNU General Public License, Version 2.0, the GNU"
+    , "    Lesser General Public License, Version 2.1, the GNU Affero General"
+    , "    Public License, Version 3.0, or any later versions of those"
+    , "    licenses."
+    , ""
+    , "1.13. \"Source Code Form\""
+    , "    means the form of the work preferred for making modifications."
+    , ""
+    , "1.14. \"You\" (or \"Your\")"
+    , "    means an individual or a legal entity exercising rights under this"
+    , "    License. For legal entities, \"You\" includes any entity that"
+    , "    controls, is controlled by, or is under common control with You. For"
+    , "    purposes of this definition, \"control\" means (a) the power, direct"
+    , "    or indirect, to cause the direction or management of such entity,"
+    , "    whether by contract or otherwise, or (b) ownership of more than"
+    , "    fifty percent (50%) of the outstanding shares or beneficial"
+    , "    ownership of such entity."
+    , ""
+    , "2. License Grants and Conditions"
+    , "--------------------------------"
+    , ""
+    , "2.1. Grants"
+    , ""
+    , "Each Contributor hereby grants You a world-wide, royalty-free,"
+    , "non-exclusive license:"
+    , ""
+    , "(a) under intellectual property rights (other than patent or trademark)"
+    , "    Licensable by such Contributor to use, reproduce, make available,"
+    , "    modify, display, perform, distribute, and otherwise exploit its"
+    , "    Contributions, either on an unmodified basis, with Modifications, or"
+    , "    as part of a Larger Work; and"
+    , ""
+    , "(b) under Patent Claims of such Contributor to make, use, sell, offer"
+    , "    for sale, have made, import, and otherwise transfer either its"
+    , "    Contributions or its Contributor Version."
+    , ""
+    , "2.2. Effective Date"
+    , ""
+    , "The licenses granted in Section 2.1 with respect to any Contribution"
+    , "become effective for each Contribution on the date the Contributor first"
+    , "distributes such Contribution."
+    , ""
+    , "2.3. Limitations on Grant Scope"
+    , ""
+    , "The licenses granted in this Section 2 are the only rights granted under"
+    , "this License. No additional rights or licenses will be implied from the"
+    , "distribution or licensing of Covered Software under this License."
+    , "Notwithstanding Section 2.1(b) above, no patent license is granted by a"
+    , "Contributor:"
+    , ""
+    , "(a) for any code that a Contributor has removed from Covered Software;"
+    , "    or"
+    , ""
+    , "(b) for infringements caused by: (i) Your and any other third party's"
+    , "    modifications of Covered Software, or (ii) the combination of its"
+    , "    Contributions with other software (except as part of its Contributor"
+    , "    Version); or"
+    , ""
+    , "(c) under Patent Claims infringed by Covered Software in the absence of"
+    , "    its Contributions."
+    , ""
+    , "This License does not grant any rights in the trademarks, service marks,"
+    , "or logos of any Contributor (except as may be necessary to comply with"
+    , "the notice requirements in Section 3.4)."
+    , ""
+    , "2.4. Subsequent Licenses"
+    , ""
+    , "No Contributor makes additional grants as a result of Your choice to"
+    , "distribute the Covered Software under a subsequent version of this"
+    , "License (see Section 10.2) or under the terms of a Secondary License (if"
+    , "permitted under the terms of Section 3.3)."
+    , ""
+    , "2.5. Representation"
+    , ""
+    , "Each Contributor represents that the Contributor believes its"
+    , "Contributions are its original creation(s) or it has sufficient rights"
+    , "to grant the rights to its Contributions conveyed by this License."
+    , ""
+    , "2.6. Fair Use"
+    , ""
+    , "This License is not intended to limit any rights You have under"
+    , "applicable copyright doctrines of fair use, fair dealing, or other"
+    , "equivalents."
+    , ""
+    , "2.7. Conditions"
+    , ""
+    , "Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted"
+    , "in Section 2.1."
+    , ""
+    , "3. Responsibilities"
+    , "-------------------"
+    , ""
+    , "3.1. Distribution of Source Form"
+    , ""
+    , "All distribution of Covered Software in Source Code Form, including any"
+    , "Modifications that You create or to which You contribute, must be under"
+    , "the terms of this License. You must inform recipients that the Source"
+    , "Code Form of the Covered Software is governed by the terms of this"
+    , "License, and how they can obtain a copy of this License. You may not"
+    , "attempt to alter or restrict the recipients' rights in the Source Code"
+    , "Form."
+    , ""
+    , "3.2. Distribution of Executable Form"
+    , ""
+    , "If You distribute Covered Software in Executable Form then:"
+    , ""
+    , "(a) such Covered Software must also be made available in Source Code"
+    , "    Form, as described in Section 3.1, and You must inform recipients of"
+    , "    the Executable Form how they can obtain a copy of such Source Code"
+    , "    Form by reasonable means in a timely manner, at a charge no more"
+    , "    than the cost of distribution to the recipient; and"
+    , ""
+    , "(b) You may distribute such Executable Form under the terms of this"
+    , "    License, or sublicense it under different terms, provided that the"
+    , "    license for the Executable Form does not attempt to limit or alter"
+    , "    the recipients' rights in the Source Code Form under this License."
+    , ""
+    , "3.3. Distribution of a Larger Work"
+    , ""
+    , "You may create and distribute a Larger Work under terms of Your choice,"
+    , "provided that You also comply with the requirements of this License for"
+    , "the Covered Software. If the Larger Work is a combination of Covered"
+    , "Software with a work governed by one or more Secondary Licenses, and the"
+    , "Covered Software is not Incompatible With Secondary Licenses, this"
+    , "License permits You to additionally distribute such Covered Software"
+    , "under the terms of such Secondary License(s), so that the recipient of"
+    , "the Larger Work may, at their option, further distribute the Covered"
+    , "Software under the terms of either this License or such Secondary"
+    , "License(s)."
+    , ""
+    , "3.4. Notices"
+    , ""
+    , "You may not remove or alter the substance of any license notices"
+    , "(including copyright notices, patent notices, disclaimers of warranty,"
+    , "or limitations of liability) contained within the Source Code Form of"
+    , "the Covered Software, except that You may alter any license notices to"
+    , "the extent required to remedy known factual inaccuracies."
+    , ""
+    , "3.5. Application of Additional Terms"
+    , ""
+    , "You may choose to offer, and to charge a fee for, warranty, support,"
+    , "indemnity or liability obligations to one or more recipients of Covered"
+    , "Software. However, You may do so only on Your own behalf, and not on"
+    , "behalf of any Contributor. You must make it absolutely clear that any"
+    , "such warranty, support, indemnity, or liability obligation is offered by"
+    , "You alone, and You hereby agree to indemnify every Contributor for any"
+    , "liability incurred by such Contributor as a result of warranty, support,"
+    , "indemnity or liability terms You offer. You may include additional"
+    , "disclaimers of warranty and limitations of liability specific to any"
+    , "jurisdiction."
+    , ""
+    , "4. Inability to Comply Due to Statute or Regulation"
+    , "---------------------------------------------------"
+    , ""
+    , "If it is impossible for You to comply with any of the terms of this"
+    , "License with respect to some or all of the Covered Software due to"
+    , "statute, judicial order, or regulation then You must: (a) comply with"
+    , "the terms of this License to the maximum extent possible; and (b)"
+    , "describe the limitations and the code they affect. Such description must"
+    , "be placed in a text file included with all distributions of the Covered"
+    , "Software under this License. Except to the extent prohibited by statute"
+    , "or regulation, such description must be sufficiently detailed for a"
+    , "recipient of ordinary skill to be able to understand it."
+    , ""
+    , "5. Termination"
+    , "--------------"
+    , ""
+    , "5.1. The rights granted under this License will terminate automatically"
+    , "if You fail to comply with any of its terms. However, if You become"
+    , "compliant, then the rights granted under this License from a particular"
+    , "Contributor are reinstated (a) provisionally, unless and until such"
+    , "Contributor explicitly and finally terminates Your grants, and (b) on an"
+    , "ongoing basis, if such Contributor fails to notify You of the"
+    , "non-compliance by some reasonable means prior to 60 days after You have"
+    , "come back into compliance. Moreover, Your grants from a particular"
+    , "Contributor are reinstated on an ongoing basis if such Contributor"
+    , "notifies You of the non-compliance by some reasonable means, this is the"
+    , "first time You have received notice of non-compliance with this License"
+    , "from such Contributor, and You become compliant prior to 30 days after"
+    , "Your receipt of the notice."
+    , ""
+    , "5.2. If You initiate litigation against any entity by asserting a patent"
+    , "infringement claim (excluding declaratory judgment actions,"
+    , "counter-claims, and cross-claims) alleging that a Contributor Version"
+    , "directly or indirectly infringes any patent, then the rights granted to"
+    , "You by any and all Contributors for the Covered Software under Section"
+    , "2.1 of this License shall terminate."
+    , ""
+    , "5.3. In the event of termination under Sections 5.1 or 5.2 above, all"
+    , "end user license agreements (excluding distributors and resellers) which"
+    , "have been validly granted by You or Your distributors under this License"
+    , "prior to termination shall survive termination."
+    , ""
+    , "************************************************************************"
+    , "*                                                                      *"
+    , "*  6. Disclaimer of Warranty                                           *"
+    , "*  -------------------------                                           *"
+    , "*                                                                      *"
+    , "*  Covered Software is provided under this License on an \"as is\"       *"
+    , "*  basis, without warranty of any kind, either expressed, implied, or  *"
+    , "*  statutory, including, without limitation, warranties that the       *"
+    , "*  Covered Software is free of defects, merchantable, fit for a        *"
+    , "*  particular purpose or non-infringing. The entire risk as to the     *"
+    , "*  quality and performance of the Covered Software is with You.        *"
+    , "*  Should any Covered Software prove defective in any respect, You     *"
+    , "*  (not any Contributor) assume the cost of any necessary servicing,   *"
+    , "*  repair, or correction. This disclaimer of warranty constitutes an   *"
+    , "*  essential part of this License. No use of any Covered Software is   *"
+    , "*  authorized under this License except under this disclaimer.         *"
+    , "*                                                                      *"
+    , "************************************************************************"
+    , ""
+    , "************************************************************************"
+    , "*                                                                      *"
+    , "*  7. Limitation of Liability                                          *"
+    , "*  --------------------------                                          *"
+    , "*                                                                      *"
+    , "*  Under no circumstances and under no legal theory, whether tort      *"
+    , "*  (including negligence), contract, or otherwise, shall any           *"
+    , "*  Contributor, or anyone who distributes Covered Software as          *"
+    , "*  permitted above, be liable to You for any direct, indirect,         *"
+    , "*  special, incidental, or consequential damages of any character      *"
+    , "*  including, without limitation, damages for lost profits, loss of    *"
+    , "*  goodwill, work stoppage, computer failure or malfunction, or any    *"
+    , "*  and all other commercial damages or losses, even if such party      *"
+    , "*  shall have been informed of the possibility of such damages. This   *"
+    , "*  limitation of liability shall not apply to liability for death or   *"
+    , "*  personal injury resulting from such party's negligence to the       *"
+    , "*  extent applicable law prohibits such limitation. Some               *"
+    , "*  jurisdictions do not allow the exclusion or limitation of           *"
+    , "*  incidental or consequential damages, so this exclusion and          *"
+    , "*  limitation may not apply to You.                                    *"
+    , "*                                                                      *"
+    , "************************************************************************"
+    , ""
+    , "8. Litigation"
+    , "-------------"
+    , ""
+    , "Any litigation relating to this License may be brought only in the"
+    , "courts of a jurisdiction where the defendant maintains its principal"
+    , "place of business and such litigation shall be governed by laws of that"
+    , "jurisdiction, without reference to its conflict-of-law provisions."
+    , "Nothing in this Section shall prevent a party's ability to bring"
+    , "cross-claims or counter-claims."
+    , ""
+    , "9. Miscellaneous"
+    , "----------------"
+    , ""
+    , "This License represents the complete agreement concerning the subject"
+    , "matter hereof. If any provision of this License is held to be"
+    , "unenforceable, such provision shall be reformed only to the extent"
+    , "necessary to make it enforceable. Any law or regulation which provides"
+    , "that the language of a contract shall be construed against the drafter"
+    , "shall not be used to construe this License against a Contributor."
+    , ""
+    , "10. Versions of the License"
+    , "---------------------------"
+    , ""
+    , "10.1. New Versions"
+    , ""
+    , "Mozilla Foundation is the license steward. Except as provided in Section"
+    , "10.3, no one other than the license steward has the right to modify or"
+    , "publish new versions of this License. Each version will be given a"
+    , "distinguishing version number."
+    , ""
+    , "10.2. Effect of New Versions"
+    , ""
+    , "You may distribute the Covered Software under the terms of the version"
+    , "of the License under which You originally received the Covered Software,"
+    , "or under the terms of any subsequent version published by the license"
+    , "steward."
+    , ""
+    , "10.3. Modified Versions"
+    , ""
+    , "If you create software not governed by this License, and you want to"
+    , "create a new license for such software, you may create and use a"
+    , "modified version of this License if you rename the license and remove"
+    , "any references to the name of the license steward (except to note that"
+    , "such modified license differs from this License)."
+    , ""
+    , "10.4. Distributing Source Code Form that is Incompatible With Secondary"
+    , "Licenses"
+    , ""
+    , "If You choose to distribute Source Code Form that is Incompatible With"
+    , "Secondary Licenses under the terms of this version of the License, the"
+    , "notice described in Exhibit B of this License must be attached."
+    , ""
+    , "Exhibit A - Source Code Form License Notice"
+    , "-------------------------------------------"
+    , ""
+    , "  This Source Code Form is subject to the terms of the Mozilla Public"
+    , "  License, v. 2.0. If a copy of the MPL was not distributed with this"
+    , "  file, You can obtain one at http://mozilla.org/MPL/2.0/."
+    , ""
+    , "If it is not possible or desirable to put the notice in a particular"
+    , "file, then You may include the notice in a location (such as a LICENSE"
+    , "file in a relevant directory) where a recipient would be likely to look"
+    , "for such a notice."
+    , ""
+    , "You may add additional accurate notices of copyright ownership."
+    , ""
+    , "Exhibit B - \"Incompatible With Secondary Licenses\" Notice"
+    , "---------------------------------------------------------"
+    , ""
+    , "  This Source Code Form is \"Incompatible With Secondary Licenses\", as"
+    , "  defined by the Mozilla Public License, v. 2.0."
     ]
diff --git a/Distribution/Client/Init/Types.hs b/Distribution/Client/Init/Types.hs
--- a/Distribution/Client/Init/Types.hs
+++ b/Distribution/Client/Init/Types.hs
@@ -41,7 +41,7 @@
               , noComments     :: Flag Bool
               , minimal        :: Flag Bool
 
-              , packageName  :: Flag String
+              , packageName  :: Flag P.PackageName
               , version      :: Flag Version
               , cabalVersion :: Flag VersionRange
               , license      :: Flag License
@@ -54,6 +54,7 @@
               , extraSrc     :: Maybe [String]
 
               , packageType  :: Flag PackageType
+              , mainIs       :: Flag FilePath
               , language     :: Flag Language
 
               , exposedModules :: Maybe [ModuleName]
@@ -98,6 +99,7 @@
     , category       = mempty
     , extraSrc       = mempty
     , packageType    = mempty
+    , mainIs         = mempty
     , language       = mempty
     , exposedModules = mempty
     , otherModules   = mempty
@@ -125,6 +127,7 @@
     , category       = combine category
     , extraSrc       = combine extraSrc
     , packageType    = combine packageType
+    , mainIs         = combine mainIs
     , language       = combine language
     , exposedModules = combine exposedModules
     , otherModules   = combine otherModules
diff --git a/Distribution/Client/Install.hs b/Distribution/Client/Install.hs
--- a/Distribution/Client/Install.hs
+++ b/Distribution/Client/Install.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.Client.Install
@@ -33,24 +34,31 @@
 import Data.Maybe
          ( isJust, fromMaybe, maybeToList )
 import Control.Exception as Exception
-         ( Exception(toException), bracket, catches, Handler(Handler), handleJust
-         , IOException, SomeException )
+         ( Exception(toException), bracket, catches
+         , Handler(Handler), handleJust, IOException, SomeException )
+#ifndef mingw32_HOST_OS
+import Control.Exception as Exception
+         ( Exception(fromException) )
+#endif
 import System.Exit
-         ( ExitCode )
+         ( ExitCode(..) )
 import Distribution.Compat.Exception
          ( catchIO, catchExit )
 import Control.Monad
          ( when, unless )
 import System.Directory
-         ( getTemporaryDirectory, doesFileExist, createDirectoryIfMissing )
+         ( getTemporaryDirectory, doesDirectoryExist, doesFileExist,
+           createDirectoryIfMissing, removeFile, renameDirectory )
 import System.FilePath
          ( (</>), (<.>), takeDirectory )
 import System.IO
-         ( openFile, IOMode(WriteMode), hClose )
+         ( openFile, IOMode(AppendMode), hClose )
 import System.IO.Error
          ( isDoesNotExistError, ioeGetFileName )
 
 import Distribution.Client.Targets
+import Distribution.Client.Configure
+         ( chooseCabalVersion )
 import Distribution.Client.Dependency
 import Distribution.Client.Dependency.Types
          ( Solver(..) )
@@ -86,7 +94,7 @@
 import qualified Distribution.Client.Win32SelfUpgrade as Win32SelfUpgrade
 import qualified Distribution.Client.World as World
 import qualified Distribution.InstalledPackageInfo as Installed
-import Paths_cabal_install (getBinDir)
+import Distribution.Client.Compat.ExecutablePath
 import Distribution.Client.JobControl
 
 import Distribution.Simple.Compiler
@@ -100,12 +108,15 @@
 import Distribution.Simple.Setup
          ( haddockCommand, HaddockFlags(..)
          , buildCommand, BuildFlags(..), emptyBuildFlags
-         , toFlag, fromFlag, fromFlagOrDefault, flagToMaybe )
+         , toFlag, fromFlag, fromFlagOrDefault, flagToMaybe, defaultDistPref )
 import qualified Distribution.Simple.Setup as Cabal
-         ( installCommand, InstallFlags(..), TestFlags(..), emptyInstallFlags
-         , emptyTestFlags, testCommand, Flag(..) )
+         ( Flag(..)
+         , copyCommand, CopyFlags(..), emptyCopyFlags
+         , registerCommand, RegisterFlags(..), emptyRegisterFlags
+         , testCommand, TestFlags(..), emptyTestFlags )
 import Distribution.Simple.Utils
-         ( rawSystemExit, comparing, writeFileAtomic )
+         ( createDirectoryIfMissingVerbose, rawSystemExit, comparing
+         , writeFileAtomic, withTempFile , withFileContents )
 import Distribution.Simple.InstallDirs as InstallDirs
          ( PathTemplate, fromPathTemplate, toPathTemplate, substPathTemplate
          , initialPathTemplateEnv, installDirsTemplateEnv )
@@ -119,12 +130,15 @@
          , FlagName(..), FlagAssignment )
 import Distribution.PackageDescription.Configuration
          ( finalizePackageDescription )
+import Distribution.ParseUtils
+         ( showPWarning )
 import Distribution.Version
-         ( Version, anyVersion, thisVersion )
+         ( Version )
 import Distribution.Simple.Utils as Utils
-         ( notice, info, warn, debugNoWrap, die, intercalate, withTempDirectory )
+         ( notice, info, warn, debug, debugNoWrap, die
+         , intercalate, withTempDirectory )
 import Distribution.Client.Utils
-         ( numberOfProcessors, inDir, mergeBy, MergeResult(..)
+         ( determineNumJobs, inDir, mergeBy, MergeResult(..)
          , tryCanonicalizePath )
 import Distribution.System
          ( Platform, OS(Windows), buildOS )
@@ -187,18 +201,18 @@
                                    then installFailedInSandbox else [])
     -- TODO: use a better error message, remove duplication.
     installFailedInSandbox =
-      "\nNote: when using a sandbox, all packages are required to have \
-      \consistent dependencies. \
-      \Try reinstalling/unregistering the offending packages or \
-      \recreating the sandbox."
+      "\nNote: when using a sandbox, all packages are required to have "
+      ++ "consistent dependencies. "
+      ++ "Try reinstalling/unregistering the offending packages or "
+      ++ "recreating the sandbox."
     logMsg message rest = debugNoWrap verbosity message >> rest
 
--- TODO: Make InstallContext a proper datatype with documented fields.
+-- TODO: Make InstallContext a proper data type with documented fields.
 -- | Common context for makeInstallPlan and processInstallPlan.
 type InstallContext = ( PackageIndex, SourcePackageDb
                       , [UserTarget], [PackageSpecifier SourcePackage] )
 
--- TODO: Make InstallArgs a proper datatype with documented fields or just get
+-- TODO: Make InstallArgs a proper data type with documented fields or just get
 -- rid of it completely.
 -- | Initial arguments given to 'install' or 'makeInstallContext'.
 type InstallArgs = ( PackageDBStack
@@ -272,12 +286,13 @@
     checkPrintPlan verbosity installedPkgIndex installPlan sourcePkgDb
       installFlags pkgSpecifiers
 
-    unless dryRun $ do
+    unless (dryRun || nothingToInstall) $ do
       installPlan' <- performInstallations verbosity
                       args installedPkgIndex installPlan
       postInstallActions verbosity args userTargets installPlan'
   where
     dryRun = fromFlag (installDryRun installFlags)
+    nothingToInstall = null (InstallPlan.ready installPlan)
 
 -- ------------------------------------------------------------
 -- * Installation planning
@@ -319,11 +334,11 @@
 
       . setShadowPkgs shadowPkgs
 
-      . setStrongFlags strongFlags
-
       . setPreferenceDefault (if upgradeDeps then PreferAllLatest
                                              else PreferLatestForSelected)
 
+      . removeUpperBounds allowNewer
+
       . addPreferences
           -- preferences from the config file or command line
           [ PackageVersionPreference name ver
@@ -364,10 +379,10 @@
     independentGoals = fromFlag (installIndependentGoals installFlags)
     avoidReinstalls  = fromFlag (installAvoidReinstalls  installFlags)
     shadowPkgs       = fromFlag (installShadowPkgs       installFlags)
-    strongFlags      = fromFlag (installStrongFlags      installFlags)
     maxBackjumps     = fromFlag (installMaxBackjumps     installFlags)
     upgradeDeps      = fromFlag (installUpgradeDeps      installFlags)
     onlyDeps         = fromFlag (installOnlyDeps         installFlags)
+    allowNewer       = fromFlag (configAllowNewer        configExFlags)
 
 -- | Remove the provided targets from the install plan.
 pruneInstallPlan :: Package pkg => [PackageSpecifier pkg] -> InstallPlan
@@ -481,7 +496,7 @@
 
 linearizeInstallPlan :: PackageIndex
                      -> InstallPlan
-                     -> [(ConfiguredPackage, PackageStatus)]
+                     -> [(ReadyPackage, PackageStatus)]
 linearizeInstallPlan installedPkgIndex plan =
     unfoldr next plan
   where
@@ -492,7 +507,9 @@
           pkgid  = packageId pkg
           status = packageStatus installedPkgIndex pkg
           plan'' = InstallPlan.completed pkgid
-                     (BuildOk DocsNotTried TestsNotTried)
+                     (BuildOk DocsNotTried TestsNotTried
+                              (Just $ Installed.emptyInstalledPackageInfo
+                              { Installed.sourcePackageId = pkgid }))
                      (InstallPlan.processing [pkg] plan')
           --FIXME: This is a bit of a hack,
           -- pretending that each package is installed
@@ -507,7 +524,7 @@
 extractReinstalls (Reinstall ipids _) = ipids
 extractReinstalls _                   = []
 
-packageStatus :: PackageIndex -> ConfiguredPackage -> PackageStatus
+packageStatus :: PackageIndex -> ReadyPackage -> PackageStatus
 packageStatus installedPkgIndex cpkg =
   case PackageIndex.lookupPackageName installedPkgIndex
                                       (packageName cpkg) of
@@ -521,7 +538,7 @@
   where
 
     changes :: Installed.InstalledPackageInfo
-            -> ConfiguredPackage
+            -> ReadyPackage
             -> [MergeResult PackageIdentifier PackageIdentifier]
     changes pkg pkg' =
       filter changed
@@ -540,7 +557,7 @@
 
 printPlan :: Bool -- is dry run
           -> Verbosity
-          -> [(ConfiguredPackage, PackageStatus)]
+          -> [(ReadyPackage, PackageStatus)]
           -> SourcePackageDb
           -> IO ()
 printPlan dryRun verbosity plan sourcePkgDb = case plan of
@@ -571,10 +588,10 @@
                 []   -> ""
                 diff -> " changes: "  ++ intercalate ", " (map change diff)
 
-    showLatest :: ConfiguredPackage -> String
+    showLatest :: ReadyPackage -> String
     showLatest pkg = case mLatestVersion of
         Just latestVersion ->
-            if pkgVersion /= latestVersion
+            if pkgVersion < latestVersion
             then (" (latest: " ++ display latestVersion ++ ")")
             else ""
         Nothing -> ""
@@ -590,15 +607,15 @@
     toFlagAssignment :: [Flag] -> FlagAssignment
     toFlagAssignment = map (\ f -> (flagName f, flagDefault f))
 
-    nonDefaultFlags :: ConfiguredPackage -> FlagAssignment
-    nonDefaultFlags (ConfiguredPackage spkg fa _ _) =
+    nonDefaultFlags :: ReadyPackage -> FlagAssignment
+    nonDefaultFlags (ReadyPackage spkg fa _ _) =
       let defaultAssignment =
             toFlagAssignment
              (genPackageFlags (Source.packageDescription spkg))
       in  fa \\ defaultAssignment
 
-    stanzas :: ConfiguredPackage -> [OptionalStanza]
-    stanzas (ConfiguredPackage _ _ sts _) = sts
+    stanzas :: ReadyPackage -> [OptionalStanza]
+    stanzas (ReadyPackage _ _ sts _) = sts
 
     showStanzas :: [OptionalStanza] -> String
     showStanzas = concatMap ((' ' :) . showStanza)
@@ -746,7 +763,7 @@
         normalUserInstall     = (UserPackageDB `elem` packageDBs)
                              && all (not . isSpecificPackageDB) packageDBs
 
-        installedDocs (InstallPlan.Installed _ (BuildOk DocsOk _)) = True
+        installedDocs (InstallPlan.Installed _ (BuildOk DocsOk _ _)) = True
         installedDocs _                                            = False
         isSpecificPackageDB (SpecificPackageDB _) = True
         isSpecificPackageDB _                     = False
@@ -804,30 +821,41 @@
       DependentFailed pkgid -> " depends on " ++ display pkgid
                             ++ " which failed to install."
       DownloadFailed  e -> " failed while downloading the package."
-                        ++ " The exception was:\n  " ++ show e
+                        ++ showException e
       UnpackFailed    e -> " failed while unpacking the package."
-                        ++ " The exception was:\n  " ++ show e
+                        ++ showException e
       ConfigureFailed e -> " failed during the configure step."
-                        ++ " The exception was:\n  " ++ show e
+                        ++ showException e
       BuildFailed     e -> " failed during the building phase."
-                        ++ " The exception was:\n  " ++ show e
+                        ++ showException e
       TestsFailed     e -> " failed during the tests phase."
-                        ++ " The exception was:\n  " ++ show e
+                        ++ showException e
       InstallFailed   e -> " failed during the final install step."
-                        ++ " The exception was:\n  " ++ show e
+                        ++ showException e
 
+    showException e   =  " The exception was:\n  " ++ show e ++ maybeOOM e
+#ifdef mingw32_HOST_OS
+    maybeOOM _        = ""
+#else
+    maybeOOM e                    = maybe "" onExitFailure (fromException e)
+    onExitFailure (ExitFailure 9) =
+      "\nThis may be due to an out-of-memory condition."
+    onExitFailure _               = ""
+#endif
+
+
 -- | If we're working inside a sandbox and some add-source deps were installed,
 -- update the timestamps of those deps.
 updateSandboxTimestampsFile :: UseSandbox -> Maybe SandboxPackageInfo
-                        -> Compiler -> Platform -> InstallPlan
-                        -> IO ()
+                            -> Compiler -> Platform -> InstallPlan
+                            -> IO ()
 updateSandboxTimestampsFile (UseSandbox sandboxDir)
                             (Just (SandboxPackageInfo _ _ _ allAddSourceDeps))
                             comp platform installPlan =
   withUpdateTimestamps sandboxDir (compilerId comp) platform $ \_ -> do
     let allInstalled = [ pkg | InstallPlan.Installed pkg _
                             <- InstallPlan.toList installPlan ]
-        allSrcPkgs   = [ pkg | ConfiguredPackage pkg _ _ _ <- allInstalled ]
+        allSrcPkgs   = [ pkg | ReadyPackage pkg _ _ _ <- allInstalled ]
         allPaths     = [ pth | LocalUnpackedPackage pth
                             <- map packageSource allSrcPkgs]
     allPathsCanonical <- mapM tryCanonicalizePath allPaths
@@ -860,22 +888,23 @@
 
   -- With 'install -j' it can be a bit hard to tell whether a sandbox is used.
   whenUsingSandbox useSandbox $ \sandboxDir ->
-    when parallelBuild $
+    when parallelInstall $
       notice verbosity $ "Notice: installing into a sandbox located at "
                          ++ sandboxDir
 
-  jobControl   <- if parallelBuild then newParallelJobControl
-                                   else newSerialJobControl
+  jobControl   <- if parallelInstall then newParallelJobControl
+                                     else newSerialJobControl
   buildLimit   <- newJobLimit numJobs
   fetchLimit   <- newJobLimit (min numJobs numFetchJobs)
   installLock  <- newLock -- serialise installation
   cacheLock    <- newLock -- serialise access to setup exe cache
 
-  executeInstallPlan verbosity jobControl useLogFile installPlan $ \cpkg ->
-    installConfiguredPackage platform compid configFlags
-                             cpkg $ \configFlags' src pkg pkgoverride ->
+  executeInstallPlan verbosity jobControl useLogFile installPlan $ \rpkg ->
+    installReadyPackage platform compid configFlags
+                        rpkg $ \configFlags' src pkg pkgoverride ->
       fetchSourcePackage verbosity fetchLimit src $ \src' ->
-        installLocalPackage verbosity buildLimit (packageId pkg) src' $ \mpath ->
+        installLocalPackage verbosity buildLimit
+                            (packageId pkg) src' distPref $ \mpath ->
           installUnpackedPackage verbosity buildLimit installLock numJobs
                                  (setupScriptOptions installedPkgIndex cacheLock)
                                  miscOptions configFlags' installFlags haddockFlags
@@ -885,15 +914,15 @@
     platform = InstallPlan.planPlatform installPlan
     compid   = InstallPlan.planCompiler installPlan
 
-    numJobs  = case installNumJobs installFlags of
-      Cabal.NoFlag        -> 1
-      Cabal.Flag Nothing  -> numberOfProcessors
-      Cabal.Flag (Just n) -> n
-    numFetchJobs  = 2
-    parallelBuild = numJobs >= 2
+    numJobs         = determineNumJobs (installNumJobs installFlags)
+    numFetchJobs    = 2
+    parallelInstall = numJobs >= 2
+    distPref        = fromFlagOrDefault (useDistPref defaultSetupScriptOptions)
+                      (configDistPref configFlags)
 
     setupScriptOptions index lock = SetupScriptOptions {
-      useCabalVersion  = maybe anyVersion thisVersion (libVersion miscOptions),
+      useCabalVersion  = chooseCabalVersion configExFlags
+                         (libVersion miscOptions),
       useCompiler      = Just comp,
       usePlatform      = Just platform,
       -- Hack: we typically want to allow the UserPackageDB for finding the
@@ -909,12 +938,10 @@
                            then Just index
                            else Nothing,
       useProgramConfig = conf,
-      useDistPref      = fromFlagOrDefault
-                           (useDistPref defaultSetupScriptOptions)
-                           (configDistPref configFlags),
+      useDistPref      = distPref,
       useLoggingHandle = Nothing,
       useWorkingDir    = Nothing,
-      forceExternalSetupMethod = parallelBuild,
+      forceExternalSetupMethod = parallelInstall,
       setupCacheLock   = Just lock
     }
     reportingLevel = fromFlag (installBuildReports installFlags)
@@ -947,14 +974,14 @@
         useDefaultTemplate
           | reportingLevel == DetailedReports = True
           | isJust installLogFile'            = False
-          | parallelBuild                     = True
+          | parallelInstall                   = True
           | otherwise                         = False
 
         overrideVerbosity :: Bool
         overrideVerbosity
           | reportingLevel == DetailedReports = True
           | isJust installLogFile'            = True
-          | parallelBuild                     = False
+          | parallelInstall                   = False
           | otherwise                         = False
 
     substLogFileName :: PathTemplate -> PackageIdentifier -> FilePath
@@ -978,7 +1005,7 @@
                    -> JobControl IO (PackageId, BuildResult)
                    -> UseLogFile
                    -> InstallPlan
-                   -> (ConfiguredPackage -> IO BuildResult)
+                   -> (ReadyPackage -> IO BuildResult)
                    -> IO InstallPlan
 executeInstallPlan verbosity jobCtl useLogFile plan0 installPkg =
     tryNewTasks 0 plan0
@@ -1046,31 +1073,43 @@
       mapM_ putStrLn (drop toDrop lns)
 
 -- | Call an installer for an 'SourcePackage' but override the configure
--- flags with the ones given by the 'ConfiguredPackage'. In particular the
--- 'ConfiguredPackage' specifies an exact 'FlagAssignment' and exactly
+-- flags with the ones given by the 'ReadyPackage'. In particular the
+-- 'ReadyPackage' specifies an exact 'FlagAssignment' and exactly
 -- versioned package dependencies. So we ignore any previous partial flag
 -- assignment or dependency constraints and use the new ones.
 --
-installConfiguredPackage :: Platform -> CompilerId
-                         ->  ConfigFlags -> ConfiguredPackage
-                         -> (ConfigFlags -> PackageLocation (Maybe FilePath)
-                                         -> PackageDescription
-                                         -> PackageDescriptionOverride -> a)
-                         -> a
-installConfiguredPackage platform comp configFlags
-  (ConfiguredPackage (SourcePackage _ gpkg source pkgoverride)
+-- NB: when updating this function, don't forget to also update
+-- 'configurePackage' in D.C.Configure.
+installReadyPackage :: Platform -> CompilerId
+                       -> ConfigFlags
+                       -> ReadyPackage
+                       -> (ConfigFlags -> PackageLocation (Maybe FilePath)
+                                       -> PackageDescription
+                                       -> PackageDescriptionOverride -> a)
+                       -> a
+installReadyPackage platform comp configFlags
+  (ReadyPackage (SourcePackage _ gpkg source pkgoverride)
    flags stanzas deps)
   installPkg = installPkg configFlags {
     configConfigurationsFlags = flags,
-    configConstraints = map thisPackageVersion deps,
-    configBenchmarks = toFlag False,
-    configTests = toFlag (TestStanzas `elem` stanzas)
+    -- We generate the legacy constraints as well as the new style precise deps.
+    -- In the end only one set gets passed to Setup.hs configure, depending on
+    -- the Cabal version we are talking to.
+    configConstraints  = [ thisPackageVersion (packageId deppkg)
+                         | deppkg <- deps ],
+    configDependencies = [ (packageName (Installed.sourcePackageId deppkg),
+                            Installed.installedPackageId deppkg)
+                         | deppkg <- deps ],
+    -- Use '--exact-configuration' if supported.
+    configExactConfiguration = toFlag True,
+    configBenchmarks         = toFlag False,
+    configTests              = toFlag (TestStanzas `elem` stanzas)
   } source pkg pkgoverride
   where
     pkg = case finalizePackageDescription flags
            (const True)
            platform comp [] (enableStanzas stanzas gpkg) of
-      Left _ -> error "finalizePackageDescription ConfiguredPackage failed"
+      Left _ -> error "finalizePackageDescription ReadyPackage failed"
       Right (desc, _) -> desc
 
 fetchSourcePackage
@@ -1092,10 +1131,10 @@
 installLocalPackage
   :: Verbosity
   -> JobLimit
-  -> PackageIdentifier -> PackageLocation FilePath
+  -> PackageIdentifier -> PackageLocation FilePath -> FilePath
   -> (Maybe FilePath -> IO BuildResult)
   -> IO BuildResult
-installLocalPackage verbosity jobLimit pkgid location installPkg =
+installLocalPackage verbosity jobLimit pkgid location distPref installPkg =
 
   case location of
 
@@ -1104,24 +1143,25 @@
 
     LocalTarballPackage tarballPath ->
       installLocalTarballPackage verbosity jobLimit
-        pkgid tarballPath installPkg
+        pkgid tarballPath distPref installPkg
 
     RemoteTarballPackage _ tarballPath ->
       installLocalTarballPackage verbosity jobLimit
-        pkgid tarballPath installPkg
+        pkgid tarballPath distPref installPkg
 
     RepoTarballPackage _ _ tarballPath ->
       installLocalTarballPackage verbosity jobLimit
-        pkgid tarballPath installPkg
+        pkgid tarballPath distPref installPkg
 
 
 installLocalTarballPackage
   :: Verbosity
   -> JobLimit
-  -> PackageIdentifier -> FilePath
+  -> PackageIdentifier -> FilePath -> FilePath
   -> (Maybe FilePath -> IO BuildResult)
   -> IO BuildResult
-installLocalTarballPackage verbosity jobLimit pkgid tarballPath installPkg = do
+installLocalTarballPackage verbosity jobLimit pkgid
+                           tarballPath distPref installPkg = do
   tmp <- getTemporaryDirectory
   withTempDirectory verbosity tmp (display pkgid) $ \tmpDirPath ->
     onFailure UnpackFailed $ do
@@ -1136,8 +1176,33 @@
         exists <- doesFileExist descFilePath
         when (not exists) $
           die $ "Package .cabal file not found: " ++ show descFilePath
+        maybeRenameDistDir absUnpackedPath
+
       installPkg (Just absUnpackedPath)
 
+  where
+    -- 'cabal sdist' puts pre-generated files in the 'dist' directory. This
+    -- fails when we use a nonstandard build directory name (as is the case
+    -- with sandboxes), so we need to rename the 'dist' dir here.
+    --
+    -- TODO: 'cabal get happy && cd sandbox && cabal install ../happy' still
+    -- fails even with this workaround. We probably can live with that.
+    maybeRenameDistDir :: FilePath -> IO ()
+    maybeRenameDistDir absUnpackedPath = do
+      let distDirPath    = absUnpackedPath </> defaultDistPref
+          distDirPathTmp = absUnpackedPath </> (defaultDistPref ++ "-tmp")
+          distDirPathNew = absUnpackedPath </> distPref
+      distDirExists <- doesDirectoryExist distDirPath
+      when distDirExists $ do
+        -- NB: we need to handle the case when 'distDirPathNew' is a
+        -- subdirectory of 'distDirPath' (e.g. 'dist/dist-sandbox-3688fbc2').
+        debug verbosity $ "Renaming '" ++ distDirPath ++ "' to '"
+          ++ distDirPathTmp ++ "'."
+        renameDirectory distDirPath distDirPathTmp
+        createDirectoryIfMissingVerbose verbosity False distDirPath
+        debug verbosity $ "Renaming '" ++ distDirPathTmp ++ "' to '"
+          ++ distDirPathNew ++ "'."
+        renameDirectory distDirPathTmp distDirPathNew
 
 installUnpackedPackage
   :: Verbosity
@@ -1158,7 +1223,7 @@
   -> IO BuildResult
 installUnpackedPackage verbosity buildLimit installLock numJobs
                        scriptOptions miscOptions
-                       configFlags installConfigFlags haddockFlags
+                       configFlags installFlags haddockFlags
                        compid platform pkg pkgoverride workingDir useLogFile = do
 
   -- Override the .cabal file if necessary
@@ -1181,21 +1246,24 @@
         configVerbosity = toFlag verbosity'
       }
 
+  -- Path to the optional log file.
+  mLogPath <- maybeLogPath
+
   -- Configure phase
   onFailure ConfigureFailed $ withJobLimit buildLimit $ do
     when (numJobs > 1) $ notice verbosity $
       "Configuring " ++ display pkgid ++ "..."
-    setup configureCommand configureFlags
+    setup configureCommand configureFlags mLogPath
 
   -- Build phase
     onFailure BuildFailed $ do
       when (numJobs > 1) $ notice verbosity $
         "Building " ++ display pkgid ++ "..."
-      setup buildCommand' buildFlags
+      setup buildCommand' buildFlags mLogPath
 
   -- Doc generation phase
       docsResult <- if shouldHaddock
-        then (do setup haddockCommand haddockFlags'
+        then (do setup haddockCommand haddockFlags' mLogPath
                  return DocsOk)
                `catchIO`   (\_ -> return DocsFailed)
                `catchExit` (\_ -> return DocsFailed)
@@ -1204,18 +1272,25 @@
   -- Tests phase
       onFailure TestsFailed $ do
         when (testsEnabled && PackageDescription.hasTests pkg) $
-            setup Cabal.testCommand testFlags
+            setup Cabal.testCommand testFlags mLogPath
 
         let testsResult | testsEnabled = TestsOk
                         | otherwise = TestsNotTried
 
       -- Install phase
-        onFailure InstallFailed $ criticalSection installLock $
+        onFailure InstallFailed $ criticalSection installLock $ do
+          -- Capture installed package configuration file
+          maybePkgConf <- maybeGenPkgConf mLogPath
+
+          -- Actual installation
           withWin32SelfUpgrade verbosity configFlags compid platform pkg $ do
             case rootCmd miscOptions of
               (Just cmd) -> reexec cmd
-              Nothing    -> setup Cabal.installCommand installFlags
-            return (Right (BuildOk docsResult testsResult))
+              Nothing    -> do
+                setup Cabal.copyCommand copyFlags mLogPath
+                when shouldRegister $ do
+                  setup Cabal.registerCommand registerFlags mLogPath
+          return (Right (BuildOk docsResult testsResult maybePkgConf))
 
   where
     pkgid            = packageId pkg
@@ -1224,20 +1299,28 @@
       buildDistPref  = configDistPref configFlags,
       buildVerbosity = toFlag verbosity'
     }
-    shouldHaddock    = fromFlag (installDocumentation installConfigFlags)
+    shouldHaddock    = fromFlag (installDocumentation installFlags)
     haddockFlags' _   = haddockFlags {
       haddockVerbosity = toFlag verbosity',
       haddockDistPref  = configDistPref configFlags
     }
     testsEnabled = fromFlag (configTests configFlags)
+                   && fromFlagOrDefault False (installRunTests installFlags)
     testFlags _ = Cabal.emptyTestFlags {
       Cabal.testDistPref = configDistPref configFlags
     }
-    installFlags _   = Cabal.emptyInstallFlags {
-      Cabal.installDistPref  = configDistPref configFlags,
-      Cabal.installVerbosity = toFlag verbosity'
+    copyFlags _ = Cabal.emptyCopyFlags {
+      Cabal.copyDistPref   = configDistPref configFlags,
+      Cabal.copyDest       = toFlag InstallDirs.NoCopyDest,
+      Cabal.copyVerbosity  = toFlag verbosity'
     }
+    shouldRegister = PackageDescription.hasLibs pkg
+    registerFlags _ = Cabal.emptyRegisterFlags {
+      Cabal.regDistPref   = configDistPref configFlags,
+      Cabal.regVerbosity  = toFlag verbosity'
+    }
     verbosity' = maybe verbosity snd useLogFile
+    tempTemplate name = name ++ "-" ++ display pkgid
 
     addDefaultInstallDirs :: ConfigFlags -> IO ConfigFlags
     addDefaultInstallDirs configFlags' = do
@@ -1254,30 +1337,59 @@
           userInstall = fromFlagOrDefault defaultUserInstall
                         (configUserInstall configFlags')
 
-    setup cmd flags  = do
+    maybeGenPkgConf :: Maybe FilePath
+                    -> IO (Maybe Installed.InstalledPackageInfo)
+    maybeGenPkgConf mLogPath =
+      if shouldRegister then do
+        tmp <- getTemporaryDirectory
+        withTempFile tmp (tempTemplate "pkgConf") $ \pkgConfFile handle -> do
+          hClose handle
+          let registerFlags' version = (registerFlags version) {
+                Cabal.regGenPkgConf = toFlag (Just pkgConfFile)
+              }
+          setup Cabal.registerCommand registerFlags' mLogPath
+          withFileContents pkgConfFile $ \pkgConfText ->
+            case Installed.parseInstalledPackageInfo pkgConfText of
+              Installed.ParseFailed perror    -> pkgConfParseFailed perror
+              Installed.ParseOk warns pkgConf -> do
+                unless (null warns) $
+                  warn verbosity $ unlines (map (showPWarning pkgConfFile) warns)
+                return (Just pkgConf)
+      else return Nothing
+
+    pkgConfParseFailed :: Installed.PError -> IO a
+    pkgConfParseFailed perror =
+      die $ "Couldn't parse the output of 'setup register --gen-pkg-config':"
+            ++ show perror
+
+    maybeLogPath :: IO (Maybe FilePath)
+    maybeLogPath =
+      case useLogFile of
+         Nothing                 -> return Nothing
+         Just (mkLogFileName, _) -> do
+           let logFileName = mkLogFileName (packageId pkg)
+               logDir      = takeDirectory logFileName
+           unless (null logDir) $ createDirectoryIfMissing True logDir
+           logFileExists <- doesFileExist logFileName
+           when logFileExists $ removeFile logFileName
+           return (Just logFileName)
+
+    setup cmd flags mLogPath =
       Exception.bracket
-              (case useLogFile of
-               Nothing                   -> return Nothing
-               Just (mkLogFileName, _) -> do
-                 let logFileName = mkLogFileName (packageId pkg)
-                     logDir      = takeDirectory logFileName
-                 unless (null logDir) $ createDirectoryIfMissing True logDir
-                 logFile <- openFile logFileName WriteMode
-                 return (Just logFile))
-              (\mHandle -> case mHandle of
-                           Just handle -> hClose handle
-                           Nothing -> return ())
-              (\logFileHandle ->
-               setupWrapper verbosity
-                 scriptOptions { useLoggingHandle = logFileHandle
-                               , useWorkingDir    = workingDir }
-                 (Just pkg)
-                 cmd flags [])
+      (maybe (return Nothing)
+             (\path -> Just `fmap` openFile path AppendMode) mLogPath)
+      (maybe (return ()) hClose)
+      (\logFileHandle ->
+        setupWrapper verbosity
+          scriptOptions { useLoggingHandle = logFileHandle
+                        , useWorkingDir    = workingDir }
+          (Just pkg)
+          cmd flags [])
+
     reexec cmd = do
-      -- look for our on executable file and re-exec ourselves using
-      -- a helper program like sudo to elevate priviledges:
-      bindir <- getBinDir
-      let self = bindir </> "cabal" <.> exeExtension
+      -- look for our own executable file and re-exec ourselves using a helper
+      -- program like sudo to elevate privileges:
+      self <- getExecutablePath
       weExist <- doesFileExist self
       if weExist
         then inDir workingDir $
@@ -1300,7 +1412,7 @@
 
 
 -- ------------------------------------------------------------
--- * Wierd windows hacks
+-- * Weird windows hacks
 -- ------------------------------------------------------------
 
 withWin32SelfUpgrade :: Verbosity
diff --git a/Distribution/Client/InstallPlan.hs b/Distribution/Client/InstallPlan.hs
--- a/Distribution/Client/InstallPlan.hs
+++ b/Distribution/Client/InstallPlan.hs
@@ -47,7 +47,9 @@
 
 import Distribution.Client.Types
          ( SourcePackage(packageDescription), ConfiguredPackage(..)
-         , InstalledPackage, BuildFailure, BuildSuccess, enableStanzas )
+         , ReadyPackage(..), readyPackageToConfiguredPackage
+         , InstalledPackage, BuildFailure, BuildSuccess(..), enableStanzas
+         , InstalledPackage (..) )
 import Distribution.Package
          ( PackageIdentifier(..), PackageName(..), Package(..), packageName
          , PackageFixedDeps(..), Dependency(..) )
@@ -73,11 +75,12 @@
          ( duplicates, duplicatesBy, mergeBy, MergeResult(..) )
 import Distribution.Simple.Utils
          ( comparing, intercalate )
+import qualified Distribution.InstalledPackageInfo as Installed
 
 import Data.List
          ( sort, sortBy )
 import Data.Maybe
-         ( fromMaybe )
+         ( fromMaybe, maybeToList )
 import qualified Data.Graph as Graph
 import Data.Graph (Graph)
 import Control.Exception
@@ -127,9 +130,11 @@
 
 data PlanPackage = PreExisting InstalledPackage
                  | Configured  ConfiguredPackage
-                 | Processing  ConfiguredPackage
-                 | Installed   ConfiguredPackage BuildSuccess
+                 | Processing  ReadyPackage
+                 | Installed   ReadyPackage BuildSuccess
                  | Failed      ConfiguredPackage BuildFailure
+                   -- ^ NB: packages in the Failed state can be *either* Ready
+                   -- or Configured.
 
 instance Package PlanPackage where
   packageId (PreExisting pkg) = packageId pkg
@@ -204,7 +209,7 @@
 -- configured state and have all their dependencies installed already.
 -- The plan is complete if the result is @[]@.
 --
-ready :: InstallPlan -> [ConfiguredPackage]
+ready :: InstallPlan -> [ReadyPackage]
 ready plan = assert check readyPackages
   where
     check = if null readyPackages && null processingPackages
@@ -212,23 +217,37 @@
               else True
     configuredPackages = [ pkg | Configured pkg <- toList plan ]
     processingPackages = [ pkg | Processing pkg <- toList plan]
-    readyPackages = filter (all isInstalled . depends) configuredPackages
-    isInstalled pkg =
-      case PackageIndex.lookupPackageId (planIndex plan) pkg of
-        Just (Configured  _) -> False
-        Just (Processing  _) -> False
-        Just (Failed    _ _) -> internalError depOnFailed
-        Just (PreExisting _) -> True
-        Just (Installed _ _) -> True
-        Nothing              -> internalError incomplete
+
+    readyPackages :: [ReadyPackage]
+    readyPackages =
+      [ ReadyPackage srcPkg flags stanzas deps
+      | pkg@(ConfiguredPackage srcPkg flags stanzas _) <- configuredPackages
+        -- select only the package that have all of their deps installed:
+      , deps <- maybeToList (hasAllInstalledDeps pkg)
+      ]
+
+    hasAllInstalledDeps :: ConfiguredPackage -> Maybe [Installed.InstalledPackageInfo]
+    hasAllInstalledDeps = mapM isInstalledDep . depends
+
+    isInstalledDep :: PackageIdentifier -> Maybe Installed.InstalledPackageInfo
+    isInstalledDep pkgid =
+      case PackageIndex.lookupPackageId (planIndex plan) pkgid of
+        Just (Configured  _)                            -> Nothing
+        Just (Processing  _)                            -> Nothing
+        Just (Failed    _ _)                            -> internalError depOnFailed
+        Just (PreExisting (InstalledPackage instPkg _)) -> Just instPkg
+        Just (Installed _ (BuildOk _ _ (Just instPkg))) -> Just instPkg
+        Just (Installed _ (BuildOk _ _ Nothing))        -> internalError depOnNonLib
+        Nothing                                         -> internalError incomplete
     incomplete  = "install plan is not closed"
     depOnFailed = "configured package depends on failed package"
+    depOnNonLib = "configured package depends on a non-library package"
 
 -- | Marks packages in the graph as currently processing (e.g. building).
 --
 -- * The package must exist in the graph and be in the configured state.
 --
-processing :: [ConfiguredPackage] -> InstallPlan -> InstallPlan
+processing :: [ReadyPackage] -> InstallPlan -> InstallPlan
 processing pkgs plan = assert (invariant plan') plan'
   where
     plan' = plan {
@@ -270,7 +289,7 @@
                }
     pkg      = lookupProcessingPackage plan pkgid
     failures = PackageIndex.fromList
-             $ Failed pkg buildResult
+             $ Failed (readyPackageToConfiguredPackage pkg) buildResult
              : [ Failed pkg' buildResult'
                | Just pkg' <- map checkConfiguredPackage
                             $ packagesThatDependOn plan pkgid ]
@@ -287,7 +306,7 @@
 -- | Lookup a package that we expect to be in the processing state.
 --
 lookupProcessingPackage :: InstallPlan
-                        -> PackageIdentifier -> ConfiguredPackage
+                        -> PackageIdentifier -> ReadyPackage
 lookupProcessingPackage plan pkgid =
   case PackageIndex.lookupPackageId (planIndex plan) pkgid of
     Just (Processing pkg) -> pkg
@@ -302,7 +321,7 @@
   internalError $ "not configured or no such pkg " ++ display (packageId pkg)
 
 -- ------------------------------------------------------------
--- * Checking valididy of plans
+-- * Checking validity of plans
 -- ------------------------------------------------------------
 
 -- | A valid installation plan is a set of packages that is 'acyclic',
@@ -330,7 +349,7 @@
 
 showPlanProblem (PackageMissingDeps pkg missingDeps) =
      "Package " ++ display (packageId pkg)
-  ++ " depends on the following packages which are missing from the plan "
+  ++ " depends on the following packages which are missing from the plan: "
   ++ intercalate ", " (map display missingDeps)
 
 showPlanProblem (PackageCycle cycleGroup) =
@@ -409,11 +428,11 @@
 -- most one version of any package in the set. It only requires that of
 -- packages which have more than one other package depending on them. We could
 -- actually make the condition even more precise and say that different
--- versions are ok so long as they are not both in the transitive closure of
+-- versions are OK so long as they are not both in the transitive closure of
 -- any other package (or equivalently that their inverse closures do not
 -- intersect). The point is we do not want to have any packages depending
 -- directly or indirectly on two different versions of the same package. The
--- current definition is just a safe aproximation of that.
+-- current definition is just a safe approximation of that.
 --
 -- * if the result is @False@ use 'PackageIndex.dependencyInconsistencies' to
 --   find out which packages are.
diff --git a/Distribution/Client/InstallSymlink.hs b/Distribution/Client/InstallSymlink.hs
--- a/Distribution/Client/InstallSymlink.hs
+++ b/Distribution/Client/InstallSymlink.hs
@@ -35,7 +35,7 @@
 #else
 
 import Distribution.Client.Types
-         ( SourcePackage(..), ConfiguredPackage(..), enableStanzas )
+         ( SourcePackage(..), ReadyPackage(..), enableStanzas )
 import Distribution.Client.Setup
          ( InstallFlags(installSymlinkBinDir) )
 import qualified Distribution.Client.InstallPlan as InstallPlan
@@ -77,18 +77,18 @@
 -- directory will be on the user's PATH. However some people are a bit nervous
 -- about letting a package manager install programs into @~/bin/@.
 --
--- A comprimise solution is that instead of installing binaries directly into
+-- A compromise solution is that instead of installing binaries directly into
 -- @~/bin/@, we could install them in a private location under @~/.cabal/bin@
 -- and then create symlinks in @~/bin/@. We can be careful when setting up the
 -- symlinks that we do not overwrite any binary that the user installed. We can
 -- check if it was a symlink we made because it would point to the private dir
 -- where we install our binaries. This means we can install normally without
 -- worrying and in a later phase set up symlinks, and if that fails then we
--- report it to the user, but even in this case the package is still in an ok
+-- report it to the user, but even in this case the package is still in an OK
 -- installed state.
 --
 -- This is an optional feature that users can choose to use or not. It is
--- controlled from the config file. Of course it only works on posix systems
+-- controlled from the config file. Of course it only works on POSIX systems
 -- with symlinks so is not available to Windows users.
 --
 symlinkBinaries :: ConfigFlags
@@ -127,12 +127,12 @@
       , exe <- PackageDescription.executables pkg
       , PackageDescription.buildable (PackageDescription.buildInfo exe) ]
 
-    pkgDescription :: ConfiguredPackage -> PackageDescription
-    pkgDescription (ConfiguredPackage (SourcePackage _ pkg _ _) flags stanzas _) =
+    pkgDescription :: ReadyPackage -> PackageDescription
+    pkgDescription (ReadyPackage (SourcePackage _ pkg _ _) flags stanzas _) =
       case finalizePackageDescription flags
              (const True)
              platform compilerId [] (enableStanzas stanzas pkg) of
-        Left _ -> error "finalizePackageDescription ConfiguredPackage failed"
+        Left _ -> error "finalizePackageDescription ReadyPackage failed"
         Right (desc, _) -> desc
 
     -- This is sadly rather complicated. We're kind of re-doing part of the
@@ -168,7 +168,7 @@
                           --   bin dir, eg @foo@
               -> String   -- ^ The name of the executable to in the private bin
                           --   dir, eg @foo-1.0@
-              -> IO Bool  -- ^ If creating the symlink was sucessful. @False@
+              -> IO Bool  -- ^ If creating the symlink was successful. @False@
                           --   if there was another file there already that we
                           --   did not own. Other errors like permission errors
                           --   just propagate as exceptions.
@@ -185,11 +185,11 @@
                                 (publicBindir   </> publicName)
     rmLink = removeLink (publicBindir </> publicName)
 
--- | Check a filepath of a symlink that we would like to create to see if it
--- is ok. For it to be ok to overwrite it must either not already exist yet or
+-- | Check a file path of a symlink that we would like to create to see if it
+-- is OK. For it to be OK to overwrite it must either not already exist yet or
 -- be a symlink to our target (in which case we can assume ownership).
 --
-targetOkToOverwrite :: FilePath -- ^ The filepath of the symlink to the private
+targetOkToOverwrite :: FilePath -- ^ The file path of the symlink to the private
                                 -- binary that we would like to create
                     -> FilePath -- ^ The canonical path of the private binary.
                                 -- Use 'canonicalizePath' to make this.
@@ -214,7 +214,7 @@
 data SymlinkStatus
    = NotExists     -- ^ The file doesn't exist so we can make a symlink.
    | OkToOverwrite -- ^ A symlink already exists, though it is ours. We'll
-                   -- have to delete it first bemore we make a new symlink.
+                   -- have to delete it first before we make a new symlink.
    | NotOurFile    -- ^ A file already exists and it is not one of our existing
                    -- symlinks (either because it is not a symlink or because
                    -- it points somewhere other than our managed space).
diff --git a/Distribution/Client/List.hs b/Distribution/Client/List.hs
--- a/Distribution/Client/List.hs
+++ b/Distribution/Client/List.hs
@@ -70,17 +70,16 @@
          ( doesDirectoryExist )
 
 
--- |Show information about packages
-list :: Verbosity
-     -> PackageDBStack
-     -> [Repo]
-     -> Compiler
-     -> ProgramConfiguration
-     -> ListFlags
-     -> [String]
-     -> IO ()
-list verbosity packageDBs repos comp conf listFlags pats = do
-
+-- | Return a list of packages matching given search strings.
+getPkgList :: Verbosity
+           -> PackageDBStack
+           -> [Repo]
+           -> Compiler
+           -> ProgramConfiguration
+           -> ListFlags
+           -> [String]
+           -> IO [PackageDisplayInfo]
+getPkgList verbosity packageDBs repos comp conf listFlags pats = do
     installedPkgIndex <- getInstalledPackages verbosity comp packageDBs conf
     sourcePkgDb       <- getSourcePackages    verbosity repos
     let sourcePkgIndex = packageIndex sourcePkgDb
@@ -104,7 +103,27 @@
                   , not onlyInstalled || not (null installedPkgs)
                   , let pref        = prefs pkgname
                         selectedPkg = latestWithPref pref sourcePkgs ]
+    return matches
+  where
+    onlyInstalled = fromFlag (listInstalled listFlags)
+    matchingPackages search index =
+      [ pkg
+      | pat <- pats
+      , pkg <- search index pat ]
 
+
+-- | Show information about packages.
+list :: Verbosity
+     -> PackageDBStack
+     -> [Repo]
+     -> Compiler
+     -> ProgramConfiguration
+     -> ListFlags
+     -> [String]
+     -> IO ()
+list verbosity packageDBs repos comp conf listFlags pats = do
+    matches <- getPkgList verbosity packageDBs repos comp conf listFlags pats
+
     if simpleOutput
       then putStr $ unlines
              [ display (pkgName pkg) ++ " " ++ display version
@@ -124,11 +143,6 @@
     onlyInstalled = fromFlag (listInstalled listFlags)
     simpleOutput  = fromFlag (listSimpleOutput listFlags)
 
-    matchingPackages search index =
-      [ pkg
-      | pat <- pats
-      , pkg <- search index pat ]
-
 info :: Verbosity
      -> PackageDBStack
      -> [Repo]
@@ -226,7 +240,7 @@
 
 
 -- | The info that we can display for each package. It is information per
--- package name and covers all installed and avilable versions.
+-- package name and covers all installed and available versions.
 --
 data PackageDisplayInfo = PackageDisplayInfo {
     pkgName           :: PackageName,
diff --git a/Distribution/Client/PackageIndex.hs b/Distribution/Client/PackageIndex.hs
--- a/Distribution/Client/PackageIndex.hs
+++ b/Distribution/Client/PackageIndex.hs
@@ -76,7 +76,7 @@
 
 -- | The collection of information about packages from one or more 'PackageDB's.
 --
--- It can be searched effeciently by package name and version.
+-- It can be searched efficiently by package name and version.
 --
 newtype PackageIndex pkg = PackageIndex
   -- This index package names to all the package records matching that package
@@ -89,6 +89,9 @@
 
   deriving (Show, Read)
 
+instance Functor PackageIndex where
+  fmap f (PackageIndex m) = PackageIndex (fmap (map f) m)
+
 instance Package pkg => Monoid (PackageIndex pkg) where
   mempty  = PackageIndex Map.empty
   mappend = merge
@@ -282,12 +285,12 @@
 
 -- | Does a case-insensitive search by package name.
 --
--- If there is only one package that compares case-insentiviely to this name
+-- If there is only one package that compares case-insensitively to this name
 -- then the search is unambiguous and we get back all versions of that package.
--- If several match case-insentiviely but one matches exactly then it is also
+-- If several match case-insensitively but one matches exactly then it is also
 -- unambiguous.
 --
--- If however several match case-insentiviely and none match exactly then we
+-- If however several match case-insensitively and none match exactly then we
 -- have an ambiguous result, and we get back all the versions of all the
 -- packages. The list of ambiguous results is split by exact package name. So
 -- it is a non-empty list of non-empty lists.
diff --git a/Distribution/Client/ParseUtils.hs b/Distribution/Client/ParseUtils.hs
--- a/Distribution/Client/ParseUtils.hs
+++ b/Distribution/Client/ParseUtils.hs
@@ -16,7 +16,7 @@
          ( Field(..) )
 
 import Control.Monad    ( foldM )
-import Text.PrettyPrint ( (<>), (<+>), ($$) )
+import Text.PrettyPrint ( (<>), (<+>), ($+$) )
 import qualified Data.Map as Map
 import qualified Text.PrettyPrint as Disp
          ( Doc, text, colon, vcat, empty, isEmpty, nest )
@@ -52,6 +52,11 @@
   | otherwise        = Disp.text name <> Disp.colon <+> cur
 
 ppSection :: String -> String -> [FieldDescr a] -> (Maybe a) -> a -> Disp.Doc
-ppSection name arg fields def cur =
-     Disp.text name <+> Disp.text arg
-  $$ Disp.nest 2 (ppFields fields def cur)
+ppSection name arg fields def cur
+  | Disp.isEmpty fieldsDoc = Disp.empty
+  | otherwise              = Disp.text name <+> argDoc
+                             $+$ (Disp.nest 2 fieldsDoc)
+  where
+    fieldsDoc = ppFields fields def cur
+    argDoc | arg == "" = Disp.empty
+           | otherwise = Disp.text arg
diff --git a/Distribution/Client/Sandbox.hs b/Distribution/Client/Sandbox.hs
--- a/Distribution/Client/Sandbox.hs
+++ b/Distribution/Client/Sandbox.hs
@@ -33,6 +33,7 @@
     tryGetIndexFilePath,
     sandboxBuildDir,
     getInstalledPackagesInSandbox,
+    updateSandboxConfigFileFlag,
 
     -- FIXME: move somewhere else
     configPackageDB', configCompilerAux'
@@ -77,9 +78,9 @@
 import Distribution.Simple.Setup              ( Flag(..), HaddockFlags(..)
                                               , fromFlagOrDefault )
 import Distribution.Simple.SrcDist            ( prepareTree )
-import Distribution.Simple.Utils              ( die, debug, notice, warn
+import Distribution.Simple.Utils              ( die, debug, notice, info, warn
                                               , debugNoWrap, defaultPackageDesc
-                                              , findPackageDesc
+                                              , tryFindPackageDesc
                                               , intercalate, topHandlerWith
                                               , createDirectoryIfMissingVerbose )
 import Distribution.Package                   ( Package(..) )
@@ -99,7 +100,7 @@
 import Data.Char                              ( ord )
 import Data.IORef                             ( newIORef, writeIORef, readIORef )
 import Data.List                              ( delete, foldl' )
-import Data.Maybe                             ( fromJust )
+import Data.Maybe                             ( fromJust, fromMaybe )
 import Data.Monoid                            ( mempty, mappend )
 import Data.Word                              ( Word32 )
 import Numeric                                ( showHex )
@@ -154,14 +155,17 @@
 -- * Basic sandbox functions.
 --
 
--- | Return the path to the package environment directory - either the current
--- directory or the one that @--sandbox-config-file@ resides in.
-getPkgEnvDir :: GlobalFlags -> IO FilePath
-getPkgEnvDir globalFlags = do
-  let sandboxConfigFileFlag = globalSandboxConfigFile globalFlags
-  case sandboxConfigFileFlag of
-    NoFlag    -> getCurrentDirectory
-    Flag path -> tryCanonicalizePath . takeDirectory $ path
+-- | If @--sandbox-config-file@ wasn't given on the command-line, set it to the
+-- value of the @CABAL_SANDBOX_CONFIG@ environment variable, or else to
+-- 'NoFlag'.
+updateSandboxConfigFileFlag :: GlobalFlags -> IO GlobalFlags
+updateSandboxConfigFileFlag globalFlags =
+  case globalSandboxConfigFile globalFlags of
+    Flag _ -> return globalFlags
+    NoFlag -> do
+      f' <- fmap (fromMaybe NoFlag . fmap Flag) . lookupEnv
+            $ "CABAL_SANDBOX_CONFIG"
+      return globalFlags { globalSandboxConfigFile = f' }
 
 -- | Return the path to the sandbox config file - either the default or the one
 -- specified with @--sandbox-config-file@.
@@ -265,14 +269,14 @@
   when packageDBExists $
     debug verbosity $ "The package database already exists: " ++ dbPath
 
--- | Entry point for the 'cabal dump-pkgenv' command.
+-- | Entry point for the 'cabal sandbox dump-pkgenv' command.
 dumpPackageEnvironment :: Verbosity -> SandboxFlags -> GlobalFlags -> IO ()
 dumpPackageEnvironment verbosity _sandboxFlags globalFlags = do
   (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags
   commentPkgEnv        <- commentPackageEnvironment sandboxDir
   putStrLn . showPackageEnvironmentWithComments (Just commentPkgEnv) $ pkgEnv
 
--- | Entry point for the 'cabal sandbox-init' command.
+-- | Entry point for the 'cabal sandbox init' command.
 sandboxInit :: Verbosity -> SandboxFlags  -> GlobalFlags -> IO ()
 sandboxInit verbosity sandboxFlags globalFlags = do
   -- Warn if there's a 'cabal-dev' sandbox.
@@ -316,7 +320,7 @@
   maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile
     (compilerId comp) platform
 
--- | Entry point for the 'cabal sandbox-delete' command.
+-- | Entry point for the 'cabal sandbox delete' command.
 sandboxDelete :: Verbosity -> SandboxFlags -> GlobalFlags -> IO ()
 sandboxDelete verbosity _sandboxFlags globalFlags = do
   (useSandbox, _) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
@@ -458,8 +462,8 @@
     notice verbosity $ "\nTo unregister source dependencies, "
                        ++ "use the 'sandbox delete-source' command."
 
--- | Invoke the @hc-pkg@ tool with provided arguments, restricted to the
--- sandbox.
+-- | Entry point for the 'cabal sandbox hc-pkg' command. Invokes the @hc-pkg@
+-- tool with provided arguments, restricted to the sandbox.
 sandboxHcPkg :: Verbosity -> SandboxFlags -> GlobalFlags -> [String] -> IO ()
 sandboxHcPkg verbosity _sandboxFlags globalFlags extraArgs = do
   (_sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags
@@ -478,14 +482,13 @@
                              -> Flag Bool    -- ^ Ignored if we're in a sandbox.
                              -> IO (UseSandbox, SavedConfig)
 loadConfigOrSandboxConfig verbosity globalFlags userInstallFlag = do
-  let configFileFlag        = globalConfigFile globalFlags
+  let configFileFlag        = globalConfigFile        globalFlags
       sandboxConfigFileFlag = globalSandboxConfigFile globalFlags
-
-  pkgEnvDir  <- getPkgEnvDir globalFlags
-  pkgEnvType <- case sandboxConfigFileFlag of
-    NoFlag -> classifyPackageEnvironment pkgEnvDir
-    Flag _ -> return SandboxPackageEnvironment
+      ignoreSandboxFlag     = globalIgnoreSandbox globalFlags
 
+  pkgEnvDir  <- getPkgEnvDir sandboxConfigFileFlag
+  pkgEnvType <- classifyPackageEnvironment pkgEnvDir sandboxConfigFileFlag
+                                           ignoreSandboxFlag
   case pkgEnvType of
     -- A @cabal.sandbox.config@ file (and possibly @cabal.config@) is present.
     SandboxPackageEnvironment -> do
@@ -498,13 +501,36 @@
     UserPackageEnvironment    -> do
       config <- loadConfig verbosity configFileFlag userInstallFlag
       userConfig <- loadUserConfig verbosity pkgEnvDir
-      return (NoSandbox, config `mappend` userConfig)
+      let config' = config `mappend` userConfig
+      dieIfSandboxRequired config'
+      return (NoSandbox, config')
 
     -- Neither @cabal.sandbox.config@ nor @cabal.config@ are present.
     AmbientPackageEnvironment -> do
       config <- loadConfig verbosity configFileFlag userInstallFlag
+      dieIfSandboxRequired config
       return (NoSandbox, config)
 
+  where
+    -- Return the path to the package environment directory - either the
+    -- current directory or the one that @--sandbox-config-file@ resides in.
+    getPkgEnvDir :: (Flag FilePath) -> IO FilePath
+    getPkgEnvDir sandboxConfigFileFlag = do
+      case sandboxConfigFileFlag of
+        NoFlag    -> getCurrentDirectory
+        Flag path -> tryCanonicalizePath . takeDirectory $ path
+
+    -- Die if @--require-sandbox@ was specified and we're not inside a sandbox.
+    dieIfSandboxRequired :: SavedConfig -> IO ()
+    dieIfSandboxRequired config = checkFlag flag
+      where
+        flag = (globalRequireSandbox . savedGlobalFlags $ config)
+               `mappend` (globalRequireSandbox globalFlags)
+        checkFlag (Flag True)  =
+          die $ "'require-sandbox' is set to True, but no sandbox is present."
+        checkFlag (Flag False) = return ()
+        checkFlag (NoFlag)     = return ()
+
 -- | If we're in a sandbox, call @withSandboxBinDirOnSearchPath@, otherwise do
 -- nothing.
 maybeWithSandboxDirOnSearchPath :: UseSandbox -> IO a -> IO a
@@ -594,7 +620,7 @@
                        configFlags comp conf
 
   -- Get the package descriptions for all add-source deps.
-  depsCabalFiles <- mapM findPackageDesc buildTreeRefs
+  depsCabalFiles <- mapM tryFindPackageDesc buildTreeRefs
   depsPkgDescs   <- mapM (readPackageDescription verbosity) depsCabalFiles
   let depsMap           = M.fromList (zip buildTreeRefs depsPkgDescs)
       isInstalled pkgid = not . null
@@ -611,9 +637,10 @@
       modifiedDepsMap = M.fromList modifiedDeps
 
   assert (all (`S.member` allAddSourceDepsSet) modifiedAddSourceDeps) (return ())
-  unless (null modifiedDeps) $
-    notice verbosity $ "Some add-source dependencies have been modified. "
-                       ++ "They will be reinstalled..."
+  if (null modifiedDeps)
+    then info   verbosity $ "Found no modified add-source deps."
+    else notice verbosity $ "Some add-source dependencies have been modified. "
+                            ++ "They will be reinstalled..."
 
   -- Get the package ids of the remaining add-source deps (some are possibly not
   -- installed).
@@ -650,19 +677,16 @@
                                -> ConfigFlags      -- ^ Saved configure flags
                                                    -- (from dist/setup-config)
                                -> GlobalFlags
-                               -> IO (UseSandbox, WereDepsReinstalled)
+                               -> IO (UseSandbox, SavedConfig
+                                     ,WereDepsReinstalled)
 maybeReinstallAddSourceDeps verbosity numJobsFlag configFlags' globalFlags' = do
-  currentDir <- getCurrentDirectory
-  pkgEnvType <- classifyPackageEnvironment currentDir
-  case pkgEnvType of
-    AmbientPackageEnvironment -> return (NoSandbox, NoDepsReinstalled)
-    UserPackageEnvironment    -> return (NoSandbox, NoDepsReinstalled)
-    SandboxPackageEnvironment -> do
-      (sandboxDir, pkgEnv)    <- tryLoadSandboxConfig verbosity globalFlags'
-
-      -- Actually reinstall the modified add-source deps.
-      let config         = pkgEnvSavedConfig pkgEnv
-          configFlags    = savedConfigureFlags config
+  (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags'
+                          (configUserInstall configFlags')
+  case useSandbox of
+    NoSandbox             -> return (NoSandbox, config, NoDepsReinstalled)
+    UseSandbox sandboxDir -> do
+      -- Reinstall the modified add-source deps.
+      let configFlags    = savedConfigureFlags config
                            `mappendSomeSavedFlags`
                            configFlags'
           configExFlags  = defaultConfigExFlags
@@ -681,7 +705,7 @@
       depsReinstalled <- reinstallAddSourceDeps verbosity
                          configFlags configExFlags installFlags globalFlags
                          sandboxDir
-      return (UseSandbox sandboxDir, depsReinstalled)
+      return (UseSandbox sandboxDir, config, depsReinstalled)
 
   where
 
@@ -702,10 +726,11 @@
         configProgramPaths = configProgramPaths sandboxConfigFlags
                              `mappend` configProgramPaths savedFlags,
         configProgramArgs  = configProgramArgs sandboxConfigFlags
-                             `mappend` configProgramArgs savedFlags
-        -- NOTE: We don't touch the @configPackageDBs@ field because
-        -- @sandboxConfigFlags@ contains the sandbox location which was set when
-        -- creating @cabal.sandbox.config@.
+                             `mappend` configProgramArgs savedFlags,
+        -- NOTE: Unconditionally choosing the value from
+        -- 'dist/setup-config'. Sandbox package DB location may have been
+        -- changed by 'configure -w'.
+        configPackageDBs   = configPackageDBs savedFlags
         -- FIXME: Is this compatible with the 'inherit' feature?
         }
 
diff --git a/Distribution/Client/Sandbox/Index.hs b/Distribution/Client/Sandbox/Index.hs
--- a/Distribution/Client/Sandbox/Index.hs
+++ b/Distribution/Client/Sandbox/Index.hs
@@ -31,7 +31,7 @@
                                  , makeAbsoluteToCwd, tryCanonicalizePath
                                  , canonicalizePathNoThrow )
 
-import Distribution.Simple.Utils ( die, debug, findPackageDesc )
+import Distribution.Simple.Utils ( die, debug, tryFindPackageDesc )
 import Distribution.Verbosity    ( Verbosity )
 
 import qualified Data.ByteString.Lazy as BS
@@ -61,7 +61,7 @@
   dirExists <- doesDirectoryExist dir
   unless dirExists $
     die $ "directory '" ++ dir ++ "' does not exist"
-  _ <- findPackageDesc dir
+  _ <- tryFindPackageDesc dir
   return . Just $ BuildTreeRef refType dir
 
 -- | Given a tar archive entry, try to parse it as a local build tree reference.
diff --git a/Distribution/Client/Sandbox/PackageEnvironment.hs b/Distribution/Client/Sandbox/PackageEnvironment.hs
--- a/Distribution/Client/Sandbox/PackageEnvironment.hs
+++ b/Distribution/Client/Sandbox/PackageEnvironment.hs
@@ -19,6 +19,7 @@
   , showPackageEnvironment
   , showPackageEnvironmentWithComments
   , setPackageDB
+  , sandboxPackageDBPath
   , loadUserConfig
 
   , basePackageEnvironment
@@ -28,9 +29,12 @@
   , userPackageEnvironmentFile
   ) where
 
-import Distribution.Client.Config      ( SavedConfig(..), commentSavedConfig,
-                                         loadConfig, configFieldDescriptions,
-                                         installDirsFields, defaultCompiler )
+import Distribution.Client.Config      ( SavedConfig(..), commentSavedConfig
+                                       , loadConfig, configFieldDescriptions
+                                       , haddockFlagsFields
+                                       , installDirsFields, withProgramsFields
+                                       , withProgramOptionsFields
+                                       , defaultCompiler )
 import Distribution.Client.ParseUtils  ( parseFields, ppFields, ppSection )
 import Distribution.Client.Setup       ( GlobalFlags(..), ConfigExFlags(..)
                                        , InstallFlags(..)
@@ -40,22 +44,25 @@
 import Distribution.Simple.InstallDirs ( InstallDirs(..), PathTemplate
                                        , defaultInstallDirs, combineInstallDirs
                                        , fromPathTemplate, toPathTemplate )
-import Distribution.Simple.Setup       ( Flag(..), ConfigFlags(..),
-                                         fromFlagOrDefault, toFlag )
-import Distribution.Simple.Utils       ( die, info, notice, warn, lowercase )
-import Distribution.ParseUtils         ( FieldDescr(..), ParseResult(..),
-                                         commaListField,
-                                         liftField, lineNo, locatedErrorMsg,
-                                         parseFilePathQ, readFields,
-                                         showPWarning, simpleField, syntaxError )
+import Distribution.Simple.Setup       ( Flag(..)
+                                       , ConfigFlags(..), HaddockFlags(..)
+                                       , fromFlagOrDefault, toFlag, flagToMaybe )
+import Distribution.Simple.Utils       ( die, info, notice, warn )
+import Distribution.ParseUtils         ( FieldDescr(..), ParseResult(..)
+                                       , commaListField, commaNewLineListField
+                                       , liftField, lineNo, locatedErrorMsg
+                                       , parseFilePathQ, readFields
+                                       , showPWarning, simpleField
+                                       , syntaxError, warning )
 import Distribution.System             ( Platform )
 import Distribution.Verbosity          ( Verbosity, normal )
-import Control.Monad                   ( foldM, when, unless )
+import Control.Monad                   ( foldM, liftM2, when, unless )
 import Data.List                       ( partition )
+import Data.Maybe                      ( isJust )
 import Data.Monoid                     ( Monoid(..) )
 import Distribution.Compat.Exception   ( catchIO )
-import System.Directory                ( doesDirectoryExist, doesFileExist,
-                                         renameFile )
+import System.Directory                ( doesDirectoryExist, doesFileExist
+                                       , renameFile )
 import System.FilePath                 ( (<.>), (</>), takeDirectory )
 import System.IO.Error                 ( isDoesNotExistError )
 import Text.PrettyPrint                ( ($+$) )
@@ -110,17 +117,24 @@
 
 -- | Is there a 'cabal.sandbox.config' or 'cabal.config' in this
 -- directory?
-classifyPackageEnvironment :: FilePath -> IO PackageEnvironmentType
-classifyPackageEnvironment pkgEnvDir = do
-  isSandbox <- configExists sandboxPackageEnvironmentFile
-  isUser    <- configExists userPackageEnvironmentFile
-  case (isSandbox, isUser) of
-    (True,  _)     -> return SandboxPackageEnvironment
-    (False, True)  -> return UserPackageEnvironment
-    (False, False) -> return AmbientPackageEnvironment
+classifyPackageEnvironment :: FilePath -> Flag FilePath -> Flag Bool
+                              -> IO PackageEnvironmentType
+classifyPackageEnvironment pkgEnvDir sandboxConfigFileFlag ignoreSandboxFlag =
+  do isSandbox <- liftM2 (||) (return forceSandboxConfig)
+                  (configExists sandboxPackageEnvironmentFile)
+     isUser    <- configExists userPackageEnvironmentFile
+     return (classify isSandbox isUser)
   where
-    configExists fname = doesFileExist (pkgEnvDir </> fname)
+    configExists fname   = doesFileExist (pkgEnvDir </> fname)
+    ignoreSandbox        = fromFlagOrDefault False ignoreSandboxFlag
+    forceSandboxConfig   = isJust . flagToMaybe $ sandboxConfigFileFlag
 
+    classify :: Bool -> Bool -> PackageEnvironmentType
+    classify True _
+      | not ignoreSandbox = SandboxPackageEnvironment
+    classify _    True    = UserPackageEnvironment
+    classify _    False   = AmbientPackageEnvironment
+
 -- | Defaults common to 'initialPackageEnvironment' and
 -- 'commentPackageEnvironment'.
 commonPackageEnvironmentConfig :: FilePath -> SavedConfig
@@ -197,14 +211,23 @@
        }
     }
 
+-- | Return the path to the sandbox package database.
+sandboxPackageDBPath :: FilePath -> Compiler -> Platform -> String
+sandboxPackageDBPath sandboxDir compiler platform =
+    sandboxDir
+         </> (Text.display platform ++ "-"
+             ++ showCompilerId compiler
+             ++ "-packages.conf.d")
+
+
 -- | Use the package DB location specific for this compiler.
 setPackageDB :: FilePath -> Compiler -> Platform -> ConfigFlags -> ConfigFlags
 setPackageDB sandboxDir compiler platform configFlags =
   configFlags {
-    configPackageDBs = [Just (SpecificPackageDB $ sandboxDir
-                              </> (Text.display platform ++ "-"
-                                   ++ showCompilerId compiler
-                                   ++ "-packages.conf.d"))]
+    configPackageDBs = [Just (SpecificPackageDB $ sandboxPackageDBPath
+                                                      sandboxDir
+                                                      compiler
+                                                      platform)]
     }
 
 -- | Almost the same as 'savedConf `mappend` pkgEnv', but some settings are
@@ -320,7 +343,8 @@
   inherited <- inheritedPackageEnvironment verbosity user
 
   -- Layer the package environment settings over settings from ~/.cabal/config.
-  cabalConfig <- loadConfig verbosity configFileFlag NoFlag
+  cabalConfig <- fmap unsetSymlinkBinDir $
+                 loadConfig verbosity configFileFlag NoFlag
   return (sandboxDir,
           updateInstallDirs $
           (base `mappend` (toPkgEnv cabalConfig) `mappend`
@@ -330,8 +354,8 @@
       toPkgEnv config = mempty { pkgEnvSavedConfig = config }
 
       updateInstallDirs pkgEnv =
-        let config         = pkgEnvSavedConfig pkgEnv
-            configureFlags = savedConfigureFlags config
+        let config         = pkgEnvSavedConfig    pkgEnv
+            configureFlags = savedConfigureFlags  config
             installDirs    = savedUserInstallDirs config
         in pkgEnv {
           pkgEnvSavedConfig = config {
@@ -341,6 +365,16 @@
              }
           }
 
+      -- We don't want to inherit the value of 'symlink-bindir' from
+      -- '~/.cabal/config'. See #1514.
+      unsetSymlinkBinDir config =
+        let installFlags = savedInstallFlags config
+        in config {
+          savedInstallFlags = installFlags {
+             installSymlinkBinDir = NoFlag
+             }
+          }
+
 -- | Should the generated package environment file include comments?
 data IncludeComments = IncludeComments | NoComments
 
@@ -368,7 +402,7 @@
     pkgEnvInherit (\v pkgEnv -> pkgEnv { pkgEnvInherit = v })
 
     -- FIXME: Should we make these fields part of ~/.cabal/config ?
-  , commaListField "constraints"
+  , commaNewLineListField "constraints"
     Text.disp Text.parse
     (configExConstraints . savedConfigureExFlags . pkgEnvSavedConfig)
     (\v pkgEnv -> updateConfigureExFlags pkgEnv
@@ -426,10 +460,20 @@
   pkgEnv <- parse others
   let config       = pkgEnvSavedConfig pkgEnv
       installDirs0 = savedUserInstallDirs config
-  -- 'install-dirs' is the only section that we care about.
-  installDirs <- foldM parseSection installDirs0 knownSections
+  (haddockFlags, installDirs, paths, args) <-
+    foldM parseSections
+    (savedHaddockFlags config, installDirs0, [], [])
+    knownSections
   return pkgEnv {
     pkgEnvSavedConfig = config {
+       savedConfigureFlags    = (savedConfigureFlags config) {
+          configProgramPaths  = paths,
+          configProgramArgs   = args
+          },
+       savedHaddockFlags      = haddockFlags {
+         haddockProgramPaths  = paths,
+         haddockProgramArgs   = args
+         },
        savedUserInstallDirs   = installDirs,
        savedGlobalInstallDirs = installDirs
        }
@@ -437,26 +481,54 @@
 
   where
     isKnownSection :: ParseUtils.Field -> Bool
-    isKnownSection (ParseUtils.Section _ "install-dirs" _ _) = True
-    isKnownSection _                                         = False
+    isKnownSection (ParseUtils.Section _ "haddock" _ _)                 = True
+    isKnownSection (ParseUtils.Section _ "install-dirs" _ _)            = True
+    isKnownSection (ParseUtils.Section _ "program-locations" _ _)       = True
+    isKnownSection (ParseUtils.Section _ "program-default-options" _ _) = True
+    isKnownSection _                                                    = False
 
     parse :: [ParseUtils.Field] -> ParseResult PackageEnvironment
     parse = parseFields pkgEnvFieldDescrs initial
 
-    parseSection :: InstallDirs (Flag PathTemplate)
-                    -> ParseUtils.Field
-                    -> ParseResult (InstallDirs (Flag PathTemplate))
-    parseSection accum (ParseUtils.Section line "install-dirs" name fs)
-      | name' == "" = do accum' <- parseFields installDirsFields accum fs
-                         return accum'
-      | otherwise   =
+    parseSections :: SectionsAccum -> ParseUtils.Field
+                     -> ParseResult SectionsAccum
+    parseSections accum@(h,d,p,a)
+                 (ParseUtils.Section _ "haddock" name fs)
+      | name == "" = do h' <- parseFields haddockFlagsFields h fs
+                        return (h', d, p, a)
+      | otherwise  = do
+          warning "The 'haddock' section should be unnamed"
+          return accum
+    parseSections (h,d,p,a)
+                  (ParseUtils.Section line "install-dirs" name fs)
+      | name == "" = do d' <- parseFields installDirsFields d fs
+                        return (h, d',p,a)
+      | otherwise  =
         syntaxError line $
         "Named 'install-dirs' section: '" ++ name
         ++ "'. Note that named 'install-dirs' sections are not allowed in the '"
         ++ userPackageEnvironmentFile ++ "' file."
-      where name' = lowercase name
-    parseSection _accum f =
-      syntaxError (lineNo f)  "Unrecognized stanza."
+    parseSections accum@(h, d,p,a)
+                  (ParseUtils.Section _ "program-locations" name fs)
+      | name == "" = do p' <- parseFields withProgramsFields p fs
+                        return (h, d, p', a)
+      | otherwise  = do
+          warning "The 'program-locations' section should be unnamed"
+          return accum
+    parseSections accum@(h, d, p, a)
+                  (ParseUtils.Section _ "program-default-options" name fs)
+      | name == "" = do a' <- parseFields withProgramOptionsFields a fs
+                        return (h, d, p, a')
+      | otherwise  = do
+          warning "The 'program-default-options' section should be unnamed"
+          return accum
+    parseSections accum f = do
+      warning $ "Unrecognized stanza on line " ++ show (lineNo f)
+      return accum
+
+-- | Accumulator type for 'parseSections'.
+type SectionsAccum = (HaddockFlags, InstallDirs (Flag PathTemplate)
+                     , [(String, FilePath)], [(String, [String])])
 
 -- | Write out the package environment file.
 writePackageEnvironmentFile :: FilePath -> IncludeComments
diff --git a/Distribution/Client/Sandbox/Timestamp.hs b/Distribution/Client/Sandbox/Timestamp.hs
--- a/Distribution/Client/Sandbox/Timestamp.hs
+++ b/Distribution/Client/Sandbox/Timestamp.hs
@@ -13,7 +13,6 @@
   withRemoveTimestamps,
   withUpdateTimestamps,
   maybeAddCompilerTimestampRecord,
-  isDepModified,
   listModifiedDeps,
   ) where
 
@@ -33,7 +32,7 @@
                                                       defaultSDistFlags,
                                                       sdistCommand)
 import Distribution.Simple.Utils                     (debug, die,
-                                                      findPackageDesc, warn)
+                                                      tryFindPackageDesc, warn)
 import Distribution.System                           (Platform)
 import Distribution.Text                             (display)
 import Distribution.Verbosity                        (Verbosity, lessVerbose,
@@ -215,7 +214,7 @@
 allPackageSourceFiles :: Verbosity -> FilePath -> IO [FilePath]
 allPackageSourceFiles verbosity packageDir = inDir (Just packageDir) $ do
   pkg <- fmap (flattenPackageDescription)
-         . readPackageDescription verbosity =<< findPackageDesc packageDir
+         . readPackageDescription verbosity =<< tryFindPackageDesc packageDir
 
   let file      = "cabal-sdist-list-sources"
       flags     = defaultSDistFlags {
diff --git a/Distribution/Client/Setup.hs b/Distribution/Client/Setup.hs
--- a/Distribution/Client/Setup.hs
+++ b/Distribution/Client/Setup.hs
@@ -11,7 +11,7 @@
 --
 -----------------------------------------------------------------------------
 module Distribution.Client.Setup
-    ( globalCommand, GlobalFlags(..), globalRepos
+    ( globalCommand, GlobalFlags(..), defaultGlobalFlags, globalRepos
     , configureCommand, ConfigFlags(..), filterConfigureFlags
     , configureExCommand, ConfigExFlags(..), defaultConfigExFlags
                         , configureExOptions
@@ -23,8 +23,10 @@
     , upgradeCommand
     , infoCommand, InfoFlags(..)
     , fetchCommand, FetchFlags(..)
+    , freezeCommand, FreezeFlags(..)
     , getCommand, unpackCommand, GetFlags(..)
     , checkCommand
+    , formatCommand
     , uploadCommand, UploadFlags(..)
     , reportCommand, ReportFlags(..)
     , runCommand
@@ -32,6 +34,7 @@
     , sdistCommand, SDistFlags(..), SDistExFlags(..), ArchiveFormat(..)
     , win32SelfUpgradeCommand, Win32SelfUpgradeFlags(..)
     , sandboxCommand, defaultSandboxLocation, SandboxFlags(..)
+    , execCommand, ExecFlags(..)
 
     , parsePackageArgs
     --TODO: stop exporting these:
@@ -44,21 +47,24 @@
 import Distribution.Client.BuildReports.Types
          ( ReportLevel(..) )
 import Distribution.Client.Dependency.Types
-         ( PreSolver(..) )
+         ( AllowNewer(..), PreSolver(..) )
 import qualified Distribution.Client.Init.Types as IT
          ( InitFlags(..), PackageType(..) )
 import Distribution.Client.Targets
          ( UserConstraint, readUserConstraint )
 
+import Distribution.Simple.Compiler (PackageDB)
 import Distribution.Simple.Program
          ( defaultProgramConfiguration )
-import Distribution.Simple.Command hiding (boolOpt)
+import Distribution.Simple.Command hiding (boolOpt, boolOpt')
+import qualified Distribution.Simple.Command as Command
 import qualified Distribution.Simple.Setup as Cabal
 import Distribution.Simple.Setup
          ( ConfigFlags(..), BuildFlags(..), TestFlags(..), BenchmarkFlags(..)
          , SDistFlags(..), HaddockFlags(..)
+         , readPackageDbList, showPackageDbList
          , Flag(..), toFlag, fromFlag, flagToMaybe, flagToList
-         , optionVerbosity, boolOpt, trueArg, falseArg )
+         , optionVerbosity, boolOpt, boolOpt', trueArg, falseArg, optionNumJobs )
 import Distribution.Simple.InstallDirs
          ( PathTemplate, InstallDirs(sysconfdir)
          , toPathTemplate, fromPathTemplate )
@@ -73,7 +79,7 @@
 import Distribution.ReadE
          ( ReadE(..), readP_to_E, succeedReadE )
 import qualified Distribution.Compat.ReadP as Parse
-         ( ReadP, readP_to_S, readS_to_P, char, munch1, pfail, (+++) )
+         ( ReadP, readP_to_S, readS_to_P, char, munch1, pfail, sepBy1, (+++) )
 import Distribution.Verbosity
          ( Verbosity, normal )
 import Distribution.Simple.Utils
@@ -108,7 +114,9 @@
     globalCacheDir          :: Flag FilePath,
     globalLocalRepos        :: [FilePath],
     globalLogsDir           :: Flag FilePath,
-    globalWorldFile         :: Flag FilePath
+    globalWorldFile         :: Flag FilePath,
+    globalRequireSandbox    :: Flag Bool,
+    globalIgnoreSandbox     :: Flag Bool
   }
 
 defaultGlobalFlags :: GlobalFlags
@@ -117,11 +125,13 @@
     globalNumericVersion    = Flag False,
     globalConfigFile        = mempty,
     globalSandboxConfigFile = mempty,
-    globalRemoteRepos       = [],
+    globalRemoteRepos       = mempty,
     globalCacheDir          = mempty,
     globalLocalRepos        = mempty,
     globalLogsDir           = mempty,
-    globalWorldFile         = mempty
+    globalWorldFile         = mempty,
+    globalRequireSandbox    = Flag False,
+    globalIgnoreSandbox     = Flag False
   }
 
 globalCommand :: CommandUI GlobalFlags
@@ -139,9 +149,9 @@
       ++ "  " ++ pname ++ " install foo [--dry-run]\n\n"
       ++ "Occasionally you need to update the list of available packages:\n"
       ++ "  " ++ pname ++ " update\n",
-    commandDefaultFlags = defaultGlobalFlags,
+    commandDefaultFlags = mempty,
     commandOptions      = \showOrParseArgs ->
-      (case showOrParseArgs of ShowArgs -> take 4; ParseArgs -> id)
+      (case showOrParseArgs of ShowArgs -> take 6; ParseArgs -> id)
       [option ['V'] ["version"]
          "Print version information"
          globalVersion (\v flags -> flags { globalVersion = v })
@@ -163,6 +173,16 @@
          globalConfigFile (\v flags -> flags { globalSandboxConfigFile = v })
          (reqArgFlag "FILE")
 
+      ,option [] ["require-sandbox"]
+         "requiring the presence of a sandbox for sandbox-aware commands"
+         globalRequireSandbox (\v flags -> flags { globalRequireSandbox = v })
+         (boolOpt' ([], ["require-sandbox"]) ([], ["no-require-sandbox"]))
+
+      ,option [] ["ignore-sandbox"]
+         "Ignore any existing sandbox"
+         globalIgnoreSandbox (\v flags -> flags { globalIgnoreSandbox = v })
+         trueArg
+
       ,option [] ["remote-repo"]
          "The name and url for a remote repository"
          globalRemoteRepos (\v flags -> flags { globalRemoteRepos = v })
@@ -200,7 +220,9 @@
     globalCacheDir          = mempty,
     globalLocalRepos        = mempty,
     globalLogsDir           = mempty,
-    globalWorldFile         = mempty
+    globalWorldFile         = mempty,
+    globalRequireSandbox    = mempty,
+    globalIgnoreSandbox     = mempty
   }
   mappend a b = GlobalFlags {
     globalVersion           = combine globalVersion,
@@ -211,7 +233,9 @@
     globalCacheDir          = combine globalCacheDir,
     globalLocalRepos        = combine globalLocalRepos,
     globalLogsDir           = combine globalLogsDir,
-    globalWorldFile         = combine globalWorldFile
+    globalWorldFile         = combine globalWorldFile,
+    globalRequireSandbox    = combine globalRequireSandbox,
+    globalIgnoreSandbox     = combine globalIgnoreSandbox
   }
     where combine field = field a `mappend` field b
 
@@ -241,24 +265,32 @@
 
 filterConfigureFlags :: ConfigFlags -> Version -> ConfigFlags
 filterConfigureFlags flags cabalLibVersion
-  | cabalLibVersion >= Version [1,18,0] [] = flags
+  | cabalLibVersion >= Version [1,19,2] [] = flags_latest
   | cabalLibVersion <  Version [1,3,10] [] = flags_1_3_10
   | cabalLibVersion <  Version [1,10,0] [] = flags_1_10_0
   | cabalLibVersion <  Version [1,14,0] [] = flags_1_14_0
   | cabalLibVersion <  Version [1,18,0] [] = flags_1_18_0
-
-  -- A no-op that silences the "pattern match is non-exhaustive" warning.
-  | otherwise = flags
+  | cabalLibVersion <  Version [1,19,1] [] = flags_1_19_0
+  | cabalLibVersion <  Version [1,19,2] [] = flags_1_19_1
+  | otherwise = flags_latest
   where
+    -- Cabal >= 1.19.1 uses '--dependency' and does not need '--constraint'.
+    flags_latest = flags        { configConstraints = [] }
+
+    -- Cabal < 1.19.2 doesn't know about '--exact-configuration'.
+    flags_1_19_1 = flags_latest { configExactConfiguration = NoFlag }
+    -- Cabal < 1.19.1 uses '--constraint' instead of '--dependency'.
+    flags_1_19_0 = flags_1_19_1 { configDependencies = []
+                                , configConstraints  = configConstraints flags }
     -- Cabal < 1.18.0 doesn't know about --extra-prog-path and --sysconfdir.
-    flags_1_18_0 = flags        { configProgramPathExtra = []
+    flags_1_18_0 = flags_1_19_0 { configProgramPathExtra = []
                                 , configInstallDirs = configInstallDirs_1_18_0}
     configInstallDirs_1_18_0 = (configInstallDirs flags) { sysconfdir = NoFlag }
-    -- Cabal < 1.14.0 doesn't know about --disable-benchmarks.
+    -- Cabal < 1.14.0 doesn't know about '--disable-benchmarks'.
     flags_1_14_0 = flags_1_18_0 { configBenchmarks  = NoFlag }
-    -- Cabal < 1.10.0 doesn't know about --disable-tests.
+    -- Cabal < 1.10.0 doesn't know about '--disable-tests'.
     flags_1_10_0 = flags_1_14_0 { configTests       = NoFlag }
-    -- Cabal < 1.3.10 does not grok the constraints flag.
+    -- Cabal < 1.3.10 does not grok the '--constraints' flag.
     flags_1_3_10 = flags_1_10_0 { configConstraints = [] }
 
 -- ------------------------------------------------------------
@@ -271,18 +303,21 @@
     configCabalVersion :: Flag Version,
     configExConstraints:: [UserConstraint],
     configPreferences  :: [Dependency],
-    configSolver       :: Flag PreSolver
+    configSolver       :: Flag PreSolver,
+    configAllowNewer   :: Flag AllowNewer
   }
 
 defaultConfigExFlags :: ConfigExFlags
-defaultConfigExFlags = mempty { configSolver = Flag defaultSolver }
+defaultConfigExFlags = mempty { configSolver     = Flag defaultSolver
+                              , configAllowNewer = Flag AllowNewerNone }
 
 configureExCommand :: CommandUI (ConfigFlags, ConfigExFlags)
 configureExCommand = configureCommand {
     commandDefaultFlags = (mempty, defaultConfigExFlags),
     commandOptions      = \showOrParseArgs ->
-         liftOptions fst setFst (filter ((/="constraint") . optionName) $
-                                 configureOptions   showOrParseArgs)
+         liftOptions fst setFst
+         (filter ((`notElem` ["constraint", "dependency", "exact-configuration"])
+                  . optionName) $ configureOptions  showOrParseArgs)
       ++ liftOptions snd setSnd (configureExOptions showOrParseArgs)
   }
   where
@@ -314,6 +349,14 @@
               (map display))
 
   , optionSolver configSolver (\v flags -> flags { configSolver = v })
+
+  , option [] ["allow-newer"]
+    "Ignore upper bounds in dependencies on some or all packages."
+    configAllowNewer (\v flags -> flags { configAllowNewer = v})
+    (optArg "PKGS"
+     (fmap Flag allowNewerParser) (Flag AllowNewerAll)
+     allowNewerPrinter)
+
   ]
 
 instance Monoid ConfigExFlags where
@@ -321,13 +364,15 @@
     configCabalVersion = mempty,
     configExConstraints= mempty,
     configPreferences  = mempty,
-    configSolver       = mempty
+    configSolver       = mempty,
+    configAllowNewer   = mempty
   }
   mappend a b = ConfigExFlags {
     configCabalVersion = combine configCabalVersion,
     configExConstraints= combine configExConstraints,
     configPreferences  = combine configPreferences,
-    configSolver       = combine configSolver
+    configSolver       = combine configSolver,
+    configAllowNewer   = combine configAllowNewer
   }
     where combine field = field a `mappend` field b
 
@@ -340,20 +385,12 @@
   deriving Eq
 
 data BuildExFlags = BuildExFlags {
-  buildNumJobs  :: Flag (Maybe Int),
   buildOnly     :: Flag SkipAddSourceDepsCheck
 }
 
 buildExOptions :: ShowOrParseArgs -> [OptionField BuildExFlags]
 buildExOptions _showOrParseArgs =
-  option "j" ["jobs"]
-  "Run NUM jobs simultaneously (or '$ncpus' if no NUM is given)"
-  buildNumJobs (\v flags -> flags { buildNumJobs = v })
-  (optArg "NUM" (fmap Flag numJobsParser)
-   (Flag Nothing)
-   (map (Just . maybe "$ncpus" show) . flagToList))
-
-  : option [] ["only"]
+  option [] ["only"]
   "Don't reinstall add-source dependencies (sandbox-only)"
   buildOnly (\v flags -> flags { buildOnly = v })
   (noArg (Flag SkipAddSourceDepsCheck))
@@ -377,11 +414,9 @@
 
 instance Monoid BuildExFlags where
   mempty = BuildExFlags {
-    buildNumJobs = mempty,
     buildOnly    = mempty
   }
   mappend a b = BuildExFlags {
-    buildNumJobs = combine buildNumJobs,
     buildOnly    = combine buildOnly
   }
     where combine field = field a `mappend` field b
@@ -390,39 +425,51 @@
 -- * Test command
 -- ------------------------------------------------------------
 
-testCommand :: CommandUI (TestFlags, BuildExFlags)
+testCommand :: CommandUI (TestFlags, BuildFlags, BuildExFlags)
 testCommand = parent {
-  commandDefaultFlags = (commandDefaultFlags parent, mempty),
+  commandDefaultFlags = (commandDefaultFlags parent,
+                         Cabal.defaultBuildFlags, mempty),
   commandOptions      =
-    \showOrParseArgs -> liftOptions fst setFst
+    \showOrParseArgs -> liftOptions get1 set1
                         (commandOptions parent showOrParseArgs)
                         ++
-                        liftOptions snd setSnd (buildExOptions showOrParseArgs)
+                        liftOptions get2 set2
+                        (Cabal.buildOptions progConf showOrParseArgs)
+                        ++
+                        liftOptions get3 set3 (buildExOptions showOrParseArgs)
   }
   where
-    setFst a (_,b) = (a,b)
-    setSnd b (a,_) = (a,b)
+    get1 (a,_,_) = a; set1 a (_,b,c) = (a,b,c)
+    get2 (_,b,_) = b; set2 b (a,_,c) = (a,b,c)
+    get3 (_,_,c) = c; set3 c (a,b,_) = (a,b,c)
 
-    parent = Cabal.testCommand
+    parent   = Cabal.testCommand
+    progConf = defaultProgramConfiguration
 
 -- ------------------------------------------------------------
 -- * Bench command
 -- ------------------------------------------------------------
 
-benchmarkCommand :: CommandUI (BenchmarkFlags, BuildExFlags)
+benchmarkCommand :: CommandUI (BenchmarkFlags, BuildFlags, BuildExFlags)
 benchmarkCommand = parent {
-  commandDefaultFlags = (commandDefaultFlags parent, mempty),
+  commandDefaultFlags = (commandDefaultFlags parent,
+                         Cabal.defaultBuildFlags, mempty),
   commandOptions      =
-    \showOrParseArgs -> liftOptions fst setFst
+    \showOrParseArgs -> liftOptions get1 set1
                         (commandOptions parent showOrParseArgs)
                         ++
-                        liftOptions snd setSnd (buildExOptions showOrParseArgs)
+                        liftOptions get2 set2
+                        (Cabal.buildOptions progConf showOrParseArgs)
+                        ++
+                        liftOptions get3 set3 (buildExOptions showOrParseArgs)
   }
   where
-    setFst a (_,b) = (a,b)
-    setSnd b (a,_) = (a,b)
+    get1 (a,_,_) = a; set1 a (_,b,c) = (a,b,c)
+    get2 (_,b,_) = b; set2 b (a,_,c) = (a,b,c)
+    get3 (_,_,c) = c; set3 c (a,b,_) = (a,b,c)
 
-    parent = Cabal.benchmarkCommand
+    parent   = Cabal.benchmarkCommand
+    progConf = defaultProgramConfiguration
 
 -- ------------------------------------------------------------
 -- * Fetch command
@@ -437,7 +484,6 @@
       fetchReorderGoals     :: Flag Bool,
       fetchIndependentGoals :: Flag Bool,
       fetchShadowPkgs       :: Flag Bool,
-      fetchStrongFlags      :: Flag Bool,
       fetchVerbosity :: Flag Verbosity
     }
 
@@ -451,7 +497,6 @@
     fetchReorderGoals     = Flag False,
     fetchIndependentGoals = Flag False,
     fetchShadowPkgs       = Flag False,
-    fetchStrongFlags      = Flag False,
     fetchVerbosity = toFlag normal
    }
 
@@ -493,11 +538,61 @@
                          fetchReorderGoals     (\v flags -> flags { fetchReorderGoals     = v })
                          fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
                          fetchShadowPkgs       (\v flags -> flags { fetchShadowPkgs       = v })
-                         fetchStrongFlags      (\v flags -> flags { fetchStrongFlags      = v })
 
   }
 
 -- ------------------------------------------------------------
+-- * Freeze command
+-- ------------------------------------------------------------
+
+data FreezeFlags = FreezeFlags {
+      freezeDryRun           :: Flag Bool,
+      freezeSolver           :: Flag PreSolver,
+      freezeMaxBackjumps     :: Flag Int,
+      freezeReorderGoals     :: Flag Bool,
+      freezeIndependentGoals :: Flag Bool,
+      freezeShadowPkgs       :: Flag Bool,
+      freezeVerbosity        :: Flag Verbosity
+    }
+
+defaultFreezeFlags :: FreezeFlags
+defaultFreezeFlags = FreezeFlags {
+    freezeDryRun           = toFlag False,
+    freezeSolver           = Flag defaultSolver,
+    freezeMaxBackjumps     = Flag defaultMaxBackjumps,
+    freezeReorderGoals     = Flag False,
+    freezeIndependentGoals = Flag False,
+    freezeShadowPkgs       = Flag False,
+    freezeVerbosity        = toFlag normal
+   }
+
+freezeCommand :: CommandUI FreezeFlags
+freezeCommand = CommandUI {
+    commandName         = "freeze",
+    commandSynopsis     = "Freeze dependencies.",
+    commandDescription  = Nothing,
+    commandUsage        = usagePackages "freeze",
+    commandDefaultFlags = defaultFreezeFlags,
+    commandOptions      = \ showOrParseArgs -> [
+         optionVerbosity freezeVerbosity (\v flags -> flags { freezeVerbosity = v })
+
+       , option [] ["dry-run"]
+           "Do not freeze anything, only print what would be frozen"
+           freezeDryRun (\v flags -> flags { freezeDryRun = v })
+           trueArg
+
+       ] ++
+
+       optionSolver      freezeSolver           (\v flags -> flags { freezeSolver           = v }) :
+       optionSolverFlags showOrParseArgs
+                         freezeMaxBackjumps     (\v flags -> flags { freezeMaxBackjumps     = v })
+                         freezeReorderGoals     (\v flags -> flags { freezeReorderGoals     = v })
+                         freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
+                         freezeShadowPkgs       (\v flags -> flags { freezeShadowPkgs       = v })
+
+  }
+
+-- ------------------------------------------------------------
 -- * Other commands
 -- ------------------------------------------------------------
 
@@ -542,6 +637,16 @@
     commandOptions      = \_ -> []
   }
 
+formatCommand  :: CommandUI (Flag Verbosity)
+formatCommand = CommandUI {
+    commandName         = "format",
+    commandSynopsis     = "Reformat the .cabal file using the standard style.",
+    commandDescription  = Nothing,
+    commandUsage        = \pname -> "Usage: " ++ pname ++ " format [FILE]\n",
+    commandDefaultFlags = toFlag normal,
+    commandOptions      = \_ -> []
+  }
+
 runCommand :: CommandUI (BuildFlags, BuildExFlags)
 runCommand = CommandUI {
     commandName         = "run",
@@ -554,7 +659,7 @@
     commandDefaultFlags = mempty,
     commandOptions      =
       \showOrParseArgs -> liftOptions fst setFst
-                          (Cabal.buildOptions progConf showOrParseArgs)
+                          (commandOptions parent showOrParseArgs)
                           ++
                           liftOptions snd setSnd
                           (buildExOptions showOrParseArgs)
@@ -563,7 +668,7 @@
     setFst a (_,b) = (a,b)
     setSnd b (a,_) = (a,b)
 
-    progConf = defaultProgramConfiguration
+    parent = Cabal.buildCommand defaultProgramConfiguration
 
 -- ------------------------------------------------------------
 -- * Report flags
@@ -650,7 +755,7 @@
        ++ "Alternatively, with -s it will\nget the code from the source "
        ++ "repository specified by the package.\n",
     commandUsage        = usagePackages "get",
-    commandDefaultFlags = mempty,
+    commandDefaultFlags = defaultGetFlags,
     commandOptions      = \_ -> [
         optionVerbosity getVerbosity (\v flags -> flags { getVerbosity = v })
 
@@ -683,7 +788,12 @@
   }
 
 instance Monoid GetFlags where
-  mempty = defaultGetFlags
+  mempty = GetFlags {
+    getDestDir          = mempty,
+    getPristine         = mempty,
+    getSourceRepository = mempty,
+    getVerbosity        = mempty
+    }
   mappend a b = GetFlags {
     getDestDir          = combine getDestDir,
     getPristine         = combine getPristine,
@@ -697,16 +807,18 @@
 -- ------------------------------------------------------------
 
 data ListFlags = ListFlags {
-    listInstalled :: Flag Bool,
+    listInstalled    :: Flag Bool,
     listSimpleOutput :: Flag Bool,
-    listVerbosity :: Flag Verbosity
+    listVerbosity    :: Flag Verbosity,
+    listPackageDBs   :: [Maybe PackageDB]
   }
 
 defaultListFlags :: ListFlags
 defaultListFlags = ListFlags {
-    listInstalled = Flag False,
+    listInstalled    = Flag False,
     listSimpleOutput = Flag False,
-    listVerbosity = toFlag normal
+    listVerbosity    = toFlag normal,
+    listPackageDBs   = []
   }
 
 listCommand  :: CommandUI ListFlags
@@ -729,15 +841,26 @@
             listSimpleOutput (\v flags -> flags { listSimpleOutput = v })
             trueArg
 
+        , option "" ["package-db"]
+          "Use a given package database. May be a specific file, 'global', 'user' or 'clear'."
+          listPackageDBs (\v flags -> flags { listPackageDBs = v })
+          (reqArg' "DB" readPackageDbList showPackageDbList)
+
         ]
   }
 
 instance Monoid ListFlags where
-  mempty = defaultListFlags
+  mempty = ListFlags {
+    listInstalled    = mempty,
+    listSimpleOutput = mempty,
+    listVerbosity    = mempty,
+    listPackageDBs   = mempty
+    }
   mappend a b = ListFlags {
-    listInstalled = combine listInstalled,
+    listInstalled    = combine listInstalled,
     listSimpleOutput = combine listSimpleOutput,
-    listVerbosity = combine listVerbosity
+    listVerbosity    = combine listVerbosity,
+    listPackageDBs   = combine listPackageDBs
   }
     where combine field = field a `mappend` field b
 
@@ -746,12 +869,14 @@
 -- ------------------------------------------------------------
 
 data InfoFlags = InfoFlags {
-    infoVerbosity :: Flag Verbosity
+    infoVerbosity  :: Flag Verbosity,
+    infoPackageDBs :: [Maybe PackageDB]
   }
 
 defaultInfoFlags :: InfoFlags
 defaultInfoFlags = InfoFlags {
-    infoVerbosity = toFlag normal
+    infoVerbosity  = toFlag normal,
+    infoPackageDBs = []
   }
 
 infoCommand  :: CommandUI InfoFlags
@@ -763,13 +888,23 @@
     commandDefaultFlags = defaultInfoFlags,
     commandOptions      = \_ -> [
         optionVerbosity infoVerbosity (\v flags -> flags { infoVerbosity = v })
+
+        , option "" ["package-db"]
+          "Use a given package database. May be a specific file, 'global', 'user' or 'clear'."
+          infoPackageDBs (\v flags -> flags { infoPackageDBs = v })
+          (reqArg' "DB" readPackageDbList showPackageDbList)
+
         ]
   }
 
 instance Monoid InfoFlags where
-  mempty = defaultInfoFlags
+  mempty = InfoFlags {
+    infoVerbosity  = mempty,
+    infoPackageDBs = mempty
+    }
   mappend a b = InfoFlags {
-    infoVerbosity = combine infoVerbosity
+    infoVerbosity  = combine infoVerbosity,
+    infoPackageDBs = combine infoPackageDBs
   }
     where combine field = field a `mappend` field b
 
@@ -787,7 +922,6 @@
     installReorderGoals     :: Flag Bool,
     installIndependentGoals :: Flag Bool,
     installShadowPkgs       :: Flag Bool,
-    installStrongFlags      :: Flag Bool,
     installReinstall        :: Flag Bool,
     installAvoidReinstalls  :: Flag Bool,
     installOverrideReinstall :: Flag Bool,
@@ -800,7 +934,8 @@
     installBuildReports     :: Flag ReportLevel,
     installSymlinkBinDir    :: Flag FilePath,
     installOneShot          :: Flag Bool,
-    installNumJobs          :: Flag (Maybe Int)
+    installNumJobs          :: Flag (Maybe Int),
+    installRunTests         :: Flag Bool
   }
 
 defaultInstallFlags :: InstallFlags
@@ -812,7 +947,6 @@
     installReorderGoals    = Flag False,
     installIndependentGoals= Flag False,
     installShadowPkgs      = Flag False,
-    installStrongFlags     = Flag False,
     installReinstall       = Flag False,
     installAvoidReinstalls = Flag False,
     installOverrideReinstall = Flag False,
@@ -825,13 +959,35 @@
     installBuildReports    = Flag NoReports,
     installSymlinkBinDir   = mempty,
     installOneShot         = Flag False,
-    installNumJobs         = mempty
+    installNumJobs         = mempty,
+    installRunTests        = mempty
   }
   where
     docIndexFile = toPathTemplate ("$datadir" </> "doc" </> "index.html")
 
+allowNewerParser :: ReadE AllowNewer
+allowNewerParser = ReadE $ \s ->
+  case s of
+    ""      -> Right AllowNewerNone
+    "False" -> Right AllowNewerNone
+    "True"  -> Right AllowNewerAll
+    _       ->
+      case readPToMaybe pkgsParser s of
+        Just pkgs -> Right . AllowNewerSome $ pkgs
+        Nothing   -> Left ("Cannot parse the list of packages: " ++ s)
+  where
+    pkgsParser = Parse.sepBy1 parse (Parse.char ',')
+
+allowNewerPrinter :: Flag AllowNewer -> [Maybe String]
+allowNewerPrinter (Flag AllowNewerNone)        = [Just "False"]
+allowNewerPrinter (Flag AllowNewerAll)         = [Just "True"]
+allowNewerPrinter (Flag (AllowNewerSome pkgs)) =
+  [Just . intercalate "," . map display $ pkgs]
+allowNewerPrinter NoFlag                       = []
+
+
 defaultMaxBackjumps :: Int
-defaultMaxBackjumps = 2000
+defaultMaxBackjumps = 200
 
 defaultSolver :: PreSolver
 defaultSolver = Choose
@@ -860,7 +1016,10 @@
      ++ "    Constrained package version\n",
   commandDefaultFlags = (mempty, mempty, mempty, mempty),
   commandOptions      = \showOrParseArgs ->
-       liftOptions get1 set1 (filter ((/="constraint") . optionName) $
+       liftOptions get1 set1
+       (filter ((`notElem` ["constraint", "dependency"
+                           , "exact-configuration"])
+                . optionName) $
                               configureOptions   showOrParseArgs)
     ++ liftOptions get2 set2 (configureExOptions showOrParseArgs)
     ++ liftOptions get3 set3 (installOptions     showOrParseArgs)
@@ -879,10 +1038,10 @@
                           | descr <- optionDescr opt] }
     | opt <- commandOptions Cabal.haddockCommand showOrParseArgs
     , let name = optionName opt
-    , name `elem` ["hoogle", "html", "html-location",
-                   "executables", "internal", "css",
-                   "hyperlink-source", "hscolour-css",
-                   "contents-location"]
+    , name `elem` ["hoogle", "html", "html-location"
+                  ,"executables", "tests", "benchmarks", "all", "internal", "css"
+                  ,"hyperlink-source", "hscolour-css"
+                  ,"contents-location"]
     ]
   where
     fmapOptFlags :: (OptFlags -> OptFlags) -> OptDescr a -> OptDescr a
@@ -914,8 +1073,7 @@
                         installMaxBackjumps     (\v flags -> flags { installMaxBackjumps     = v })
                         installReorderGoals     (\v flags -> flags { installReorderGoals     = v })
                         installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
-                        installShadowPkgs       (\v flags -> flags { installShadowPkgs       = v })
-                        installStrongFlags      (\v flags -> flags { installStrongFlags      = v }) ++
+                        installShadowPkgs       (\v flags -> flags { installShadowPkgs       = v }) ++
 
       [ option [] ["reinstall"]
           "Install even if it means installing the same version again."
@@ -981,12 +1139,14 @@
           installOneShot (\v flags -> flags { installOneShot = v })
           (yesNoOpt showOrParseArgs)
 
-      , option "j" ["jobs"]
-        "Run NUM jobs simultaneously (or '$ncpus' if no NUM is given)."
+      , option [] ["run-tests"]
+          "Run package test suites during installation."
+          installRunTests (\v flags -> flags { installRunTests = v })
+          trueArg
+
+      , optionNumJobs
         installNumJobs (\v flags -> flags { installNumJobs = v })
-        (optArg "NUM" (fmap Flag numJobsParser)
-                      (Flag Nothing)
-                      (map (Just . maybe "$ncpus" show) . flagToList))
+
       ] ++ case showOrParseArgs of      -- TODO: remove when "cabal install"
                                         -- avoids
           ParseArgs ->
@@ -1010,7 +1170,6 @@
     installReorderGoals    = mempty,
     installIndependentGoals= mempty,
     installShadowPkgs      = mempty,
-    installStrongFlags     = mempty,
     installOnly            = mempty,
     installOnlyDeps        = mempty,
     installRootCmd         = mempty,
@@ -1019,7 +1178,8 @@
     installBuildReports    = mempty,
     installSymlinkBinDir   = mempty,
     installOneShot         = mempty,
-    installNumJobs         = mempty
+    installNumJobs         = mempty,
+    installRunTests        = mempty
   }
   mappend a b = InstallFlags {
     installDocumentation   = combine installDocumentation,
@@ -1033,7 +1193,6 @@
     installReorderGoals    = combine installReorderGoals,
     installIndependentGoals= combine installIndependentGoals,
     installShadowPkgs      = combine installShadowPkgs,
-    installStrongFlags     = combine installStrongFlags,
     installOnly            = combine installOnly,
     installOnlyDeps        = combine installOnlyDeps,
     installRootCmd         = combine installRootCmd,
@@ -1042,7 +1201,8 @@
     installBuildReports    = combine installBuildReports,
     installSymlinkBinDir   = combine installSymlinkBinDir,
     installOneShot         = combine installOneShot,
-    installNumJobs         = combine installNumJobs
+    installNumJobs         = combine installNumJobs,
+    installRunTests        = combine installRunTests
   }
     where combine field = field a `mappend` field b
 
@@ -1173,7 +1333,9 @@
       , option ['p'] ["package-name"]
         "Name of the Cabal package to create."
         IT.packageName (\v flags -> flags { IT.packageName = v })
-        (reqArgFlag "PACKAGE")
+        (reqArg "PACKAGE" (readP_to_E ("Cannot parse package name: "++)
+                                      (toFlag `fmap` parse))
+                          (flagToList . fmap display))
 
       , option [] ["version"]
         "Initial version of the package."
@@ -1239,6 +1401,12 @@
         (\v flags -> flags { IT.packageType = v })
         (noArg (Flag IT.Executable))
 
+      , option [] ["main-is"]
+        "Specify the main module."
+        IT.mainIs
+        (\v flags -> flags { IT.mainIs = v })
+        (reqArgFlag "FILE")
+
       , option [] ["language"]
         "Specify the default language."
         IT.language
@@ -1369,10 +1537,12 @@
 }
 
 instance Monoid Win32SelfUpgradeFlags where
-  mempty = defaultWin32SelfUpgradeFlags
+  mempty      = Win32SelfUpgradeFlags {
+    win32SelfUpgradeVerbosity = mempty
+    }
   mappend a b = Win32SelfUpgradeFlags {
     win32SelfUpgradeVerbosity = combine win32SelfUpgradeVerbosity
-  }
+    }
     where combine field = field a `mappend` field b
 
 -- ------------------------------------------------------------
@@ -1440,21 +1610,43 @@
     where combine field = field a `mappend` field b
 
 -- ------------------------------------------------------------
--- * Shared options utils
+-- * Exec Flags
 -- ------------------------------------------------------------
 
--- | Common parser for the @-j@ flag of @build@ and @install@.
-numJobsParser :: ReadE (Maybe Int)
-numJobsParser = ReadE $ \s ->
-  case s of
-    "$ncpus" -> Right Nothing
-    _        -> case reads s of
-      [(n, "")]
-        | n < 1     -> Left "The number of jobs should be 1 or more."
-        | n > 64    -> Left "You probably don't want that many jobs."
-        | otherwise -> Right (Just n)
-      _             -> Left "The jobs value should be a number or '$ncpus'"
+data ExecFlags = ExecFlags {
+  execVerbosity :: Flag Verbosity
+}
 
+defaultExecFlags :: ExecFlags
+defaultExecFlags = ExecFlags {
+  execVerbosity = toFlag normal
+  }
+
+execCommand :: CommandUI ExecFlags
+execCommand = CommandUI {
+  commandName         = "exec",
+  commandSynopsis     = "Run a command with the cabal environment",
+  commandDescription  = Nothing,
+  commandUsage        = \pname ->
+       "Usage: " ++ pname ++ " exec [FLAGS] COMMAND [-- [ARGS...]]\n\n"
+    ++ "Flags for exec:",
+
+  commandDefaultFlags = defaultExecFlags,
+  commandOptions      = \_ ->
+    [ optionVerbosity execVerbosity
+      (\v flags -> flags { execVerbosity = v })
+    ]
+  }
+
+instance Monoid ExecFlags where
+  mempty = ExecFlags {
+    execVerbosity = mempty
+    }
+  mappend a b = ExecFlags {
+    execVerbosity = combine execVerbosity
+    }
+    where combine field = field a `mappend` field b
+
 -- ------------------------------------------------------------
 -- * GetOpt Utils
 -- ------------------------------------------------------------
@@ -1469,7 +1661,7 @@
 
 yesNoOpt :: ShowOrParseArgs -> MkOptDescr (b -> Flag Bool) (Flag Bool -> b -> b) b
 yesNoOpt ShowArgs sf lf = trueArg sf lf
-yesNoOpt _        sf lf = boolOpt' flagToMaybe Flag (sf, lf) ([], map ("no-" ++) lf) sf lf
+yesNoOpt _        sf lf = Command.boolOpt' flagToMaybe Flag (sf, lf) ([], map ("no-" ++) lf) sf lf
 
 optionSolver :: (flags -> Flag PreSolver)
              -> (Flag PreSolver -> flags -> flags)
@@ -1487,9 +1679,8 @@
                   -> (flags -> Flag Bool  ) -> (Flag Bool   -> flags -> flags)
                   -> (flags -> Flag Bool  ) -> (Flag Bool   -> flags -> flags)
                   -> (flags -> Flag Bool  ) -> (Flag Bool   -> flags -> flags)
-                  -> (flags -> Flag Bool  ) -> (Flag Bool   -> flags -> flags)
                   -> [OptionField flags]
-optionSolverFlags showOrParseArgs getmbj setmbj getrg setrg _getig _setig getsip setsip getstrfl setstrfl =
+optionSolverFlags showOrParseArgs getmbj setmbj getrg setrg _getig _setig getsip setsip =
   [ option [] ["max-backjumps"]
       ("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
       getmbj setmbj
@@ -1510,11 +1701,7 @@
   , option [] ["shadow-installed-packages"]
       "If multiple package instances of the same version are installed, treat all but one as shadowed."
       getsip setsip
-      (yesNoOpt showOrParseArgs)
-  , option [] ["strong-flags"]
-      "Do not defer flag choices (this used to be the default in cabal-install <= 1.20)."
-      getstrfl setstrfl
-      (yesNoOpt showOrParseArgs)
+      trueArg
   ]
 
 
diff --git a/Distribution/Client/SetupWrapper.hs b/Distribution/Client/SetupWrapper.hs
--- a/Distribution/Client/SetupWrapper.hs
+++ b/Distribution/Client/SetupWrapper.hs
@@ -26,7 +26,7 @@
          ( Version(..), VersionRange, anyVersion
          , intersectVersionRanges, orLaterVersion
          , withinRange )
-import Distribution.InstalledPackageInfo (installedPackageId, sourcePackageId)
+import Distribution.InstalledPackageInfo (installedPackageId)
 import Distribution.Package
          ( InstalledPackageId(..), PackageIdentifier(..),
            PackageName(..), Package(..), packageName
@@ -42,8 +42,9 @@
 import Distribution.Compiler ( buildCompilerId )
 import Distribution.Simple.Compiler
          ( CompilerFlavor(GHC), Compiler(compilerId)
-         , compilerVersion
          , PackageDB(..), PackageDBStack )
+import Distribution.Simple.PreProcess
+         ( runSimplePreProcessor, ppUnlit )
 import Distribution.Simple.Program
          ( ProgramConfiguration, emptyProgramConfiguration
          , getProgramSearchPath, getDbProgramOutput, runDbProgram, ghcProgram )
@@ -68,11 +69,12 @@
 import Distribution.Simple.Setup
          ( Flag(..) )
 import Distribution.Simple.Utils
-         ( die, debug, info, cabalVersion, findPackageDesc, comparing
+         ( die, debug, info, cabalVersion, tryFindPackageDesc, comparing
          , createDirectoryIfMissingVerbose, installExecutableFile
-         , moreRecentFile, rewriteFile, intercalate )
+         , copyFileVerbose, rewriteFile, intercalate )
 import Distribution.Client.Utils
-         ( inDir, tryCanonicalizePath )
+         ( inDir, tryCanonicalizePath
+         , existsAndIsMoreRecentThan, moreRecentFile )
 import Distribution.System ( Platform(..), buildPlatform )
 import Distribution.Text
          ( display )
@@ -81,16 +83,17 @@
 import Distribution.Compat.Exception
          ( catchIO )
 
-import System.Directory  ( doesFileExist )
-import System.FilePath   ( (</>), (<.>) )
-import System.IO         ( Handle, hPutStr )
-import System.Exit       ( ExitCode(..), exitWith )
-import System.Process    ( runProcess, waitForProcess )
-import Control.Monad     ( when, unless )
-import Data.List         ( foldl1' )
-import Data.Maybe        ( fromMaybe, isJust )
-import Data.Monoid       ( mempty )
-import Data.Char         ( isSpace )
+import System.Directory    ( doesFileExist )
+import System.FilePath     ( (</>), (<.>) )
+import System.IO           ( Handle, hPutStr )
+import System.Exit         ( ExitCode(..), exitWith )
+import System.Process      ( runProcess, waitForProcess )
+import Control.Applicative ( (<$>), (<*>) )
+import Control.Monad       ( when, unless )
+import Data.List           ( foldl1' )
+import Data.Maybe          ( fromMaybe, isJust )
+import Data.Monoid         ( mempty )
+import Data.Char           ( isSpace )
 
 data SetupScriptOptions = SetupScriptOptions {
     useCabalVersion          :: VersionRange,
@@ -156,7 +159,7 @@
   checkBuildType buildType'
   setupMethod verbosity options' (packageId pkg) buildType' mkArgs
   where
-    getPkg = findPackageDesc (fromMaybe "." (useWorkingDir options))
+    getPkg = tryFindPackageDesc (fromMaybe "." (useWorkingDir options))
          >>= readPackageDescription verbosity
          >>= return . packageDescription
 
@@ -212,15 +215,13 @@
 externalSetupMethod verbosity options pkg bt mkargs = do
   debug verbosity $ "Using external setup method with build-type " ++ show bt
   createDirectoryIfMissingVerbose verbosity True setupDir
-  (cabalLibVersion, options') <- cabalLibVersionToUse
+  (cabalLibVersion, mCabalLibInstalledPkgId, options') <- cabalLibVersionToUse
   debug verbosity $ "Using Cabal library version " ++ display cabalLibVersion
-  setupHs <- updateSetupScript cabalLibVersion bt
-  debug verbosity $ "Using " ++ setupHs ++ " as setup script."
-  path <- case bt of
-    -- TODO: Should we also cache the setup exe for the Make and Configure build
-    -- types?
-    Simple -> getCachedSetupExecutable options' cabalLibVersion setupHs
-    _      -> compileSetupExecutable options' cabalLibVersion setupHs False
+  path <- if useCachedSetupExecutable
+          then getCachedSetupExecutable options'
+               cabalLibVersion mCabalLibInstalledPkgId
+          else compileSetupExecutable   options'
+               cabalLibVersion mCabalLibInstalledPkgId False
   invokeSetupScript options' path (mkargs cabalLibVersion)
 
   where
@@ -228,8 +229,12 @@
                        []  -> "."
                        dir -> dir
   setupDir         = workingDir </> useDistPref options </> "setup"
-  setupVersionFile = setupDir </> "setup" <.> "version"
+  setupVersionFile = setupDir   </> "setup" <.> "version"
+  setupHs          = setupDir   </> "setup" <.> "hs"
+  setupProgFile    = setupDir   </> "setup" <.> exeExtension
 
+  useCachedSetupExecutable = (bt == Simple || bt == Configure || bt == Make)
+
   maybeGetInstalledPackages :: SetupScriptOptions -> Compiler
                                -> ProgramConfiguration -> IO PackageIndex
   maybeGetInstalledPackages options' comp conf =
@@ -238,34 +243,98 @@
       Nothing    -> getInstalledPackages verbosity
                     comp (usePackageDB options') conf
 
-  cabalLibVersionToUse :: IO (Version, SetupScriptOptions)
+  cabalLibVersionToUse :: IO (Version, (Maybe InstalledPackageId)
+                             ,SetupScriptOptions)
   cabalLibVersionToUse = do
-    savedVersion <- savedCabalVersion
-    case savedVersion of
+    savedVer <- savedVersion
+    case savedVer of
       Just version | version `withinRange` useCabalVersion options
-        -> return (version, options)
-      _ -> do (comp, conf, options') <- configureCompiler options
-              version <- installedCabalVersion options' comp conf
-              writeFile setupVersionFile (show version ++ "\n")
-              return (version, options')
+        -> do updateSetupScript version bt
+              -- Does the previously compiled setup executable still exist and
+              -- is it up-to date?
+              useExisting <- canUseExistingSetup version
+              if useExisting
+                then return (version, Nothing, options)
+                else installedVersion
+      _ -> installedVersion
+    where
+      -- This check duplicates the checks in 'getCachedSetupExecutable' /
+      -- 'compileSetupExecutable'. Unfortunately, we have to perform it twice
+      -- because the selected Cabal version may change as a result of this
+      -- check.
+      canUseExistingSetup :: Version -> IO Bool
+      canUseExistingSetup version =
+        if useCachedSetupExecutable
+        then do
+          (_, cachedSetupProgFile) <- cachedSetupDirAndProg options version
+          doesFileExist cachedSetupProgFile
+        else
+          (&&) <$> setupProgFile `existsAndIsMoreRecentThan` setupHs
+               <*> setupProgFile `existsAndIsMoreRecentThan` setupVersionFile
 
-  savedCabalVersion = do
-    versionString <- readFile setupVersionFile `catchIO` \_ -> return ""
-    case reads versionString of
-      [(version,s)] | all isSpace s -> return (Just version)
-      _                             -> return Nothing
+      installedVersion :: IO (Version, Maybe InstalledPackageId
+                             ,SetupScriptOptions)
+      installedVersion = do
+        (comp,    conf,    options')  <- configureCompiler options
+        (version, mipkgid, options'') <- installedCabalVersion options' comp conf
+        updateSetupScript version bt
+        writeFile setupVersionFile (show version ++ "\n")
+        return (version, mipkgid, options'')
 
-  installedCabalVersion :: SetupScriptOptions -> Compiler
-                        -> ProgramConfiguration -> IO Version
-  installedCabalVersion options' comp conf = do
-    index <- maybeGetInstalledPackages options' comp conf
-    let cabalDep = Dependency (PackageName "Cabal") (useCabalVersion options')
+      savedVersion :: IO (Maybe Version)
+      savedVersion = do
+        versionString <- readFile setupVersionFile `catchIO` \_ -> return ""
+        case reads versionString of
+          [(version,s)] | all isSpace s -> return (Just version)
+          _                             -> return Nothing
+
+  -- | Update a Setup.hs script, creating it if necessary.
+  updateSetupScript :: Version -> BuildType -> IO ()
+  updateSetupScript _ Custom = do
+    useHs  <- doesFileExist customSetupHs
+    useLhs <- doesFileExist customSetupLhs
+    unless (useHs || useLhs) $ die
+      "Using 'build-type: Custom' but there is no Setup.hs or Setup.lhs script."
+    let src = (if useHs then customSetupHs else customSetupLhs)
+    srcNewer <- src `moreRecentFile` setupHs
+    when srcNewer $ if useHs
+                    then copyFileVerbose verbosity src setupHs
+                    else runSimplePreProcessor ppUnlit src setupHs verbosity
+    where
+      customSetupHs   = workingDir </> "Setup.hs"
+      customSetupLhs  = workingDir </> "Setup.lhs"
+
+  updateSetupScript cabalLibVersion _ =
+    rewriteFile setupHs (buildTypeScript cabalLibVersion)
+
+  buildTypeScript :: Version -> String
+  buildTypeScript cabalLibVersion = case bt of
+    Simple    -> "import Distribution.Simple; main = defaultMain\n"
+    Configure -> "import Distribution.Simple; main = defaultMainWithHooks "
+              ++ if cabalLibVersion >= Version [1,3,10] []
+                   then "autoconfUserHooks\n"
+                   else "defaultUserHooks\n"
+    Make      -> "import Distribution.Make; main = defaultMain\n"
+    Custom             -> error "buildTypeScript Custom"
+    UnknownBuildType _ -> error "buildTypeScript UnknownBuildType"
+
+  installedCabalVersion :: SetupScriptOptions -> Compiler -> ProgramConfiguration
+                        -> IO (Version, Maybe InstalledPackageId
+                              ,SetupScriptOptions)
+  installedCabalVersion options' _ _ | packageName pkg == PackageName "Cabal" =
+    return (packageVersion pkg, Nothing, options')
+  installedCabalVersion options' compiler conf = do
+    index <- maybeGetInstalledPackages options' compiler conf
+    let cabalDep   = Dependency (PackageName "Cabal") (useCabalVersion options')
+        options''  = options' { usePackageIndex = Just index }
     case PackageIndex.lookupDependency index cabalDep of
       []   -> die $ "The package '" ++ display (packageName pkg)
                  ++ "' requires Cabal library version "
                  ++ display (useCabalVersion options)
                  ++ " but no suitable version is installed."
-      pkgs -> return $ bestVersion id (map fst pkgs)
+      pkgs -> let ipkginfo = head . snd . bestVersion fst $ pkgs
+              in return (packageVersion ipkginfo
+                        ,Just . installedPackageId $ ipkginfo, options'')
 
   bestVersion :: (a -> Version) -> [a] -> a
   bestVersion f = firstMaximumBy (comparing (preference . f))
@@ -297,23 +366,6 @@
                                _       -> False
           latestVersion    = version
 
-  -- TODO: This function looks a lot like @installedCabalVersion@ - can the
-  -- duplication be removed?
-  installedCabalPkgId :: SetupScriptOptions -> Compiler -> ProgramConfiguration
-                         -> Version -> IO (Maybe InstalledPackageId)
-  installedCabalPkgId _ _ _ _ | packageName pkg == PackageName "Cabal" =
-    return Nothing
-  installedCabalPkgId options' compiler conf cabalLibVersion = do
-    index <- maybeGetInstalledPackages options' compiler conf
-    let cabalPkgid = PackageIdentifier (PackageName "Cabal") cabalLibVersion
-    case PackageIndex.lookupSourcePackageId index cabalPkgid of
-      []           -> die $ "The package '" ++ display (packageName pkg)
-                      ++ "' requires Cabal library version "
-                      ++ display (cabalLibVersion)
-                      ++ " but no suitable version is installed."
-      iPkgInfos   -> return . Just . installedPackageId
-                     . bestVersion (pkgVersion . sourcePackageId) $ iPkgInfos
-
   configureCompiler :: SetupScriptOptions
                     -> IO (Compiler, ProgramConfiguration, SetupScriptOptions)
   configureCompiler options' = do
@@ -330,107 +382,90 @@
                                    usePackageIndex  = Just index,
                                    useProgramConfig = conf })
 
-  -- | Decide which Setup.hs script to use, creating it if necessary.
-  --
-  updateSetupScript :: Version -> BuildType -> IO FilePath
-  updateSetupScript _ Custom = do
-    useHs  <- doesFileExist setupHs
-    useLhs <- doesFileExist setupLhs
-    unless (useHs || useLhs) $ die
-      "Using 'build-type: Custom' but there is no Setup.hs or Setup.lhs script."
-    return (if useHs then setupHs else setupLhs)
-    where
-      setupHs  = workingDir </> "Setup.hs"
-      setupLhs = workingDir </> "Setup.lhs"
-
-  updateSetupScript cabalLibVersion _ = do
-    rewriteFile setupHs (buildTypeScript cabalLibVersion)
-    return setupHs
-    where
-      setupHs  = setupDir </> "setup.hs"
-
-  buildTypeScript :: Version -> String
-  buildTypeScript cabalLibVersion = case bt of
-    Simple    -> "import Distribution.Simple; main = defaultMain\n"
-    Configure -> "import Distribution.Simple; main = defaultMainWithHooks "
-              ++ if cabalLibVersion >= Version [1,3,10] []
-                   then "autoconfUserHooks\n"
-                   else "defaultUserHooks\n"
-    Make      -> "import Distribution.Make; main = defaultMain\n"
-    Custom             -> error "buildTypeScript Custom"
-    UnknownBuildType _ -> error "buildTypeScript UnknownBuildType"
+  -- | Path to the setup exe cache directory and path to the cached setup
+  -- executable.
+  cachedSetupDirAndProg :: SetupScriptOptions -> Version
+                        -> IO (FilePath, FilePath)
+  cachedSetupDirAndProg options' cabalLibVersion = do
+    cabalDir <- defaultCabalDir
+    let setupCacheDir       = cabalDir </> "setup-exe-cache"
+        cachedSetupProgFile = setupCacheDir
+                              </> ("setup-" ++ buildTypeString ++ "-"
+                                   ++ cabalVersionString ++ "-"
+                                   ++ platformString ++ "-"
+                                   ++ compilerVersionString)
+                              <.> exeExtension
+    return (setupCacheDir, cachedSetupProgFile)
+      where
+        buildTypeString       = show bt
+        cabalVersionString    = "Cabal-" ++ (display cabalLibVersion)
+        compilerVersionString = display $
+                                fromMaybe buildCompilerId
+                                (fmap compilerId . useCompiler $ options')
+        platformString        = display $
+                                fromMaybe buildPlatform (usePlatform options')
 
   -- | Look up the setup executable in the cache; update the cache if the setup
   -- executable is not found.
-  getCachedSetupExecutable :: SetupScriptOptions -> Version -> FilePath
+  getCachedSetupExecutable :: SetupScriptOptions
+                           -> Version -> Maybe InstalledPackageId
                            -> IO FilePath
-  getCachedSetupExecutable options' cabalLibVersion setupHsFile = do
-    cabalDir <- defaultCabalDir
-    let setupCacheDir = cabalDir </> "setup-exe-cache"
-    let setupProgFile = setupCacheDir
-                        </> ("setup-" ++ cabalVersionString ++ "-"
-                             ++ platformString ++ "-"
-                             ++ compilerVersionString)
-                        <.> exeExtension
-    setupProgFileExists <- doesFileExist setupProgFile
-    if setupProgFileExists
+  getCachedSetupExecutable options' cabalLibVersion
+                           maybeCabalLibInstalledPkgId = do
+    (setupCacheDir, cachedSetupProgFile) <-
+      cachedSetupDirAndProg options' cabalLibVersion
+    cachedSetupExists <- doesFileExist cachedSetupProgFile
+    if cachedSetupExists
       then debug verbosity $
-           "Found cached setup executable: " ++ setupProgFile
+           "Found cached setup executable: " ++ cachedSetupProgFile
       else criticalSection' $ do
         -- The cache may have been populated while we were waiting.
-        setupProgFileExists' <- doesFileExist setupProgFile
-        if setupProgFileExists'
+        cachedSetupExists' <- doesFileExist cachedSetupProgFile
+        if cachedSetupExists'
           then debug verbosity $
-               "Found cached setup executable: " ++ setupProgFile
+               "Found cached setup executable: " ++ cachedSetupProgFile
           else do
           debug verbosity $ "Setup executable not found in the cache."
-          src <- compileSetupExecutable options' cabalLibVersion setupHsFile True
+          src <- compileSetupExecutable options'
+                 cabalLibVersion maybeCabalLibInstalledPkgId True
           createDirectoryIfMissingVerbose verbosity True setupCacheDir
-          installExecutableFile verbosity src setupProgFile
-    return setupProgFile
+          installExecutableFile verbosity src cachedSetupProgFile
+    return cachedSetupProgFile
       where
-        cabalVersionString    = "Cabal-" ++ (display cabalLibVersion)
-        compilerVersionString = display $
-                                fromMaybe buildCompilerId
-                                (fmap compilerId . useCompiler $ options')
-        platformString        = display $
-                                fromMaybe buildPlatform (usePlatform options')
         criticalSection'      = fromMaybe id
                                 (fmap criticalSection $ setupCacheLock options')
 
   -- | If the Setup.hs is out of date wrt the executable then recompile it.
   -- Currently this is GHC only. It should really be generalised.
   --
-  compileSetupExecutable :: SetupScriptOptions -> Version -> FilePath -> Bool
+  compileSetupExecutable :: SetupScriptOptions
+                         -> Version -> Maybe InstalledPackageId -> Bool
                          -> IO FilePath
-  compileSetupExecutable options' cabalLibVersion setupHsFile forceCompile = do
-    setupHsNewer      <- setupHsFile      `moreRecentFile` setupProgFile
+  compileSetupExecutable options' cabalLibVersion maybeCabalLibInstalledPkgId
+                         forceCompile = do
+    setupHsNewer      <- setupHs          `moreRecentFile` setupProgFile
     cabalVersionNewer <- setupVersionFile `moreRecentFile` setupProgFile
     let outOfDate = setupHsNewer || cabalVersionNewer
     when (outOfDate || forceCompile) $ do
       debug verbosity "Setup executable needs to be updated, compiling..."
       (compiler, conf, options'') <- configureCompiler options'
       let cabalPkgid = PackageIdentifier (PackageName "Cabal") cabalLibVersion
-      maybeCabalInstalledPkgId <- installedCabalPkgId options'' compiler conf
-                                  cabalLibVersion
       let ghcOptions = mempty {
               ghcOptVerbosity       = Flag verbosity
             , ghcOptMode            = Flag GhcModeMake
-            , ghcOptInputFiles      = [setupHsFile]
+            , ghcOptInputFiles      = [setupHs]
             , ghcOptOutputFile      = Flag setupProgFile
             , ghcOptObjDir          = Flag setupDir
             , ghcOptHiDir           = Flag setupDir
             , ghcOptSourcePathClear = Flag True
-            , ghcOptSourcePath      = case bt of
-                                      Custom -> [workingDir]
-                                      _      -> []
+            , ghcOptSourcePath      = [workingDir]
             , ghcOptPackageDBs      = usePackageDB options''
-            , ghcOptPackages        =
-              maybe []
-              (\cabalInstalledPkgId -> [(cabalInstalledPkgId, cabalPkgid)])
-              maybeCabalInstalledPkgId
+            , ghcOptPackages        = maybe []
+                                      (\ipkgid -> [(ipkgid, cabalPkgid)])
+                                      maybeCabalLibInstalledPkgId
+            , ghcOptExtra           = ["-threaded"]
             }
-      let ghcCmdLine = renderGhcOptions (compilerVersion compiler) ghcOptions
+      let ghcCmdLine = renderGhcOptions compiler ghcOptions
       case useLoggingHandle options of
         Nothing          -> runDbProgram verbosity ghcProgram conf ghcCmdLine
 
@@ -439,8 +474,6 @@
                                          conf ghcCmdLine
                                hPutStr logHandle output
     return setupProgFile
-    where
-      setupProgFile = setupDir </> "setup" <.> exeExtension
 
   invokeSetupScript :: SetupScriptOptions -> FilePath -> [String] -> IO ()
   invokeSetupScript options' path args = do
diff --git a/Distribution/Client/SrcDist.hs b/Distribution/Client/SrcDist.hs
--- a/Distribution/Client/SrcDist.hs
+++ b/Distribution/Client/SrcDist.hs
@@ -117,7 +117,7 @@
         zipfile   = targetPref </> dir <.> "zip"
     (zipProg, _) <- requireProgram verbosity zipProgram emptyProgramDb
 
-    -- zip has an annoying habbit of updating the target rather than creating
+    -- zip has an annoying habit of updating the target rather than creating
     -- it from scratch. While that might sound like an optimisation, it doesn't
     -- remove files already in the archive that are no longer present in the
     -- uncompressed tree.
diff --git a/Distribution/Client/Tar.hs b/Distribution/Client/Tar.hs
--- a/Distribution/Client/Tar.hs
+++ b/Distribution/Client/Tar.hs
@@ -71,7 +71,8 @@
 import Data.Bits     (Bits, shiftL, testBit)
 import Data.List     (foldl')
 import Numeric       (readOct, showOct)
-import Control.Monad (MonadPlus(mplus), when)
+import Control.Applicative (Applicative(..))
+import Control.Monad (MonadPlus(mplus), when, ap, liftM)
 import qualified Data.Map as Map
 import qualified Data.ByteString.Lazy as BS
 import qualified Data.ByteString.Lazy.Char8 as BS.Char8
@@ -94,6 +95,7 @@
 import System.Posix.Types
          ( FileMode )
 import Distribution.Client.Compat.Time
+         ( EpochTime, getModTime )
 import System.IO
          ( IOMode(ReadMode), openBinaryFile, hFileSize )
 import System.IO.Unsafe (unsafeInterleaveIO)
@@ -228,7 +230,7 @@
      V7Format
 
      -- | The \"USTAR\" format is an extension of the classic V7 format. It was
-     -- later standardised by POSIX. It has some restructions but is the most
+     -- later standardised by POSIX. It has some restrictions but is the most
      -- portable format.
      --
    | UstarFormat
@@ -253,7 +255,7 @@
 directoryPermissions  = 0o0755
 
 isExecutable :: Permissions -> Bool
-isExecutable p = testBit p 0 || testBit p 6 -- user or other exectuable
+isExecutable p = testBit p 0 || testBit p 6 -- user or other executable
 
 -- | An 'Entry' with all default values except for the file name and type. It
 -- uses the portable USTAR/POSIX format (see 'UstarHeader').
@@ -317,7 +319,7 @@
 --
 -- So it's understandable but rather annoying.
 --
--- * Tar paths use posix format (ie @\'/\'@ directory separators), irrespective
+-- * Tar paths use POSIX format (ie @\'/\'@ directory separators), irrespective
 --   of the local path conventions.
 --
 -- * The directory separator between the prefix and name is /not/ stored.
@@ -366,7 +368,7 @@
 -- | Take a sanitized path, split on directory separators and try to pack it
 -- into the 155 + 100 tar file name format.
 --
--- The stragey is this: take the name-directory components in reverse order
+-- The strategy is this: take the name-directory components in reverse order
 -- and try to fit as many components into the 100 long name area as possible.
 -- If all the remaining components fit in the 155 name area then we win.
 --
@@ -482,7 +484,7 @@
 -- * file names are valid
 --
 -- These checks are from the perspective of the current OS. That means we check
--- for \"@C:\blah@\" files on Windows and \"\/blah\" files on unix. For archive
+-- for \"@C:\blah@\" files on Windows and \"\/blah\" files on Unix. For archive
 -- entry types 'HardLink' and 'SymbolicLink' the same checks are done for the
 -- link target. A failure in any entry terminates the sequence of entries with
 -- an error.
@@ -675,6 +677,13 @@
 partial :: Partial a -> Either String a
 partial (Error msg) = Left msg
 partial (Ok x)      = Right x
+
+instance Functor Partial where
+    fmap          = liftM
+
+instance Applicative Partial where
+    pure          = return
+    (<*>)         = ap
 
 instance Monad Partial where
     return        = Ok
diff --git a/Distribution/Client/Targets.hs b/Distribution/Client/Targets.hs
--- a/Distribution/Client/Targets.hs
+++ b/Distribution/Client/Targets.hs
@@ -70,7 +70,7 @@
          ( Text(..), display )
 import Distribution.Verbosity (Verbosity)
 import Distribution.Simple.Utils
-         ( die, warn, intercalate, findPackageDesc, fromUTF8, lowercase )
+         ( die, warn, intercalate, tryFindPackageDesc, fromUTF8, lowercase )
 
 import Data.List
          ( find, nub )
@@ -177,7 +177,6 @@
    | SpecificSourcePackage pkg
   deriving Show
 
-
 pkgSpecifierTarget :: Package pkg => PackageSpecifier pkg -> PackageName
 pkgSpecifierTarget (NamedPackage name _)       = name
 pkgSpecifierTarget (SpecificSourcePackage pkg) = packageName pkg
@@ -423,7 +422,7 @@
 
     UserTargetLocalCabalFile file -> do
       let dir = takeDirectory file
-      _   <- findPackageDesc dir -- just as a check
+      _   <- tryFindPackageDesc dir -- just as a check
       return [ PackageTargetLocation (LocalUnpackedPackage dir) ]
 
     UserTargetLocalTarball tarballFile ->
@@ -469,7 +468,7 @@
     PackageTargetLocation location -> case location of
 
       LocalUnpackedPackage dir -> do
-        pkg <- readPackageDescription verbosity =<< findPackageDesc dir
+        pkg <- readPackageDescription verbosity =<< tryFindPackageDesc dir
         return $ PackageTargetLocation $
                    SourcePackage {
                      packageInfoId        = packageId pkg,
diff --git a/Distribution/Client/Types.hs b/Distribution/Client/Types.hs
--- a/Distribution/Client/Types.hs
+++ b/Distribution/Client/Types.hs
@@ -91,7 +91,28 @@
 instance PackageFixedDeps ConfiguredPackage where
   depends (ConfiguredPackage _ _ _ deps) = deps
 
+-- | Like 'ConfiguredPackage', but with all dependencies guaranteed to be
+-- installed already, hence itself ready to be installed.
+data ReadyPackage = ReadyPackage
+       SourcePackage           -- see 'ConfiguredPackage'.
+       FlagAssignment          --
+       [OptionalStanza]        --
+       [InstalledPackageInfo]  -- Installed dependencies.
+  deriving Show
 
+instance Package ReadyPackage where
+  packageId (ReadyPackage pkg _ _ _) = packageId pkg
+
+instance PackageFixedDeps ReadyPackage where
+  depends (ReadyPackage _ _ _ deps) = map packageId deps
+
+-- | Sometimes we need to convert a 'ReadyPackage' back to a
+-- 'ConfiguredPackage'. For example, a failed 'PlanPackage' can be *either*
+-- Ready or Configured.
+readyPackageToConfiguredPackage :: ReadyPackage -> ConfiguredPackage
+readyPackageToConfiguredPackage (ReadyPackage srcpkg flags stanzas deps) =
+  ConfiguredPackage srcpkg flags stanzas (map packageId deps)
+
 -- | A package description along with the location of the package sources.
 --
 data SourcePackage = SourcePackage {
@@ -188,6 +209,7 @@
                   | TestsFailed     SomeException
                   | InstallFailed   SomeException
 data BuildSuccess = BuildOk         DocsResult TestsResult
+                                    (Maybe InstalledPackageInfo)
 
 data DocsResult  = DocsNotTried  | DocsFailed  | DocsOk
 data TestsResult = TestsNotTried | TestsOk
diff --git a/Distribution/Client/Upload.hs b/Distribution/Client/Upload.hs
--- a/Distribution/Client/Upload.hs
+++ b/Distribution/Client/Upload.hs
@@ -3,6 +3,9 @@
 
 module Distribution.Client.Upload (check, upload, report) where
 
+import qualified Data.ByteString.Lazy.Char8 as B (concat, length, pack, readFile, unpack)
+import           Data.ByteString.Lazy.Char8 (ByteString)
+
 import Distribution.Client.Types (Username(..), Password(..),Repo(..),RemoteRepo(..))
 import Distribution.Client.HttpUtils (isOldHackageURI, cabalBrowse)
 
@@ -15,16 +18,17 @@
 import qualified Distribution.Client.BuildReports.Upload as BuildReport
 
 import Network.Browser
-         ( request )
+         ( BrowserAction, request
+         , Authority(..), addAuthority )
 import Network.HTTP
          ( Header(..), HeaderName(..), findHeader
          , Request(..), RequestMethod(..), Response(..) )
+import Network.TCP (HandleStream)
 import Network.URI (URI(uriPath), parseURI)
 
 import Data.Char        (intToDigit)
 import Numeric          (showHex)
-import System.IO        (hFlush, stdin, stdout, hGetEcho, hSetEcho
-                        ,openBinaryFile, IOMode(ReadMode), hGetContents)
+import System.IO        (hFlush, stdin, stdout, hGetEcho, hSetEcho)
 import Control.Exception (bracket)
 import System.Random    (randomRIO)
 import System.FilePath  ((</>), takeExtension, takeFileName)
@@ -49,7 +53,12 @@
                           else targetRepoURI{uriPath = uriPath targetRepoURI `FilePath.Posix.combine` "upload"}
           Username username <- maybe promptUsername return mUsername
           Password password <- maybe promptPassword return mPassword
-          let auth = Just (username, password)
+          let auth = addAuthority AuthBasic {
+                       auRealm    = "Hackage",
+                       auUsername = username,
+                       auPassword = password,
+                       auSite     = uploadURI
+                     }
           flip mapM_ paths $ \path -> do
             notice verbosity $ "Uploading " ++ path ++ "... "
             handlePackage verbosity uploadURI auth path
@@ -75,9 +84,17 @@
 
 report :: Verbosity -> [Repo] -> Maybe Username -> Maybe Password -> IO ()
 report verbosity repos mUsername mPassword = do
+      let uploadURI = if isOldHackageURI targetRepoURI
+                      then legacyUploadURI
+                      else targetRepoURI{uriPath = ""}
       Username username <- maybe promptUsername return mUsername
       Password password <- maybe promptPassword return mPassword
-      let auth = Just (username, password)
+      let auth = addAuthority AuthBasic {
+                   auRealm    = "Hackage",
+                   auUsername = username,
+                   auPassword = password,
+                   auSite     = uploadURI
+                 }
       forM_ repos $ \repo -> case repoKind repo of
         Left remoteRepo
             -> do dotCabal <- defaultCabalDir
@@ -96,14 +113,16 @@
                                     cabalBrowse verbosity auth $ BuildReport.uploadReports (remoteRepoURI remoteRepo) [(report', Just buildLog)]
                                     return ()
         Right{} -> return ()
+  where
+    targetRepoURI = remoteRepoURI $ last [ remoteRepo | Left remoteRepo <- map repoKind repos ] --FIXME: better error message when no repos are given
 
 check :: Verbosity -> [FilePath] -> IO ()
 check verbosity paths = do
           flip mapM_ paths $ \path -> do
             notice verbosity $ "Checking " ++ path ++ "... "
-            handlePackage verbosity checkURI Nothing path
+            handlePackage verbosity checkURI (return ()) path
 
-handlePackage :: Verbosity -> URI -> Maybe (String, String)
+handlePackage :: Verbosity -> URI -> BrowserAction (HandleStream ByteString) ()
               -> FilePath -> IO ()
 handlePackage verbosity uri auth path =
   do req <- mkRequest uri path
@@ -118,31 +137,31 @@
                      case findHeader HdrContentType resp of
                        Just contenttype
                          | takeWhile (/= ';') contenttype == "text/plain"
-                         -> notice verbosity $ rspBody resp
-                       _ -> debug verbosity $ rspBody resp
+                         -> notice verbosity $ B.unpack $ rspBody resp
+                       _ -> debug verbosity $ B.unpack $ rspBody resp
 
-mkRequest :: URI -> FilePath -> IO (Request String)
+mkRequest :: URI -> FilePath -> IO (Request ByteString)
 mkRequest uri path = 
     do pkg <- readBinaryFile path
        boundary <- genBoundary
-       let body = printMultiPart boundary (mkFormData path pkg)
+       let body = printMultiPart (B.pack boundary) (mkFormData path pkg)
        return $ Request {
                          rqURI = uri,
                          rqMethod = POST,
                          rqHeaders = [Header HdrContentType ("multipart/form-data; boundary="++boundary),
-                                      Header HdrContentLength (show (length body)),
+                                      Header HdrContentLength (show (B.length body)),
                                       Header HdrAccept ("text/plain")],
                          rqBody = body
                         }
 
-readBinaryFile :: FilePath -> IO String
-readBinaryFile path = openBinaryFile path ReadMode >>= hGetContents
+readBinaryFile :: FilePath -> IO ByteString
+readBinaryFile = B.readFile
 
 genBoundary :: IO String
 genBoundary = do i <- randomRIO (0x10000000000000,0xFFFFFFFFFFFFFF) :: IO Integer
                  return $ showHex i ""
 
-mkFormData :: FilePath -> String -> [BodyPart]
+mkFormData :: FilePath -> ByteString -> [BodyPart]
 mkFormData path pkg =
   -- yes, web browsers are that stupid (re quoting)
   [BodyPart [Header hdrContentDisposition $
@@ -155,14 +174,17 @@
 
 -- * Multipart, partly stolen from the cgi package.
 
-data BodyPart = BodyPart [Header] String
+data BodyPart = BodyPart [Header] ByteString
 
-printMultiPart :: String -> [BodyPart] -> String
-printMultiPart boundary xs = 
-    concatMap (printBodyPart boundary) xs ++ crlf ++ "--" ++ boundary ++ "--" ++ crlf
+printMultiPart :: ByteString -> [BodyPart] -> ByteString
+printMultiPart boundary xs =
+    B.concat $ map (printBodyPart boundary) xs ++ [crlf, dd, boundary, dd, crlf]
 
-printBodyPart :: String -> BodyPart -> String
-printBodyPart boundary (BodyPart hs c) = crlf ++ "--" ++ boundary ++ crlf ++ concatMap show hs ++ crlf ++ c
+printBodyPart :: ByteString -> BodyPart -> ByteString
+printBodyPart boundary (BodyPart hs c) = B.concat $ [crlf, dd, boundary, crlf] ++ map (B.pack . show) hs ++ [crlf, c]
 
-crlf :: String
-crlf = "\r\n"
+crlf :: ByteString
+crlf = B.pack "\r\n"
+
+dd :: ByteString
+dd = B.pack "--"
diff --git a/Distribution/Client/Utils.hs b/Distribution/Client/Utils.hs
--- a/Distribution/Client/Utils.hs
+++ b/Distribution/Client/Utils.hs
@@ -2,14 +2,17 @@
 
 module Distribution.Client.Utils ( MergeResult(..)
                                  , mergeBy, duplicates, duplicatesBy
-                                 , inDir, numberOfProcessors
+                                 , inDir, determineNumJobs, numberOfProcessors
                                  , removeExistingFile
                                  , makeAbsoluteToCwd, filePathToByteString
                                  , byteStringToFilePath, tryCanonicalizePath
-                                 , canonicalizePathNoThrow )
+                                 , canonicalizePathNoThrow
+                                 , moreRecentFile, existsAndIsMoreRecentThan )
        where
 
-import Distribution.Compat.Exception ( catchIO )
+import Distribution.Compat.Exception   ( catchIO )
+import Distribution.Client.Compat.Time ( getModTime )
+import Distribution.Simple.Setup       ( Flag(..) )
 import qualified Data.ByteString.Lazy as BS
 import Control.Monad
          ( when )
@@ -32,8 +35,10 @@
 import System.IO.Unsafe ( unsafePerformIO )
 
 #if defined(mingw32_HOST_OS)
+import Prelude hiding (ioError)
 import Control.Monad (liftM2, unless)
 import System.Directory (doesDirectoryExist)
+import System.IO.Error (ioError, mkIOError, doesNotExistErrorType)
 #endif
 
 -- | Generic merging utility. For sorted input lists this is a full outer join.
@@ -88,6 +93,14 @@
 numberOfProcessors :: Int
 numberOfProcessors = fromEnum $ unsafePerformIO c_getNumberOfProcessors
 
+-- | Determine the number of jobs to use given the value of the '-j' flag.
+determineNumJobs :: Flag (Maybe Int) -> Int
+determineNumJobs numJobsFlag =
+  case numJobsFlag of
+    NoFlag        -> 1
+    Flag Nothing  -> numberOfProcessors
+    Flag (Just n) -> n
+
 -- | Given a relative path, make it absolute relative to the current
 -- directory. Absolute paths are returned unmodified.
 makeAbsoluteToCwd :: FilePath -> IO FilePath
@@ -139,8 +152,8 @@
 #if defined(mingw32_HOST_OS)
   exists <- liftM2 (||) (doesFileExist ret) (doesDirectoryExist ret)
   unless exists $
-    error $ ret ++ ": canonicalizePath: does not exist "
-                ++ "(No such file or directory)"
+    ioError $ mkIOError doesNotExistErrorType "canonicalizePath"
+                        Nothing (Just ret)
 #endif
   return ret
 
@@ -149,3 +162,26 @@
 canonicalizePathNoThrow :: FilePath -> IO FilePath
 canonicalizePathNoThrow path = do
   canonicalizePath path `catchIO` (\_ -> return path)
+
+--------------------
+-- Modification time
+
+-- | Like Distribution.Simple.Utils.moreRecentFile, but uses getModTime instead
+-- of getModificationTime for higher precision. We can't merge the two because
+-- Distribution.Client.Time uses MIN_VERSION macros.
+moreRecentFile :: FilePath -> FilePath -> IO Bool
+moreRecentFile a b = do
+  exists <- doesFileExist b
+  if not exists
+    then return True
+    else do tb <- getModTime b
+            ta <- getModTime a
+            return (ta > tb)
+
+-- | Like 'moreRecentFile', but also checks that the first file exists.
+existsAndIsMoreRecentThan :: FilePath -> FilePath -> IO Bool
+existsAndIsMoreRecentThan a b = do
+  exists <- doesFileExist a
+  if not exists
+    then return False
+    else a `moreRecentFile` b
diff --git a/Distribution/Client/Win32SelfUpgrade.hs b/Distribution/Client/Win32SelfUpgrade.hs
--- a/Distribution/Client/Win32SelfUpgrade.hs
+++ b/Distribution/Client/Win32SelfUpgrade.hs
@@ -25,7 +25,7 @@
 --
 -- * Move our own exe file to a new name
 -- * Copy a new exe file to the previous name
--- * Run the new exe file, passing our own pid and new path
+-- * Run the new exe file, passing our own PID and new path
 -- * Wait for the new process to start
 -- * Close the new exe file
 -- * Exit old process
@@ -61,7 +61,7 @@
 -- that the nested action can replace our own exe file.
 --
 -- We require that the new process accepts a command line invocation that
--- calls 'deleteOldExeFile', passing in the pid and exe file.
+-- calls 'deleteOldExeFile', passing in the PID and exe file.
 --
 possibleSelfUpgrade :: Verbosity
                     -> [FilePath]
@@ -87,7 +87,7 @@
 -- old and new processes. We need to synchronise to make sure that the old
 -- process has not yet terminated by the time the new one starts up and looks
 -- for the old process. Otherwise the old one might have already terminated
--- and we could not wait on it terminating reliably (eg the pid might get
+-- and we could not wait on it terminating reliably (eg the PID might get
 -- re-used).
 --
 syncEventName :: String
@@ -131,7 +131,7 @@
 
 -- | Assuming we're now in the new child process, we've been asked by the old
 -- process to wait for it to terminate and then we can remove the old exe file
--- that it renamted itself to.
+-- that it renamed itself to.
 --
 deleteOldExeFile :: Verbosity -> Int -> FilePath -> IO ()
 deleteOldExeFile verbosity oldPID tmpPath = do
diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -22,8 +22,10 @@
          , InstallFlags(..), defaultInstallFlags
          , installCommand, upgradeCommand
          , FetchFlags(..), fetchCommand
+         , FreezeFlags(..), freezeCommand
          , GetFlags(..), getCommand, unpackCommand
          , checkCommand
+         , formatCommand
          , updateCommand
          , ListFlags(..), listCommand
          , InfoFlags(..), infoCommand
@@ -34,10 +36,11 @@
          , SDistFlags(..), SDistExFlags(..), sdistCommand
          , Win32SelfUpgradeFlags(..), win32SelfUpgradeCommand
          , SandboxFlags(..), sandboxCommand
+         , ExecFlags(..), execCommand
          , reportCommand
          )
 import Distribution.Simple.Setup
-         ( HaddockFlags(..), haddockCommand
+         ( HaddockFlags(..), haddockCommand, defaultHaddockFlags
          , HscolourFlags(..), hscolourCommand
          , ReplFlags(..), replCommand
          , CopyFlags(..), copyCommand
@@ -61,6 +64,7 @@
 import Distribution.Client.Configure          (configure)
 import Distribution.Client.Update             (update)
 import Distribution.Client.Fetch              (fetch)
+import Distribution.Client.Freeze             (freeze)
 import Distribution.Client.Check as Check     (check)
 --import Distribution.Client.Clean            (clean)
 import Distribution.Client.Upload as Upload   (upload, check, report)
@@ -74,6 +78,7 @@
                                               ,sandboxListSources
                                               ,sandboxHcPkg
                                               ,dumpPackageEnvironment
+                                              ,withSandboxBinDirOnSearchPath
 
                                               ,getSandboxConfigFilePath
                                               ,loadConfigOrSandboxConfig
@@ -84,19 +89,29 @@
                                               ,maybeReinstallAddSourceDeps
                                               ,tryGetIndexFilePath
                                               ,sandboxBuildDir
+                                              ,updateSandboxConfigFileFlag
 
                                               ,configCompilerAux'
                                               ,configPackageDB')
 import Distribution.Client.Sandbox.PackageEnvironment
                                               (setPackageDB
+                                              ,sandboxPackageDBPath
                                               ,userPackageEnvironmentFile)
 import Distribution.Client.Sandbox.Timestamp  (maybeAddCompilerTimestampRecord)
 import Distribution.Client.Sandbox.Types      (UseSandbox(..), whenUsingSandbox)
 import Distribution.Client.Init               (initCabal)
 import qualified Distribution.Client.Win32SelfUpgrade as Win32SelfUpgrade
+import Distribution.Client.Utils              (determineNumJobs
+                                              ,existsAndIsMoreRecentThan)
 
 import Distribution.PackageDescription
          ( Executable(..) )
+import Distribution.PackageDescription.Parse
+         ( readPackageDescription )
+import Distribution.PackageDescription.PrettyPrint
+         ( writeGenericPackageDescription )
+import Distribution.Simple.Build
+         ( startInterpreter )
 import Distribution.Simple.Command
          ( CommandParse(..), CommandUI(..), Command
          , commandsRun, commandAddAction, hiddenCommand )
@@ -107,10 +122,14 @@
          , ConfigStateFileErrorType(..), localBuildInfoFile
          , getPersistBuildConfig, tryGetPersistBuildConfig )
 import qualified Distribution.Simple.LocalBuildInfo as LBI
-import Distribution.Simple.Program (defaultProgramConfiguration)
+import Distribution.Simple.GHC (ghcGlobalPackageDB)
+import Distribution.Simple.Program (defaultProgramConfiguration, lookupProgram, ghcProgram)
+import Distribution.Simple.Program.Run (getEffectiveEnvironment)
 import qualified Distribution.Simple.Setup as Cabal
 import Distribution.Simple.Utils
-         ( cabalVersion, die, notice, info, moreRecentFile, topHandler )
+         ( cabalVersion, debug, die, notice, info, topHandler
+         , findPackageDesc, tryFindPackageDesc , rawSystemExit
+         , rawSystemExitWithEnv )
 import Distribution.Text
          ( display )
 import Distribution.Verbosity as Verbosity
@@ -124,7 +143,7 @@
 import System.FilePath          (splitExtension, takeExtension)
 import System.IO                (BufferMode(LineBuffering),
                                  hSetBuffering, stdout)
-import System.Directory         (doesFileExist)
+import System.Directory         (doesFileExist, getCurrentDirectory)
 import Data.List                (intercalate)
 import Data.Monoid              (Monoid(..))
 import Control.Monad            (when, unless)
@@ -144,14 +163,18 @@
     CommandHelp   help                 -> printGlobalHelp help
     CommandList   opts                 -> printOptionsList opts
     CommandErrors errs                 -> printErrors errs
-    CommandReadyToGo (globalflags, commandParse)  ->
+    CommandReadyToGo (globalFlags, commandParse)  ->
       case commandParse of
-        _ | fromFlag (globalVersion globalflags)        -> printVersion
-          | fromFlag (globalNumericVersion globalflags) -> printNumericVersion
+        _ | fromFlagOrDefault False (globalVersion globalFlags)
+            -> printVersion
+          | fromFlagOrDefault False (globalNumericVersion globalFlags)
+            -> printNumericVersion
         CommandHelp     help           -> printCommandHelp help
         CommandList     opts           -> printOptionsList opts
         CommandErrors   errs           -> printErrors errs
-        CommandReadyToGo action        -> action globalflags
+        CommandReadyToGo action        -> do
+          globalFlags' <- updateSandboxConfigFileFlag globalFlags
+          action globalFlags'
 
   where
     printCommandHelp help = do
@@ -182,6 +205,7 @@
       ,listCommand            `commandAddAction` listAction
       ,infoCommand            `commandAddAction` infoAction
       ,fetchCommand           `commandAddAction` fetchAction
+      ,freezeCommand          `commandAddAction` freezeAction
       ,getCommand             `commandAddAction` getAction
       ,hiddenCommand $
        unpackCommand          `commandAddAction` unpackAction
@@ -196,10 +220,10 @@
       ,replCommand defaultProgramConfiguration
                               `commandAddAction` replAction
       ,sandboxCommand         `commandAddAction` sandboxAction
+      ,haddockCommand         `commandAddAction` haddockAction
+      ,execCommand            `commandAddAction` execAction
       ,wrapperAction copyCommand
                      copyVerbosity     copyDistPref
-      ,wrapperAction haddockCommand
-                     haddockVerbosity  haddockDistPref
       ,wrapperAction cleanCommand
                      cleanVerbosity    cleanDistPref
       ,wrapperAction hscolourCommand
@@ -209,6 +233,8 @@
       ,testCommand            `commandAddAction` testAction
       ,benchmarkCommand       `commandAddAction` benchmarkAction
       ,hiddenCommand $
+       formatCommand          `commandAddAction` formatAction
+      ,hiddenCommand $
        upgradeCommand         `commandAddAction` upgradeAction
       ,hiddenCommand $
        win32SelfUpgradeCommand`commandAddAction` win32SelfUpgradeAction
@@ -253,6 +279,9 @@
 
   whenUsingSandbox useSandbox $ \sandboxDir -> do
     initPackageDBIfNeeded verbosity configFlags'' comp conf
+    -- NOTE: We do not write the new sandbox package DB location to
+    -- 'cabal.sandbox.config' here because 'configure -w' must not affect
+    -- subsequent 'install' (for UI compatibility with non-sandboxed mode).
 
     indexFile     <- tryGetIndexFilePath config
     maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile
@@ -274,57 +303,94 @@
 
   -- Calls 'configureAction' to do the real work, so nothing special has to be
   -- done to support sandboxes.
-  useSandbox <- reconfigure verbosity distPref
-                mempty [] globalFlags noAddSource (buildNumJobs buildExFlags)
-                (const Nothing)
+  (useSandbox, config) <- reconfigure verbosity distPref
+                          mempty [] globalFlags noAddSource
+                          (buildNumJobs buildFlags) (const Nothing)
 
   maybeWithSandboxDirOnSearchPath useSandbox $
-    build verbosity distPref buildFlags extraArgs
+    build verbosity config distPref buildFlags extraArgs
 
 
 -- | Actually do the work of building the package. This is separate from
 -- 'buildAction' so that 'testAction' and 'benchmarkAction' do not invoke
 -- 'reconfigure' twice.
-build :: Verbosity -> FilePath -> BuildFlags -> [String] -> IO ()
-build verbosity distPref buildFlags extraArgs =
+build :: Verbosity -> SavedConfig -> FilePath -> BuildFlags -> [String] -> IO ()
+build verbosity config distPref buildFlags extraArgs =
   setupWrapper verbosity setupOptions Nothing
-               (Cabal.buildCommand progConf) (const buildFlags') extraArgs
+               (Cabal.buildCommand progConf) mkBuildFlags extraArgs
   where
     progConf     = defaultProgramConfiguration
     setupOptions = defaultSetupScriptOptions { useDistPref = distPref }
-    buildFlags'  = buildFlags
+
+    mkBuildFlags version = filterBuildFlags version config buildFlags'
+    buildFlags' = buildFlags
       { buildVerbosity = toFlag verbosity
-      , buildDistPref = toFlag distPref
+      , buildDistPref  = toFlag distPref
       }
 
+-- | Make sure that we don't pass new flags to setup scripts compiled against
+-- old versions of Cabal.
+filterBuildFlags :: Version -> SavedConfig -> BuildFlags -> BuildFlags
+filterBuildFlags version config buildFlags
+  | version >= Version [1,19,1] [] = buildFlags_latest
+  -- Cabal < 1.19.1 doesn't support 'build -j'.
+  | otherwise                      = buildFlags_pre_1_19_1
+  where
+    buildFlags_pre_1_19_1 = buildFlags {
+      buildNumJobs = NoFlag
+      }
+    buildFlags_latest     = buildFlags {
+      -- Take the 'jobs' setting '~/.cabal/config' into account.
+      buildNumJobs = Flag . Just . determineNumJobs $
+                     (numJobsConfigFlag `mappend` numJobsCmdLineFlag)
+      }
+    numJobsConfigFlag  = installNumJobs . savedInstallFlags $ config
+    numJobsCmdLineFlag = buildNumJobs buildFlags
+
+
 replAction :: ReplFlags -> [String] -> GlobalFlags -> IO ()
 replAction replFlags extraArgs globalFlags = do
-  let distPref    = fromFlagOrDefault (useDistPref defaultSetupScriptOptions)
-                    (replDistPref replFlags)
-      verbosity   = fromFlagOrDefault normal (replVerbosity replFlags)
-      noAddSource = case replReload replFlags of
-                      Flag True -> SkipAddSourceDepsCheck
-                      _         -> DontSkipAddSourceDepsCheck
+  cwd     <- getCurrentDirectory
+  pkgDesc <- findPackageDesc cwd
+  either (const onNoPkgDesc) (const onPkgDesc) pkgDesc
+  where
+    verbosity = fromFlagOrDefault normal (replVerbosity replFlags)
 
-  -- Calls 'configureAction' to do the real work, so nothing special has to be
-  -- done to support sandboxes.
-  useSandbox <- reconfigure verbosity distPref
-                mempty [] globalFlags noAddSource NoFlag
-                (const Nothing)
+    -- There is a .cabal file in the current directory: start a REPL and load
+    -- the project's modules.
+    onPkgDesc = do
+      let distPref    = fromFlagOrDefault (useDistPref defaultSetupScriptOptions)
+                        (replDistPref replFlags)
+          noAddSource = case replReload replFlags of
+                          Flag True -> SkipAddSourceDepsCheck
+                          _         -> DontSkipAddSourceDepsCheck
+          progConf     = defaultProgramConfiguration
+          setupOptions = defaultSetupScriptOptions
+            { useCabalVersion = orLaterVersion $ Version [1,18,0] []
+            , useDistPref     = distPref
+            }
+          replFlags'   = replFlags
+            { replVerbosity = toFlag verbosity
+            , replDistPref  = toFlag distPref
+            }
+      -- Calls 'configureAction' to do the real work, so nothing special has to
+      -- be done to support sandboxes.
+      (useSandbox, _config) <- reconfigure verbosity distPref
+                               mempty [] globalFlags noAddSource NoFlag
+                               (const Nothing)
 
-  maybeWithSandboxDirOnSearchPath useSandbox $
-    let progConf     = defaultProgramConfiguration
-        setupOptions = defaultSetupScriptOptions
-          { useCabalVersion = orLaterVersion $ Version [1,18,0] []
-          , useDistPref     = distPref
-          }
-        replFlags'   = replFlags
-          { replVerbosity = toFlag verbosity
-          , replDistPref  = toFlag distPref
-          }
-    in setupWrapper verbosity setupOptions Nothing
-         (Cabal.replCommand progConf) (const replFlags') extraArgs
+      maybeWithSandboxDirOnSearchPath useSandbox $
+        setupWrapper verbosity setupOptions Nothing
+        (Cabal.replCommand progConf) (const replFlags') extraArgs
 
+    -- No .cabal file in the current directory: just start the REPL (possibly
+    -- using the sandbox package DB).
+    onNoPkgDesc = do
+      (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags
+                               mempty
+      let configFlags = savedConfigureFlags config
+      (comp, _platform, programDb) <- configCompilerAux' configFlags
+      startInterpreter verbosity programDb comp (configPackageDB' configFlags)
 
 -- | Re-configure the package in the current directory if needed. Deciding
 -- when to reconfigure and with which options is convoluted:
@@ -383,7 +449,7 @@
                             -- prefix setting is always required, it is checked
                             -- automatically; this function need not check
                             -- for it.
-            -> IO UseSandbox
+            -> IO (UseSandbox, SavedConfig)
 reconfigure verbosity distPref     addConfigFlags extraArgs globalFlags
             skipAddSourceDepsCheck numJobsFlag    checkFlags = do
   eLbi <- tryGetPersistBuildConfig distPref
@@ -397,7 +463,8 @@
     --
     -- If we're in a sandbox: add-source deps don't have to be reinstalled
     -- (since we don't know the compiler & platform).
-    onNoBuildConfig :: String -> ConfigStateFileErrorType -> IO UseSandbox
+    onNoBuildConfig :: String -> ConfigStateFileErrorType
+                       -> IO (UseSandbox, SavedConfig)
     onNoBuildConfig err errCode = do
       let msg = case errCode of
             ConfigStateFileMissing    -> "Package has never been configured."
@@ -411,15 +478,14 @@
             $ msg ++ " Configuring with default flags." ++ configureManually
           configureAction (defaultFlags, defaultConfigExFlags)
             extraArgs globalFlags
-      (useSandbox, _) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
-      return useSandbox
+      loadConfigOrSandboxConfig verbosity globalFlags mempty
 
     -- Package has been configured, but the configuration may be out of
     -- date or required flags may not be set.
     --
     -- If we're in a sandbox: reinstall the modified add-source deps and
     -- force reconfigure if we did.
-    onBuildConfig :: LBI.LocalBuildInfo -> IO UseSandbox
+    onBuildConfig :: LBI.LocalBuildInfo -> IO (UseSandbox, SavedConfig)
     onBuildConfig lbi = do
       let configFlags = LBI.configFlags lbi
           flags       = mconcat [configFlags, addConfigFlags, distVerbFlags]
@@ -436,14 +502,17 @@
             | isSandboxConfigNewer = SkipAddSourceDepsCheck
             | otherwise            = skipAddSourceDepsCheck
 
-      (useSandbox, depsReinstalled) <-
+      when (skipAddSourceDepsCheck' == SkipAddSourceDepsCheck) $
+        info verbosity "Skipping add-source deps check..."
+
+      (useSandbox, config, depsReinstalled) <-
         case skipAddSourceDepsCheck' of
         DontSkipAddSourceDepsCheck     ->
           maybeReinstallAddSourceDeps verbosity numJobsFlag flags globalFlags
         SkipAddSourceDepsCheck -> do
-          (useSandbox, _) <- loadConfigOrSandboxConfig verbosity
-                             globalFlags mempty
-          return (useSandbox, NoDepsReinstalled)
+          (useSandbox, config) <- loadConfigOrSandboxConfig verbosity
+                                  globalFlags (configUserInstall flags)
+          return (useSandbox, config, NoDepsReinstalled)
 
       -- Is the @cabal.config@ file newer than @dist/setup.config@? Then we need
       -- to force reconfigure. Note that it's possible to use @cabal.config@
@@ -460,22 +529,14 @@
 
         -- No message for the user indicates that reconfiguration
         -- is not required.
-        Nothing -> return useSandbox
+        Nothing -> return (useSandbox, config)
 
         -- Show the message and reconfigure.
         Just msg -> do
           notice verbosity msg
           configureAction (flags, defaultConfigExFlags)
             extraArgs globalFlags
-          return useSandbox
-
-    -- True if the first file exists and is more recent than the second file.
-    existsAndIsMoreRecentThan :: FilePath -> FilePath -> IO Bool
-    existsAndIsMoreRecentThan a b = do
-      exists <- doesFileExist a
-      if not exists
-        then return False
-        else a `moreRecentFile` b
+          return (useSandbox, config)
 
     -- Determine what message, if any, to display to the user if reconfiguration
     -- is required.
@@ -576,11 +637,14 @@
   let sandboxDistPref = case useSandbox of
         NoSandbox             -> NoFlag
         UseSandbox sandboxDir -> Flag $ sandboxBuildDir sandboxDir
-      configFlags'    = savedConfigureFlags   config `mappend` configFlags
+      configFlags'    = maybeForceTests installFlags' $
+                        savedConfigureFlags   config `mappend` configFlags
       configExFlags'  = defaultConfigExFlags         `mappend`
                         savedConfigureExFlags config `mappend` configExFlags
       installFlags'   = defaultInstallFlags          `mappend`
                         savedInstallFlags     config `mappend` installFlags
+      haddockFlags'   = defaultHaddockFlags          `mappend`
+                        savedHaddockFlags     config `mappend` haddockFlags
       globalFlags'    = savedGlobalFlags      config `mappend` globalFlags
   (comp, platform, conf) <- configCompilerAux' configFlags'
 
@@ -615,15 +679,25 @@
               comp platform conf
               useSandbox mSandboxPkgInfo
               globalFlags' configFlags'' configExFlags'
-              installFlags' haddockFlags
+              installFlags' haddockFlags'
               targets
 
-testAction :: (TestFlags, BuildExFlags) -> [String] -> GlobalFlags -> IO ()
-testAction (testFlags, buildExFlags) extraArgs globalFlags = do
+    where
+      -- '--run-tests' implies '--enable-tests'.
+      maybeForceTests installFlags' configFlags' =
+        if fromFlagOrDefault False (installRunTests installFlags')
+        then configFlags' { configTests = toFlag True }
+        else configFlags'
+
+testAction :: (TestFlags, BuildFlags, BuildExFlags) -> [String] -> GlobalFlags
+              -> IO ()
+testAction (testFlags, buildFlags, buildExFlags) extraArgs globalFlags = do
   let verbosity      = fromFlagOrDefault normal (testVerbosity testFlags)
       distPref       = fromFlagOrDefault (useDistPref defaultSetupScriptOptions)
                        (testDistPref testFlags)
       setupOptions   = defaultSetupScriptOptions { useDistPref = distPref }
+      buildFlags'    = buildFlags { buildVerbosity = testVerbosity testFlags
+                                  , buildDistPref  = testDistPref testFlags }
       addConfigFlags = mempty { configTests = toFlag True }
       checkFlags flags
         | fromFlagOrDefault False (configTests flags) = Nothing
@@ -633,24 +707,30 @@
 
   -- reconfigure also checks if we're in a sandbox and reinstalls add-source
   -- deps if needed.
-  useSandbox <- reconfigure verbosity distPref addConfigFlags []
-                globalFlags noAddSource (buildNumJobs buildExFlags) checkFlags
+  (useSandbox, config) <- reconfigure verbosity distPref addConfigFlags []
+                          globalFlags noAddSource
+                          (buildNumJobs buildFlags') checkFlags
 
   maybeWithSandboxDirOnSearchPath useSandbox $
-    build verbosity distPref mempty extraArgs
+    build verbosity config distPref buildFlags' extraArgs
 
   maybeWithSandboxDirOnSearchPath useSandbox $
     setupWrapper verbosity setupOptions Nothing
       Cabal.testCommand (const testFlags) extraArgs
 
-benchmarkAction :: (BenchmarkFlags, BuildExFlags) -> [String] -> GlobalFlags
+benchmarkAction :: (BenchmarkFlags, BuildFlags, BuildExFlags)
+                   -> [String] -> GlobalFlags
                    -> IO ()
-benchmarkAction (benchmarkFlags, buildExFlags) extraArgs globalFlags = do
+benchmarkAction (benchmarkFlags, buildFlags, buildExFlags)
+                extraArgs globalFlags = do
   let verbosity      = fromFlagOrDefault normal
                        (benchmarkVerbosity benchmarkFlags)
       distPref       = fromFlagOrDefault (useDistPref defaultSetupScriptOptions)
                        (benchmarkDistPref benchmarkFlags)
       setupOptions   = defaultSetupScriptOptions { useDistPref = distPref }
+      buildFlags'    = buildFlags
+        { buildVerbosity = benchmarkVerbosity benchmarkFlags
+        , buildDistPref  = benchmarkDistPref  benchmarkFlags }
       addConfigFlags = mempty { configBenchmarks = toFlag True }
       checkFlags flags
         | fromFlagOrDefault False (configBenchmarks flags) = Nothing
@@ -660,22 +740,40 @@
 
   -- reconfigure also checks if we're in a sandbox and reinstalls add-source
   -- deps if needed.
-  useSandbox <- reconfigure verbosity distPref addConfigFlags []
-                globalFlags noAddSource (buildNumJobs buildExFlags)
-                checkFlags
+  (useSandbox, config) <- reconfigure verbosity distPref addConfigFlags []
+                          globalFlags noAddSource (buildNumJobs buildFlags')
+                          checkFlags
 
   maybeWithSandboxDirOnSearchPath useSandbox $
-    build verbosity distPref mempty extraArgs
+    build verbosity config distPref buildFlags' extraArgs
 
   maybeWithSandboxDirOnSearchPath useSandbox $
     setupWrapper verbosity setupOptions Nothing
       Cabal.benchmarkCommand (const benchmarkFlags) extraArgs
 
+haddockAction :: HaddockFlags -> [String] -> GlobalFlags -> IO ()
+haddockAction haddockFlags extraArgs globalFlags = do
+  let verbosity = fromFlag (haddockVerbosity haddockFlags)
+  (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
+  let haddockFlags' = defaultHaddockFlags      `mappend`
+                      savedHaddockFlags config `mappend` haddockFlags
+      setupScriptOptions = defaultSetupScriptOptions {
+        useDistPref = fromFlagOrDefault
+                      (useDistPref defaultSetupScriptOptions)
+                      (haddockDistPref haddockFlags')
+        }
+  setupWrapper verbosity setupScriptOptions Nothing
+    haddockCommand (const haddockFlags') extraArgs
+
 listAction :: ListFlags -> [String] -> GlobalFlags -> IO ()
 listAction listFlags extraArgs globalFlags = do
   let verbosity = fromFlag (listVerbosity listFlags)
-  (_, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
-  let configFlags  = savedConfigureFlags config
+  (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
+  let configFlags' = savedConfigureFlags config
+      configFlags  = configFlags' {
+        configPackageDBs = configPackageDBs configFlags'
+                           `mappend` listPackageDBs listFlags
+        }
       globalFlags' = savedGlobalFlags    config `mappend` globalFlags
   (comp, _, conf) <- configCompilerAux' configFlags
   List.list verbosity
@@ -690,8 +788,12 @@
 infoAction infoFlags extraArgs globalFlags = do
   let verbosity = fromFlag (infoVerbosity infoFlags)
   targets <- readUserTargets verbosity extraArgs
-  (_, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
-  let configFlags  = savedConfigureFlags config
+  (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
+  let configFlags' = savedConfigureFlags config
+      configFlags  = configFlags' {
+        configPackageDBs = configPackageDBs configFlags'
+                           `mappend` infoPackageDBs infoFlags
+        }
       globalFlags' = savedGlobalFlags    config `mappend` globalFlags
   (comp, _, conf) <- configCompilerAuxEx configFlags
   List.info verbosity
@@ -708,7 +810,7 @@
   unless (null extraArgs) $
     die $ "'update' doesn't take any extra arguments: " ++ unwords extraArgs
   let verbosity = fromFlag verbosityFlag
-  (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags NoFlag
+  config <- loadConfig verbosity (globalConfigFile globalFlags) mempty
   let globalFlags' = savedGlobalFlags config `mappend` globalFlags
   update verbosity (globalRepos globalFlags')
 
@@ -741,6 +843,24 @@
         comp platform conf globalFlags' fetchFlags
         targets
 
+freezeAction :: FreezeFlags -> [String] -> GlobalFlags -> IO ()
+freezeAction freezeFlags _extraArgs globalFlags = do
+  let verbosity = fromFlag (freezeVerbosity freezeFlags)
+  (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
+  let configFlags  = savedConfigureFlags config
+      globalFlags' = savedGlobalFlags config `mappend` globalFlags
+  (comp, platform, conf) <- configCompilerAux' configFlags
+
+  maybeWithSandboxPackageInfo verbosity configFlags globalFlags'
+                              comp platform conf useSandbox $ \mSandboxPkgInfo ->
+                              maybeWithSandboxDirOnSearchPath useSandbox $
+      freeze verbosity
+            (configPackageDB' configFlags)
+            (globalRepos globalFlags')
+            comp platform conf
+            mSandboxPkgInfo
+            globalFlags' freezeFlags
+
 uploadAction :: UploadFlags -> [String] -> GlobalFlags -> IO ()
 uploadAction uploadFlags extraArgs globalFlags = do
   let verbosity = fromFlag (uploadVerbosity uploadFlags)
@@ -780,6 +900,16 @@
   allOk <- Check.check (fromFlag verbosityFlag)
   unless allOk exitFailure
 
+formatAction :: Flag Verbosity -> [String] -> GlobalFlags -> IO ()
+formatAction verbosityFlag extraArgs _globalFlags = do
+  let verbosity = fromFlag verbosityFlag
+  path <- case extraArgs of
+    [] -> do cwd <- getCurrentDirectory
+             tryFindPackageDesc cwd
+    (p:_) -> return p
+  pkgDesc <- readPackageDescription verbosity path
+  -- Uses 'writeFileAtomic' under the hood.
+  writeGenericPackageDescription path pkgDesc
 
 sdistAction :: (SDistFlags, SDistExFlags) -> [String] -> GlobalFlags -> IO ()
 sdistAction (sdistFlags, sdistExFlags) extraArgs _globalFlags = do
@@ -811,15 +941,15 @@
 
   -- reconfigure also checks if we're in a sandbox and reinstalls add-source
   -- deps if needed.
-  useSandbox <- reconfigure verbosity distPref mempty []
-                globalFlags noAddSource (buildNumJobs buildExFlags)
-                (const Nothing)
+  (useSandbox, config) <- reconfigure verbosity distPref mempty []
+                          globalFlags noAddSource (buildNumJobs buildFlags)
+                          (const Nothing)
 
   lbi <- getPersistBuildConfig distPref
   (exe, exeArgs) <- splitRunArgs lbi extraArgs
 
   maybeWithSandboxDirOnSearchPath useSandbox $
-    build verbosity distPref mempty ["exe:" ++ exeName exe]
+    build verbosity config distPref buildFlags ["exe:" ++ exeName exe]
 
   maybeWithSandboxDirOnSearchPath useSandbox $
     run verbosity lbi exe exeArgs
@@ -843,7 +973,7 @@
 initAction :: InitFlags -> [String] -> GlobalFlags -> IO ()
 initAction initFlags _extraArgs globalFlags = do
   let verbosity = fromFlag (initVerbosity initFlags)
-  config <- loadConfig verbosity (globalConfigFile globalFlags) mempty
+  (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags mempty
   let configFlags  = savedConfigureFlags config
   (comp, _, conf) <- configCompilerAux' configFlags
   initCabal verbosity
@@ -886,6 +1016,37 @@
 
   where
     noExtraArgs = (<1) . length
+
+execAction :: ExecFlags -> [String] -> GlobalFlags -> IO ()
+execAction execFlags extraArgs globalFlags = do
+  let verbosity = fromFlag (execVerbosity execFlags)
+  (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags
+                           mempty
+  case extraArgs of
+    (exec:args) -> do
+      case useSandbox of
+          NoSandbox ->
+              rawSystemExit verbosity exec args
+          (UseSandbox sandboxDir) -> do
+              let configFlags = savedConfigureFlags config
+              (comp, platform, conf) <- configCompilerAux' configFlags
+              withSandboxBinDirOnSearchPath sandboxDir $ do
+                  menv <- newEnv sandboxDir comp platform conf verbosity
+                  case menv of
+                      Just env -> rawSystemExitWithEnv verbosity exec args env
+                      Nothing  -> rawSystemExit        verbosity exec args
+    -- Error handling.
+    [] -> die $ "Please specify an executable to run"
+  where
+    newEnv sandboxDir comp platform conf verbosity = do
+        let s = sandboxPackageDBPath sandboxDir comp platform
+        case lookupProgram ghcProgram conf of
+            Nothing -> do
+                debug verbosity "sandbox exec only works with GHC"
+                exitFailure
+            Just ghcProg ->  do
+                g <- ghcGlobalPackageDB verbosity ghcProg
+                getEffectiveEnvironment [("GHC_PACKAGE_PATH", Just $ s ++ ":" ++ g)]
 
 -- | See 'Distribution.Client.Install.withWin32SelfUpgrade' for details.
 --
diff --git a/bootstrap.sh b/bootstrap.sh
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env sh
 
 # A script to bootstrap cabal-install.
 
@@ -12,19 +12,78 @@
 #EXTRA_BUILD_OPTS
 #EXTRA_INSTALL_OPTS
 
+die () { printf "\nError during cabal-install bootstrap:\n$1\n" >&2 && exit 2 ;}
+
 # programs, you can override these by setting environment vars
-GHC=${GHC:-ghc}
-GHC_PKG=${GHC_PKG:-ghc-pkg}
-WGET=${WGET:-wget}
-CURL=${CURL:-curl}
-FETCH=${FETCH:-fetch}
-TAR=${TAR:-tar}
-GUNZIP=${GUNZIP:-gunzip}
+GHC="${GHC:-ghc}"
+GHC_PKG="${GHC_PKG:-ghc-pkg}"
+GHC_VER="$(${GHC} --numeric-version)"
+HADDOCK=${HADDOCK:-haddock}
+WGET="${WGET:-wget}"
+CURL="${CURL:-curl}"
+FETCH="${FETCH:-fetch}"
+TAR="${TAR:-tar}"
+GZIP="${GZIP:-gzip}"
 SCOPE_OF_INSTALLATION="--user"
 DEFAULT_PREFIX="${HOME}/.cabal"
 
+# Try to respect $TMPDIR but override if needed - see #1710.
+[ -"$TMPDIR"- = -""- ] || echo "$TMPDIR" | grep -q ld &&
+  export TMPDIR=/tmp/cabal-$(echo $(od -XN4 -An /dev/random)) && mkdir $TMPDIR
 
-for arg in $*
+# Check for a C compiler.
+[ ! -x "$CC" ] && for ccc in gcc clang cc icc; do
+  ${ccc} --version > /dev/null 2>&1 && CC=$ccc &&
+  echo "Using $CC for C compiler. If this is not what you want, set CC." >&2 &&
+  break
+done
+
+# None found.
+[ ! -x `which "$CC"` ] &&
+  die "C compiler not found (or could not be run).
+       If a C compiler is installed make sure it is on your PATH,
+       or set the CC variable."
+
+# Check the C compiler/linker work.
+LINK="$(for link in collect2 ld; do
+  echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
+  echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep    $link |
+  sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
+done)"
+
+# They don't.
+[ -z "$LINK" ] &&
+  die "C compiler and linker could not compile a simple test program.
+       Please check your toolchain."
+
+## Warn that were's overriding $LD if set (if you want).
+
+[ -x "$LD" ] && [ "$LD" != "$LINK" ] &&
+  echo "Warning: value set in $LD is not the same as C compiler's $LINK." >&2
+  echo "Using $LINK instead." >&2
+
+# Set LD, overriding environment if necessary.
+LD=$LINK
+
+# Check we're in the right directory, etc.
+grep "cabal-install" ./cabal-install.cabal > /dev/null 2>&1 ||
+  die "The bootstrap.sh script must be run in the cabal-install directory"
+
+${GHC} --numeric-version > /dev/null 2>&1  ||
+  die "${GHC} not found (or could not be run).
+       If ghc is installed,  make sure it is on your PATH,
+       or set the GHC and GHC_PKG vars."
+
+${GHC_PKG} --version     > /dev/null 2>&1  || die "${GHC_PKG} not found."
+
+GHC_VER="$(${GHC} --numeric-version)"
+GHC_PKG_VER="$(${GHC_PKG} --version | cut -d' ' -f 5)"
+
+[ ${GHC_VER} = ${GHC_PKG_VER} ] ||
+  die "Version mismatch between ${GHC} and ${GHC_PKG}.
+       If you set the GHC variable then set GHC_PKG too."
+
+for arg in "$@"
 do
   case "${arg}" in
     "--user")
@@ -34,6 +93,9 @@
       SCOPE_OF_INSTALLATION=${arg}
       DEFAULT_PREFIX="/usr/local"
       shift;;
+    "--no-doc")
+      NO_DOCUMENTATION=1
+      shift;;
     *)
       echo "Unknown argument or option, quitting: ${arg}"
       echo "usage: bootstrap.sh [OPTION]"
@@ -41,54 +103,52 @@
       echo "options:"
       echo "   --user    Install for the local user (default)"
       echo "   --global  Install systemwide (must be run as root)"
+      echo "   --no-doc  Do not generate documentation for installed packages"
       exit;;
   esac
 done
 
+# Check for haddock unless no documentation should be generated.
+if [ ! ${NO_DOCUMENTATION} ]
+then
+  ${HADDOCK} --version     > /dev/null 2>&1  || die "${HADDOCK} not found."
+fi
+
 PREFIX=${PREFIX:-${DEFAULT_PREFIX}}
 
 # Versions of the packages to install.
 # The version regex says what existing installed versions are ok.
-PARSEC_VER="3.1.5";    PARSEC_VER_REGEXP="[23]\."              # == 2.* || == 3.*
-DEEPSEQ_VER="1.3.0.2"; DEEPSEQ_VER_REGEXP="1\.[1-9]\."         # >= 1.1 && < 2
-TEXT_VER="1.1.0.0";    TEXT_VER_REGEXP="((1\.[01]\.)|(0\.([2-9]|(1[0-1]))\.))" # >= 0.2 && < 1.2
-NETWORK_VER="2.6.0.2"; NETWORK_VER_REGEXP="2\."                # == 2.*
-CABAL_VER="1.18.1.7";  CABAL_VER_REGEXP="1\.1[89]\."           # >= 1.18 && < 1.20
-TRANS_VER="0.3.0.0";   TRANS_VER_REGEXP="0\.[23]\."            # >= 0.2.* && < 0.4.*
-MTL_VER="2.1.2";       MTL_VER_REGEXP="[2]\."                  #  == 2.*
-HTTP_VER="4000.2.16.1";  HTTP_VER_REGEXP="4000\.[012]\."         # == 4000.0.* || 4000.1.* || 4000.2.*
-ZLIB_VER="0.5.4.1";    ZLIB_VER_REGEXP="0\.[45]\."             # == 0.4.* || == 0.5.*
-TIME_VER="1.4.1";      TIME_VER_REGEXP="1\.[12345]\.?"         # >= 1.1 && < 1.6
-RANDOM_VER="1.0.1.1";  RANDOM_VER_REGEXP="1\.0\."              # >= 1 && < 1.1
-STM_VER="2.4.2";       STM_VER_REGEXP="2\."                    # == 2.*
-NETWORK_URI_VER="2.6.0.1"; NETWORK_URI_VER_REGEXP="2\.[6-9]\." # >= 2.6
-
-HACKAGE_URL="http://hackage.haskell.org/packages/archive"
-
-die () {
-  echo
-  echo "Error during cabal-install bootstrap:"
-  echo $1 >&2
-  exit 2
-}
-
-# Check we're in the right directory:
-grep "cabal-install" ./cabal-install.cabal > /dev/null 2>&1 \
-  || die "The bootstrap.sh script must be run in the cabal-install directory"
+PARSEC_VER="3.1.5";    PARSEC_VER_REGEXP="[23]\."
+                       # == 2.* || == 3.*
+DEEPSEQ_VER="1.3.0.2"; DEEPSEQ_VER_REGEXP="1\.[1-9]\."
+                       # >= 1.1 && < 2
+TEXT_VER="1.1.0.1";    TEXT_VER_REGEXP="((1\.[01]\.)|(0\.([2-9]|(1[0-1]))\.))"
+                       # >= 0.2 && < 1.2
+NETWORK_VER="2.4.2.3"; NETWORK_VER_REGEXP="2\.[0-5]\."
+                       # >= 2.0 && < 2.6
+CABAL_VER="1.20.0.0";  CABAL_VER_REGEXP="1\.2[01]\."
+                       # >= 1.20 && < 1.21
+TRANS_VER="0.3.0.0";   TRANS_VER_REGEXP="0\.[23]\."
+                       # >= 0.2.* && < 0.4.*
+MTL_VER="2.1.3.1";     MTL_VER_REGEXP="[2]\."
+                       #  == 2.*
+HTTP_VER="4000.2.12";  HTTP_VER_REGEXP="4000\.2\.[5-9]"
+                       # >= 4000.2.5 < 4000.3
+ZLIB_VER="0.5.4.1";    ZLIB_VER_REGEXP="0\.[45]\."
+                       # == 0.4.* || == 0.5.*
+TIME_VER="1.4.2"       TIME_VER_REGEXP="1\.[1234]\.?"
+                       # >= 1.1 && < 1.5
+RANDOM_VER="1.0.1.1"   RANDOM_VER_REGEXP="1\.0\."
+                       # >= 1 && < 1.1
+STM_VER="2.4.3";       STM_VER_REGEXP="2\."
+                       # == 2.*
 
-${GHC} --numeric-version > /dev/null \
-  || die "${GHC} not found (or could not be run). If ghc is installed make sure it is on your PATH or set the GHC and GHC_PKG vars."
-${GHC_PKG} --version     > /dev/null \
-  || die "${GHC_PKG} not found."
-GHC_VER=`${GHC} --numeric-version`
-GHC_PKG_VER=`${GHC_PKG} --version | cut -d' ' -f 5`
-[ ${GHC_VER} = ${GHC_PKG_VER} ] \
-  || die "Version mismatch between ${GHC} and ${GHC_PKG} If you set the GHC variable then set GHC_PKG too"
+HACKAGE_URL="https://hackage.haskell.org/package"
 
 # Cache the list of packages:
 echo "Checking installed packages for ghc-${GHC_VER}..."
-${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg.list \
-  || die "running '${GHC_PKG} list' failed"
+${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg.list ||
+  die "running '${GHC_PKG} list' failed"
 
 # Will we need to install this package, or is a suitable version installed?
 need_pkg () {
@@ -120,10 +180,13 @@
   PKG=$1
   VER=$2
 
-  URL=${HACKAGE_URL}/${PKG}/${VER}/${PKG}-${VER}.tar.gz
+  URL=${HACKAGE_URL}/${PKG}-${VER}/${PKG}-${VER}.tar.gz
   if which ${CURL} > /dev/null
   then
-    ${CURL} -L --fail -C - -O ${URL} || die "Failed to download ${PKG}."
+    # TODO: switch back to resuming curl command once
+    #       https://github.com/haskell/hackage-server/issues/111 is resolved
+    #${CURL} -L --fail -C - -O ${URL} || die "Failed to download ${PKG}."
+    ${CURL} -L --fail -O ${URL} || die "Failed to download ${PKG}."
   elif which ${WGET} > /dev/null
   then
     ${WGET} -c ${URL} || die "Failed to download ${PKG}."
@@ -133,21 +196,17 @@
   else
     die "Failed to find a downloader. 'curl', 'wget' or 'fetch' is required."
   fi
-  [ -f "${PKG}-${VER}.tar.gz" ] \
-    || die "Downloading ${URL} did not create ${PKG}-${VER}.tar.gz"
+  [ -f "${PKG}-${VER}.tar.gz" ] ||
+     die "Downloading ${URL} did not create ${PKG}-${VER}.tar.gz"
 }
 
 unpack_pkg () {
   PKG=$1
   VER=$2
 
-  rm -rf "${PKG}-${VER}.tar" "${PKG}-${VER}"/
-  ${GUNZIP} -f "${PKG}-${VER}.tar.gz" \
-    || die "Failed to gunzip ${PKG}-${VER}.tar.gz"
-  ${TAR} -xf "${PKG}-${VER}.tar" \
-    || die "Failed to untar ${PKG}-${VER}.tar.gz"
-  [ -d "${PKG}-${VER}" ] \
-    || die "Unpacking ${PKG}-${VER}.tar.gz did not create ${PKG}-${VER}/"
+  rm -rf "${PKG}-${VER}.tar" "${PKG}-${VER}"
+  ${GZIP} -d < "${PKG}-${VER}.tar.gz" | ${TAR} -x
+  [ -d "${PKG}-${VER}" ] || die "Failed to unpack ${PKG}-${VER}.tar.gz"
 }
 
 install_pkg () {
@@ -156,20 +215,28 @@
   [ -x Setup ] && ./Setup clean
   [ -f Setup ] && rm Setup
 
-  ${GHC} --make Setup -o Setup \
-    || die "Compiling the Setup script failed"
+  ${GHC} --make Setup -o Setup ||
+    die "Compiling the Setup script failed."
+
   [ -x Setup ] || die "The Setup script does not exist or cannot be run"
 
-  ./Setup configure ${SCOPE_OF_INSTALLATION} "--prefix=${PREFIX}" \
-    --with-compiler=${GHC} --with-hc-pkg=${GHC_PKG} \
-    ${EXTRA_CONFIGURE_OPTS} ${VERBOSE} \
-    || die "Configuring the ${PKG} package failed"
+  args="${SCOPE_OF_INSTALLATION} --prefix=${PREFIX} --with-compiler=${GHC}"
+  args="$args --with-hc-pkg=${GHC_PKG} --with-gcc=${CC} --with-ld=${LD}"
+  args="$args ${EXTRA_CONFIGURE_OPTS} ${VERBOSE}"
 
-  ./Setup build ${EXTRA_BUILD_OPTS} ${VERBOSE} \
-    || die "Building the ${PKG} package failed"
+  ./Setup configure $args || die "Configuring the ${PKG} package failed."
 
-  ./Setup install ${SCOPE_OF_INSTALLATION} ${EXTRA_INSTALL_OPTS} ${VERBOSE} \
-    || die "Installing the ${PKG} package failed"
+  ./Setup build ${EXTRA_BUILD_OPTS} ${VERBOSE} ||
+     die "Building the ${PKG} package failed."
+
+  if [ ! ${NO_DOCUMENTATION} ]
+  then
+    ./Setup haddock --with-ghc=${GHC} --with-haddock=${HADDOCK} ${VERBOSE} ||
+      die "Documenting the ${PKG} package failed."
+  fi
+
+  ./Setup install ${SCOPE_OF_INSTALLATION} ${EXTRA_INSTALL_OPTS} ${VERBOSE} ||
+     die "Installing the ${PKG} package failed."
 }
 
 do_pkg () {
@@ -189,25 +256,6 @@
   fi
 }
 
-# Replicate the flag selection logic for network-uri in the .cabal file.
-do_network_uri_pkg () {
-  # Refresh installed package list.
-  ${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg-stage2.list \
-    || die "running '${GHC_PKG} list' failed"
-
-  NETWORK_URI_DUMMY_VER="2.5.0.0"; NETWORK_URI_DUMMY_VER_REGEXP="2\.5\." # < 2.6
-  if egrep " network-2\.[6-9]\." ghc-pkg-stage2.list > /dev/null 2>&1
-  then
-    # Use network >= 2.6 && network-uri >= 2.6
-    info_pkg "network-uri" ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
-    do_pkg   "network-uri" ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
-  else
-    # Use network < 2.6 && network-uri < 2.6
-    info_pkg "network-uri" ${NETWORK_URI_DUMMY_VER} ${NETWORK_URI_DUMMY_VER_REGEXP}
-    do_pkg   "network-uri" ${NETWORK_URI_DUMMY_VER} ${NETWORK_URI_DUMMY_VER_REGEXP}
-  fi
-}
-
 # Actually do something!
 
 info_pkg "deepseq"      ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
@@ -231,10 +279,6 @@
 do_pkg   "text"         ${TEXT_VER}    ${TEXT_VER_REGEXP}
 do_pkg   "parsec"       ${PARSEC_VER}  ${PARSEC_VER_REGEXP}
 do_pkg   "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
-
-# We conditionally install network-uri, depending on the network version.
-do_network_uri_pkg
-
 do_pkg   "HTTP"         ${HTTP_VER}    ${HTTP_VER_REGEXP}
 do_pkg   "zlib"         ${ZLIB_VER}    ${ZLIB_VER_REGEXP}
 do_pkg   "random"       ${RANDOM_VER}  ${RANDOM_VER_REGEXP}
diff --git a/cabal-install.cabal b/cabal-install.cabal
--- a/cabal-install.cabal
+++ b/cabal-install.cabal
@@ -1,5 +1,5 @@
 Name:               cabal-install
-Version:            1.18.2.0
+Version:            1.20.0.0
 Synopsis:           The command-line interface for Cabal and Hackage.
 Description:
     The \'cabal\' command-line program simplifies the process of managing
@@ -34,10 +34,6 @@
   description:  Use directory < 1.2 and old-time
   default:      False
 
-flag network-uri
-  description: Get Network.URI from the network-uri package
-  default: True
-
 executable cabal
     main-is:        Main.hs
     ghc-options:    -Wall -fwarn-tabs
@@ -75,6 +71,7 @@
         Distribution.Client.Dependency.Modular.Version
         Distribution.Client.Fetch
         Distribution.Client.FetchUtils
+        Distribution.Client.Freeze
         Distribution.Client.Get
         Distribution.Client.GZipUtils
         Distribution.Client.Haddock
@@ -110,7 +107,9 @@
         Distribution.Client.World
         Distribution.Client.Win32SelfUpgrade
         Distribution.Client.Compat.Environment
+        Distribution.Client.Compat.ExecutablePath
         Distribution.Client.Compat.FilePerms
+        Distribution.Client.Compat.Process
         Distribution.Client.Compat.Semaphore
         Distribution.Client.Compat.Time
         Paths_cabal_install
@@ -119,18 +118,18 @@
     -- in bootstrap.sh.
     build-depends:
         array      >= 0.1      && < 0.6,
-        base       >= 4        && < 4.8,
+        base       >= 4.3      && < 5,
         bytestring >= 0.9      && < 1,
-        Cabal      >= 1.18.0   && < 1.19,
+        Cabal      >= 1.20.0   && < 1.21,
         containers >= 0.1      && < 0.6,
         filepath   >= 1.0      && < 1.4,
-        HTTP       >= 4000.0.8 && < 4001,
+        HTTP       >= 4000.2.5 && < 4000.3,
         mtl        >= 2.0      && < 3,
-        network    >= 1        && < 3,
+        network    >= 2.0      && < 2.6,
         pretty     >= 1        && < 1.2,
-        random     >= 1        && < 1.2,
+        random     >= 1        && < 1.1,
         stm        >= 2.0      && < 3,
-        time       >= 1.1      && < 1.6,
+        time       >= 1.1      && < 1.5,
         zlib       >= 0.5.3    && < 0.6
 
     if flag(old-directory)
@@ -140,11 +139,6 @@
       build-depends: directory >= 1.2 && < 1.3,
                      process   >= 1.1.0.2  && < 1.3
 
-    if flag(network-uri)
-      build-depends: network-uri >= 2.6, network >= 2.6
-    else
-      build-depends: network-uri < 2.6, network < 2.6
-
     if os(windows)
       build-depends: Win32 >= 2 && < 3
       cpp-options: -DWIN32
@@ -152,7 +146,7 @@
       build-depends: unix >= 2.0 && < 2.8
 
     if arch(arm) && impl(ghc < 7.6)
-       -- older ghc on arm does not supprt -threaded
+       -- older ghc on arm does not support -threaded
        cc-options:  -DCABAL_NO_THREADED
     else
        ghc-options: -threaded
@@ -176,12 +170,14 @@
         Cabal,
         containers,
         mtl,
+        network,
         pretty,
         process,
         directory,
         filepath,
         stm,
         time,
+        network,
         HTTP,
         zlib,
 
@@ -193,11 +189,6 @@
 
   if flag(old-directory)
     build-depends: old-time
-
-  if flag(network-uri)
-    build-depends: network-uri >= 2.6, network >= 2.6
-  else
-    build-depends: network-uri < 2.6, network < 2.6
 
   if os(windows)
     build-depends: Win32
