diff options
-rw-r--r-- | Annex/Content/Direct.hs | 4 | ||||
-rw-r--r-- | Annex/Direct.hs | 3 | ||||
-rw-r--r-- | Command/Add.hs | 2 | ||||
-rw-r--r-- | Utility/InodeCache.hs | 53 | ||||
-rw-r--r-- | debian/changelog | 1 | ||||
-rw-r--r-- | doc/bugs/Windows_file_timestamp_timezone_madness.mdwn | 3 |
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]] |