1{- git check-ignore interface, with handle automatically stored in
2 - the Annex monad
3 -
4 - Copyright 2013-2020 Joey Hess <id@joeyh.name>
5 -
6 - Licensed under the GNU AGPL version 3 or higher.
7 -}
8
9module Annex.CheckIgnore (
10	CheckGitIgnore(..),
11	checkIgnored,
12	checkIgnoreStop,
13	mkConcurrentCheckIgnoreHandle,
14) where
15
16import Annex.Common
17import qualified Git.CheckIgnore as Git
18import qualified Annex
19import Utility.ResourcePool
20import Types.Concurrency
21import Annex.Concurrent.Utility
22
23newtype CheckGitIgnore = CheckGitIgnore Bool
24
25checkIgnored :: CheckGitIgnore -> RawFilePath -> Annex Bool
26checkIgnored (CheckGitIgnore False) _ = pure False
27checkIgnored (CheckGitIgnore True) file =
28	ifM (Annex.getState Annex.force)
29		( pure False
30		, withCheckIgnoreHandle $ \h -> liftIO $ Git.checkIgnored h file
31		)
32
33withCheckIgnoreHandle :: (Git.CheckIgnoreHandle -> Annex a) -> Annex a
34withCheckIgnoreHandle a =
35	maybe mkpool go =<< Annex.getState Annex.checkignorehandle
36  where
37	go p = withResourcePool p start a
38	start = inRepo Git.checkIgnoreStart
39	mkpool = do
40		-- This only runs in non-concurrent code paths;
41		-- a concurrent pool is set up earlier when needed.
42		p <- mkResourcePoolNonConcurrent start
43		Annex.changeState $ \s -> s { Annex.checkignorehandle = Just p }
44		go p
45
46mkConcurrentCheckIgnoreHandle :: Concurrency -> Annex (ResourcePool Git.CheckIgnoreHandle)
47mkConcurrentCheckIgnoreHandle c =
48	Annex.getState Annex.checkignorehandle >>= \case
49		Just p@(ResourcePool {}) -> return p
50		_ -> mkResourcePool =<< liftIO (maxCheckIgnores c)
51
52{- git check-ignore is typically CPU bound, and is not likely to be the main
53 - bottleneck for any command. So limit to the number of CPU cores, maximum,
54 - while respecting the -Jn value.
55 -}
56maxCheckIgnores :: Concurrency -> IO Int
57maxCheckIgnores = concurrencyUpToCpus
58
59checkIgnoreStop :: Annex ()
60checkIgnoreStop = maybe noop stop =<< Annex.getState Annex.checkignorehandle
61  where
62	stop p = do
63		liftIO $ freeResourcePool p Git.checkIgnoreStop
64		Annex.changeState $ \s -> s { Annex.checkignorehandle = Nothing }
65