git-annex/Logs/Unused.hs

111 lines
3.2 KiB
Haskell
Raw Normal View History

{- git-annex unused log file
-
- This file is stored locally in .git/annex/, not in the git-annex branch.
-
- The format: "int key timestamp"
-
- The int is a short, stable identifier that the user can use to
- refer to this key. (Equivilant to a filename.)
-
- The timestamp indicates when the key was first determined to be unused.
- Older versions of the log omit the timestamp.
-
- Copyright 2010-2014 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Logs.Unused (
2013-07-04 06:36:02 +00:00
UnusedMap,
updateUnusedLog,
readUnusedLog,
readUnusedMap,
2014-01-23 19:09:43 +00:00
dateUnusedLog,
unusedKeys,
2014-01-23 19:09:43 +00:00
unusedKeys',
setUnusedKeys,
) where
import qualified Data.Map as M
import qualified Data.Set as S
import Data.Time.Clock.POSIX
import Data.Time
import Annex.Common
import qualified Annex
import Logs.TimeStamp
import Logs.File
-- everything that is stored in the unused log
type UnusedLog = M.Map Key (Int, Maybe POSIXTime)
-- used to look up unused keys specified by the user
type UnusedMap = M.Map Int Key
log2map :: UnusedLog -> UnusedMap
log2map = M.fromList . map (\(k, (i, _t)) -> (i, k)) . M.toList
map2log :: POSIXTime -> UnusedMap -> UnusedLog
map2log t = M.fromList . map (\(i, k) -> (k, (i, Just t))) . M.toList
{- Only keeps keys that are in the new log, but uses any timestamps
- those keys had in the old log. -}
preserveTimestamps :: UnusedLog -> UnusedLog -> UnusedLog
preserveTimestamps oldl newl = M.intersection (M.unionWith oldts oldl newl) newl
where
oldts _old@(_, ts) _new@(int, _) = (int, ts)
updateUnusedLog :: FilePath -> UnusedMap -> Annex ()
updateUnusedLog prefix m = do
oldl <- readUnusedLog prefix
newl <- preserveTimestamps oldl . flip map2log m <$> liftIO getPOSIXTime
writeUnusedLog prefix newl
writeUnusedLog :: FilePath -> UnusedLog -> Annex ()
writeUnusedLog prefix l = do
logfile <- fromRepo $ gitAnnexUnusedLog prefix
writeLogFile logfile $ unlines $ map format $ M.toList l
where
format (k, (i, Just t)) = show i ++ " " ++ key2file k ++ " " ++ show t
format (k, (i, Nothing)) = show i ++ " " ++ key2file k
readUnusedLog :: FilePath -> Annex UnusedLog
readUnusedLog prefix = do
f <- fromRepo $ gitAnnexUnusedLog prefix
ifM (liftIO $ doesFileExist f)
2013-04-03 07:52:41 +00:00
( M.fromList . mapMaybe parse . lines
<$> liftIO (readFileStrict f)
, return M.empty
)
2012-11-11 04:51:07 +00:00
where
parse line = case (readish sint, file2key skey, parsePOSIXTime ts) of
(Just int, Just key, mtimestamp) -> Just (key, (int, mtimestamp))
2012-11-11 04:51:07 +00:00
_ -> Nothing
where
(sint, rest) = separate (== ' ') line
(rts, rskey) = separate (== ' ') (reverse rest)
skey = reverse rskey
ts = reverse rts
readUnusedMap :: FilePath -> Annex UnusedMap
readUnusedMap = log2map <$$> readUnusedLog
2014-01-23 19:09:43 +00:00
dateUnusedLog :: FilePath -> Annex (Maybe UTCTime)
dateUnusedLog prefix = do
f <- fromRepo $ gitAnnexUnusedLog prefix
liftIO $ catchMaybeIO $ getModificationTime f
{- Set of unused keys. This is cached for speed. -}
unusedKeys :: Annex (S.Set Key)
unusedKeys = maybe (setUnusedKeys =<< unusedKeys') return
=<< Annex.getState Annex.unusedkeys
unusedKeys' :: Annex [Key]
unusedKeys' = M.keys <$> readUnusedLog ""
setUnusedKeys :: [Key] -> Annex (S.Set Key)
setUnusedKeys ks = do
let v = S.fromList ks
Annex.changeState $ \s -> s { Annex.unusedkeys = Just v }
return v