summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex/Content/Direct.hs4
-rw-r--r--Annex/Direct.hs3
-rw-r--r--Command/Add.hs2
-rw-r--r--Utility/InodeCache.hs53
-rw-r--r--debian/changelog1
-rw-r--r--doc/bugs/Windows_file_timestamp_timezone_madness.mdwn3
6 files changed, 40 insertions, 26 deletions
diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs
index 2d271eee4..b249e0557 100644
--- a/Annex/Content/Direct.hs
+++ b/Annex/Content/Direct.hs
@@ -175,9 +175,9 @@ sameInodeCache file old = go =<< withTSDelta (liftIO . genInodeCache file)
{- Checks if a FileStatus matches the recorded InodeCache of a file. -}
sameFileStatus :: Key -> FileStatus -> Annex Bool
-sameFileStatus key status = withTSDelta $ \delta -> do
+sameFileStatus key status = do
old <- recordedInodeCache key
- let curr = toInodeCache delta status
+ curr <- withTSDelta $ \delta -> liftIO $ toInodeCache delta status
case (old, curr) of
(_, Just c) -> elemInodeCaches c old
([], Nothing) -> return True
diff --git a/Annex/Direct.hs b/Annex/Direct.hs
index e3dbfb6d8..5442113af 100644
--- a/Annex/Direct.hs
+++ b/Annex/Direct.hs
@@ -56,8 +56,9 @@ stageDirect = do
go (file, Just sha, Just mode) = withTSDelta $ \delta -> do
shakey <- catKey sha mode
mstat <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file
+ mcache <- liftIO $ maybe (pure Nothing) (toInodeCache delta) mstat
filekey <- isAnnexLink file
- case (shakey, filekey, mstat, toInodeCache delta =<< mstat) of
+ case (shakey, filekey, mstat, mcache) of
(_, Just key, _, _)
| shakey == filekey -> noop
{- A changed symlink. -}
diff --git a/Command/Add.hs b/Command/Add.hs
index fc55eb655..ae895464e 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -155,7 +155,7 @@ ingest (Just source) = withTSDelta $ \delta -> do
backend <- chooseBackend $ keyFilename source
k <- genKey source backend
ms <- liftIO $ catchMaybeIO $ getFileStatus $ contentLocation source
- let mcache = toInodeCache delta =<< ms
+ mcache <- maybe (pure Nothing) (liftIO . toInodeCache delta) ms
case (mcache, inodeCache source) of
(_, Nothing) -> go k mcache ms
(Just newc, Just c) | compareStrong c newc -> go k mcache ms
diff --git a/Utility/InodeCache.hs b/Utility/InodeCache.hs
index b0718e0be..b3534487d 100644
--- a/Utility/InodeCache.hs
+++ b/Utility/InodeCache.hs
@@ -107,15 +107,17 @@ readInodeCache s = case words s of
genInodeCache :: FilePath -> TSDelta -> IO (Maybe InodeCache)
genInodeCache f delta = catchDefaultIO Nothing $
- toInodeCache delta <$> getFileStatus f
-
-toInodeCache :: TSDelta -> FileStatus -> Maybe InodeCache
-toInodeCache (TSDelta delta) s
- | isRegularFile s = Just $ InodeCache $ InodeCachePrim
- (fileID s)
- (fileSize s)
- (modificationTime s + delta)
- | otherwise = Nothing
+ toInodeCache delta =<< getFileStatus f
+
+toInodeCache :: TSDelta -> FileStatus -> IO (Maybe InodeCache)
+toInodeCache (TSDelta getdelta) s
+ | isRegularFile s = do
+ delta <- getdelta
+ return $ Just $ InodeCache $ InodeCachePrim
+ (fileID s)
+ (fileSize s)
+ (modificationTime s + delta)
+ | otherwise = pure Nothing
{- Some filesystem get new random inodes each time they are mounted.
- To detect this and other problems, a sentinal file can be created.
@@ -130,12 +132,13 @@ data SentinalFile = SentinalFile
{- On Windows, the mtime of a file appears to change when the time zone is
- changed. To deal with this, a TSDelta can be used; the delta is added to
- the mtime when generating an InodeCache. The current delta can be found
- - by looking at the SentinalFile. -}
-newtype TSDelta = TSDelta EpochTime
- deriving (Show)
+ - by looking at the SentinalFile. Effectively, this makes all InodeCaches
+ - use the same time zone that was in use when the sential file was
+ - originally written. -}
+newtype TSDelta = TSDelta (IO EpochTime)
noTSDelta :: TSDelta
-noTSDelta = TSDelta 0
+noTSDelta = TSDelta (pure 0)
writeSentinalFile :: SentinalFile -> IO ()
writeSentinalFile s = do
@@ -147,16 +150,15 @@ data SentinalStatus = SentinalStatus
{ sentinalInodesChanged :: Bool
, sentinalTSDelta :: TSDelta
}
- deriving (Show)
{- Checks if the InodeCache of the sentinal file is the same
- as it was when it was originally created.
-
- - On Windows, there's no change even when there is a nonzero
- - TSDelta between the original and current InodeCaches.
+ - On Windows, time stamp differences are ignored, since they change
+ - with the timezone.
-
- - If the sential does not exist, returns a dummy value indicating
- - that it's apparently changed.
+ - When the sential file does not exist, InodeCaches canot reliably be
+ - compared, so the assumption is that there is has been a change.
-}
checkSentinalFile :: SentinalFile -> IO SentinalStatus
checkSentinalFile s = do
@@ -172,14 +174,21 @@ checkSentinalFile s = do
loadoldcache = catchDefaultIO Nothing $
readInodeCache <$> readFile (sentinalCacheFile s)
gennewcache = genInodeCache (sentinalFile s) noTSDelta
- calc (InodeCache (InodeCachePrim inode1 size1 mtime1)) (InodeCache (InodeCachePrim inode2 size2 mtime2)) =
+ calc (InodeCache (InodeCachePrim oldinode oldsize oldmtime)) (InodeCache (InodeCachePrim newinode newsize newmtime)) =
SentinalStatus (not unchanged) tsdelta
where
#ifdef mingw32_HOST_OS
- unchanged = inode1 == inode2 && size1 == size2
- tsdelta = TSDelta (mtime1 - mtime2)
+ unchanged = oldinode == newinode && oldsize == newsize
+ tsdelta = TSDelta $ do
+ -- Run when generating an InodeCache,
+ -- to get the current delta.
+ mnew <- gennewcache
+ return $ case mnew of
+ Just (InodeCache (InodeCachePrim _ _ currmtime)) ->
+ oldmtime - currmtime
+ Nothing -> 0
#else
- unchanged = inode1 == inode2 && size1 == size2 && mtime1 == mtime2
+ unchanged = oldinode == newinode && oldsize == newsize && oldmtime == newmtime
tsdelta = noTSDelta
#endif
dummy = SentinalStatus True noTSDelta
diff --git a/debian/changelog b/debian/changelog
index 9b9f93d9c..5b5274ea3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -11,6 +11,7 @@ git-annex (5.20140607) UNRELEASED; urgency=medium
Linux's caching of higher res timestamps while a FAT is mounted, caused
direct mode repositories on FAT to seem to have modified files after
they were unmounted and remounted.
+ * Deal with Windows's horrible handling of time zone changes.
-- Joey Hess <joeyh@debian.org> Mon, 09 Jun 2014 14:44:09 -0400
diff --git a/doc/bugs/Windows_file_timestamp_timezone_madness.mdwn b/doc/bugs/Windows_file_timestamp_timezone_madness.mdwn
index a90c58f24..fb0b08d9d 100644
--- a/doc/bugs/Windows_file_timestamp_timezone_madness.mdwn
+++ b/doc/bugs/Windows_file_timestamp_timezone_madness.mdwn
@@ -14,3 +14,6 @@ Unfortunately, Data.Time.LocalTime.getCurrentTimeZone doesn't seem to really
work on windows. It always returns a time zone 60 minutes from UTS in my tests,
no matter what the zone really is. I need to test this more widely and file
a GHC bug if appropriate.
+
+> [[fixed|done]], avoiding using getCurrentTime for now, although I have a
+> patch to fix it too. --[[Joey]]