module Darcs.UI.Commands.ShowRepo ( showRepo ) where
import Darcs.Prelude
import Data.Char ( toLower, isSpace )
import Data.List ( intercalate )
import Control.Monad ( when, unless, liftM )
import Text.Html ( tag, stringToHtml )
import Darcs.Util.Path ( AbsolutePath )
import Darcs.UI.Flags ( DarcsFlag, useCache, hasXmlOutput, enumeratePatches )
import Darcs.UI.Options ( (^), oid, (?) )
import qualified Darcs.UI.Options.All as O
import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository )
import Darcs.UI.Completion ( noArgs )
import Darcs.Repository
( Repository
, repoFormat
, repoLocation
, repoPristineType
, repoCache
, withRepository
, RepoJob(..)
, readPatches )
import Darcs.Repository.Hashed( repoXor )
import Darcs.Repository.PatchIndex ( isPatchIndexDisabled, doesPatchIndexExist )
import Darcs.Repository.Prefs
( Pref(Author, Defaultrepo, Prefs)
, getMotd
, getPreflist
)
import Darcs.Patch ( RepoPatch )
import Darcs.Patch.Set ( patchSet2RL )
import Darcs.Patch.Witnesses.Ordered ( lengthRL )
import qualified Data.ByteString.Char8 as BC (unpack)
import Darcs.Patch.Apply( ApplyState )
import Darcs.Util.Printer ( Doc, text )
import Darcs.Util.Tree ( Tree )
showRepoHelp :: Doc
showRepoHelp :: Doc
showRepoHelp = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$
String
"The `darcs show repo` command displays statistics about the current\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"repository, allowing third-party scripts to access this information\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"without inspecting `_darcs` directly (and without breaking when the\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"`_darcs` format changes).\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"The 'Weak Hash' identifies the set of patches of a repository independently\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"of ordering. It can be used to easily compare two repositories of a same\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"project. It is not cryptographically secure.\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"By default, output includes statistics that require walking through the patches\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"recorded in the repository, namely the 'Weak Hash' and the count of patches.\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"If this data isn't needed, use `--no-enum-patches` to accelerate this command\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"from O(n) to O(1).\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"By default, output is in a human-readable format. The `--xml-output`\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"option can be used to generate output for machine postprocessing.\n"
showRepoDescription :: String
showRepoDescription :: String
showRepoDescription = String
"Show repository summary information"
showRepo :: DarcsCommand
showRepo :: DarcsCommand
showRepo = DarcsCommand
{ commandProgramName :: String
commandProgramName = String
"darcs"
, commandName :: String
commandName = String
"repo"
, commandHelp :: Doc
commandHelp = Doc
showRepoHelp
, commandDescription :: String
commandDescription = String
showRepoDescription
, commandExtraArgs :: Int
commandExtraArgs = Int
0
, commandExtraArgHelp :: [String]
commandExtraArgHelp = []
, commandCommand :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
commandCommand = (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
repoCmd
, commandPrereq :: [DarcsFlag] -> IO (Either String ())
commandPrereq = [DarcsFlag] -> IO (Either String ())
amInRepository
, commandCompleteArgs :: (AbsolutePath, AbsolutePath)
-> [DarcsFlag] -> [String] -> IO [String]
commandCompleteArgs = (AbsolutePath, AbsolutePath)
-> [DarcsFlag] -> [String] -> IO [String]
noArgs
, commandArgdefaults :: [DarcsFlag] -> AbsolutePath -> [String] -> IO [String]
commandArgdefaults = [DarcsFlag] -> AbsolutePath -> [String] -> IO [String]
nodefaults
, commandOptions :: CommandOptions
commandOptions = CommandOptions
showRepoOpts
}
where
showRepoBasicOpts :: OptSpec
DarcsOptDescr
DarcsFlag
a
(Maybe String -> XmlOutput -> EnumPatches -> a)
showRepoBasicOpts = PrimOptSpec
DarcsOptDescr
DarcsFlag
(XmlOutput -> EnumPatches -> a)
(Maybe String)
PrimDarcsOption (Maybe String)
O.repoDir PrimOptSpec
DarcsOptDescr
DarcsFlag
(XmlOutput -> EnumPatches -> a)
(Maybe String)
-> OptSpec
DarcsOptDescr
DarcsFlag
(EnumPatches -> a)
(XmlOutput -> EnumPatches -> a)
-> OptSpec
DarcsOptDescr
DarcsFlag
(EnumPatches -> a)
(Maybe String -> XmlOutput -> EnumPatches -> a)
forall (d :: * -> *) f b c a.
OptSpec d f b c -> OptSpec d f a b -> OptSpec d f a c
^ OptSpec
DarcsOptDescr
DarcsFlag
(EnumPatches -> a)
(XmlOutput -> EnumPatches -> a)
PrimDarcsOption XmlOutput
O.xmlOutput OptSpec
DarcsOptDescr
DarcsFlag
(EnumPatches -> a)
(Maybe String -> XmlOutput -> EnumPatches -> a)
-> OptSpec DarcsOptDescr DarcsFlag a (EnumPatches -> a)
-> OptSpec
DarcsOptDescr
DarcsFlag
a
(Maybe String -> XmlOutput -> EnumPatches -> a)
forall (d :: * -> *) f b c a.
OptSpec d f b c -> OptSpec d f a b -> OptSpec d f a c
^ OptSpec DarcsOptDescr DarcsFlag a (EnumPatches -> a)
PrimDarcsOption EnumPatches
O.enumPatches
showRepoOpts :: CommandOptions
showRepoOpts = OptSpec
DarcsOptDescr
DarcsFlag
(Maybe StdCmdAction
-> Verbosity
-> UseCache
-> UseIndex
-> HooksConfig
-> Bool
-> Bool
-> [DarcsFlag])
(Maybe String
-> XmlOutput
-> EnumPatches
-> Maybe StdCmdAction
-> Verbosity
-> UseCache
-> UseIndex
-> HooksConfig
-> Bool
-> Bool
-> [DarcsFlag])
forall {a}.
OptSpec
DarcsOptDescr
DarcsFlag
a
(Maybe String -> XmlOutput -> EnumPatches -> a)
showRepoBasicOpts OptSpec
DarcsOptDescr
DarcsFlag
(Maybe StdCmdAction
-> Verbosity
-> UseCache
-> UseIndex
-> HooksConfig
-> Bool
-> Bool
-> [DarcsFlag])
(Maybe String
-> XmlOutput
-> EnumPatches
-> Maybe StdCmdAction
-> Verbosity
-> UseCache
-> UseIndex
-> HooksConfig
-> Bool
-> Bool
-> [DarcsFlag])
-> DarcsOption
(UseCache
-> UseIndex -> HooksConfig -> Bool -> Bool -> [DarcsFlag])
(UseCache
-> UseIndex -> HooksConfig -> Bool -> Bool -> [DarcsFlag])
-> CommandOptions
forall b c.
DarcsOption (Maybe StdCmdAction -> Verbosity -> b) c
-> DarcsOption
(UseCache
-> UseIndex -> HooksConfig -> Bool -> Bool -> [DarcsFlag])
b
-> CommandOptions
`withStdOpts` DarcsOption
(UseCache
-> UseIndex -> HooksConfig -> Bool -> Bool -> [DarcsFlag])
(UseCache
-> UseIndex -> HooksConfig -> Bool -> Bool -> [DarcsFlag])
forall (d :: * -> *) f a. OptSpec d f a a
oid
repoCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
repoCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
repoCmd (AbsolutePath, AbsolutePath)
_ [DarcsFlag]
opts [String]
_ =
let put_mode :: String -> String -> String
put_mode = if [DarcsFlag] -> Bool
hasXmlOutput [DarcsFlag]
opts then String -> String -> String
showInfoXML else String -> String -> String
showInfoUsr
in UseCache -> RepoJob 'RO () -> IO ()
forall a. UseCache -> RepoJob 'RO a -> IO a
withRepository (PrimOptSpec DarcsOptDescr DarcsFlag a UseCache
PrimDarcsOption UseCache
useCache PrimDarcsOption UseCache -> [DarcsFlag] -> UseCache
forall (d :: * -> *) f v.
(forall a. PrimOptSpec d f a v) -> [f] -> v
? [DarcsFlag]
opts) (RepoJob 'RO () -> IO ()) -> RepoJob 'RO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TreePatchJob 'RO () -> RepoJob 'RO ()
forall (rt :: AccessType) a. TreePatchJob rt a -> RepoJob rt a
RepoJob (TreePatchJob 'RO () -> RepoJob 'RO ())
-> TreePatchJob 'RO () -> RepoJob 'RO ()
forall a b. (a -> b) -> a -> b
$ \Repository 'RO p wU wR
repository ->
PutInfo -> Repository 'RO p wU wR -> [DarcsFlag] -> IO ()
forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
(RepoPatch p, ApplyState p ~ Tree) =>
PutInfo -> Repository rt p wU wR -> [DarcsFlag] -> IO ()
actuallyShowRepo ((String -> String -> String) -> PutInfo
putInfo String -> String -> String
put_mode) Repository 'RO p wU wR
repository [DarcsFlag]
opts
type ShowInfo = String -> String -> String
showInfoXML :: ShowInfo
showInfoXML :: String -> String -> String
showInfoXML String
t String
i = Html -> String
forall a. Show a => a -> String
show (Html -> String) -> Html -> String
forall a b. (a -> b) -> a -> b
$ String -> Html -> Html
tag (String -> String
safeTag String
t) (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ String -> Html
stringToHtml String
i
safeTag :: String -> String
safeTag :: String -> String
safeTag [] = []
safeTag (Char
' ':String
cs) = String -> String
safeTag String
cs
safeTag (Char
'#':String
cs) = String
"num_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
safeTag String
cs
safeTag (Char
c:String
cs) = Char -> Char
toLower Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
safeTag String
cs
showInfoUsr :: ShowInfo
showInfoUsr :: String -> String -> String
showInfoUsr String
t String
i = Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
15 Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
t) Char
' ' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate (Char
'\n' Char -> String -> String
forall a. a -> [a] -> [a]
: Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
17 Char
' ') (String -> [String]
lines String
i) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n"
type PutInfo = String -> String -> IO ()
putInfo :: ShowInfo -> PutInfo
putInfo :: (String -> String -> String) -> PutInfo
putInfo String -> String -> String
m String
t String
i = Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
i) (String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> String -> String
m String
t String
i)
actuallyShowRepo
:: (RepoPatch p, ApplyState p ~ Tree)
=> PutInfo -> Repository rt p wU wR -> [DarcsFlag] -> IO ()
actuallyShowRepo :: forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
(RepoPatch p, ApplyState p ~ Tree) =>
PutInfo -> Repository rt p wU wR -> [DarcsFlag] -> IO ()
actuallyShowRepo PutInfo
out Repository rt p wU wR
r [DarcsFlag]
opts = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([DarcsFlag] -> Bool
hasXmlOutput [DarcsFlag]
opts) (String -> IO ()
putStr String
"<repository>\n")
PutInfo
out String
"Format" (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ RepoFormat -> String
forall a. Show a => a -> String
showInOneLine (RepoFormat -> String) -> RepoFormat -> String
forall a b. (a -> b) -> a -> b
$ Repository rt p wU wR -> RepoFormat
forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
Repository rt p wU wR -> RepoFormat
repoFormat Repository rt p wU wR
r
let loc :: String
loc = Repository rt p wU wR -> String
forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
Repository rt p wU wR -> String
repoLocation Repository rt p wU wR
r
PutInfo
out String
"Root" String
loc
PutInfo
out String
"PristineType" (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ PristineType -> String
forall a. Show a => a -> String
show (PristineType -> String) -> PristineType -> String
forall a b. (a -> b) -> a -> b
$ Repository rt p wU wR -> PristineType
forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
Repository rt p wU wR -> PristineType
repoPristineType Repository rt p wU wR
r
PutInfo
out String
"Cache" (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Cache -> String
forall a. Show a => a -> String
showInOneLine (Cache -> String) -> Cache -> String
forall a b. (a -> b) -> a -> b
$ Repository rt p wU wR -> Cache
forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
Repository rt p wU wR -> Cache
repoCache Repository rt p wU wR
r
Bool
piExists <- String -> IO Bool
doesPatchIndexExist String
loc
Bool
piDisabled <- String -> IO Bool
isPatchIndexDisabled String
loc
PutInfo
out String
"PatchIndex" (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
case (Bool
piExists, Bool
piDisabled) of
(Bool
_, Bool
True) -> String
"disabled"
(Bool
True, Bool
False) -> String
"enabled"
(Bool
False, Bool
False) -> String
"enabled, but not yet created"
PutInfo -> IO ()
showRepoPrefs PutInfo
out
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([DarcsFlag] -> Bool
enumeratePatches [DarcsFlag]
opts) (do Repository rt p wU wR -> IO Int
forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
(RepoPatch p, ApplyState p ~ Tree) =>
Repository rt p wU wR -> IO Int
numPatches Repository rt p wU wR
r IO Int -> (Int -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (PutInfo
out String
"Num Patches" (String -> IO ()) -> (Int -> String) -> Int -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show)
PutInfo -> Repository rt p wU wR -> IO ()
forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
(RepoPatch p, ApplyState p ~ Tree) =>
PutInfo -> Repository rt p wU wR -> IO ()
showXor PutInfo
out Repository rt p wU wR
r)
PutInfo -> Repository rt p wU wR -> IO ()
forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
PutInfo -> Repository rt p wU wR -> IO ()
showRepoMOTD PutInfo
out Repository rt p wU wR
r
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([DarcsFlag] -> Bool
hasXmlOutput [DarcsFlag]
opts) (String -> IO ()
putStr String
"</repository>\n")
showXor :: (RepoPatch p, ApplyState p ~ Tree)
=> PutInfo -> Repository rt p wU wR -> IO ()
showXor :: forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
(RepoPatch p, ApplyState p ~ Tree) =>
PutInfo -> Repository rt p wU wR -> IO ()
showXor PutInfo
out Repository rt p wU wR
repo = do
SHA1
theXor <- Repository rt p wU wR -> IO SHA1
forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
RepoPatch p =>
Repository rt p wU wR -> IO SHA1
repoXor Repository rt p wU wR
repo
PutInfo
out String
"Weak Hash" (SHA1 -> String
forall a. Show a => a -> String
show SHA1
theXor)
showInOneLine :: Show a => a -> String
showInOneLine :: forall a. Show a => a -> String
showInOneLine = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ([String] -> String) -> (a -> [String]) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> [String]) -> (a -> String) -> a -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
showRepoPrefs :: PutInfo -> IO ()
showRepoPrefs :: PutInfo -> IO ()
showRepoPrefs PutInfo
out = do
Pref -> IO [String]
getPreflist Pref
Prefs IO [String] -> ([String] -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (String -> IO ()) -> [String] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ String -> IO ()
prefOut
Pref -> IO [String]
getPreflist Pref
Author IO [String] -> ([String] -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= PutInfo
out String
"Author" (String -> IO ()) -> ([String] -> String) -> [String] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines
Pref -> IO [String]
getPreflist Pref
Defaultrepo IO [String] -> ([String] -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= PutInfo
out String
"Default Remote" (String -> IO ()) -> ([String] -> String) -> [String] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines
where prefOut :: String -> IO ()
prefOut = PutInfo -> (String, String) -> IO ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry PutInfo
out ((String, String) -> IO ())
-> (String -> (String, String)) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\(String
p,String
v) -> (String
pString -> String -> String
forall a. [a] -> [a] -> [a]
++String
" Pref", (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace String
v)) ((String, String) -> (String, String))
-> (String -> (String, String)) -> String -> (String, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
isSpace
showRepoMOTD :: PutInfo -> Repository rt p wU wR -> IO ()
showRepoMOTD :: forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
PutInfo -> Repository rt p wU wR -> IO ()
showRepoMOTD PutInfo
out Repository rt p wU wR
repo = String -> IO ByteString
getMotd (Repository rt p wU wR -> String
forall (rt :: AccessType) (p :: * -> * -> *) wU wR.
Repository rt p wU wR -> String
repoLocation Repository rt p wU wR
repo) IO ByteString -> (ByteString -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= PutInfo
out String
"MOTD" (String -> IO ()) -> (ByteString -> String) -> ByteString -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> String
BC.unpack
numPatches :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wU wR -> IO Int
numPatches :: forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
(RepoPatch p, ApplyState p ~ Tree) =>
Repository rt p wU wR -> IO Int
numPatches Repository rt p wU wR
r = (RL (PatchInfoAnd p) Origin wR -> Int
forall (a :: * -> * -> *) wX wZ. RL a wX wZ -> Int
lengthRL (RL (PatchInfoAnd p) Origin wR -> Int)
-> (PatchSet p Origin wR -> RL (PatchInfoAnd p) Origin wR)
-> PatchSet p Origin wR
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatchSet p Origin wR -> RL (PatchInfoAnd p) Origin wR
forall (p :: * -> * -> *) wStart wX.
PatchSet p wStart wX -> RL (PatchInfoAnd p) wStart wX
patchSet2RL) (PatchSet p Origin wR -> Int)
-> IO (PatchSet p Origin wR) -> IO Int
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` Repository rt p wU wR -> IO (PatchSet p Origin wR)
forall (p :: * -> * -> *) (rt :: AccessType) wU wR.
RepoPatch p =>
Repository rt p wU wR -> IO (PatchSet p Origin wR)
readPatches Repository rt p wU wR
r