blob: 3b080c469ad69edc16980c3669d0639a6b1e5528 [file] [log] [blame]
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
module Mulkup.Main where
import Colog (Message, richMessageAction, simpleMessageAction)
import Colog.Polysemy.Effect (Log, runLogAction)
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Set as Set
import Data.Time
import Mulkup.Bupstash
import Mulkup.Config
import Mulkup.Flags
import Mulkup.Logging
import Mulkup.Prelude
import Optics
import Options.Applicative
( execParser,
fullDesc,
helper,
info,
)
import Polysemy (Member, Sem)
import Polysemy.Error
import Polysemy.Final
import Polysemy.Reader (Reader, asks, runReader)
main :: IO ()
main = do
flags <- execParser $ info (flagParser <**> helper) fullDesc
let messageAction =
if verbose flags
then richMessageAction
else simpleMessageAction
config <- readConfig "./config.dhall"
result <-
main'
& runBupstash
& runLogAction @IO messageAction
& runReader (config :: MulkupConfig)
& errorToIOFinal @Text
& embedToFinal @IO
& runFinal @IO
case result of
Left err -> do
error err
Right () ->
return ()
main' :: (Member (Log Message) r, Member (Reader MulkupConfig) r, Member Bupstash r) => Sem r ()
main' = do
stashes <- asks @MulkupConfig (^. #stashes)
forM_ stashes $ \stash -> do
let labels = [("name", stash ^. #name)]
currentItems <- bupList (BupFilter labels Nothing)
let tiers =
[ (utctHour . bupItemUTCTime, #hourly),
(utctJulianDay . bupItemUTCTime, #daily),
(utctWeek . bupItemUTCTime, #weekly),
(utctMonth . bupItemUTCTime, #monthly)
]
let keepIds =
Set.unions $
map
( \(discriminator, cfgLens) ->
let tierCfg = stash ^. #tiers ^. cfgLens
in tierKeepIds discriminator (tierCfg ^. #keep) currentItems
)
tiers
let currentIds = Set.fromList (map (^. #id) currentItems)
let rmIds = Set.difference currentIds keepIds
logInfo (show labels <> " Keeping: " <> show (Set.toList keepIds))
logInfo (show labels <> " Removing: " <> show (Set.toList rmIds))
bupRemove (Set.toList rmIds)
logInfo (show labels <> " Creating backup.")
bupPut
(stash ^. #baseDir)
(stash ^. #exclusions)
labels
tierKeepIds :: (BupItem -> Integer) -> Natural -> [BupItem] -> Set Text
tierKeepIds discriminator keep items =
fromList $
take (fromIntegral keep) $
map (^. #id) $
reverse $
sortWith bupItemUTCTime $
map (head . NonEmpty.sortWith bupItemUTCTime) $
elems $
(groupBy discriminator items :: HashMap Integer (NonEmpty BupItem))
utctHour :: UTCTime -> Integer
utctHour (UTCTime (ModifiedJulianDay julianDay) tdiff) = (julianDay * 24) + (diffTimeToPicoseconds tdiff `div` (10 ^ (12 :: Integer)) `div` 3600)
utctJulianDay :: UTCTime -> Integer
utctJulianDay (UTCTime (ModifiedJulianDay julianDay) _) = julianDay
utctWeek :: UTCTime -> Integer
utctWeek (UTCTime day _) =
julianDay + fromIntegral (dayOfWeekDiff (dayOfWeek day) Sunday)
where
(ModifiedJulianDay julianDay) = day
dayOfWeekDiff a b = mod (fromEnum a - fromEnum b) 7
utctMonth :: UTCTime -> Integer
utctMonth (UTCTime day _) = fromIntegral m
where
(_, m, _) = toGregorian day