2012-12-07 21:28:23 +00:00
|
|
|
{- git-annex file content managing for direct mode
|
|
|
|
-
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
- Copyright 2012-2014 Joey Hess <joey@kitenet.net>
|
2012-12-07 21:28:23 +00:00
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
2012-12-07 21:28:23 +00:00
|
|
|
module Annex.Content.Direct (
|
|
|
|
associatedFiles,
|
2013-06-15 18:44:43 +00:00
|
|
|
associatedFilesRelative,
|
2012-12-12 23:20:38 +00:00
|
|
|
removeAssociatedFile,
|
2013-05-20 20:28:33 +00:00
|
|
|
removeAssociatedFileUnchecked,
|
2013-11-15 18:52:03 +00:00
|
|
|
removeAssociatedFiles,
|
2012-12-12 23:20:38 +00:00
|
|
|
addAssociatedFile,
|
2012-12-08 21:03:39 +00:00
|
|
|
goodContent,
|
2013-02-14 20:17:40 +00:00
|
|
|
recordedInodeCache,
|
|
|
|
updateInodeCache,
|
2013-04-06 20:01:39 +00:00
|
|
|
addInodeCache,
|
2013-02-14 20:17:40 +00:00
|
|
|
writeInodeCache,
|
2013-03-11 06:57:48 +00:00
|
|
|
compareInodeCaches,
|
2013-03-11 16:56:47 +00:00
|
|
|
compareInodeCachesWith,
|
2013-02-19 20:26:07 +00:00
|
|
|
sameInodeCache,
|
2013-04-06 20:01:39 +00:00
|
|
|
elemInodeCaches,
|
2013-02-22 21:01:48 +00:00
|
|
|
sameFileStatus,
|
2013-02-15 20:37:57 +00:00
|
|
|
removeInodeCache,
|
2013-02-14 20:17:40 +00:00
|
|
|
toInodeCache,
|
2013-02-20 17:55:53 +00:00
|
|
|
inodesChanged,
|
|
|
|
createInodeSentinalFile,
|
2013-05-17 19:59:37 +00:00
|
|
|
addContentWhenNotPresent,
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
withTSDelta,
|
|
|
|
getTSDelta,
|
2012-12-07 21:28:23 +00:00
|
|
|
) where
|
|
|
|
|
|
|
|
import Common.Annex
|
2013-02-19 20:26:07 +00:00
|
|
|
import qualified Annex
|
2013-01-26 09:09:15 +00:00
|
|
|
import Annex.Perms
|
2012-12-07 21:28:23 +00:00
|
|
|
import qualified Git
|
2013-05-12 23:19:28 +00:00
|
|
|
import Utility.Tmp
|
2012-12-12 23:20:38 +00:00
|
|
|
import Logs.Location
|
2013-02-14 20:17:40 +00:00
|
|
|
import Utility.InodeCache
|
2013-05-17 19:59:37 +00:00
|
|
|
import Utility.CopyFile
|
|
|
|
import Annex.ReplaceFile
|
|
|
|
import Annex.Link
|
2012-12-07 21:28:23 +00:00
|
|
|
|
2013-01-18 16:20:08 +00:00
|
|
|
{- Absolute FilePaths of Files in the tree that are associated with a key. -}
|
2012-12-07 21:28:23 +00:00
|
|
|
associatedFiles :: Key -> Annex [FilePath]
|
|
|
|
associatedFiles key = do
|
2012-12-12 17:11:59 +00:00
|
|
|
files <- associatedFilesRelative key
|
|
|
|
top <- fromRepo Git.repoPath
|
|
|
|
return $ map (top </>) files
|
2012-12-07 21:28:23 +00:00
|
|
|
|
2012-12-12 17:11:59 +00:00
|
|
|
{- List of files in the tree that are associated with a key, relative to
|
|
|
|
- the top of the repo. -}
|
|
|
|
associatedFilesRelative :: Key -> Annex [FilePath]
|
|
|
|
associatedFilesRelative key = do
|
2013-04-04 19:46:33 +00:00
|
|
|
mapping <- calcRepo $ gitAnnexMapping key
|
2014-02-03 14:16:05 +00:00
|
|
|
liftIO $ catchDefaultIO [] $ withFile mapping ReadMode $ \h -> do
|
2013-01-18 16:26:45 +00:00
|
|
|
fileEncoding h
|
2014-02-03 14:20:18 +00:00
|
|
|
-- Read strictly to ensure the file is closed
|
|
|
|
-- before changeAssociatedFiles tries to write to it.
|
|
|
|
-- (Especially needed on Windows.)
|
|
|
|
lines <$> hGetContentsStrict h
|
2012-12-10 19:02:44 +00:00
|
|
|
|
2012-12-10 18:37:24 +00:00
|
|
|
{- Changes the associated files information for a key, applying a
|
2013-01-18 16:20:08 +00:00
|
|
|
- transformation to the list. Returns new associatedFiles value. -}
|
2012-12-12 23:20:38 +00:00
|
|
|
changeAssociatedFiles :: Key -> ([FilePath] -> [FilePath]) -> Annex [FilePath]
|
2012-12-10 18:37:24 +00:00
|
|
|
changeAssociatedFiles key transform = do
|
2013-04-04 19:46:33 +00:00
|
|
|
mapping <- calcRepo $ gitAnnexMapping key
|
2012-12-12 17:11:59 +00:00
|
|
|
files <- associatedFilesRelative key
|
2012-12-10 19:02:44 +00:00
|
|
|
let files' = transform files
|
2014-02-11 04:39:50 +00:00
|
|
|
when (files /= files') $
|
2013-11-15 18:52:03 +00:00
|
|
|
modifyContent mapping $
|
2014-02-03 14:08:28 +00:00
|
|
|
liftIO $ viaTmp writeFileAnyEncoding mapping $
|
|
|
|
unlines files'
|
2013-01-18 16:20:08 +00:00
|
|
|
top <- fromRepo Git.repoPath
|
|
|
|
return $ map (top </>) files'
|
2012-12-10 18:37:24 +00:00
|
|
|
|
2013-11-15 18:52:03 +00:00
|
|
|
{- Removes the list of associated files. -}
|
|
|
|
removeAssociatedFiles :: Key -> Annex ()
|
|
|
|
removeAssociatedFiles key = do
|
|
|
|
mapping <- calcRepo $ gitAnnexMapping key
|
|
|
|
modifyContent mapping $
|
|
|
|
liftIO $ nukeFile mapping
|
|
|
|
|
2013-05-20 20:28:33 +00:00
|
|
|
{- Removes an associated file. Returns new associatedFiles value.
|
|
|
|
- Checks if this was the last copy of the object, and updates location
|
|
|
|
- log. -}
|
2012-12-12 23:20:38 +00:00
|
|
|
removeAssociatedFile :: Key -> FilePath -> Annex [FilePath]
|
|
|
|
removeAssociatedFile key file = do
|
2013-05-20 20:28:33 +00:00
|
|
|
fs <- removeAssociatedFileUnchecked key file
|
2012-12-12 23:20:38 +00:00
|
|
|
when (null fs) $
|
|
|
|
logStatus key InfoMissing
|
|
|
|
return fs
|
2012-12-10 18:37:24 +00:00
|
|
|
|
2013-05-20 20:28:33 +00:00
|
|
|
{- Removes an associated file. Returns new associatedFiles value. -}
|
|
|
|
removeAssociatedFileUnchecked :: Key -> FilePath -> Annex [FilePath]
|
|
|
|
removeAssociatedFileUnchecked key file = do
|
|
|
|
file' <- normaliseAssociatedFile file
|
|
|
|
changeAssociatedFiles key $ filter (/= file')
|
|
|
|
|
2013-01-18 16:20:08 +00:00
|
|
|
{- Adds an associated file. Returns new associatedFiles value. -}
|
2012-12-12 23:20:38 +00:00
|
|
|
addAssociatedFile :: Key -> FilePath -> Annex [FilePath]
|
2013-01-18 16:20:08 +00:00
|
|
|
addAssociatedFile key file = do
|
|
|
|
file' <- normaliseAssociatedFile file
|
2013-02-18 06:39:40 +00:00
|
|
|
changeAssociatedFiles key $ \files ->
|
2013-01-18 16:20:08 +00:00
|
|
|
if file' `elem` files
|
|
|
|
then files
|
|
|
|
else file':files
|
|
|
|
|
|
|
|
{- Associated files are always stored relative to the top of the repository.
|
2013-10-17 19:11:21 +00:00
|
|
|
- The input FilePath is relative to the CWD, or is absolute. -}
|
2013-01-18 16:20:08 +00:00
|
|
|
normaliseAssociatedFile :: FilePath -> Annex FilePath
|
|
|
|
normaliseAssociatedFile file = do
|
|
|
|
top <- fromRepo Git.repoPath
|
|
|
|
liftIO $ relPathDirToFile top <$> absPath file
|
2012-12-10 18:37:24 +00:00
|
|
|
|
2012-12-07 21:28:23 +00:00
|
|
|
{- Checks if a file in the tree, associated with a key, has not been modified.
|
|
|
|
-
|
|
|
|
- To avoid needing to fsck the file's content, which can involve an
|
|
|
|
- expensive checksum, this relies on a cache that contains the file's
|
|
|
|
- expected mtime and inode.
|
|
|
|
-}
|
2012-12-08 21:03:39 +00:00
|
|
|
goodContent :: Key -> FilePath -> Annex Bool
|
2013-02-19 20:26:07 +00:00
|
|
|
goodContent key file = sameInodeCache file =<< recordedInodeCache key
|
2012-12-08 21:03:39 +00:00
|
|
|
|
2013-04-06 20:01:39 +00:00
|
|
|
{- Gets the recorded inode cache for a key.
|
|
|
|
-
|
|
|
|
- A key can be associated with multiple files, so may return more than
|
|
|
|
- one. -}
|
|
|
|
recordedInodeCache :: Key -> Annex [InodeCache]
|
2013-02-14 20:17:40 +00:00
|
|
|
recordedInodeCache key = withInodeCacheFile key $ \f ->
|
2013-04-06 20:01:39 +00:00
|
|
|
liftIO $ catchDefaultIO [] $
|
2013-05-14 00:29:52 +00:00
|
|
|
mapMaybe readInodeCache . lines <$> readFileStrict f
|
2012-12-08 17:13:36 +00:00
|
|
|
|
2013-04-06 20:01:39 +00:00
|
|
|
{- Caches an inode for a file.
|
|
|
|
-
|
|
|
|
- Anything else already cached is preserved.
|
|
|
|
-}
|
2013-02-14 20:17:40 +00:00
|
|
|
updateInodeCache :: Key -> FilePath -> Annex ()
|
2013-04-06 20:01:39 +00:00
|
|
|
updateInodeCache key file = maybe noop (addInodeCache key)
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
=<< withTSDelta (liftIO . genInodeCache file)
|
2012-12-12 23:20:38 +00:00
|
|
|
|
2013-04-06 20:01:39 +00:00
|
|
|
{- Adds another inode to the cache for a key. -}
|
|
|
|
addInodeCache :: Key -> InodeCache -> Annex ()
|
|
|
|
addInodeCache key cache = do
|
|
|
|
oldcaches <- recordedInodeCache key
|
|
|
|
unlessM (elemInodeCaches cache oldcaches) $
|
|
|
|
writeInodeCache key (cache:oldcaches)
|
|
|
|
|
|
|
|
{- Writes inode cache for a key. -}
|
|
|
|
writeInodeCache :: Key -> [InodeCache] -> Annex ()
|
2013-11-15 18:52:03 +00:00
|
|
|
writeInodeCache key caches = withInodeCacheFile key $ \f ->
|
|
|
|
modifyContent f $
|
|
|
|
liftIO $ writeFile f $
|
|
|
|
unlines $ map showInodeCache caches
|
2012-12-10 18:37:24 +00:00
|
|
|
|
2013-02-15 20:37:57 +00:00
|
|
|
{- Removes an inode cache. -}
|
|
|
|
removeInodeCache :: Key -> Annex ()
|
2013-11-15 18:52:03 +00:00
|
|
|
removeInodeCache key = withInodeCacheFile key $ \f ->
|
|
|
|
modifyContent f $
|
|
|
|
liftIO $ nukeFile f
|
2013-02-15 20:37:57 +00:00
|
|
|
|
2013-02-14 20:17:40 +00:00
|
|
|
withInodeCacheFile :: Key -> (FilePath -> Annex a) -> Annex a
|
2013-04-04 19:46:33 +00:00
|
|
|
withInodeCacheFile key a = a =<< calcRepo (gitAnnexInodeCache key)
|
2013-02-19 20:26:07 +00:00
|
|
|
|
2013-02-22 19:19:28 +00:00
|
|
|
{- Checks if a InodeCache matches the current version of a file. -}
|
2013-04-06 20:01:39 +00:00
|
|
|
sameInodeCache :: FilePath -> [InodeCache] -> Annex Bool
|
|
|
|
sameInodeCache _ [] = return False
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
sameInodeCache file old = go =<< withTSDelta (liftIO . genInodeCache file)
|
2013-02-19 20:26:07 +00:00
|
|
|
where
|
|
|
|
go Nothing = return False
|
2013-04-06 20:01:39 +00:00
|
|
|
go (Just curr) = elemInodeCaches curr old
|
2013-02-22 19:19:28 +00:00
|
|
|
|
2013-02-22 21:01:48 +00:00
|
|
|
{- Checks if a FileStatus matches the recorded InodeCache of a file. -}
|
|
|
|
sameFileStatus :: Key -> FileStatus -> Annex Bool
|
finish fixing windows timezone madness
Rather than calculating the TSDelta once, and caching it, this now
reads the inode sential file's InodeCache file once, and then each time a
new InodeCache is generated, looks at the sentinal file to get the current
delta.
This way, if the time zone changes while git-annex is running, it will
adapt.
This adds some inneffiency, but only on Windows, and only 1 stat per new
file added. The worst innefficiency is that `git annex status` and
`git annex sync` will now (on Windows) stat the inode sentinal file once per
file in the repo.
It would be more efficient to use getCurrentTimeZone, rather than needing
to stat the sentinal file. This should be easy to do, once the time
package gets my bugfix patch.
This commit was sponsored by Jürgen Lüters.
2014-06-12 17:43:16 +00:00
|
|
|
sameFileStatus key status = do
|
2013-02-22 21:01:48 +00:00
|
|
|
old <- recordedInodeCache key
|
finish fixing windows timezone madness
Rather than calculating the TSDelta once, and caching it, this now
reads the inode sential file's InodeCache file once, and then each time a
new InodeCache is generated, looks at the sentinal file to get the current
delta.
This way, if the time zone changes while git-annex is running, it will
adapt.
This adds some inneffiency, but only on Windows, and only 1 stat per new
file added. The worst innefficiency is that `git annex status` and
`git annex sync` will now (on Windows) stat the inode sentinal file once per
file in the repo.
It would be more efficient to use getCurrentTimeZone, rather than needing
to stat the sentinal file. This should be easy to do, once the time
package gets my bugfix patch.
This commit was sponsored by Jürgen Lüters.
2014-06-12 17:43:16 +00:00
|
|
|
curr <- withTSDelta $ \delta -> liftIO $ toInodeCache delta status
|
2013-04-03 07:52:41 +00:00
|
|
|
case (old, curr) of
|
2013-04-06 20:01:39 +00:00
|
|
|
(_, Just c) -> elemInodeCaches c old
|
|
|
|
([], Nothing) -> return True
|
2013-02-22 21:01:48 +00:00
|
|
|
_ -> return False
|
|
|
|
|
2013-02-22 19:19:28 +00:00
|
|
|
{- If the inodes have changed, only the size and mtime are compared. -}
|
|
|
|
compareInodeCaches :: InodeCache -> InodeCache -> Annex Bool
|
|
|
|
compareInodeCaches x y
|
2013-03-11 16:56:47 +00:00
|
|
|
| compareStrong x y = return True
|
2013-02-22 19:19:28 +00:00
|
|
|
| otherwise = ifM inodesChanged
|
2013-03-16 20:58:40 +00:00
|
|
|
( return $ compareWeak x y
|
|
|
|
, return False
|
2013-02-22 19:19:28 +00:00
|
|
|
)
|
2013-02-19 20:26:07 +00:00
|
|
|
|
2013-04-06 20:01:39 +00:00
|
|
|
elemInodeCaches :: InodeCache -> [InodeCache] -> Annex Bool
|
|
|
|
elemInodeCaches _ [] = return False
|
|
|
|
elemInodeCaches c (l:ls) = ifM (compareInodeCaches c l)
|
|
|
|
( return True
|
|
|
|
, elemInodeCaches c ls
|
|
|
|
)
|
|
|
|
|
2013-03-11 16:56:47 +00:00
|
|
|
compareInodeCachesWith :: Annex InodeComparisonType
|
|
|
|
compareInodeCachesWith = ifM inodesChanged ( return Weakly, return Strongly )
|
|
|
|
|
2013-05-17 19:59:37 +00:00
|
|
|
{- Copies the contentfile to the associated file, if the associated
|
2013-05-23 00:58:27 +00:00
|
|
|
- file has no content. If the associated file does have content,
|
2013-05-17 19:59:37 +00:00
|
|
|
- even if the content differs, it's left unchanged. -}
|
|
|
|
addContentWhenNotPresent :: Key -> FilePath -> FilePath -> Annex ()
|
|
|
|
addContentWhenNotPresent key contentfile associatedfile = do
|
|
|
|
v <- isAnnexLink associatedfile
|
2013-09-25 07:09:06 +00:00
|
|
|
when (Just key == v) $
|
2013-05-17 19:59:37 +00:00
|
|
|
replaceFile associatedfile $
|
|
|
|
liftIO . void . copyFileExternal contentfile
|
2013-05-17 20:16:10 +00:00
|
|
|
updateInodeCache key associatedfile
|
2013-05-17 19:59:37 +00:00
|
|
|
|
2013-02-19 20:26:07 +00:00
|
|
|
{- Some filesystems get new inodes each time they are mounted.
|
|
|
|
- In order to work on such a filesystem, a sentinal file is used to detect
|
2013-02-20 17:55:53 +00:00
|
|
|
- when the inodes have changed.
|
|
|
|
-
|
|
|
|
- If the sentinal file does not exist, we have to assume that the
|
|
|
|
- inodes have changed.
|
|
|
|
-}
|
2013-02-19 20:26:07 +00:00
|
|
|
inodesChanged :: Annex Bool
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
inodesChanged = sentinalInodesChanged <$> sentinalStatus
|
2013-02-20 17:55:53 +00:00
|
|
|
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
withTSDelta :: (TSDelta -> Annex a) -> Annex a
|
|
|
|
withTSDelta a = a =<< getTSDelta
|
2013-02-20 17:55:53 +00:00
|
|
|
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
getTSDelta :: Annex TSDelta
|
|
|
|
#ifdef mingw32_HOST_OS
|
|
|
|
getTSDelta = sentinalTSDelta <$> sentinalStatus
|
|
|
|
#else
|
|
|
|
getTSDelta = pure noTSDelta -- optimisation
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sentinalStatus :: Annex SentinalStatus
|
|
|
|
sentinalStatus = maybe check return =<< Annex.getState Annex.sentinalstatus
|
|
|
|
where
|
|
|
|
check = do
|
|
|
|
sc <- liftIO . checkSentinalFile =<< annexSentinalFile
|
|
|
|
Annex.changeState $ \s -> s { Annex.sentinalstatus = Just sc }
|
|
|
|
return sc
|
2013-02-20 17:55:53 +00:00
|
|
|
|
|
|
|
{- The sentinal file is only created when first initializing a repository.
|
|
|
|
- If there are any annexed objects in the repository already, creating
|
|
|
|
- the file would invalidate their inode caches. -}
|
|
|
|
createInodeSentinalFile :: Annex ()
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
createInodeSentinalFile = unlessM (alreadyexists <||> hasobjects) $ do
|
|
|
|
s <- annexSentinalFile
|
|
|
|
createAnnexDirectory (parentDir (sentinalFile s))
|
|
|
|
liftIO $ writeSentinalFile s
|
2013-02-20 17:55:53 +00:00
|
|
|
where
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
alreadyexists = liftIO. sentinalFileExists =<< annexSentinalFile
|
2013-02-20 17:55:53 +00:00
|
|
|
hasobjects = liftIO . doesDirectoryExist =<< fromRepo gitAnnexObjectDir
|
fix for Windows file timestamp timezone madness
On Windows, changing the time zone causes the apparent mtime of files to
change. This confuses git-annex, which natually thinks this means the files
have actually been modified (since THAT'S WHAT A MTIME IS FOR, BILL <sheesh>).
Work around this stupidity, by using the inode sentinal file to detect if
the timezone has changed, and calculate a TSDelta, which will be applied
when generating InodeCaches.
This should add no overhead at all on unix. Indeed, I sped up a few
things slightly in the refactoring.
Seems to basically work! But it has a big known problem:
If the timezone changes while the assistant (or a long-running command)
runs, it won't notice, since it only checks the inode cache once, and
so will use the old delta for all new inode caches it generates for new
files it's added. Which will result in them seeming changed the next time
it runs.
This commit was sponsored by Vincent Demeester.
2014-06-11 21:51:12 +00:00
|
|
|
|
|
|
|
annexSentinalFile :: Annex SentinalFile
|
|
|
|
annexSentinalFile = do
|
|
|
|
sentinalfile <- fromRepo gitAnnexInodeSentinal
|
|
|
|
sentinalcachefile <- fromRepo gitAnnexInodeSentinalCache
|
|
|
|
return $ SentinalFile
|
|
|
|
{ sentinalFile = sentinalfile
|
|
|
|
, sentinalCacheFile = sentinalcachefile
|
|
|
|
}
|