fsck: Now works in bare repositories.

Checks location log information, and file contents.

Does not check that numcopies is satisfied, as .gitattributes information
about numcopies is not available in a bare repository. In practice, that
should not be a problem, since fsck is also run in a checkout and will
check numcopies there.
This commit is contained in:
Joey Hess 2011-10-29 17:49:37 -04:00
parent fef2cf7398
commit 2566eb85fe
7 changed files with 77 additions and 31 deletions

View file

@ -81,18 +81,6 @@ doCommand = start
success = return True success = return True
failure = showEndFail >> return False failure = showEndFail >> return False
notAnnexed :: FilePath -> Annex (Maybe a) -> Annex (Maybe a)
notAnnexed file a = maybe a (const $ return Nothing) =<< Backend.lookupFile file
isAnnexed :: FilePath -> ((Key, Backend Annex) -> Annex (Maybe a)) -> Annex (Maybe a)
isAnnexed file a = maybe (return Nothing) a =<< Backend.lookupFile file
notBareRepo :: Annex a -> Annex a
notBareRepo a = do
whenM (Git.repoIsLocalBare <$> gitRepo) $
error "You cannot run this subcommand in a bare repository."
a
{- These functions find appropriate files or other things based on a {- These functions find appropriate files or other things based on a
user's parameters, and prepare actions operating on them. -} user's parameters, and prepare actions operating on them. -}
withFilesInGit :: (FilePath -> CommandStart) -> CommandSeek withFilesInGit :: (FilePath -> CommandStart) -> CommandSeek
@ -168,7 +156,18 @@ runFilteredGen a d fs = do
ok <- matcher f ok <- matcher f
if ok then a v else stop if ok then a v else stop
{- filter out symlinks -} notAnnexed :: FilePath -> Annex (Maybe a) -> Annex (Maybe a)
notAnnexed file a = maybe a (const $ return Nothing) =<< Backend.lookupFile file
isAnnexed :: FilePath -> ((Key, Backend Annex) -> Annex (Maybe a)) -> Annex (Maybe a)
isAnnexed file a = maybe (return Nothing) a =<< Backend.lookupFile file
notBareRepo :: Annex a -> Annex a
notBareRepo a = do
whenM (Git.repoIsLocalBare <$> gitRepo) $
error "You cannot run this subcommand in a bare repository."
a
notSymlink :: FilePath -> IO Bool notSymlink :: FilePath -> IO Bool
notSymlink f = liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f notSymlink f = liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f

View file

@ -1,6 +1,6 @@
{- git-annex command {- git-annex command
- -
- Copyright 2010,2011 Joey Hess <joey@kitenet.net> - Copyright 2010-2011 Joey Hess <joey@kitenet.net>
- -
- Licensed under the GNU GPL version 3 or higher. - Licensed under the GNU GPL version 3 or higher.
-} -}
@ -12,6 +12,8 @@ import Command
import qualified Remote import qualified Remote
import qualified Types.Backend import qualified Types.Backend
import qualified Types.Key import qualified Types.Key
import qualified Backend
import qualified Git
import Annex.Content import Annex.Content
import Logs.Location import Logs.Location
import Logs.Trust import Logs.Trust
@ -24,30 +26,61 @@ def :: [Command]
def = [command "fsck" paramPaths seek "check for problems"] def = [command "fsck" paramPaths seek "check for problems"]
seek :: [CommandSeek] seek :: [CommandSeek]
seek = [withNumCopies start] seek = [withNumCopies start, withBarePresentKeys startBare]
start :: FilePath -> Maybe Int -> CommandStart start :: FilePath -> Maybe Int -> CommandStart
start file numcopies = notBareRepo $ isAnnexed file $ \(key, backend) -> do start file numcopies = isAnnexed file $ \(key, backend) -> do
showStart "fsck" file showStart "fsck" file
next $ perform key file backend numcopies next $ perform key file backend numcopies
perform :: Key -> FilePath -> Backend Annex -> Maybe Int -> CommandPerform perform :: Key -> FilePath -> Backend Annex -> Maybe Int -> CommandPerform
perform key file backend numcopies = check =<< sequence perform key file backend numcopies = check
-- order matters -- order matters
[ verifyLocationLog key file [ verifyLocationLog key file
, checkKeySize key , checkKeySize key
, checkKeyNumCopies key file numcopies , checkKeyNumCopies key file numcopies
, (Types.Backend.fsckKey backend) key , (Types.Backend.fsckKey backend) key
] ]
{- To fsck a bare repository, fsck each key in the location log. -}
withBarePresentKeys :: (Key -> CommandStart) -> CommandSeek
withBarePresentKeys a params = do
bare <- Git.repoIsLocalBare <$> gitRepo
if bare
then do
unless (null params) $ do
error "fsck should be run without parameters in a bare repository"
liftM (map a) loggedKeys
else return []
startBare :: Key -> CommandStart
startBare key = case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of
Nothing -> stop
Just backend -> do
showStart "fsck" (show key)
next $ performBare key backend
{- Note that numcopies cannot be checked in a bare repository, because
- getting the numcopies value requires a working copy with .gitattributes
- files. -}
performBare :: Key -> Backend Annex -> CommandPerform
performBare key backend = check
[ verifyLocationLog key (show key)
, checkKeySize key
, (Types.Backend.fsckKey backend) key
]
check :: [Annex Bool] -> CommandPerform
check s = sequence s >>= dispatch
where where
check vs dispatch vs
| all (== True) vs = next $ return True | all (== True) vs = next $ return True
| otherwise = stop | otherwise = stop
{- Checks that the location log reflects the current status of the key, {- Checks that the location log reflects the current status of the key,
in this repository only. -} in this repository only. -}
verifyLocationLog :: Key -> FilePath -> Annex Bool verifyLocationLog :: Key -> String -> Annex Bool
verifyLocationLog key file = do verifyLocationLog key desc = do
g <- gitRepo g <- gitRepo
present <- inAnnex key present <- inAnnex key
@ -69,7 +102,7 @@ verifyLocationLog key file = do
(False, True) -> do (False, True) -> do
fix g u InfoMissing fix g u InfoMissing
warning $ warning $
"** Based on the location log, " ++ file "** Based on the location log, " ++ desc
++ "\n** was expected to be present, " ++ ++ "\n** was expected to be present, " ++
"but its content is missing." "but its content is missing."
return False return False

View file

@ -67,19 +67,11 @@ checkRemoteUnused name = do
checkRemoteUnused' :: Remote.Remote Annex -> Annex () checkRemoteUnused' :: Remote.Remote Annex -> Annex ()
checkRemoteUnused' r = do checkRemoteUnused' r = do
showAction "checking for unused data" showAction "checking for unused data"
remotehas <- filterM isthere =<< loggedKeys remotehas <- loggedKeysFor (Remote.uuid r)
remoteunused <- excludeReferenced remotehas remoteunused <- excludeReferenced remotehas
let list = number 0 remoteunused let list = number 0 remoteunused
writeUnusedFile "" list writeUnusedFile "" list
unless (null remoteunused) $ showLongNote $ remoteUnusedMsg r list unless (null remoteunused) $ showLongNote $ remoteUnusedMsg r list
where
{- This should run strictly to avoid the filterM
- building many thunks containing keyLocations data. -}
isthere k = do
us <- keyLocations k
let !there = uuid `elem` us
return there
uuid = Remote.uuid r
writeUnusedFile :: FilePath -> [(Int, Key)] -> Annex () writeUnusedFile :: FilePath -> [(Int, Key)] -> Annex ()
writeUnusedFile prefix l = do writeUnusedFile prefix l = do

View file

@ -17,6 +17,7 @@ module Logs.Location (
readLog, readLog,
keyLocations, keyLocations,
loggedKeys, loggedKeys,
loggedKeysFor,
logFile, logFile,
logFileKey logFileKey
) where ) where
@ -44,6 +45,18 @@ keyLocations = currentLog . logFile
loggedKeys :: Annex [Key] loggedKeys :: Annex [Key]
loggedKeys = mapMaybe (logFileKey . takeFileName) <$> Annex.Branch.files loggedKeys = mapMaybe (logFileKey . takeFileName) <$> Annex.Branch.files
{- Finds all keys that have location log information indicating
- they are present for the specified repository. -}
loggedKeysFor :: UUID -> Annex [Key]
loggedKeysFor u = filterM isthere =<< loggedKeys
where
{- This should run strictly to avoid the filterM
- building many thunks containing keyLocations data. -}
isthere k = do
us <- keyLocations k
let !there = u `elem` us
return there
{- The filename of the log file for a given key. -} {- The filename of the log file for a given key. -}
logFile :: Key -> String logFile :: Key -> String
logFile key = hashDirLower key ++ keyFile key ++ ".log" logFile key = hashDirLower key ++ keyFile key ++ ".log"

4
debian/changelog vendored
View file

@ -8,6 +8,10 @@ git-annex (3.20111026) UNRELEASED; urgency=low
* drop --from is now supported to remove file content from a remote. * drop --from is now supported to remove file content from a remote.
* status: Now always shows the current repository, even when it does not * status: Now always shows the current repository, even when it does not
appear in uuid.log. appear in uuid.log.
* fsck: Now works in bare repositories. Checks location log information,
and file contents. Does not check that numcopies is satisfied, as
.gitattributes information about numcopies is not available in a bare
repository.
-- Joey Hess <joeyh@debian.org> Thu, 27 Oct 2011 13:58:53 -0400 -- Joey Hess <joeyh@debian.org> Thu, 27 Oct 2011 13:58:53 -0400

View file

@ -17,3 +17,5 @@ See http://lists.madduck.net/pipermail/vcs-home/2011-June/000433.html
>>> While storing the data is no longer an issue in bare repos, fsck would >>> While storing the data is no longer an issue in bare repos, fsck would
>>> need a special mode that examines all the location logs, since it >>> need a special mode that examines all the location logs, since it
>>> cannot run thru the checked out files. --[[Joey]] >>> cannot run thru the checked out files. --[[Joey]]
>>>> [[done]]! --[[Joey]]

View file

@ -1,6 +1,5 @@
What is says on the tin: What is says on the tin:
22:56:54 < RichiH> joeyh_: by the way, i have been thinking about fsck on bare repos 22:56:54 < RichiH> joeyh_: by the way, i have been thinking about fsck on bare repos
22:57:37 < RichiH> joeyh_: the best i could come with is to have a bare and a non-bare access the same repo store 22:57:37 < RichiH> joeyh_: the best i could come with is to have a bare and a non-bare access the same repo store
22:58:00 < RichiH> joeyh_: alternatively, with the SHA* backend, you have all the information to verify that the local data is correct 22:58:00 < RichiH> joeyh_: alternatively, with the SHA* backend, you have all the information to verify that the local data is correct
@ -10,3 +9,7 @@ What is says on the tin:
23:14:51 < joeyh_> unused/dropunused could work in bare repos too btw 23:14:51 < joeyh_> unused/dropunused could work in bare repos too btw
> Also `status`'s total annex keys/size could be handled for bare repos. --[[Joey]] > Also `status`'s total annex keys/size could be handled for bare repos. --[[Joey]]
>> Fsck is done. Rest not done yet. --[[Joey]]
[[!meta title="support status, unused, dropunused in bare repos"]]