2012-06-19 06:40:21 +00:00
|
|
|
{- git-annex assistant change tracking
|
|
|
|
-
|
|
|
|
- Copyright 2012 Joey Hess <joey@kitenet.net>
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Assistant.Changes where
|
|
|
|
|
|
|
|
import Common.Annex
|
|
|
|
import qualified Annex.Queue
|
2012-06-20 23:04:16 +00:00
|
|
|
import Types.KeySource
|
2012-06-19 06:40:21 +00:00
|
|
|
|
|
|
|
import Control.Concurrent.STM
|
|
|
|
import Data.Time.Clock
|
|
|
|
|
2012-06-20 23:04:16 +00:00
|
|
|
data ChangeType = AddChange | LinkChange | RmChange | RmDirChange
|
2012-06-19 06:40:21 +00:00
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
|
|
type ChangeChan = TChan Change
|
|
|
|
|
2012-06-20 23:04:16 +00:00
|
|
|
data Change
|
|
|
|
= Change
|
|
|
|
{ changeTime :: UTCTime
|
|
|
|
, changeFile :: FilePath
|
|
|
|
, changeType :: ChangeType
|
|
|
|
}
|
|
|
|
| PendingAddChange
|
|
|
|
{ changeTime ::UTCTime
|
|
|
|
, keySource :: KeySource
|
|
|
|
}
|
2012-06-19 06:40:21 +00:00
|
|
|
deriving (Show)
|
|
|
|
|
|
|
|
runChangeChan :: STM a -> IO a
|
|
|
|
runChangeChan = atomically
|
|
|
|
|
|
|
|
newChangeChan :: IO ChangeChan
|
|
|
|
newChangeChan = atomically newTChan
|
|
|
|
|
|
|
|
{- Handlers call this when they made a change that needs to get committed. -}
|
|
|
|
madeChange :: FilePath -> ChangeType -> Annex (Maybe Change)
|
|
|
|
madeChange f t = do
|
|
|
|
-- Just in case the commit thread is not flushing the queue fast enough.
|
2012-06-20 23:04:16 +00:00
|
|
|
Annex.Queue.flushWhenFull
|
2012-06-19 06:40:21 +00:00
|
|
|
liftIO $ Just <$> (Change <$> getCurrentTime <*> pure f <*> pure t)
|
|
|
|
|
|
|
|
noChange :: Annex (Maybe Change)
|
|
|
|
noChange = return Nothing
|
|
|
|
|
2012-06-20 23:04:16 +00:00
|
|
|
{- Indicates an add is in progress. -}
|
|
|
|
pendingAddChange :: KeySource -> Annex (Maybe Change)
|
|
|
|
pendingAddChange ks =
|
|
|
|
liftIO $ Just <$> (PendingAddChange <$> getCurrentTime <*> pure ks)
|
|
|
|
|
|
|
|
isPendingAddChange :: Change -> Bool
|
|
|
|
isPendingAddChange (PendingAddChange {}) = True
|
|
|
|
isPendingAddChange _ = False
|
|
|
|
|
|
|
|
finishedChange :: Change -> Change
|
|
|
|
finishedChange c@(PendingAddChange { keySource = ks }) = Change
|
|
|
|
{ changeTime = changeTime c
|
|
|
|
, changeFile = keyFilename ks
|
|
|
|
, changeType = AddChange
|
|
|
|
}
|
|
|
|
finishedChange c = c
|
|
|
|
|
2012-06-19 06:40:21 +00:00
|
|
|
{- Gets all unhandled changes.
|
|
|
|
- Blocks until at least one change is made. -}
|
|
|
|
getChanges :: ChangeChan -> IO [Change]
|
|
|
|
getChanges chan = runChangeChan $ do
|
|
|
|
c <- readTChan chan
|
|
|
|
go [c]
|
|
|
|
where
|
|
|
|
go l = do
|
|
|
|
v <- tryReadTChan chan
|
|
|
|
case v of
|
|
|
|
Nothing -> return l
|
|
|
|
Just c -> go (c:l)
|
|
|
|
|
|
|
|
{- Puts unhandled changes back into the channel.
|
|
|
|
- Note: Original order is not preserved. -}
|
|
|
|
refillChanges :: ChangeChan -> [Change] -> IO ()
|
|
|
|
refillChanges chan cs = runChangeChan $ mapM_ (writeTChan chan) cs
|