{- git check-ignore interface, with handle automatically stored in - the Annex monad - - Copyright 2013-2020 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} module Annex.CheckIgnore ( CheckGitIgnore(..), checkIgnored, checkIgnoreStop, mkConcurrentCheckIgnoreHandle, ) where import Annex.Common import qualified Git.CheckIgnore as Git import qualified Annex import Utility.ResourcePool import Types.Concurrency import Annex.Concurrent.Utility newtype CheckGitIgnore = CheckGitIgnore Bool checkIgnored :: CheckGitIgnore -> RawFilePath -> Annex Bool checkIgnored (CheckGitIgnore False) _ = pure False checkIgnored (CheckGitIgnore True) file = ifM (Annex.getRead Annex.force) ( pure False , withCheckIgnoreHandle $ \h -> liftIO $ Git.checkIgnored h file ) withCheckIgnoreHandle :: (Git.CheckIgnoreHandle -> Annex a) -> Annex a withCheckIgnoreHandle a = maybe mkpool go =<< Annex.getState Annex.checkignorehandle where go p = withResourcePool p start a start = inRepo Git.checkIgnoreStart mkpool = do -- This only runs in non-concurrent code paths; -- a concurrent pool is set up earlier when needed. p <- mkResourcePoolNonConcurrent start Annex.changeState $ \s -> s { Annex.checkignorehandle = Just p } go p mkConcurrentCheckIgnoreHandle :: Concurrency -> Annex (ResourcePool Git.CheckIgnoreHandle) mkConcurrentCheckIgnoreHandle c = Annex.getState Annex.checkignorehandle >>= \case Just p@(ResourcePool {}) -> return p _ -> mkResourcePool =<< liftIO (maxCheckIgnores c) {- git check-ignore is typically CPU bound, and is not likely to be the main - bottleneck for any command. So limit to the number of CPU cores, maximum, - while respecting the -Jn value. -} maxCheckIgnores :: Concurrency -> IO Int maxCheckIgnores = concurrencyUpToCpus checkIgnoreStop :: Annex () checkIgnoreStop = maybe noop stop =<< Annex.getState Annex.checkignorehandle where stop p = do liftIO $ freeResourcePool p Git.checkIgnoreStop Annex.changeState $ \s -> s { Annex.checkignorehandle = Nothing }