diff --git a/CHANGELOG b/CHANGELOG index 16cd4f0098..88f7ce5a5e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,8 @@ git-annex (8.20211232) UNRELEASED; urgency=medium a retry from failing again. (reversion introduced in version 8.20210903) * adb: Added ignorefinderror configuration parameter. + * Avoid crashing when run in a bare git repo that somehow contains an + index file. -- Joey Hess Mon, 03 Jan 2022 14:01:14 -0400 diff --git a/Database/Keys.hs b/Database/Keys.hs index 386c3245b1..a342274f5e 100644 --- a/Database/Keys.hs +++ b/Database/Keys.hs @@ -49,6 +49,7 @@ import Git.Sha import Git.CatFile import Git.Branch (writeTreeQuiet, update') import qualified Git.Ref +import qualified Git.Config import Config.Smudge 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 - some of them may not be any longer. -} 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. -} getAssociatedFilesIncluding :: AssociatedFile -> Key -> Annex [RawFilePath] -getAssociatedFilesIncluding afile k = do +getAssociatedFilesIncluding afile k = emptyWhenBare $ do g <- Annex.gitRepo l <- map (`fromTopFilePath` g) <$> getAssociatedFiles k 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. - (Should be one or none but the database doesn't enforce that.) -} getAssociatedKey :: TopFilePath -> Annex [Key] -getAssociatedKey = runReaderIO . SQL.getAssociatedKey +getAssociatedKey f = emptyWhenBare $ runReaderIO $ SQL.getAssociatedKey f removeAssociatedFile :: Key -> TopFilePath -> Annex () removeAssociatedFile k = runWriterIO . SQL.removeAssociatedFile k @@ -233,7 +246,7 @@ isInodeKnown i s = or <$> runReaderIO ((:[]) <$$> SQL.isInodeKnown i s) - is an associated file. -} reconcileStaged :: H.DbQueue -> Annex () -reconcileStaged qh = do +reconcileStaged qh = unlessM (Git.Config.isBare <$> gitRepo) $ do gitindex <- inRepo currentIndexFile indexcache <- fromRawFilePath <$> fromRepo gitAnnexKeysDbIndexCache withTSDelta (liftIO . genInodeCache gitindex) >>= \case diff --git a/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all.mdwn b/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all.mdwn index 9cbb3926ff..1c861fd5aa 100644 --- a/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all.mdwn +++ b/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all.mdwn @@ -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! +> [[fixed|done]] --[[Joey]] diff --git a/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all/comment_1_22fb9214e6e31d04b0ffe3266d26ea69._comment b/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all/comment_1_22fb9214e6e31d04b0ffe3266d26ea69._comment new file mode 100644 index 0000000000..082b7b7332 --- /dev/null +++ b/doc/bugs/Repo_manipulation_breaks_git-annex_drop_--all/comment_1_22fb9214e6e31d04b0ffe3266d26ea69._comment @@ -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. +"""]]