implement fastDebug

Most of the changes here involve global option parsing: GlobalSetter
changed so it can both run an Annex action to set state, but can also
change the AnnexRead value, which is immutable once the Annex monad is
running.

That allowed a debugselector value to be added to AnnexRead, seeded
from the git config. The --debugfilter option's GlobalSetter then updates
the AnnexRead.

This improved GlobalSetter can later be used to move more stuff to
AnnexRead. Things that don't involve a git config will be easier to
move, and probably a *lot* of things can be moved eventually.

fastDebug, while implemented, is not used anywhere yet. But it should be
fast..
This commit is contained in:
Joey Hess 2021-04-06 15:14:00 -04:00
parent 6136006106
commit d16d739ce2
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
12 changed files with 194 additions and 84 deletions

View file

@ -76,6 +76,7 @@ import Types.RemoteConfig
import Types.TransferrerPool import Types.TransferrerPool
import Types.VectorClock import Types.VectorClock
import Annex.VectorClock.Utility import Annex.VectorClock.Utility
import Annex.Debug.Utility
import qualified Database.Keys.Handle as Keys import qualified Database.Keys.Handle as Keys
import Utility.InodeCache import Utility.InodeCache
import Utility.Url import Utility.Url
@ -119,10 +120,11 @@ data AnnexRead = AnnexRead
, sshstalecleaned :: TMVar Bool , sshstalecleaned :: TMVar Bool
, signalactions :: TVar (M.Map SignalAction (Int -> IO ())) , signalactions :: TVar (M.Map SignalAction (Int -> IO ()))
, transferrerpool :: TransferrerPool , transferrerpool :: TransferrerPool
, debugselector :: DebugSelector
} }
newAnnexRead :: IO AnnexRead newAnnexRead :: GitConfig -> IO AnnexRead
newAnnexRead = do newAnnexRead c = do
emptyactivekeys <- newTVarIO M.empty emptyactivekeys <- newTVarIO M.empty
emptyactiveremotes <- newMVar M.empty emptyactiveremotes <- newMVar M.empty
kh <- Keys.newDbHandle kh <- Keys.newDbHandle
@ -136,6 +138,7 @@ newAnnexRead = do
, sshstalecleaned = sc , sshstalecleaned = sc
, signalactions = si , signalactions = si
, transferrerpool = tp , transferrerpool = tp
, debugselector = debugSelectorFromGitConfig c
} }
-- Values that can change while running an Annex action. -- Values that can change while running an Annex action.
@ -261,7 +264,7 @@ new r = do
r' <- Git.Config.read r r' <- Git.Config.read r
let c = extractGitConfig FromGitConfig r' let c = extractGitConfig FromGitConfig r'
st <- newAnnexState c =<< fixupRepo r' c st <- newAnnexState c =<< fixupRepo r' c
rd <- newAnnexRead rd <- newAnnexRead c
return (st, rd) return (st, rd)
{- Performs an action in the Annex monad from a starting state, {- Performs an action in the Annex monad from a starting state,

30
Annex/Debug.hs Normal file
View file

@ -0,0 +1,30 @@
{- git-annex debugging
-
- Copyright 2021 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module Annex.Debug (
DebugSelector(..),
DebugSource(..),
debug,
fastDebug,
configureDebug,
debugSelectorFromGitConfig,
parseDebugSelector,
) where
import Common
import qualified Annex
import Utility.Debug hiding (fastDebug)
import qualified Utility.Debug
import Annex.Debug.Utility
-- | This is faster than using debug, because the DebugSelector
-- is read from the Annex monad, which avoids any IORef access overhead
-- when debugging is not enabled.
fastDebug :: DebugSource -> String -> Annex.Annex ()
fastDebug src msg = do
selector <- Annex.getRead Annex.debugselector
liftIO $ Utility.Debug.fastDebug selector src msg

32
Annex/Debug/Utility.hs Normal file
View file

@ -0,0 +1,32 @@
{- git-annex debugging, utility functions
-
- Copyright 2021 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module Annex.Debug.Utility (
debugSelectorFromGitConfig,
parseDebugSelector,
DebugSelector,
) where
import Types.GitConfig
import Utility.Debug
import Utility.Split
import Utility.FileSystemEncoding
import qualified Data.ByteString as S
debugSelectorFromGitConfig :: GitConfig -> DebugSelector
debugSelectorFromGitConfig =
maybe NoDebugSelector parseDebugSelector . annexDebugFilter
parseDebugSelector :: String -> DebugSelector
parseDebugSelector = DebugSelector . matchDebugSource . splitSelectorNames
splitSelectorNames :: String -> [S.ByteString]
splitSelectorNames = map encodeBS . splitc ','
matchDebugSource :: [S.ByteString] -> DebugSource -> Bool
matchDebugSource names (DebugSource s) = any (`S.isInfixOf` s) names

View file

@ -53,14 +53,14 @@ dispatch' subcommandname args fuzzy cmds allargs allcmds fields getgitrepo progn
where where
go (Right g) = do go (Right g) = do
g' <- Git.Config.read g g' <- Git.Config.read g
(cmd, seek, globalconfig) <- parsewith False cmdparser (cmd, seek, globalsetter) <- parsewith False cmdparser
(\a -> a (Just g')) (\a -> a (Just g'))
O.handleParseResult O.handleParseResult
state <- Annex.new g' state <- applyAnnexReadSetter globalsetter <$> Annex.new g'
Annex.eval state $ do Annex.eval state $ do
checkEnvironment checkEnvironment
forM_ fields $ uncurry Annex.setField forM_ fields $ uncurry Annex.setField
prepRunCommand cmd globalconfig prepRunCommand cmd globalsetter
startup startup
performCommandAction cmd seek $ performCommandAction cmd seek $
shutdown $ cmdnocommit cmd shutdown $ cmdnocommit cmd
@ -141,11 +141,14 @@ subCmdName argv = (name, args)
| "-" `isPrefixOf` a = findname as (a:c) | "-" `isPrefixOf` a = findname as (a:c)
| otherwise = (Just a, reverse c ++ as) | otherwise = (Just a, reverse c ++ as)
-- | Note that the GlobalSetter must have already had its annexReadSetter
-- applied before entering the Annex monad; that cannot be changed while
-- running in the Annex monad.
prepRunCommand :: Command -> GlobalSetter -> Annex () prepRunCommand :: Command -> GlobalSetter -> Annex ()
prepRunCommand cmd globalconfig = do prepRunCommand cmd globalsetter = do
when (cmdnomessages cmd) $ when (cmdnomessages cmd) $
Annex.setOutput QuietOutput Annex.setOutput QuietOutput
getParsed globalconfig annexStateSetter globalsetter
whenM (annexDebug <$> Annex.getGitConfig) $ whenM (annexDebug <$> Annex.getGitConfig) $
enableDebugOutput enableDebugOutput

View file

@ -43,55 +43,55 @@ import Annex.Concurrent
-- although not always used. -- although not always used.
gitAnnexGlobalOptions :: [GlobalOption] gitAnnexGlobalOptions :: [GlobalOption]
gitAnnexGlobalOptions = commonGlobalOptions ++ gitAnnexGlobalOptions = commonGlobalOptions ++
[ globalSetter setnumcopies $ option auto [ globalOption (setAnnexState . setnumcopies) $ option auto
( long "numcopies" <> short 'N' <> metavar paramNumber ( long "numcopies" <> short 'N' <> metavar paramNumber
<> help "override desired number of copies" <> help "override desired number of copies"
<> hidden <> hidden
) )
, globalSetter setmincopies $ option auto , globalOption (setAnnexState . setmincopies) $ option auto
( long "mincopies" <> short 'N' <> metavar paramNumber ( long "mincopies" <> short 'N' <> metavar paramNumber
<> help "override minimum number of copies" <> help "override minimum number of copies"
<> hidden <> hidden
) )
, globalSetter (Remote.forceTrust Trusted) $ strOption , globalOption (setAnnexState . Remote.forceTrust Trusted) $ strOption
( long "trust" <> metavar paramRemote ( long "trust" <> metavar paramRemote
<> help "deprecated, does not override trust setting" <> help "deprecated, does not override trust setting"
<> hidden <> hidden
<> completeRemotes <> completeRemotes
) )
, globalSetter (Remote.forceTrust SemiTrusted) $ strOption , globalOption (setAnnexState . Remote.forceTrust SemiTrusted) $ strOption
( long "semitrust" <> metavar paramRemote ( long "semitrust" <> metavar paramRemote
<> help "override trust setting back to default" <> help "override trust setting back to default"
<> hidden <> hidden
<> completeRemotes <> completeRemotes
) )
, globalSetter (Remote.forceTrust UnTrusted) $ strOption , globalOption (setAnnexState . Remote.forceTrust UnTrusted) $ strOption
( long "untrust" <> metavar paramRemote ( long "untrust" <> metavar paramRemote
<> help "override trust setting to untrusted" <> help "override trust setting to untrusted"
<> hidden <> hidden
<> completeRemotes <> completeRemotes
) )
, globalSetter setgitconfig $ strOption , globalOption (setAnnexState . setgitconfig) $ strOption
( long "config" <> short 'c' <> metavar "NAME=VALUE" ( long "config" <> short 'c' <> metavar "NAME=VALUE"
<> help "override git configuration setting" <> help "override git configuration setting"
<> hidden <> hidden
) )
, globalSetter setuseragent $ strOption , globalOption (setAnnexState . setuseragent) $ strOption
( long "user-agent" <> metavar paramName ( long "user-agent" <> metavar paramName
<> help "override default User-Agent" <> help "override default User-Agent"
<> hidden <> hidden
) )
, globalFlag (toplevelWarning False "--trust-glacier no longer has any effect") , globalFlag (setAnnexState $ toplevelWarning False "--trust-glacier no longer has any effect")
( long "trust-glacier" ( long "trust-glacier"
<> help "deprecated, does not trust Amazon Glacier inventory" <> help "deprecated, does not trust Amazon Glacier inventory"
<> hidden <> hidden
) )
, globalFlag (setdesktopnotify mkNotifyFinish) , globalFlag (setAnnexState $ setdesktopnotify mkNotifyFinish)
( long "notify-finish" ( long "notify-finish"
<> help "show desktop notification after transfer finishes" <> help "show desktop notification after transfer finishes"
<> hidden <> hidden
) )
, globalFlag (setdesktopnotify mkNotifyStart) , globalFlag (setAnnexState $ setdesktopnotify mkNotifyStart)
( long "notify-start" ( long "notify-start"
<> help "show desktop notification after transfer starts" <> help "show desktop notification after transfer starts"
<> hidden <> hidden
@ -241,80 +241,81 @@ keyMatchingOptions = keyMatchingOptions' ++ combiningOptions ++ timeLimitOption
keyMatchingOptions' :: [GlobalOption] keyMatchingOptions' :: [GlobalOption]
keyMatchingOptions' = keyMatchingOptions' =
[ globalSetter Limit.addIn $ strOption [ globalOption (setAnnexState . Limit.addIn) $ strOption
( long "in" <> short 'i' <> metavar paramRemote ( long "in" <> short 'i' <> metavar paramRemote
<> help "match files present in a remote" <> help "match files present in a remote"
<> hidden <> hidden
<> completeRemotes <> completeRemotes
) )
, globalSetter Limit.addCopies $ strOption , globalOption (setAnnexState . Limit.addCopies) $ strOption
( long "copies" <> short 'C' <> metavar paramRemote ( long "copies" <> short 'C' <> metavar paramRemote
<> help "skip files with fewer copies" <> help "skip files with fewer copies"
<> hidden <> hidden
) )
, globalSetter (Limit.addLackingCopies False) $ strOption , globalOption (setAnnexState . Limit.addLackingCopies False) $ strOption
( long "lackingcopies" <> metavar paramNumber ( long "lackingcopies" <> metavar paramNumber
<> help "match files that need more copies" <> help "match files that need more copies"
<> hidden <> hidden
) )
, globalSetter (Limit.addLackingCopies True) $ strOption , globalOption (setAnnexState . Limit.addLackingCopies True) $ strOption
( long "approxlackingcopies" <> metavar paramNumber ( long "approxlackingcopies" <> metavar paramNumber
<> help "match files that need more copies (faster)" <> help "match files that need more copies (faster)"
<> hidden <> hidden
) )
, globalSetter Limit.addInBackend $ strOption , globalOption (setAnnexState . Limit.addInBackend) $ strOption
( long "inbackend" <> short 'B' <> metavar paramName ( long "inbackend" <> short 'B' <> metavar paramName
<> help "match files using a key-value backend" <> help "match files using a key-value backend"
<> hidden <> hidden
<> completeBackends <> completeBackends
) )
, globalFlag Limit.addSecureHash , globalFlag (setAnnexState Limit.addSecureHash)
( long "securehash" ( long "securehash"
<> help "match files using a cryptographically secure hash" <> help "match files using a cryptographically secure hash"
<> hidden <> hidden
) )
, globalSetter Limit.addInAllGroup $ strOption , globalOption (setAnnexState . Limit.addInAllGroup) $ strOption
( long "inallgroup" <> metavar paramGroup ( long "inallgroup" <> metavar paramGroup
<> help "match files present in all remotes in a group" <> help "match files present in all remotes in a group"
<> hidden <> hidden
) )
, globalSetter Limit.addMetaData $ strOption , globalOption (setAnnexState . Limit.addMetaData) $ strOption
( long "metadata" <> metavar "FIELD=VALUE" ( long "metadata" <> metavar "FIELD=VALUE"
<> help "match files with attached metadata" <> help "match files with attached metadata"
<> hidden <> hidden
) )
, globalFlag Limit.Wanted.addWantGet , globalFlag (setAnnexState Limit.Wanted.addWantGet)
( long "want-get" ( long "want-get"
<> help "match files the repository wants to get" <> help "match files the repository wants to get"
<> hidden <> hidden
) )
, globalFlag Limit.Wanted.addWantDrop , globalFlag (setAnnexState Limit.Wanted.addWantDrop)
( long "want-drop" ( long "want-drop"
<> help "match files the repository wants to drop" <> help "match files the repository wants to drop"
<> hidden <> hidden
) )
, globalSetter Limit.addAccessedWithin $ option (eitherReader parseDuration) , globalOption (setAnnexState . Limit.addAccessedWithin) $
option (eitherReader parseDuration)
( long "accessedwithin" ( long "accessedwithin"
<> metavar paramTime <> metavar paramTime
<> help "match files accessed within a time interval" <> help "match files accessed within a time interval"
<> hidden <> hidden
) )
, globalSetter Limit.addMimeType $ strOption , globalOption (setAnnexState . Limit.addMimeType) $ strOption
( long "mimetype" <> metavar paramGlob ( long "mimetype" <> metavar paramGlob
<> help "match files by mime type" <> help "match files by mime type"
<> hidden <> hidden
) )
, globalSetter Limit.addMimeEncoding $ strOption , globalOption (setAnnexState . Limit.addMimeEncoding) $ strOption
( long "mimeencoding" <> metavar paramGlob ( long "mimeencoding" <> metavar paramGlob
<> help "match files by mime encoding" <> help "match files by mime encoding"
<> hidden <> hidden
) )
, globalFlag Limit.addUnlocked , globalFlag (setAnnexState Limit.addUnlocked)
( long "unlocked" ( long "unlocked"
<> help "match files that are unlocked" <> help "match files that are unlocked"
<> hidden <> hidden
) )
, globalFlag Limit.addLocked , globalFlag (setAnnexState Limit.addLocked)
( long "locked" ( long "locked"
<> help "match files that are locked" <> help "match files that are locked"
<> hidden <> hidden
@ -327,22 +328,22 @@ fileMatchingOptions lb = fileMatchingOptions' lb ++ combiningOptions ++ timeLimi
fileMatchingOptions' :: Limit.LimitBy -> [GlobalOption] fileMatchingOptions' :: Limit.LimitBy -> [GlobalOption]
fileMatchingOptions' lb = fileMatchingOptions' lb =
[ globalSetter Limit.addExclude $ strOption [ globalOption (setAnnexState . Limit.addExclude) $ strOption
( long "exclude" <> short 'x' <> metavar paramGlob ( long "exclude" <> short 'x' <> metavar paramGlob
<> help "skip files matching the glob pattern" <> help "skip files matching the glob pattern"
<> hidden <> hidden
) )
, globalSetter Limit.addInclude $ strOption , globalOption (setAnnexState . Limit.addInclude) $ strOption
( long "include" <> short 'I' <> metavar paramGlob ( long "include" <> short 'I' <> metavar paramGlob
<> help "limit to files matching the glob pattern" <> help "limit to files matching the glob pattern"
<> hidden <> hidden
) )
, globalSetter (Limit.addLargerThan lb) $ strOption , globalOption (setAnnexState . Limit.addLargerThan lb) $ strOption
( long "largerthan" <> metavar paramSize ( long "largerthan" <> metavar paramSize
<> help "match files larger than a size" <> help "match files larger than a size"
<> hidden <> hidden
) )
, globalSetter (Limit.addSmallerThan lb) $ strOption , globalOption (setAnnexState . Limit.addSmallerThan lb) $ strOption
( long "smallerthan" <> metavar paramSize ( long "smallerthan" <> metavar paramSize
<> help "match files smaller than a size" <> help "match files smaller than a size"
<> hidden <> hidden
@ -358,17 +359,19 @@ combiningOptions =
, shortopt ')' "close group of options" , shortopt ')' "close group of options"
] ]
where where
longopt o h = globalFlag (Limit.addSyntaxToken o) ( long o <> help h <> hidden ) longopt o h = globalFlag (setAnnexState $ Limit.addSyntaxToken o)
shortopt o h = globalFlag (Limit.addSyntaxToken [o]) ( short o <> help h <> hidden ) ( long o <> help h <> hidden )
shortopt o h = globalFlag (setAnnexState $ Limit.addSyntaxToken [o])
( short o <> help h <> hidden )
jsonOptions :: [GlobalOption] jsonOptions :: [GlobalOption]
jsonOptions = jsonOptions =
[ globalFlag (Annex.setOutput (JSONOutput stdjsonoptions)) [ globalFlag (setAnnexState $ Annex.setOutput (JSONOutput stdjsonoptions))
( long "json" <> short 'j' ( long "json" <> short 'j'
<> help "enable JSON output" <> help "enable JSON output"
<> hidden <> hidden
) )
, globalFlag (Annex.setOutput (JSONOutput jsonerrormessagesoptions)) , globalFlag (setAnnexState $ Annex.setOutput (JSONOutput jsonerrormessagesoptions))
( long "json-error-messages" ( long "json-error-messages"
<> help "include error messages in JSON" <> help "include error messages in JSON"
<> hidden <> hidden
@ -383,7 +386,7 @@ jsonOptions =
jsonProgressOption :: [GlobalOption] jsonProgressOption :: [GlobalOption]
jsonProgressOption = jsonProgressOption =
[ globalFlag (Annex.setOutput (JSONOutput jsonoptions)) [ globalFlag (setAnnexState $ Annex.setOutput (JSONOutput jsonoptions))
( long "json-progress" ( long "json-progress"
<> help "include progress in JSON output" <> help "include progress in JSON output"
<> hidden <> hidden
@ -399,7 +402,7 @@ jsonProgressOption =
-- action in `allowConcurrentOutput`. -- action in `allowConcurrentOutput`.
jobsOption :: [GlobalOption] jobsOption :: [GlobalOption]
jobsOption = jobsOption =
[ globalSetter (setConcurrency . ConcurrencyCmdLine) $ [ globalOption (setAnnexState . setConcurrency . ConcurrencyCmdLine) $
option (maybeReader parseConcurrency) option (maybeReader parseConcurrency)
( long "jobs" <> short 'J' ( long "jobs" <> short 'J'
<> metavar (paramNumber `paramOr` "cpus") <> metavar (paramNumber `paramOr` "cpus")
@ -410,14 +413,14 @@ jobsOption =
timeLimitOption :: [GlobalOption] timeLimitOption :: [GlobalOption]
timeLimitOption = timeLimitOption =
[ globalSetter settimelimit $ option (eitherReader parseDuration) [ globalOption settimelimit $ option (eitherReader parseDuration)
( long "time-limit" <> short 'T' <> metavar paramTime ( long "time-limit" <> short 'T' <> metavar paramTime
<> help "stop after the specified amount of time" <> help "stop after the specified amount of time"
<> hidden <> hidden
) )
] ]
where where
settimelimit duration = do settimelimit duration = setAnnexState $ do
start <- liftIO getPOSIXTime start <- liftIO getPOSIXTime
let cutoff = start + durationToPOSIXTime duration let cutoff = start + durationToPOSIXTime duration
Annex.changeState $ \s -> s { Annex.timelimit = Just (duration, cutoff) } Annex.changeState $ \s -> s { Annex.timelimit = Just (duration, cutoff) }

View file

@ -74,7 +74,7 @@ addGlobalOptions c = c { cmdglobaloptions = globalOptions ++ cmdglobaloptions c
globalOptions :: [GlobalOption] globalOptions :: [GlobalOption]
globalOptions = globalOptions =
globalSetter checkUUID (strOption globalOption (setAnnexState . checkUUID) (strOption
( long "uuid" <> metavar paramUUID ( long "uuid" <> metavar paramUUID
<> help "local repository uuid" <> help "local repository uuid"
)) ))

View file

@ -7,19 +7,30 @@
module CmdLine.GlobalSetter where module CmdLine.GlobalSetter where
import Types.DeferredParse
import Common import Common
import Annex import Annex
import Types.DeferredParse
import Options.Applicative import Options.Applicative
globalFlag :: Annex () -> Mod FlagFields GlobalSetter -> GlobalOption setAnnexState :: Annex () -> GlobalSetter
globalFlag setter = flag' (DeferredParse setter) setAnnexState a = GlobalSetter a id
globalSetter :: (v -> Annex ()) -> Parser v -> GlobalOption setAnnexRead :: (AnnexRead -> AnnexRead) -> GlobalSetter
globalSetter setter parser = DeferredParse . setter <$> parser setAnnexRead f = GlobalSetter (return ()) f
globalFlag :: GlobalSetter -> Mod FlagFields GlobalSetter -> GlobalOption
globalFlag = flag'
globalOption :: (v -> GlobalSetter) -> Parser v -> GlobalOption
globalOption mk parser = mk <$> parser
-- | Combines a bunch of GlobalOptions together into a Parser
-- that returns a GlobalSetter that can be used to set all the options that
-- are enabled.
parserGlobalOptions :: [GlobalOption] -> Parser GlobalSetter parserGlobalOptions :: [GlobalOption] -> Parser GlobalSetter
parserGlobalOptions [] = DeferredParse <$> pure noop parserGlobalOptions [] = pure mempty
parserGlobalOptions l = DeferredParse . mapM_ getParsed parserGlobalOptions l = mconcat <$> many (foldl1 (<|>) l)
<$> many (foldl1 (<|>) l)
applyAnnexReadSetter :: GlobalSetter -> (AnnexState, AnnexRead) -> (AnnexState, AnnexRead)
applyAnnexReadSetter gs (st, rd) = (st, annexReadSetter gs rd)

View file

@ -20,46 +20,47 @@ import Types.GitConfig
import Git.Types (ConfigKey(..)) import Git.Types (ConfigKey(..))
import Git.Config import Git.Config
import Utility.FileSystemEncoding import Utility.FileSystemEncoding
import Annex.Debug
-- Global options accepted by both git-annex and git-annex-shell sub-commands. -- Global options accepted by both git-annex and git-annex-shell sub-commands.
commonGlobalOptions :: [GlobalOption] commonGlobalOptions :: [GlobalOption]
commonGlobalOptions = commonGlobalOptions =
[ globalFlag (setforce True) [ globalFlag (setAnnexState $ setforce True)
( long "force" ( long "force"
<> help "allow actions that may lose annexed data" <> help "allow actions that may lose annexed data"
<> hidden <> hidden
) )
, globalFlag (setfast True) , globalFlag (setAnnexState $ setfast True)
( long "fast" <> short 'F' ( long "fast" <> short 'F'
<> help "avoid slow operations" <> help "avoid slow operations"
<> hidden <> hidden
) )
, globalFlag (Annex.setOutput QuietOutput) , globalFlag (setAnnexState $ Annex.setOutput QuietOutput)
( long "quiet" <> short 'q' ( long "quiet" <> short 'q'
<> help "avoid verbose output" <> help "avoid verbose output"
<> hidden <> hidden
) )
, globalFlag (Annex.setOutput NormalOutput) , globalFlag (setAnnexState $ Annex.setOutput NormalOutput)
( long "verbose" <> short 'v' ( long "verbose" <> short 'v'
<> help "allow verbose output (default)" <> help "allow verbose output (default)"
<> hidden <> hidden
) )
, globalFlag (setdebug True) , globalFlag (setAnnexState $ setdebug True)
( long "debug" <> short 'd' ( long "debug" <> short 'd'
<> help "show debug messages" <> help "show debug messages"
<> hidden <> hidden
) )
, globalFlag (setdebug False) , globalFlag (setAnnexState $ setdebug False)
( long "no-debug" ( long "no-debug"
<> help "don't show debug messages" <> help "don't show debug messages"
<> hidden <> hidden
) )
, globalSetter setdebugfilter $ strOption , globalOption setdebugfilter $ strOption
( long "debugfilter" <> metavar "NAME[,NAME..]" ( long "debugfilter" <> metavar "NAME[,NAME..]"
<> help "show debug messages coming from a module" <> help "show debug messages coming from a module"
<> hidden <> hidden
) )
, globalSetter setforcebackend $ strOption , globalOption setforcebackend $ strOption
( long "backend" <> short 'b' <> metavar paramName ( long "backend" <> short 'b' <> metavar paramName
<> help "specify key-value backend to use" <> help "specify key-value backend to use"
<> hidden <> hidden
@ -67,13 +68,26 @@ commonGlobalOptions =
] ]
where where
setforce v = Annex.changeState $ \s -> s { Annex.force = v } setforce v = Annex.changeState $ \s -> s { Annex.force = v }
setfast v = Annex.changeState $ \s -> s { Annex.fast = v } setfast v = Annex.changeState $ \s -> s { Annex.fast = v }
setforcebackend v = Annex.changeState $ \s -> s { Annex.forcebackend = Just v }
setforcebackend v = setAnnexState $
Annex.changeState $ \s -> s { Annex.forcebackend = Just v }
-- Overriding this way, rather than just setting annexDebug -- Overriding this way, rather than just setting annexDebug
-- makes the config be passed on to any git-annex child processes. -- makes the config be passed on to any git-annex child processes.
setdebug v = Annex.addGitConfigOverride $ setdebug v = Annex.addGitConfigOverride $
decodeBS' $ debugconfig <> "=" <> boolConfig' v decodeBS' $ debugconfig <> "=" <> boolConfig' v
setdebugfilter v = Annex.addGitConfigOverride $
setdebugfilter v = mconcat
[ setAnnexRead $ \rd -> rd
{ Annex.debugselector = parseDebugSelector v
}
-- Also set in git config so it will be passed on to any
-- git-annex child processes.
, setAnnexState $ Annex.addGitConfigOverride $
decodeBS' (debugfilterconfig <> "=") ++ v decodeBS' (debugfilterconfig <> "=") ++ v
]
(ConfigKey debugconfig) = annexConfig "debug" (ConfigKey debugconfig) = annexConfig "debug"
(ConfigKey debugfilterconfig) = annexConfig "debugfilter" (ConfigKey debugfilterconfig) = annexConfig "debugfilter"

View file

@ -64,7 +64,7 @@ import Types.Command (StartMessage(..), SeekInput)
import Types.Transfer (transferKey) import Types.Transfer (transferKey)
import Messages.Internal import Messages.Internal
import Messages.Concurrent import Messages.Concurrent
import Utility.Debug import Annex.Debug
import Annex.Concurrent.Utility import Annex.Concurrent.Utility
import qualified Messages.JSON as JSON import qualified Messages.JSON as JSON
import qualified Annex import qualified Annex
@ -251,7 +251,7 @@ showRaw s = outputMessage JSON.none (s <> "\n")
setupConsole :: IO () setupConsole :: IO ()
setupConsole = do setupConsole = do
dd <- debugDisplayer dd <- debugDisplayer
configureDebug dd mempty configureDebug dd (DebugSelector (const False))
{- Force output to be line buffered. This is normally the case when {- Force output to be line buffered. This is normally the case when
- it's connected to a terminal, but may not be when redirected to - it's connected to a terminal, but may not be when redirected to
- a file or a pipe. -} - a file or a pipe. -}
@ -260,17 +260,14 @@ setupConsole = do
enableDebugOutput :: Annex () enableDebugOutput :: Annex ()
enableDebugOutput = do enableDebugOutput = do
names <- map encodeBS . annexDebugFilter <$> Annex.getGitConfig selector <- Annex.getRead Annex.debugselector
let selector
| null names = const True
| otherwise = \(DebugSource s) -> any (`S.isInfixOf` s) names
dd <- liftIO debugDisplayer dd <- liftIO debugDisplayer
liftIO $ configureDebug dd (DebugSelector selector) liftIO $ configureDebug dd selector
disableDebugOutput :: Annex () disableDebugOutput :: Annex ()
disableDebugOutput = liftIO $ do disableDebugOutput = liftIO $ do
dd <- debugDisplayer dd <- debugDisplayer
configureDebug dd mempty configureDebug dd (DebugSelector (const False))
debugDisplayer :: IO (S.ByteString -> IO ()) debugDisplayer :: IO (S.ByteString -> IO ())
debugDisplayer = do debugDisplayer = do

View file

@ -1,6 +1,6 @@
{- git-annex deferred parse values {- git-annex deferred parse values
- -
- Copyright 2015 Joey Hess <id@joeyh.name> - Copyright 2015-2021 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -12,6 +12,8 @@ module Types.DeferredParse where
import Annex import Annex
import Options.Applicative import Options.Applicative
import qualified Data.Semigroup as Sem
import Prelude
-- Some values cannot be fully parsed without performing an action. -- Some values cannot be fully parsed without performing an action.
-- The action may be expensive, so it's best to call finishParse on such a -- The action may be expensive, so it's best to call finishParse on such a
@ -36,6 +38,20 @@ instance DeferredParseClass (Maybe (DeferredParse a)) where
instance DeferredParseClass [DeferredParse a] where instance DeferredParseClass [DeferredParse a] where
finishParse v = mapM finishParse v finishParse v = mapM finishParse v
-- Use when the Annex action modifies Annex state.
type GlobalSetter = DeferredParse ()
type GlobalOption = Parser GlobalSetter type GlobalOption = Parser GlobalSetter
-- Used for global options that can modify Annex state by running
-- an arbitrary action in it, and can also set up AnnexRead.
data GlobalSetter = GlobalSetter
{ annexStateSetter :: Annex ()
, annexReadSetter :: AnnexRead -> AnnexRead
}
instance Sem.Semigroup GlobalSetter where
a <> b = GlobalSetter
{ annexStateSetter = annexStateSetter a >> annexStateSetter b
, annexReadSetter = annexReadSetter b . annexReadSetter a
}
instance Monoid GlobalSetter where
mempty = GlobalSetter (return ()) id

View file

@ -90,7 +90,7 @@ data GitConfig = GitConfig
, annexSyncContent :: GlobalConfigurable Bool , annexSyncContent :: GlobalConfigurable Bool
, annexSyncOnlyAnnex :: GlobalConfigurable Bool , annexSyncOnlyAnnex :: GlobalConfigurable Bool
, annexDebug :: Bool , annexDebug :: Bool
, annexDebugFilter :: [String] , annexDebugFilter :: Maybe String
, annexWebOptions :: [String] , annexWebOptions :: [String]
, annexYoutubeDlOptions :: [String] , annexYoutubeDlOptions :: [String]
, annexAriaTorrentOptions :: [String] , annexAriaTorrentOptions :: [String]
@ -171,8 +171,7 @@ extractGitConfig configsource r = GitConfig
, annexSyncOnlyAnnex = configurable False $ , annexSyncOnlyAnnex = configurable False $
getmaybebool (annexConfig "synconlyannex") getmaybebool (annexConfig "synconlyannex")
, annexDebug = getbool (annexConfig "debug") False , annexDebug = getbool (annexConfig "debug") False
, annexDebugFilter = maybe [] (splitc ',') $ , annexDebugFilter = getmaybe (annexConfig "debugfilter")
getmaybe (annexConfig "debugfilter")
, annexWebOptions = getwords (annexConfig "web-options") , annexWebOptions = getwords (annexConfig "web-options")
, annexYoutubeDlOptions = getwords (annexConfig "youtube-dl-options") , annexYoutubeDlOptions = getwords (annexConfig "youtube-dl-options")
, annexAriaTorrentOptions = getwords (annexConfig "aria-torrent-options") , annexAriaTorrentOptions = getwords (annexConfig "aria-torrent-options")

View file

@ -627,6 +627,8 @@ Executable git-annex
Annex.Content.LowLevel Annex.Content.LowLevel
Annex.Content.PointerFile Annex.Content.PointerFile
Annex.CurrentBranch Annex.CurrentBranch
Annex.Debug
Annex.Debug.Utility
Annex.Difference Annex.Difference
Annex.DirHashes Annex.DirHashes
Annex.Drop Annex.Drop