catch all (non-async) exceptions when running a commandAction

When a command is operating on multiple files and there's an error with
one, try harder to continue to the rest. (As was already done for many
types of errors including IO errors.)

This handles cases like lockContentForRemoval throwing an exception when
the content is already locked. Just because a drop of one file fails, does
not mean it shouldn't go on to try to drop other files.

I looked over uses of `giveup` in Command/*; there are too many to check
them all extensively, but none stood out as being problems that should let
one commandAction stop running other commandActions. Worst case, something
bad will happen and rather than stopping right away with an error,
git-annex will display multiple errors as it fails over and over on each
file. I don't think I ever really intended `error`/`giveup` to stop other
commandActions; this was a relic of old confusion over haskell exception
handling.

Test suite passes.

This commit was sponsored by Ethan Aubin.
This commit is contained in:
Joey Hess 2018-11-15 15:59:43 -04:00
parent c8bd5710b1
commit 39fbaa0682
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 17 additions and 3 deletions

View file

@ -43,8 +43,7 @@ performCommandAction Command { cmdcheck = c, cmdname = name } seek cont = do
{- Runs one of the actions needed to perform a command.
- Individual actions can fail without stopping the whole command,
- including by throwing IO errors (but other errors terminate the whole
- command).
- including by throwing non-async exceptions.
-
- When concurrency is enabled, a thread is forked off to run the action
- in the background, as soon as a free slot is available.
@ -128,7 +127,7 @@ findFreeSlot = go []
{- Like commandAction, but without the concurrency. -}
includeCommandAction :: CommandStart -> CommandCleanup
includeCommandAction a = account =<< tryIO (callCommandAction a)
includeCommandAction a = account =<< tryNonAsync (callCommandAction a)
where
account (Right True) = return True
account (Right False) = incerr