handle overBranchFileContents with read-only unmerged git-annex branches

This makes --all error out in that situation. Which is better than
ignoring information from the branches.

To really handle the branches right, overBranchFileContents would need
to both query all the branches and union merge file contents
(or perhaps not provide any file content), as well as diffing between
branches to find files that are only present in the unmerged branches.
And also, it would need to handle transitions..

Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
Joey Hess 2021-12-27 14:30:51 -04:00
parent d9d0fe5fa4
commit 7f6b2ca49c
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 35 additions and 7 deletions

View file

@ -820,13 +820,32 @@ rememberTreeishLocked treeish graftpoint jl = do
- The action is passed a callback that it can repeatedly call to read - The action is passed a callback that it can repeatedly call to read
- the next file and its contents. When there are no more files, the - the next file and its contents. When there are no more files, the
- callback will return Nothing. - callback will return Nothing.
-
- In some cases the callback may return the same file more than once,
- with different content. This happens rarely, only when the journal
- contains additional information, and the last version of the
- file it returns is the most current one.
-
- In a read-only repository that has other git-annex branches that have
- not been merged in, returns Nothing, because it's not possible to
- efficiently handle that.
-} -}
overBranchFileContents overBranchFileContents
:: (RawFilePath -> Maybe v) :: (RawFilePath -> Maybe v)
-> (Annex (Maybe (v, RawFilePath, Maybe L.ByteString)) -> Annex a) -> (Annex (Maybe (v, RawFilePath, Maybe L.ByteString)) -> Annex a)
-> Annex a -> Annex (Maybe a)
overBranchFileContents select go = do overBranchFileContents select go = do
st <- update st <- update
if not (null (unmergedRefs st))
then return Nothing
else Just <$> overBranchFileContents' select go st
overBranchFileContents'
:: (RawFilePath -> Maybe v)
-> (Annex (Maybe (v, RawFilePath, Maybe L.ByteString)) -> Annex a)
-> BranchState
-> Annex a
overBranchFileContents' select go st = do
g <- Annex.gitRepo g <- Annex.gitRepo
(l, cleanup) <- inRepo $ Git.LsTree.lsTree (l, cleanup) <- inRepo $ Git.LsTree.lsTree
Git.LsTree.LsTreeRecursive Git.LsTree.LsTreeRecursive
@ -836,7 +855,7 @@ overBranchFileContents select go = do
buf <- liftIO newEmptyMVar buf <- liftIO newEmptyMVar
let go' reader = go $ liftIO reader >>= \case let go' reader = go $ liftIO reader >>= \case
Just ((v, f), content) -> do Just ((v, f), content) -> do
content' <- checkjournal st f content content' <- checkjournal f content
return (Just (v, f, content')) return (Just (v, f, content'))
Nothing Nothing
| journalIgnorable st -> return Nothing | journalIgnorable st -> return Nothing
@ -853,7 +872,7 @@ overBranchFileContents select go = do
`finally` liftIO (void cleanup) `finally` liftIO (void cleanup)
where where
-- Check the journal, in case it did not get committed to the branch -- Check the journal, in case it did not get committed to the branch
checkjournal st f branchcontent checkjournal f branchcontent
| journalIgnorable st = return branchcontent | journalIgnorable st = return branchcontent
| otherwise = getJournalFileStale (GetPrivate True) f >>= return . \case | otherwise = getJournalFileStale (GetPrivate True) f >>= return . \case
NoJournalledContent -> branchcontent NoJournalledContent -> branchcontent

View file

@ -282,7 +282,9 @@ withKeyOptions' ko auto mkkeyaction fallbackaction worktreeitems = do
keyaction Nothing (SeekInput [], k, mkActionItem k) keyaction Nothing (SeekInput [], k, mkActionItem k)
go reader go reader
Nothing -> return () Nothing -> return ()
Annex.Branch.overBranchFileContents getk go Annex.Branch.overBranchFileContents getk go >>= \case
Just r -> return r
Nothing -> giveup "This repository is read-only, and there are unmerged git-annex branches, which prevents operating on all keys. (Set annex.merge-annex-branches to false to ignore the unmerged git-annex branches.)"
runkeyaction getks = do runkeyaction getks = do
keyaction <- mkkeyaction keyaction <- mkkeyaction

View file

@ -150,7 +150,9 @@ getCache opttemplate = ifM (Annex.getState Annex.force)
{- Scan all url logs and metadata logs in the branch and find urls {- Scan all url logs and metadata logs in the branch and find urls
- and ItemIds that are already known. -} - and ItemIds that are already known. -}
knownItems :: Annex ([URLString], [ItemId]) knownItems :: Annex ([URLString], [ItemId])
knownItems = Annex.Branch.overBranchFileContents select (go [] []) knownItems = Annex.Branch.overBranchFileContents select (go [] []) >>= \case
Just r -> return r
Nothing -> giveup "This repository is read-only."
where where
select f select f
| isUrlLog f = Just () | isUrlLog f = Just ()

View file

@ -1061,8 +1061,13 @@ repository, using [[git-annex-config]]. See its man page for a list.)
are automatically merged into the local git-annex branch, so that are automatically merged into the local git-annex branch, so that
git-annex has the most up-to-date possible knowledge. git-annex has the most up-to-date possible knowledge.
To avoid that merging, set this to "false". This can be useful To avoid that merging, set this to "false".
particularly when you don't have write permission to the repository.
This can be useful particularly when you don't have write permission
to the repository. While git-annex is mostly able to work in a read-only
repository with unmerged git-annex branches, some things do not work,
and when it does work it will be slower due to needing to look at each of
the unmerged branches.
* `annex.private` * `annex.private`