Skip to content

Commit d4d4dfa

Browse files
author
Lennart Spitzner
committed
Add "status" command
The "status" command prints a summary over several aspects of a cabal environment, such as the cabal and ghc versions, the package and its components, the package-databases, the sandbox etc.
1 parent 109cd83 commit d4d4dfa

File tree

12 files changed

+631
-24
lines changed

12 files changed

+631
-24
lines changed

Cabal/Distribution/Simple/Configure.hs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module Distribution.Simple.Configure (configure,
4040
computeComponentId,
4141
localBuildInfoFile,
4242
getInstalledPackages, getPackageDBContents,
43+
checkPackageDBs,
4344
configCompiler, configCompilerAux,
4445
configCompilerEx, configCompilerAuxEx,
4546
ccLdOptionsBuildInfo,
@@ -105,7 +106,7 @@ import Distribution.Simple.LocalBuildInfo
105106
import Distribution.Simple.BuildPaths
106107
( autogenModulesDir )
107108
import Distribution.Simple.Utils
108-
( die, warn, info, setupMessage
109+
( die, warn, info, debug, setupMessage
109110
, createDirectoryIfMissingVerbose, moreRecentFile
110111
, intercalate, cabalVersion
111112
, writeFileAtomic
@@ -928,6 +929,29 @@ getInstalledPackages verbosity comp packageDBs progconf = do
928929
flv -> die $ "don't know how to find the installed packages for "
929930
++ display flv
930931

932+
-- | Check the consistency of the given package databases.
933+
checkPackageDBs :: Verbosity -> Compiler
934+
-> PackageDBStack -- ^ The stack of package databases.
935+
-> ProgramConfiguration
936+
-> IO [(PackageDB, [String])]
937+
checkPackageDBs verbosity comp packageDBs progconf = do
938+
when (null packageDBs) $
939+
die $ "No package databases have been specified. If you use "
940+
++ "--package-db=clear, you must follow it with --package-db= "
941+
++ "with 'global', 'user' or a specific file."
942+
943+
debug verbosity "checking package-db..."
944+
case compilerFlavor comp of
945+
GHC -> GHC.checkPackageDBs verbosity comp packageDBs progconf
946+
-- GHCJS -> GHCJS.checkPackageDBs verbosity packageDBs progconf
947+
-- JHC -> JHC.checkPackageDBs verbosity packageDBs progconf
948+
-- LHC -> LHC.checkPackageDBs verbosity packageDBs progconf
949+
-- UHC -> UHC.checkPackageDBs verbosity comp packageDBs progconf
950+
-- HaskellSuite {} ->
951+
-- HaskellSuite.checkPackageDBs verbosity packageDBs progconf
952+
flv -> die $ "don't know how to check the packages database for "
953+
++ display flv
954+
931955
-- | Like 'getInstalledPackages', but for a single package DB.
932956
getPackageDBContents :: Verbosity -> Compiler
933957
-> PackageDB -> ProgramConfiguration

Cabal/Distribution/Simple/GHC.hs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
module Distribution.Simple.GHC (
3434
getGhcInfo,
35-
configure, getInstalledPackages, getPackageDBContents,
35+
configure, getInstalledPackages, checkPackageDBs, getPackageDBContents,
3636
buildLib, buildExe,
3737
replLib, replExe,
3838
startInterpreter,
@@ -287,6 +287,17 @@ getInstalledPackages verbosity comp packagedbs conf = do
287287
_ -> index -- No (or multiple) ghc rts package is registered!!
288288
-- Feh, whatever, the ghc test suite does some crazy stuff.
289289

290+
-- | Check the consistency of the given package databases.
291+
checkPackageDBs :: Verbosity -> Compiler -> PackageDBStack -> ProgramConfiguration
292+
-> IO [(PackageDB, [String])]
293+
checkPackageDBs verbosity comp packagedbs conf = do
294+
checkPackageDbEnvVar
295+
checkPackageDbStack comp packagedbs
296+
sequence
297+
[ do strs <- HcPkg.check (hcPkgInfo conf) verbosity packagedb
298+
return (packagedb, strs)
299+
| packagedb <- packagedbs ]
300+
290301
-- | Given a list of @(PackageDB, InstalledPackageInfo)@ pairs, produce a
291302
-- @PackageIndex@. Helper function used by 'getPackageDBContents' and
292303
-- 'getInstalledPackages'.

Cabal/Distribution/Simple/Program/HcPkg.hs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module Distribution.Simple.Program.HcPkg (
2121
hide,
2222
dump,
2323
describe,
24+
check,
2425
list,
2526

2627
-- * Program invocations
@@ -57,7 +58,7 @@ import Distribution.Simple.Utils
5758
import Distribution.Verbosity
5859
( Verbosity, deafening, silent )
5960
import Distribution.Compat.Exception
60-
( catchIO )
61+
( catchIO, catchExit )
6162

6263
import Data.Char
6364
( isSpace )
@@ -209,6 +210,14 @@ splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines
209210
_:ws -> splitWith p ws
210211
where (ys,zs) = break p xs
211212

213+
-- | Call @hc-pkg@ to check the consistency of the specified package db.
214+
check :: HcPkgInfo -> Verbosity -> PackageDB -> IO [String]
215+
check hpi verbosity packagedb = do
216+
fmap lines $ getProgramInvocationOutput
217+
verbosity
218+
(checkInvocation hpi verbosity packagedb)
219+
`catchExit` \_ -> die $ programId (hcPkgProgram hpi) ++ " dump failed"
220+
212221
mungePackagePaths :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo
213222
-- Perform path/URL variable substitution as per the Cabal ${pkgroot} spec
214223
-- (http://www.haskell.org/pipermail/libraries/2009-May/011772.html)
@@ -373,6 +382,17 @@ dumpInvocation hpi _verbosity packagedb =
373382
-- We use verbosity level 'silent' because it is important that we
374383
-- do not contaminate the output with info/debug messages.
375384

385+
checkInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation
386+
checkInvocation hpi _verbosity packagedb =
387+
(programInvocation (hcPkgProgram hpi) args) {
388+
progInvokeOutputEncoding = IOEncodingUTF8
389+
}
390+
where
391+
args = ["check", packageDbOpts hpi packagedb]
392+
++ verbosityOpts hpi silent
393+
-- We use verbosity level 'silent' because it is important that we
394+
-- do not contaminate the output with info/debug messages.
395+
376396
listInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation
377397
listInvocation hpi _verbosity packagedb =
378398
(programInvocation (hcPkgProgram hpi) args) {

Cabal/Distribution/Simple/Utils.hs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ module Distribution.Simple.Utils (
9898
-- * .cabal and .buildinfo files
9999
defaultPackageDesc,
100100
findPackageDesc,
101+
listPackageDescs,
101102
tryFindPackageDesc,
102103
defaultHookedPackageDesc,
103104
findHookedPackageDesc,
@@ -1183,30 +1184,37 @@ defaultPackageDesc _verbosity = tryFindPackageDesc currentDir
11831184
-- @.cabal@ files.
11841185
findPackageDesc :: FilePath -- ^Where to look
11851186
-> IO (Either String FilePath) -- ^<pkgname>.cabal
1186-
findPackageDesc dir
1187-
= do files <- getDirectoryContents dir
1188-
-- to make sure we do not mistake a ~/.cabal/ dir for a <pkgname>.cabal
1189-
-- file we filter to exclude dirs and null base file names:
1190-
cabalFiles <- filterM doesFileExist
1191-
[ dir </> file
1192-
| file <- files
1193-
, let (name, ext) = splitExtension file
1194-
, not (null name) && ext == ".cabal" ]
1195-
case cabalFiles of
1196-
[] -> return (Left noDesc)
1197-
[cabalFile] -> return (Right cabalFile)
1198-
multiple -> return (Left $ multiDesc multiple)
1199-
1187+
findPackageDesc dir = do
1188+
cabalFiles <- listPackageDescs dir
1189+
case cabalFiles of
1190+
[] -> return (Left noDesc)
1191+
[cabalFile] -> return (Right cabalFile)
1192+
multiple -> return (Left $ multiDesc multiple)
12001193
where
12011194
noDesc :: String
12021195
noDesc = "No cabal file found.\n"
12031196
++ "Please create a package description file <pkgname>.cabal"
1204-
12051197
multiDesc :: [String] -> String
12061198
multiDesc l = "Multiple cabal files found.\n"
12071199
++ "Please use only one of: "
12081200
++ intercalate ", " l
12091201

1202+
-- | List all package descriptions in the given directory.
1203+
--
1204+
-- In contrast to 'findPackageDesc', finding more than one
1205+
-- package description is possible and does not lead
1206+
-- to an error/'Left' value.
1207+
listPackageDescs :: FilePath -> IO [FilePath]
1208+
listPackageDescs dir = do
1209+
files <- getDirectoryContents dir
1210+
-- to make sure we do not mistake a ~/.cabal/ dir for a <pkgname>.cabal
1211+
-- file we filter to exclude dirs and null base file names:
1212+
filterM doesFileExist
1213+
[ dir </> file
1214+
| file <- files
1215+
, let (name, ext) = splitExtension file
1216+
, not (null name) && ext == ".cabal" ]
1217+
12101218
-- |Like 'findPackageDesc', but calls 'die' in case of error.
12111219
tryFindPackageDesc :: FilePath -> IO FilePath
12121220
tryFindPackageDesc dir = either die return =<< findPackageDesc dir

Cabal/Distribution/Text.hs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ module Distribution.Text (
1515
Text(..),
1616
display,
1717
simpleParse,
18+
render,
19+
brokenString
1820
) where
1921

2022
import qualified Distribution.Compat.ReadP as Parse
@@ -27,13 +29,27 @@ class Text a where
2729
disp :: a -> Disp.Doc
2830
parse :: Parse.ReadP r a
2931

32+
-- | Display a 'Text' value with the Cabal default style.
3033
display :: Text a => a -> String
31-
display = Disp.renderStyle style . disp
32-
where style = Disp.Style {
33-
Disp.mode = Disp.PageMode,
34-
Disp.lineLength = 79,
35-
Disp.ribbonsPerLine = 1.0
36-
}
34+
display = Disp.renderStyle defaultStyle . disp
35+
36+
-- | similar to Disp.render, but using the Cabal default style
37+
-- (which is different from Text.Prettyprint default).
38+
render :: Disp.Doc -> String
39+
render = Disp.renderStyle defaultStyle
40+
41+
-- | Takes a string, and turns it into a paragraph-like
42+
-- Doc, i.e. an fsep of the words in it. Main purpose is
43+
-- to produce indented paragraphs.
44+
brokenString :: String -> Disp.Doc
45+
brokenString s = Disp.fsep $ fmap Disp.text $ words s
46+
47+
defaultStyle :: Disp.Style
48+
defaultStyle = Disp.Style
49+
{ Disp.mode = Disp.PageMode
50+
, Disp.lineLength = 79 -- Disp default: 100
51+
, Disp.ribbonsPerLine = 1.0 -- Disp default: 1.5
52+
}
3753

3854
simpleParse :: Text a => String -> Maybe a
3955
simpleParse str = case [ p | (p, s) <- Parse.readP_to_S parse str

Cabal/changelog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
program to detect that is connected to a terminal, and works
1818
reliable with a non-threaded runtime (#2911, and serves as a
1919
work-around for #2398)
20+
* Add command 'status'
2021

2122
1.22.0.0 Johan Tibell <[email protected]> January 2015
2223
* Support GHC 7.10.

cabal-install/Distribution/Client/Freeze.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
-----------------------------------------------------------------------------
1515
module Distribution.Client.Freeze (
1616
freeze,
17+
planPackages
1718
) where
1819

1920
import Distribution.Client.Config ( SavedConfig(..) )

cabal-install/Distribution/Client/Sandbox.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module Distribution.Client.Sandbox (
2020
withSandboxBinDirOnSearchPath,
2121

2222
getSandboxConfigFilePath,
23+
tryLoadSandboxConfig,
2324
loadConfigOrSandboxConfig,
2425
findSavedDistPref,
2526
initPackageDBIfNeeded,

cabal-install/Distribution/Client/Setup.hs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ module Distribution.Client.Setup
1919
, buildCommand, BuildFlags(..), BuildExFlags(..), SkipAddSourceDepsCheck(..)
2020
, replCommand, testCommand, benchmarkCommand
2121
, installCommand, InstallFlags(..), installOptions, defaultInstallFlags
22+
, defaultFreezeFlags
2223
, listCommand, ListFlags(..)
2324
, updateCommand
2425
, upgradeCommand
2526
, uninstallCommand
2627
, infoCommand, InfoFlags(..)
2728
, fetchCommand, FetchFlags(..)
2829
, freezeCommand, FreezeFlags(..)
30+
, statusCommand, StatusFlags(..)
2931
, getCommand, unpackCommand, GetFlags(..)
3032
, checkCommand
3133
, formatCommand
@@ -196,6 +198,7 @@ globalCommand commands = CommandUI {
196198
, "register"
197199
, "sandbox"
198200
, "exec"
201+
, "status"
199202
]
200203
maxlen = maximum $ [length name | (name, _) <- cmdDescs]
201204
align str = str ++ replicate (maxlen - length str) ' '
@@ -216,6 +219,7 @@ globalCommand commands = CommandUI {
216219
, addCmd "install"
217220
, par
218221
, addCmd "help"
222+
, addCmd "status"
219223
, addCmd "info"
220224
, addCmd "list"
221225
, addCmd "fetch"
@@ -810,6 +814,105 @@ freezeCommand = CommandUI {
810814

811815
}
812816

817+
-- ------------------------------------------------------------
818+
-- * Status command
819+
-- ------------------------------------------------------------
820+
821+
data StatusFlags = StatusFlags {
822+
statusVersion :: Flag Bool,
823+
statusProgVersions :: Flag Bool,
824+
statusCompiler :: Flag Bool,
825+
statusPackage :: Flag Bool,
826+
statusPlan :: Flag Bool,
827+
statusSandbox :: Flag Bool,
828+
statusPkgDbs :: Flag Bool,
829+
statusCheckDb :: Flag Bool,
830+
statusAll :: Flag Bool,
831+
statusVerbosity :: Flag Verbosity
832+
}
833+
834+
defaultStatusFlags :: StatusFlags
835+
defaultStatusFlags = StatusFlags {
836+
statusVersion = toFlag False,
837+
statusProgVersions = toFlag False,
838+
statusCompiler = toFlag False,
839+
statusPackage = toFlag False,
840+
statusPlan = toFlag False,
841+
statusSandbox = toFlag False,
842+
statusPkgDbs = toFlag False,
843+
statusCheckDb = toFlag False,
844+
statusAll = toFlag False,
845+
statusVerbosity = toFlag normal
846+
}
847+
848+
statusCommand :: CommandUI StatusFlags
849+
statusCommand = CommandUI {
850+
commandName = "status",
851+
commandSynopsis = "Show various cabal/packagedb-related information.",
852+
commandUsage = usageAlternatives "status" [ "[FLAGS]" ],
853+
commandDescription = Just $ \_ -> wrapText $
854+
"A summary of the state of your cabal environment (for the local"
855+
++ " folder). Shows all, or a subset of: Various program versions,"
856+
++ " information about the local package (if present),"
857+
++ " the sandbox (if present), and the package-databases"
858+
++ " in use (and their contents and consistency).",
859+
commandNotes = Nothing,
860+
commandDefaultFlags = defaultStatusFlags,
861+
commandOptions = \ _showOrParseArgs -> [
862+
optionVerbosity statusVerbosity (\v flags -> flags { statusVerbosity = v })
863+
864+
, option [] ["version"]
865+
"print the version of this program."
866+
statusVersion (\v flags -> flags { statusVersion = v })
867+
trueArg
868+
869+
, option [] ["versions"]
870+
"list the versions of all known/related programs"
871+
statusProgVersions (\v flags -> flags { statusProgVersions = v })
872+
trueArg
873+
874+
, option [] ["compiler"]
875+
"print the currently configured compiler info"
876+
statusCompiler (\v flags -> flags { statusCompiler = v })
877+
trueArg
878+
879+
, option [] ["package"]
880+
(wrapText $ "print information about the package in the"
881+
++ " current directory")
882+
statusPackage (\v flags -> flags { statusPackage = v })
883+
trueArg
884+
885+
, option [] ["plan"]
886+
(wrapText $ "list all packages in the install plan for the current"
887+
++ " package. Implies --package.")
888+
statusPlan (\v flags -> flags { statusPlan = v })
889+
trueArg
890+
891+
, option [] ["sandbox"]
892+
(wrapText $ "print if there is a configured sandbox, and"
893+
++ " information about it.")
894+
statusSandbox (\v flags -> flags { statusSandbox = v })
895+
trueArg
896+
897+
, option [] ["databases"]
898+
(wrapText $ "list all the packages in the global, local"
899+
++ " and sandbox package databases")
900+
statusPkgDbs (\v flags -> flags { statusPkgDbs = v })
901+
trueArg
902+
903+
, option [] ["check"]
904+
"check package-databases for consistency"
905+
statusCheckDb (\v flags -> flags { statusCheckDb = v })
906+
trueArg
907+
908+
, option [] ["all"]
909+
"include all the information"
910+
statusAll (\v flags -> flags { statusAll = v })
911+
trueArg
912+
913+
]
914+
}
915+
813916
-- ------------------------------------------------------------
814917
-- * Other commands
815918
-- ------------------------------------------------------------

0 commit comments

Comments
 (0)