cabalUnpack :: FilePath -> Text -> Bool -> Maybe Text -> C.Sink ToolOutput IDEM () -> (FilePath -> IDEAction) -> IDEAction
cabalUnpack parentDir packageToUnpack sourceRepo mbNewName log activateAction = do
    let tempDir = parentDir </> (T.unpack packageToUnpack ++ ".leksah.temp")
    liftIO $ do
        oldDirExists <- doesDirectoryExist tempDir
        when oldDirExists $ removeDirectoryRecursive tempDir
        createDirectory tempDir
    runExternalTool' (__ "Unpacking") "cabal" (["unpack"]
              ++ (if sourceRepo then ["--source-repository"] else [])
              ++ ["--destdir=" <> T.pack tempDir, packageToUnpack]) tempDir $ do
        mbLastOutput <- C.getZipSink $ const <$> C.ZipSink sinkLast <*> C.ZipSink log
        case mbLastOutput of
            Just (ToolExit ExitSuccess) -> do
                contents <- liftIO $ getDirectoryContents tempDir
                case filter (not . isPrefixOf ".") contents of
                    [] -> do
                        liftIO $ removeDirectoryRecursive tempDir
                        lift $ ideMessage High $ "Nothing found in " <> T.pack tempDir <> " after doing a cabal unpack."
                    [repoName] -> do
                        let destDir = parentDir </> (fromMaybe repoName $ T.unpack <$> mbNewName)
                        exists <- liftIO $ (||) <$> doesDirectoryExist destDir <*> doesFileExist destDir
                        if exists
                            then lift $ ideMessage High $ T.pack destDir <> " already exists"
                            else do
                                liftIO $ renameDirectory (tempDir </> repoName) destDir
                                mbCabalFile <- liftIO $ cabalFileName destDir
                                window <- lift $ getMainWindow
                                lift $ case (mbCabalFile, mbNewName) of
                                    (Just cfn, Just newName) -> do
                                        let newCfn = takeDirectory cfn </> (T.unpack newName) ++ ".cabal"
                                        when (cfn /= newCfn) . liftIO $ do
                                            s <- T.readFile cfn
                                            T.writeFile newCfn $ renameCabalFile (T.pack $ takeBaseName cfn) newName s
                                            removeFile cfn
                                        activateAction newCfn
                                    (Just cfn, _) -> activateAction cfn
                                    _  -> ideMessage High $ "Unpacked source reposity to " <> T.pack destDir <> " but it does not contain a .cabal file in the root directory."
                        liftIO $ removeDirectoryRecursive tempDir
                    _ -> do
                        liftIO $ removeDirectoryRecursive tempDir
                        lift $ ideMessage High $ "More than one subdirectory found in " <> T.pack tempDir <> " after doing a cabal unpack."

            _ -> do
                liftIO $ removeDirectoryRecursive tempDir
                lift $ ideMessage High $ "Failed to unpack source reposity to " <> T.pack tempDir
cabalUnpack :: FilePath -> Text -> Bool -> Maybe Text -> C.Sink ToolOutput IDEM () -> (FilePath -> IDEAction) -> IDEAction
cabalUnpack parentDir packageToUnpack sourceRepo mbNewName log activateAction = do
    let tempDir = parentDir </> (T.unpack packageToUnpack ++ ".leksah.temp")
    liftIO $ do
        oldDirExists <- doesDirectoryExist tempDir
        when oldDirExists $ removeDirectoryRecursive tempDir
        createDirectory tempDir
    runExternalTool' (__ "Unpacking") "cabal" (["unpack"]
              ++ (if sourceRepo then ["--source-repository"] else [])
              ++ ["--destdir=" <> T.pack tempDir, packageToUnpack]) tempDir $ do
        mbLastOutput <- C.getZipSink $ const <$> C.ZipSink sinkLast <*> C.ZipSink log
        case mbLastOutput of
            Just (ToolExit ExitSuccess) -> do
                contents <- liftIO $ getDirectoryContents tempDir
                case filter (not . isPrefixOf ".") contents of
                    [] -> do
                        liftIO $ removeDirectoryRecursive tempDir
                        lift $ ideMessage High $ "Nothing found in " <> T.pack tempDir <> " after doing a cabal unpack."
                    [repoName] -> do
                        let destDir = parentDir </> (fromMaybe repoName $ T.unpack <$> mbNewName)
                        exists <- liftIO $ (||) <$> doesDirectoryExist destDir <*> doesFileExist destDir
                        if exists
                            then lift $ ideMessage High $ T.pack destDir <> " already exists"
                            else do
                                liftIO $ renameDirectory (tempDir </> repoName) destDir
                                mbCabalFile <- liftIO $ cabalFileName destDir
                                window <- lift $ getMainWindow
                                lift $ case (mbCabalFile, mbNewName) of
                                    (Just cfn, Just newName) -> do
                                        let newCfn = takeDirectory cfn </> (T.unpack newName) ++ ".cabal"
                                        when (cfn /= newCfn) . liftIO $ do
                                            s <- T.readFile cfn
                                            T.writeFile newCfn $ renameCabalFile (T.pack $ takeBaseName cfn) newName s
                                            removeFile cfn
                                        activateAction newCfn
                                    (Just cfn, _) -> activateAction cfn
                                    _  -> ideMessage High $ "Unpacked source reposity to " <> T.pack destDir <> " but it does not contain a .cabal file in the root directory."
                        liftIO $ removeDirectoryRecursive tempDir
                    _ -> do
                        liftIO $ removeDirectoryRecursive tempDir
                        lift $ ideMessage High $ "More than one subdirectory found in " <> T.pack tempDir <> " after doing a cabal unpack."

            _ -> do
                liftIO $ removeDirectoryRecursive tempDir
                lift $ ideMessage High $ "Failed to unpack source reposity to " <> T.pack tempDir
cabalUnpack parentDir packageToUnpack sourceRepo mbNewName log activateAction = do
    let tempDir = parentDir </> (T.unpack packageToUnpack ++ ".leksah.temp")
    liftIO $ do
        oldDirExists <- doesDirectoryExist tempDir
        when oldDirExists $ removeDirectoryRecursive tempDir
        createDirectory tempDir
    runExternalTool' (__ "Unpacking") "cabal" (["unpack"]
              ++ (if sourceRepo then ["--source-repository"] else [])
              ++ ["--destdir=" <> T.pack tempDir, packageToUnpack]) tempDir $ do
        mbLastOutput <- C.getZipSink $ const <$> C.ZipSink sinkLast <*> C.ZipSink log
        case mbLastOutput of
            Just (ToolExit ExitSuccess) -> do
                contents <- liftIO $ getDirectoryContents tempDir
                case filter (not . isPrefixOf ".") contents of
                    [] -> do
                        liftIO $ removeDirectoryRecursive tempDir
                        lift $ ideMessage High $ "Nothing found in " <> T.pack tempDir <> " after doing a cabal unpack."
                    [repoName] -> do
                        let destDir = parentDir </> (fromMaybe repoName $ T.unpack <$> mbNewName)
                        exists <- liftIO $ (||) <$> doesDirectoryExist destDir <*> doesFileExist destDir
                        if exists
                            then lift $ ideMessage High $ T.pack destDir <> " already exists"
                            else do
                                liftIO $ renameDirectory (tempDir </> repoName) destDir
                                mbCabalFile <- liftIO $ cabalFileName destDir
                                window <- lift $ getMainWindow
                                lift $ case (mbCabalFile, mbNewName) of
                                    (Just cfn, Just newName) -> do
                                        let newCfn = takeDirectory cfn </> (T.unpack newName) ++ ".cabal"
                                        when (cfn /= newCfn) . liftIO $ do
                                            s <- T.readFile cfn
                                            T.writeFile newCfn $ renameCabalFile (T.pack $ takeBaseName cfn) newName s
                                            removeFile cfn
                                        activateAction newCfn
                                    (Just cfn, _) -> activateAction cfn
                                    _  -> ideMessage High $ "Unpacked source reposity to " <> T.pack destDir <> " but it does not contain a .cabal file in the root directory."
                        liftIO $ removeDirectoryRecursive tempDir
                    _ -> do
                        liftIO $ removeDirectoryRecursive tempDir
                        lift $ ideMessage High $ "More than one subdirectory found in " <> T.pack tempDir <> " after doing a cabal unpack."

            _ -> do
                liftIO $ removeDirectoryRecursive tempDir
                lift $ ideMessage High $ "Failed to unpack source reposity to " <> T.pack tempDir