content: {-# LANGUAGE NoImplicitPrelude, OverloadedStrings, FlexibleContexts #-}
  
  module IHaskell.BrokenPackages (getBrokenPackages) where
  
  import           IHaskellPrelude
  import qualified Data.Text as T
  
  import           Text.Parsec
  import           Text.Parsec.String
  
  import           Shelly
  
  data BrokenPackage = BrokenPackage String [String]
  
  instance Show BrokenPackage where
    show (BrokenPackage packageID _) = packageID
  
  -- | Get a list of broken packages. This function internally shells out to `ghc-pkg`, and parses the
  -- output in order to determine what packages are broken.
  getBrokenPackages :: IO [String]
  getBrokenPackages = shelly $ do
    _ <- silently $ errExit False $ run "ghc-pkg" ["check"]
    checkOut <- lastStderr
  
    -- Get rid of extraneous things
    let rightStart str = "There are problems" `isPrefixOf` str ||
                         "  dependency" `isPrefixOf` str
        ghcPkgOutput = unlines . filter rightStart . lines $ T.unpack checkOut
  
    return $
      case parse (many check) "ghc-pkg output" ghcPkgOutput of
        Left _     -> []
        Right pkgs -> map show pkgs
  
  check :: Parser BrokenPackage
  check = string "There are problems in package "
          >> BrokenPackage <$> ident <* string ":\n" <*> many1 dependency
  
  ident :: Parser String
  ident = many (alphaNum <|> oneOf "-.")
  
  dependency :: Parser String
  dependency = string "  dependency \"" *> ident <* string "\" doesn't exist\n"
  