assistant direct mode file add/change bookkeeping

When a file is changed in direct mode, the old content is probably lost
(at least from the local repo), and bookeeping needs to be updated to
reflect this.

Also, synthetic add events are generated at assistant startup, so
make it detect when the file has not really changed, and avoid re-adding
it.

This does add the overhead of querying the runing git cat-file for the
key that's recorded in git for the file, each time a file is added or
modified in direct mode.
This commit is contained in:
Joey Hess 2012-12-25 15:48:15 -04:00
parent 221584ec7f
commit eb40227d15
4 changed files with 39 additions and 7 deletions

View file

@ -44,6 +44,6 @@ catFileHandle = maybe startup return =<< Annex.getState Annex.catfilehandle
Annex.changeState $ \s -> s { Annex.catfilehandle = Just h } Annex.changeState $ \s -> s { Annex.catfilehandle = Just h }
return h return h
{- From the Sha of a symlink back to the key. -} {- From the Sha or Ref of a symlink back to the key. -}
catKey :: Sha -> Annex (Maybe Key) catKey :: Ref -> Annex (Maybe Key)
catKey sha = fileKey . takeFileName . encodeW8 . L.unpack <$> catObject sha catKey ref = fileKey . takeFileName . encodeW8 . L.unpack <$> catObject ref

View file

@ -10,6 +10,7 @@ module Annex.Content.Direct (
removeAssociatedFile, removeAssociatedFile,
addAssociatedFile, addAssociatedFile,
goodContent, goodContent,
changedFileStatus,
updateCache, updateCache,
recordedCache, recordedCache,
compareCache, compareCache,
@ -79,6 +80,12 @@ goodContent key file = do
old <- recordedCache key old <- recordedCache key
compareCache file old compareCache file old
changedFileStatus :: Key -> FileStatus -> Annex Bool
changedFileStatus key status = do
old <- recordedCache key
let curr = toCache status
return $ curr == old
{- Gets the recorded cache for a key. -} {- Gets the recorded cache for a key. -}
recordedCache :: Key -> Annex (Maybe Cache) recordedCache :: Key -> Annex (Maybe Cache)
recordedCache key = withCacheFile key $ \cachefile -> recordedCache key = withCacheFile key $ \cachefile ->

View file

@ -209,3 +209,11 @@ removeDirect k f = do
liftIO $ do liftIO $ do
nukeFile f nukeFile f
void $ catchMaybeIO $ removeDirectory $ parentDir f void $ catchMaybeIO $ removeDirectory $ parentDir f
{- Called when a direct mode file has been changed. Its old content may be
- lost. -}
changedDirect :: Key -> FilePath -> Annex ()
changedDirect oldk f = do
locs <- removeAssociatedFile oldk f
whenM (pure (null locs) <&&> not <$> inAnnex oldk) $
logStatus oldk InfoMissing

View file

@ -33,6 +33,8 @@ import qualified Git.HashObject
import qualified Git.LsFiles as LsFiles import qualified Git.LsFiles as LsFiles
import qualified Backend import qualified Backend
import Annex.Content import Annex.Content
import Annex.Direct
import Annex.Content.Direct
import Annex.CatFile import Annex.CatFile
import Git.Types import Git.Types
import Config import Config
@ -60,7 +62,7 @@ watchThread :: NamedThread
watchThread = NamedThread "Watcher" $ do watchThread = NamedThread "Watcher" $ do
startup <- asIO1 startupScan startup <- asIO1 startupScan
direct <- liftAnnex isDirect direct <- liftAnnex isDirect
addhook <- hook $ onAdd direct addhook <- hook $ if direct then onAddDirect else onAdd
delhook <- hook onDel delhook <- hook onDel
addsymlinkhook <- hook onAddSymlink addsymlinkhook <- hook onAddSymlink
deldirhook <- hook onDelDir deldirhook <- hook onDelDir
@ -126,12 +128,27 @@ runHandler handler file filestatus = void $ do
liftAnnex $ Annex.Queue.flushWhenFull liftAnnex $ Annex.Queue.flushWhenFull
recordChange change recordChange change
onAdd :: Bool -> Handler onAdd :: Handler
onAdd isdirect file filestatus onAdd file filestatus
| isdirect = pendingAddChange file
| maybe False isRegularFile filestatus = pendingAddChange file | maybe False isRegularFile filestatus = pendingAddChange file
| otherwise = noChange | otherwise = noChange
{- In direct mode, add events are received for both new files, and
- modified existing files. Or, in some cases, existing files that have not
- really been modified. -}
onAddDirect :: Handler
onAddDirect file fs = do
v <- liftAnnex $ catKey (Ref $ ':':file)
case (v, fs) of
(Just key, Just filestatus) ->
ifM (liftAnnex $ changedFileStatus key filestatus)
( noChange
, do
liftAnnex $ changedDirect key file
pendingAddChange file
)
_ -> pendingAddChange file
{- A symlink might be an arbitrary symlink, which is just added. {- A symlink might be an arbitrary symlink, which is just added.
- Or, if it is a git-annex symlink, ensure it points to the content - Or, if it is a git-annex symlink, ensure it points to the content
- before adding it. - before adding it.