upgradeCabal :: (MonadIO m, MonadLogger m, MonadReader env m, HasHttpManager env, HasConfig env, MonadBaseControl IO m, MonadMask m)
             => EnvOverride
             -> m ()
upgradeCabal menv = do
    let name = $(mkPackageName "Cabal")
    rmap <- resolvePackages menv Set.empty (Set.singleton name)
    newest <-
        case Map.keys rmap of
            [] -> error "No Cabal library found in index, cannot upgrade"
            [PackageIdentifier name' version]
                | name == name' -> return version
            x -> error $ "Unexpected results for resolvePackages: " ++ show x
    installed <- getCabalPkgVer menv
    if installed >= newest
        then $logInfo $ T.concat
            [ "Currently installed Cabal is "
            , T.pack $ versionString installed
            , ", newest is "
            , T.pack $ versionString newest
            , ". I'm not upgrading Cabal."
            ]
        else withSystemTempDirectory "stack-cabal-upgrade" $ \tmpdir -> do
            $logInfo $ T.concat
                [ "Installing Cabal-"
                , T.pack $ versionString newest
                , " to replace "
                , T.pack $ versionString installed
                ]
            tmpdir' <- parseAbsDir tmpdir
            let ident = PackageIdentifier name newest
            m <- unpackPackageIdents menv tmpdir' Nothing (Set.singleton ident)

            ghcPath <- join $ findExecutable menv "ghc"
            newestDir <- parseRelDir $ versionString newest
            let installRoot = toFilePath $ parent (parent ghcPath)
                                       </> $(mkRelDir "new-cabal")
                                       </> newestDir

            dir <-
                case Map.lookup ident m of
                    Nothing -> error $ "upgradeCabal: Invariant violated, dir missing"
                    Just dir -> return dir

            runIn dir "ghc" menv ["Setup.hs"] Nothing
            let setupExe = toFilePath $ dir </> $(mkRelFile "Setup")
                dirArgument name' = concat
                    [ "--"
                    , name'
                    , "dir="
                    , installRoot FP.</> name'
                    ]
            runIn dir setupExe menv
                ( "configure"
                : map dirArgument (words "lib bin data doc")
                )
                Nothing
            runIn dir setupExe menv ["build"] Nothing
            runIn dir setupExe menv ["install"] Nothing
            $logInfo "New Cabal library installed"

-- | Get the major version of the system GHC, if available
upgradeCabal :: (MonadIO m, MonadLogger m, MonadReader env m, HasHttpManager env, HasConfig env, MonadBaseControl IO m, MonadMask m)
             => EnvOverride
             -> m ()
upgradeCabal menv = do
    let name = $(mkPackageName "Cabal")
    rmap <- resolvePackages menv Set.empty (Set.singleton name)
    newest <-
        case Map.keys rmap of
            [] -> error "No Cabal library found in index, cannot upgrade"
            [PackageIdentifier name' version]
                | name == name' -> return version
            x -> error $ "Unexpected results for resolvePackages: " ++ show x
    installed <- getCabalPkgVer menv
    if installed >= newest
        then $logInfo $ T.concat
            [ "Currently installed Cabal is "
            , T.pack $ versionString installed
            , ", newest is "
            , T.pack $ versionString newest
            , ". I'm not upgrading Cabal."
            ]
        else withSystemTempDirectory "stack-cabal-upgrade" $ \tmpdir -> do
            $logInfo $ T.concat
                [ "Installing Cabal-"
                , T.pack $ versionString newest
                , " to replace "
                , T.pack $ versionString installed
                ]
            tmpdir' <- parseAbsDir tmpdir
            let ident = PackageIdentifier name newest
            m <- unpackPackageIdents menv tmpdir' Nothing (Set.singleton ident)

            ghcPath <- join $ findExecutable menv "ghc"
            newestDir <- parseRelDir $ versionString newest
            let installRoot = toFilePath $ parent (parent ghcPath)
                                       </> $(mkRelDir "new-cabal")
                                       </> newestDir

            dir <-
                case Map.lookup ident m of
                    Nothing -> error $ "upgradeCabal: Invariant violated, dir missing"
                    Just dir -> return dir

            runIn dir "ghc" menv ["Setup.hs"] Nothing
            let setupExe = toFilePath $ dir </> $(mkRelFile "Setup")
                dirArgument name' = concat
                    [ "--"
                    , name'
                    , "dir="
                    , installRoot FP.</> name'
                    ]
            runIn dir setupExe menv
                ( "configure"
                : map dirArgument (words "lib bin data doc")
                )
                Nothing
            runIn dir setupExe menv ["build"] Nothing
            runIn dir setupExe menv ["install"] Nothing
            $logInfo "New Cabal library installed"

-- | Get the major version of the system GHC, if available
upgradeCabal menv = do
    let name = $(mkPackageName "Cabal")
    rmap <- resolvePackages menv Set.empty (Set.singleton name)
    newest <-
        case Map.keys rmap of
            [] -> error "No Cabal library found in index, cannot upgrade"
            [PackageIdentifier name' version]
                | name == name' -> return version
            x -> error $ "Unexpected results for resolvePackages: " ++ show x
    installed <- getCabalPkgVer menv
    if installed >= newest
        then $logInfo $ T.concat
            [ "Currently installed Cabal is "
            , T.pack $ versionString installed
            , ", newest is "
            , T.pack $ versionString newest
            , ". I'm not upgrading Cabal."
            ]
        else withSystemTempDirectory "stack-cabal-upgrade" $ \tmpdir -> do
            $logInfo $ T.concat
                [ "Installing Cabal-"
                , T.pack $ versionString newest
                , " to replace "
                , T.pack $ versionString installed
                ]
            tmpdir' <- parseAbsDir tmpdir
            let ident = PackageIdentifier name newest
            m <- unpackPackageIdents menv tmpdir' Nothing (Set.singleton ident)

            ghcPath <- join $ findExecutable menv "ghc"
            newestDir <- parseRelDir $ versionString newest
            let installRoot = toFilePath $ parent (parent ghcPath)
                                       </> $(mkRelDir "new-cabal")
                                       </> newestDir

            dir <-
                case Map.lookup ident m of
                    Nothing -> error $ "upgradeCabal: Invariant violated, dir missing"
                    Just dir -> return dir

            runIn dir "ghc" menv ["Setup.hs"] Nothing
            let setupExe = toFilePath $ dir </> $(mkRelFile "Setup")
                dirArgument name' = concat
                    [ "--"
                    , name'
                    , "dir="
                    , installRoot FP.</> name'
                    ]
            runIn dir setupExe menv
                ( "configure"
                : map dirArgument (words "lib bin data doc")
                )
                Nothing
            runIn dir setupExe menv ["build"] Nothing
            runIn dir setupExe menv ["install"] Nothing
            $logInfo "New Cabal library installed"

-- | Get the major version of the system GHC, if available