licensor-0.5.0: app/Main.hs
----------------------------------------------------------------------
-- |
-- Module: Main
-- Description:
--
--
--
----------------------------------------------------------------------
module Main
( main
)
where
-- Cabal
import Distribution.PackageDescription
import Distribution.Text
-- base
import Control.Monad (unless, when)
import Data.Foldable (for_, traverse_)
import Data.List (foldl', intercalate)
import Data.Version (showVersion)
import System.Console.GetOpt
import System.Environment (getArgs, getProgName)
import System.Exit (die, exitFailure, exitSuccess)
import System.IO (hPutStrLn, stderr, stdout)
-- containers
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
-- directory
import System.Directory (doesFileExist)
-- licensor
import Licensor
prettyUsageInfo :: String -> String
prettyUsageInfo progName =
"usage: " <> usageInfo progName optDescrs
prettyVersion :: String -> String
prettyVersion progName =
unwords [progName, showVersion version]
optDescrs :: [OptDescr ((Bool, Bool) -> IO (Bool, Bool))]
optDescrs =
[ Option ['q', 's'] ["quiet", "silent"]
(NoArg (\(_, b) -> pure (False, b)))
"Quiet/silent mode"
, Option [] ["licenses"]
(NoArg (\(a, _) -> pure (a, True)))
"Fetch license files"
, Option ['h'] ["help"]
(NoArg (\_ -> exitWith prettyUsageInfo))
"Display help message"
, Option ['V'] ["version"]
(NoArg (\_ -> exitWith prettyVersion))
"Print version information"
]
where
exitWith f = do
progName <- getProgName
hPutStrLn stdout (f progName)
exitSuccess
main :: IO ()
main = do
args <- getArgs
progName <- getProgName
case getOpt' Permute optDescrs args of
(opts, [], [], []) -> do
verbose <- foldl' (>>=) (pure (True, False)) opts
main' verbose
(_, command:_, _, _) -> do
hPutStrLn stderr ("unknown command: " <> command)
hPutStrLn stderr (prettyUsageInfo progName)
exitFailure
(_, _, option:_, _) -> do
hPutStrLn stderr ("unknown option: " <> option)
hPutStrLn stderr (prettyUsageInfo progName)
exitFailure
(_, _, _, _) -> do
hPutStrLn stderr (prettyUsageInfo progName)
exitFailure
main' :: (Bool, Bool) -> IO ()
main' (verbose, fetchLicenses) = do
let silent = not verbose
maybePackage <- getPackage
pid <-
case maybePackage of
Nothing -> do
stack <- doesFileExist "stack.yaml"
if stack
then do
putStrLn "Found stack.yaml..."
pure Nothing
else
die "Error: No stack.yaml file found."
Just pd -> do
when fetchLicenses $ do
putStrLn $ "# " <> display (package pd)
putStrLn ""
putStrLn $
"Package: "
<> display (package pd)
<> " ("
<> "License: "
<> display (license pd)
<> ")"
pure (Just $ package pd)
maybeDependencies <- getDependencies
maybeLicenses <- getLicenses
case (maybeDependencies, maybeLicenses) of
(Just dependencies, Just licenses) -> do
(dependenciesByLicense, failed) <-
orderPackagesByLicense silent pid licenses dependencies
for_ (Map.keys dependenciesByLicense) $
\li ->
let
n = dependenciesByLicense Map.! li
in do
when fetchLicenses $ do
putStrLn ""
putStrLn $ "## " <> display li
putStrLn ""
putStrLn $
show (Set.size n)
<> (if Set.size n == 1 then " package " else " packages ")
<> "licensed under "
<> display li
<> ": "
<> intercalate ", " (Set.toList (Set.map display n))
when fetchLicenses $
traverse_ getPackageLicenseFiles (Set.toList n)
unless (null failed) $ do
putStr "Failed: "
print failed
_ ->
die "Error: Unable to run 'stack ls dependencies'"