module Propellor.Property.Ccache (
hasCache,
hasLimits,
Limit(..),
DataSize,
) where
import Propellor.Base
import qualified Propellor.Property.File as File
import qualified Propellor.Property.Apt as Apt
import Utility.DataUnits
import System.Posix.Files
import qualified Data.Semigroup as Sem
data Limit
= MaxSize DataSize
| MaxFiles Integer
| NoLimit
| Limit :+ Limit
instance Sem.Semigroup Limit where
<> :: Limit -> Limit -> Limit
(<>) = Limit -> Limit -> Limit
(:+)
instance Monoid Limit where
mempty :: Limit
mempty = Limit
NoLimit
mappend :: Limit -> Limit -> Limit
mappend = Limit -> Limit -> Limit
forall a. Semigroup a => a -> a -> a
(Sem.<>)
type DataSize = String
maxSizeParam :: DataSize -> Maybe String
maxSizeParam :: DataSize -> Maybe DataSize
maxSizeParam DataSize
s = [Unit] -> DataSize -> Maybe ByteSize
readSize [Unit]
dataUnits DataSize
s
Maybe ByteSize -> (ByteSize -> Maybe DataSize) -> Maybe DataSize
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ByteSize
sz -> DataSize -> Maybe DataSize
forall a. a -> Maybe a
Just (DataSize -> Maybe DataSize) -> DataSize -> Maybe DataSize
forall a b. (a -> b) -> a -> b
$ DataSize
"--max-size=" DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ ByteSize -> DataSize
ccacheSizeUnits ByteSize
sz
ccacheSizeUnits :: Integer -> String
ccacheSizeUnits :: ByteSize -> DataSize
ccacheSizeUnits ByteSize
sz = (Char -> Bool) -> DataSize -> DataSize
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ') ([Unit] -> Bool -> ByteSize -> DataSize
roughSize [Unit]
cfgfileunits Bool
True ByteSize
sz)
where
cfgfileunits :: [Unit]
cfgfileunits :: [Unit]
cfgfileunits =
[ ByteSize -> DataSize -> DataSize -> Unit
Unit (ByteSize -> ByteSize
p ByteSize
4) DataSize
"Ti" DataSize
"terabyte"
, ByteSize -> DataSize -> DataSize -> Unit
Unit (ByteSize -> ByteSize
p ByteSize
3) DataSize
"Gi" DataSize
"gigabyte"
, ByteSize -> DataSize -> DataSize -> Unit
Unit (ByteSize -> ByteSize
p ByteSize
2) DataSize
"Mi" DataSize
"megabyte"
, ByteSize -> DataSize -> DataSize -> Unit
Unit (ByteSize -> ByteSize
p ByteSize
1) DataSize
"Ki" DataSize
"kilobyte"
]
p :: Integer -> Integer
p :: ByteSize -> ByteSize
p ByteSize
n = ByteSize
1024ByteSize -> ByteSize -> ByteSize
forall a b. (Num a, Integral b) => a -> b -> a
^ByteSize
n
hasLimits :: FilePath -> Limit -> Property DebianLike
DataSize
path hasLimits :: DataSize -> Limit -> Property DebianLike
`hasLimits` Limit
limit = Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
go Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
-> CombinedType
(Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
(Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
where
go :: Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
go
| [DataSize] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [DataSize]
params' = Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall k (t :: k). SingI t => Property (MetaTypes t)
doNothing
| [DataSize] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [DataSize]
errors =
DataSize
-> [DataSize]
-> [(DataSize, DataSize)]
-> UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
cmdPropertyEnv DataSize
"ccache" [DataSize]
params' [(DataSize
"CCACHE_DIR", DataSize
path)]
UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> DataSize
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall (p :: * -> *) i.
Checkable p i =>
p i -> DataSize -> Property i
`changesFileContent` (DataSize
path DataSize -> DataSize -> DataSize
</> DataSize
"ccache.conf")
| Bool
otherwise = DataSize
-> Propellor Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall k (metatypes :: k).
SingI metatypes =>
DataSize -> Propellor Result -> Property (MetaTypes metatypes)
property DataSize
"couldn't parse ccache limits" (Propellor Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
-> Propellor Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall a b. (a -> b) -> a -> b
$
DataSize -> Propellor Result
forall (m :: * -> *) a. MonadIO m => DataSize -> m a
errorMessage (DataSize -> Propellor Result) -> DataSize -> Propellor Result
forall a b. (a -> b) -> a -> b
$ [DataSize] -> DataSize
unlines [DataSize]
errors
params :: [Either DataSize DataSize]
params = Limit -> [Either DataSize DataSize]
limitToParams Limit
limit
([DataSize]
errors, [DataSize]
params') = [Either DataSize DataSize] -> ([DataSize], [DataSize])
forall a b. [Either a b] -> ([a], [b])
partitionEithers [Either DataSize DataSize]
params
limitToParams :: Limit -> [Either String String]
limitToParams :: Limit -> [Either DataSize DataSize]
limitToParams Limit
NoLimit = []
limitToParams (MaxSize DataSize
s) = case DataSize -> Maybe DataSize
maxSizeParam DataSize
s of
Just DataSize
param -> [DataSize -> Either DataSize DataSize
forall a b. b -> Either a b
Right DataSize
param]
Maybe DataSize
Nothing -> [DataSize -> Either DataSize DataSize
forall a b. a -> Either a b
Left (DataSize -> Either DataSize DataSize)
-> DataSize -> Either DataSize DataSize
forall a b. (a -> b) -> a -> b
$ DataSize
"unable to parse data size " DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
s]
limitToParams (MaxFiles ByteSize
f) = [DataSize -> Either DataSize DataSize
forall a b. b -> Either a b
Right (DataSize -> Either DataSize DataSize)
-> DataSize -> Either DataSize DataSize
forall a b. (a -> b) -> a -> b
$ DataSize
"--max-files=" DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ ByteSize -> DataSize
forall t. ConfigurableValue t => t -> DataSize
val ByteSize
f]
limitToParams (Limit
l1 :+ Limit
l2) = Limit -> [Either DataSize DataSize]
limitToParams Limit
l1 [Either DataSize DataSize]
-> [Either DataSize DataSize] -> [Either DataSize DataSize]
forall a. Semigroup a => a -> a -> a
<> Limit -> [Either DataSize DataSize]
limitToParams Limit
l2
hasCache :: Group -> Limit -> RevertableProperty DebianLike UnixLike
group :: Group
group@(Group DataSize
g) hasCache :: Group
-> Limit
-> RevertableProperty
DebianLike
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
`hasCache` Limit
limit = (Property DebianLike
make Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed) Property DebianLike
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> RevertableProperty
DebianLike
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
delete
where
make :: Property DebianLike
make = DataSize -> Props DebianLike -> Property DebianLike
forall k (metatypes :: k).
SingI metatypes =>
DataSize
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
propertyList (DataSize
"ccache for " DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
g DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
" group exists") (Props DebianLike -> Property DebianLike)
-> Props DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$ Props
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
props
Props
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Props
(MetaTypes
(Combine
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& DataSize
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
File.dirExists DataSize
path
Props
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Props
(MetaTypes
(Combine
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& DataSize
-> User
-> Group
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
File.ownerGroup DataSize
path (DataSize -> User
User DataSize
"root") Group
group
Props
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Props
(MetaTypes
(Combine
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& DataSize
-> FileMode
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
File.mode DataSize
path ([FileMode] -> FileMode
combineModes ([FileMode] -> FileMode) -> [FileMode] -> FileMode
forall a b. (a -> b) -> a -> b
$
[FileMode]
readModes [FileMode] -> [FileMode] -> [FileMode]
forall a. [a] -> [a] -> [a]
++ [FileMode]
executeModes [FileMode] -> [FileMode] -> [FileMode]
forall a. [a] -> [a] -> [a]
++
[ FileMode
ownerWriteMode
, FileMode
groupWriteMode
, FileMode
setGroupIDMode
]) Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> CombinedType
(Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
(Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
fixSetgidBit
Props
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
-> Props
(MetaTypes
(Combine
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& DataSize -> Limit -> Property DebianLike
hasLimits DataSize
path Limit
limit
delete :: Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
delete = IO Bool
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (DataSize -> IO Bool
doesDirectoryExist DataSize
path) (Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall a b. (a -> b) -> a -> b
$
DataSize
-> [DataSize]
-> UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
cmdProperty DataSize
"rm" [DataSize
"-r", DataSize
path] UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
MadeChange
Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> DataSize
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall p. IsProp p => p -> DataSize -> p
`describe` (DataSize
"ccache for " DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
g DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
" does not exist")
fixSetgidBit :: Property UnixLike
fixSetgidBit :: Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
fixSetgidBit =
(DataSize
-> [DataSize]
-> UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
cmdProperty DataSize
"find"
[ DataSize
path
, DataSize
"-type", DataSize
"d"
, DataSize
"-exec", DataSize
"chmod", DataSize
"g+s"
, DataSize
"{}", DataSize
"+"
] UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
MadeChange)
Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> CombinedType
(Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
(Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
forall x y. Combines x y => x -> y -> CombinedType x y
`before`
(DataSize
-> [DataSize]
-> UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
cmdProperty DataSize
"chown"
[ DataSize
"-R"
, DataSize
"root:" DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
g
, DataSize
path
] UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
MadeChange)
path :: DataSize
path = DataSize
"/var/cache/ccache-" DataSize -> DataSize -> DataSize
forall a. [a] -> [a] -> [a]
++ DataSize
g
installed :: Property DebianLike
installed :: Property DebianLike
installed = [DataSize] -> Property DebianLike
Apt.installed [DataSize
"ccache"]