Avoid crashing when run in a bare git repo that somehow contains an index file

Do not populate the keys database with associated files,
because a bare repo has no working tree, and so it does not make sense to
populate it.

Queries of associated files in the keys database always return empty lists
in a bare repo, even if it's somehow populated. One way it could be
populated is if a user converts a non-bare repo to a bare repo.

Note that Git.Config.isBare does a string comparison, so this is not free!
But, that string comparison is very small compared to a sqlite query.

Sponsored-by: Erik Bjäreholt on Patreon
This commit is contained in:
Joey Hess 2022-01-11 13:01:49 -04:00
parent c031d19c32
commit f54c58f0df
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 48 additions and 4 deletions

View file

@ -10,6 +10,8 @@ git-annex (8.20211232) UNRELEASED; urgency=medium
a retry from failing again. a retry from failing again.
(reversion introduced in version 8.20210903) (reversion introduced in version 8.20210903)
* adb: Added ignorefinderror configuration parameter. * adb: Added ignorefinderror configuration parameter.
* Avoid crashing when run in a bare git repo that somehow contains an
index file.
-- Joey Hess <id@joeyh.name> Mon, 03 Jan 2022 14:01:14 -0400 -- Joey Hess <id@joeyh.name> Mon, 03 Jan 2022 14:01:14 -0400

View file

@ -49,6 +49,7 @@ import Git.Sha
import Git.CatFile import Git.CatFile
import Git.Branch (writeTreeQuiet, update') import Git.Branch (writeTreeQuiet, update')
import qualified Git.Ref import qualified Git.Ref
import qualified Git.Config
import Config.Smudge import Config.Smudge
import qualified Utility.RawFilePath as R import qualified Utility.RawFilePath as R
@ -154,11 +155,23 @@ addAssociatedFile k f = runWriterIO $ SQL.addAssociatedFile k f
{- Note that the files returned were once associated with the key, but {- Note that the files returned were once associated with the key, but
- some of them may not be any longer. -} - some of them may not be any longer. -}
getAssociatedFiles :: Key -> Annex [TopFilePath] getAssociatedFiles :: Key -> Annex [TopFilePath]
getAssociatedFiles = runReaderIO . SQL.getAssociatedFiles getAssociatedFiles k = emptyWhenBare $ runReaderIO $ SQL.getAssociatedFiles k
{- Queries for associated files never return anything when in a bare
- repository, since without a work tree there can be no associated files.
-
- Normally the keys database is not even populated with associated files
- in a bare repository, but it might happen if a non-bare repo got
- converted to bare. -}
emptyWhenBare :: Annex [a] -> Annex [a]
emptyWhenBare a = ifM (Git.Config.isBare <$> gitRepo)
( return []
, a
)
{- Include a known associated file along with any recorded in the database. -} {- Include a known associated file along with any recorded in the database. -}
getAssociatedFilesIncluding :: AssociatedFile -> Key -> Annex [RawFilePath] getAssociatedFilesIncluding :: AssociatedFile -> Key -> Annex [RawFilePath]
getAssociatedFilesIncluding afile k = do getAssociatedFilesIncluding afile k = emptyWhenBare $ do
g <- Annex.gitRepo g <- Annex.gitRepo
l <- map (`fromTopFilePath` g) <$> getAssociatedFiles k l <- map (`fromTopFilePath` g) <$> getAssociatedFiles k
return $ case afile of return $ case afile of
@ -168,7 +181,7 @@ getAssociatedFilesIncluding afile k = do
{- Gets any keys that are on record as having a particular associated file. {- Gets any keys that are on record as having a particular associated file.
- (Should be one or none but the database doesn't enforce that.) -} - (Should be one or none but the database doesn't enforce that.) -}
getAssociatedKey :: TopFilePath -> Annex [Key] getAssociatedKey :: TopFilePath -> Annex [Key]
getAssociatedKey = runReaderIO . SQL.getAssociatedKey getAssociatedKey f = emptyWhenBare $ runReaderIO $ SQL.getAssociatedKey f
removeAssociatedFile :: Key -> TopFilePath -> Annex () removeAssociatedFile :: Key -> TopFilePath -> Annex ()
removeAssociatedFile k = runWriterIO . SQL.removeAssociatedFile k removeAssociatedFile k = runWriterIO . SQL.removeAssociatedFile k
@ -233,7 +246,7 @@ isInodeKnown i s = or <$> runReaderIO ((:[]) <$$> SQL.isInodeKnown i s)
- is an associated file. - is an associated file.
-} -}
reconcileStaged :: H.DbQueue -> Annex () reconcileStaged :: H.DbQueue -> Annex ()
reconcileStaged qh = do reconcileStaged qh = unlessM (Git.Config.isBare <$> gitRepo) $ do
gitindex <- inRepo currentIndexFile gitindex <- inRepo currentIndexFile
indexcache <- fromRawFilePath <$> fromRepo gitAnnexKeysDbIndexCache indexcache <- fromRawFilePath <$> fromRepo gitAnnexKeysDbIndexCache
withTSDelta (liftIO . genInodeCache gitindex) >>= \case withTSDelta (liftIO . genInodeCache gitindex) >>= \case

View file

@ -55,3 +55,4 @@ AFAICS this creates the same records as if I would have done this in a regular w
Is this a bug, or am I doing something wrong? Thanks in advance for your time! Is this a bug, or am I doing something wrong? Thanks in advance for your time!
> [[fixed|done]] --[[Joey]]

View file

@ -0,0 +1,28 @@
[[!comment format=mdwn
username="joey"
subject="""comment 1"""
date="2022-01-11T16:25:50Z"
content="""
`git update-index` creates an index file. A repo with an index file is no
longer a bare repo to a certain extent, at least it is very unusual for a
repo to be both bare and contain an index file, since after all an index
file is a record of the files in the working tree. This seems to be the root
of the confusion.
I was able to reproduce this by simply copying `.git/index` from a non-bare
repo into the bare repo and then running `git-annex drop --all`.
Removing the index file was not sufficient to fix it. It turned out I also
needed to delete `annex/keydb*`. Then things returned to normal.
So, it seems that the keys database is getting populated in a bare repo
when there's an index file, and once the keys database is populated, it
runs code paths that will not work in a bare repo, because that database
contains paths (taken from the index) that it treats as being present in a
nonexistant working tree. I've fixed it to both avoid populating the keys
database, and ignore a populated keys database in this situation.
But.. My suggestion is, if you need to do this kind of thing in a bare repo,
set `GIT_INDEX_FILE` to some other file. That's how git-annex makes similar
tree objects.
"""]]