packages feed

cabal-install 1.18.2.0 → 1.20.0.0

raw patch · 53 files changed

+2956/−1310 lines, 53 filesdep −network-uridep ~Cabaldep ~HTTPdep ~base

Dependencies removed: network-uri

Dependency ranges changed: Cabal, HTTP, base, network, random, time

Files

Distribution/Client/BuildReports/Anonymous.hs view
@@ -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 =
Distribution/Client/BuildReports/Storage.hs view
@@ -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
Distribution/Client/Compat/Environment.hs view
@@ -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_ 
+ Distribution/Client/Compat/ExecutablePath.hs view
@@ -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
+ Distribution/Client/Compat/Process.hs view
@@ -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
Distribution/Client/Config.hs view
@@ -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)]]
Distribution/Client/Configure.hs view
@@ -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
Distribution/Client/Dependency.hs view
@@ -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
Distribution/Client/Dependency/Modular.hs view
@@ -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) 
Distribution/Client/Dependency/Modular/Builder.hs view
@@ -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
Distribution/Client/Dependency/Modular/Dependency.hs view
@@ -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)
Distribution/Client/Dependency/Modular/Explore.hs view
@@ -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.
Distribution/Client/Dependency/Modular/Flag.hs view
@@ -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.
Distribution/Client/Dependency/Modular/IndexConversion.hs view
@@ -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
Distribution/Client/Dependency/Modular/PSQ.hs view
@@ -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.
Distribution/Client/Dependency/Modular/Preference.hs view
@@ -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
Distribution/Client/Dependency/Modular/Solver.hs view
@@ -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
Distribution/Client/Dependency/Modular/Tree.hs view
@@ -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)
Distribution/Client/Dependency/Modular/Validate.hs view
@@ -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.
Distribution/Client/Dependency/Modular/Version.hs view
@@ -40,4 +40,3 @@ -- | Make a version number. mkV :: [Int] -> Ver mkV xs = CV.Version xs []-
Distribution/Client/Dependency/Types.hs view
@@ -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
Distribution/Client/Fetch.hs view
@@ -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)  
+ Distribution/Client/Freeze.hs view
@@ -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
Distribution/Client/Get.hs view
@@ -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.
Distribution/Client/Haddock.hs view
@@ -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-
Distribution/Client/HttpUtils.hs view
@@ -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
Distribution/Client/IndexUtils.hs view
@@ -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
Distribution/Client/Init.hs view
@@ -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              ])
Distribution/Client/Init/Heuristics.hs view
@@ -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
Distribution/Client/Init/Licenses.hs view
@@ -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."     ]
Distribution/Client/Init/Types.hs view
@@ -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
Distribution/Client/Install.hs view
@@ -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
Distribution/Client/InstallPlan.hs view
@@ -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.
Distribution/Client/InstallSymlink.hs view
@@ -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).
Distribution/Client/List.hs view
@@ -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,
Distribution/Client/PackageIndex.hs view
@@ -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.
Distribution/Client/ParseUtils.hs view
@@ -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
Distribution/Client/Sandbox.hs view
@@ -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?         } 
Distribution/Client/Sandbox/Index.hs view
@@ -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.
Distribution/Client/Sandbox/PackageEnvironment.hs view
@@ -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
Distribution/Client/Sandbox/Timestamp.hs view
@@ -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 {
Distribution/Client/Setup.hs view
@@ -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   ]  
Distribution/Client/SetupWrapper.hs view
@@ -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
Distribution/Client/SrcDist.hs view
@@ -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.
Distribution/Client/Tar.hs view
@@ -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
Distribution/Client/Targets.hs view
@@ -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,
Distribution/Client/Types.hs view
@@ -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
Distribution/Client/Upload.hs view
@@ -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 "--"
Distribution/Client/Utils.hs view
@@ -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
Distribution/Client/Win32SelfUpgrade.hs view
@@ -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
Main.hs view
@@ -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. --
bootstrap.sh view
@@ -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}
cabal-install.cabal view
@@ -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