summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assistant/Threads/SanityChecker.hs12
-rw-r--r--Assistant/Threads/Watcher.hs7
-rw-r--r--Assistant/Types/DaemonStatus.hs3
-rw-r--r--Git/Repair.hs27
-rw-r--r--debian/changelog2
5 files changed, 39 insertions, 12 deletions
diff --git a/Assistant/Threads/SanityChecker.hs b/Assistant/Threads/SanityChecker.hs
index b03298510..585a85cdf 100644
--- a/Assistant/Threads/SanityChecker.hs
+++ b/Assistant/Threads/SanityChecker.hs
@@ -25,8 +25,10 @@ import Utility.Batch
import Utility.NotificationBroadcaster
import Config
import Utility.HumanTime
+import Git.Repair
import Data.Time.Clock.POSIX
+import qualified Data.Set as S
{- This thread runs once at startup, and most other threads wait for it
- to finish. (However, the webapp thread does not, to prevent the UI
@@ -36,6 +38,16 @@ sanityCheckerStartupThread startupdelay = namedThreadUnchecked "SanityCheckerSta
{- Stale git locks can prevent commits from happening, etc. -}
void $ repairStaleGitLocks =<< liftAnnex gitRepo
+ {- A corrupt index file can prevent the assistant from working at
+ - all, so detect and repair. -}
+ unlessM (liftAnnex $ inRepo $ checkIndex S.empty) $ do
+ debug ["corrupt index found at startup; removing"]
+ liftAnnex $ inRepo nukeIndex
+ {- Normally the startup scan avoids re-staging files,
+ - but with the index deleted, everything needs to be
+ - restaged. -}
+ modifyDaemonStatus_ $ \s -> s { forceRestage = True }
+
{- If there's a startup delay, it's done here. -}
liftIO $ maybe noop (threadDelaySeconds . Seconds . fromIntegral . durationSeconds) startupdelay
diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs
index 3eedbe145..6a56eadbb 100644
--- a/Assistant/Threads/Watcher.hs
+++ b/Assistant/Threads/Watcher.hs
@@ -200,6 +200,9 @@ onAdd matcher file filestatus
add matcher file
| otherwise = noChange
+shouldRestage :: DaemonStatus -> Bool
+shouldRestage ds = scanComplete ds || forceRestage ds
+
{- In direct mode, add events are received for both new files, and
- modified existing files.
-}
@@ -214,7 +217,7 @@ onAddDirect symlinkssupported matcher file fs = do
- really modified, but it might have
- just been deleted and been put back,
- so it symlink is restaged to make sure. -}
- ( ifM (scanComplete <$> getDaemonStatus)
+ ( ifM (shouldRestage <$> getDaemonStatus)
( do
link <- liftAnnex $ inRepo $ gitAnnexLink file key
addLink file link (Just key)
@@ -286,7 +289,7 @@ onAddSymlink' linktarget mk isdirect file filestatus = go mk
- links too.)
-}
ensurestaged (Just link) daemonstatus
- | scanComplete daemonstatus = addLink file link mk
+ | shouldRestage daemonstatus = addLink file link mk
| otherwise = case filestatus of
Just s
| not (afterLastDaemonRun (statusChangeTime s) daemonstatus) -> noChange
diff --git a/Assistant/Types/DaemonStatus.hs b/Assistant/Types/DaemonStatus.hs
index a1a0d64dc..5d2f5bb37 100644
--- a/Assistant/Types/DaemonStatus.hs
+++ b/Assistant/Types/DaemonStatus.hs
@@ -28,6 +28,8 @@ data DaemonStatus = DaemonStatus
{ startedThreads :: M.Map ThreadName (Async (), IO ())
-- False when the daemon is performing its startup scan
, scanComplete :: Bool
+ -- True when all files should be restaged.
+ , forceRestage :: Bool
-- Time when a previous process of the daemon was running ok
, lastRunning :: Maybe POSIXTime
-- True when the daily sanity checker is running
@@ -81,6 +83,7 @@ newDaemonStatus :: IO DaemonStatus
newDaemonStatus = DaemonStatus
<$> pure M.empty
<*> pure False
+ <*> pure False
<*> pure Nothing
<*> pure False
<*> pure Nothing
diff --git a/Git/Repair.hs b/Git/Repair.hs
index dbb43c06f..85fcc6680 100644
--- a/Git/Repair.hs
+++ b/Git/Repair.hs
@@ -13,6 +13,7 @@ module Git.Repair (
resetLocalBranches,
removeTrackingBranches,
checkIndex,
+ nukeIndex,
emptyGoodCommits,
) where
@@ -368,15 +369,18 @@ verifyTree missing treesha r
else cleanup
{- Checks that the index file only refers to objects that are not missing,
- - and is not itself corrupt. -}
+ - and is not itself corrupt or missing. -}
checkIndex :: MissingObjects -> Repo -> IO Bool
-checkIndex missing r = do
- (bad, _good, cleanup) <- partitionIndex missing r
- if null bad
- then cleanup
- else do
- void cleanup
- return False
+checkIndex missing r = ifM (doesFileExist (localGitDir r </> "index"))
+ ( do
+ (bad, _good, cleanup) <- partitionIndex missing r
+ if null bad
+ then cleanup
+ else do
+ void cleanup
+ return False
+ , return False
+ )
partitionIndex :: MissingObjects -> Repo -> IO ([LsFiles.StagedDetails], [LsFiles.StagedDetails], IO Bool)
partitionIndex missing r = do
@@ -396,7 +400,7 @@ rewriteIndex missing r
| otherwise = do
(bad, good, cleanup) <- partitionIndex missing r
unless (null bad) $ do
- nukeFile (localGitDir r </> "index")
+ nukeIndex r
UpdateIndex.streamUpdateIndex r
=<< (catMaybes <$> mapM reinject good)
void cleanup
@@ -408,6 +412,9 @@ rewriteIndex missing r
UpdateIndex.stageFile sha blobtype file r
reinject _ = return Nothing
+nukeIndex :: Repo -> IO ()
+nukeIndex r = nukeFile (localGitDir r </> "index")
+
newtype GoodCommits = GoodCommits (S.Set Sha)
emptyGoodCommits :: GoodCommits
@@ -502,7 +509,7 @@ runRepairOf fsckresult forced referencerepo g = do
return (True, stillmissing, modifiedbranches)
corruptedindex = do
- nukeFile (localGitDir g </> "index")
+ nukeIndex g
putStrLn "Removed the corrupted index file. You should look at what files are present in your working tree and git add them back to the index when appropriate."
return (True, S.empty, [])
diff --git a/debian/changelog b/debian/changelog
index c4de252c1..e316b5e1a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -27,6 +27,8 @@ git-annex (5.20131102) UNRELEASED; urgency=low
* Work around Android linker problem that had prevented git-annex from
running on Android 4.3 and 4.4.
* repair: Handle case where index file is corrupt, but all objects are ok.
+ * assistant: Notice on startup when the index file is corrupt, and
+ auto-repair.
-- Joey Hess <joeyh@debian.org> Wed, 06 Nov 2013 16:14:14 -0400