module Main where import Data.List (intercalate) import System.Environment (getArgs) import System.Process (system, runInteractiveCommand) import System.Exit (ExitCode(..)) import System.IO (hGetContents, hFlush, stdout) import System.Directory (doesDirectoryExist, removeDirectoryRecursive) import System.FilePath (takeDirectory, dropTrailingPathSeparator, splitDirectories) import Control.Monad.Instances () main :: IO () main = do input <- getArgs case input of package:args -> do let useForce = parseForceArg args res <- directoryOfPackage package case (res, useForce) of (Left err , _ ) -> putStr err (_ , Nothing ) -> putStrLn usageInfo (Right packageDir, Just force) -> do exitcode <- unregisterPackage package force case exitcode of ExitFailure _ -> return () ExitSuccess -> do b <- doesDirectoryExist packageDir if b then removePackageDirectory packageDir else putStrLn "package directory already deleted" _ -> putStrLn usageInfo usageInfo :: String usageInfo = "usage: cabal-uninstall [--force]\n\ \use sudo if the package is installed globally" internalErrorInfo :: String internalErrorInfo = "internal error: please contact Jan Christiansen (info@monoid-it.de)" multiplePackagesInfo :: [String] -> String multiplePackagesInfo packages = "There are multiple packages you might refer to, namely\n" ++ " " ++ intercalate ", " packages ++ "\n" ++ "please reinvoke cabal-uninstall and specify the version of the package\n" ++ "(for example 'cabal-uninstall parsec-3.1.3')\n." parseForceArg :: [String] -> Maybe Bool parseForceArg [] = Just False parseForceArg ["--force"] = Just True parseForceArg _ = Nothing directoryOfPackage :: String -> IO (Either String FilePath) directoryOfPackage package = do let command = "ghc-pkg field " ++ package ++ " library-dirs" (_, hout, herr, _) <- runInteractiveCommand command result <- hGetContents hout case result of [] -> hGetContents herr >>= return . Left _ -> return (packageDir (words result)) where packageDir libDirs = case extractLibDirs libDirs of Right [packDir] -> Right packDir Right packDirs -> Left (multiplePackagesInfo (map (last . splitDirectories) packDirs)) Left err -> Left err extractLibDirs :: [String] -> Either String [String] extractLibDirs [] = Right [] extractLibDirs ("library-dirs:":libDir:libDirs) = do packDirs <- extractLibDirs libDirs return (takeDirectory (dropTrailingPathSeparator libDir):packDirs) extractLibDirs _ = Left internalErrorInfo removePackageDirectory :: FilePath -> IO () removePackageDirectory packageDir = do putStr ("delete library directory " ++ packageDir ++ "? (yes/no)") hFlush stdout choice <- getLine case choice of "yes" -> removeDirectoryRecursive packageDir _ -> return () unregisterPackage :: String -> Bool -> IO ExitCode unregisterPackage package force = do putStrLn "unregistering package" system ("ghc-pkg unregister " ++ useForce force ++ package) where useForce True = "--force " useForce False = ""