fix concurrency bug causing EXPORT to be sent to the wrong external

Fix bug that caused broken protocol to be used with external remotes that
use exporttree=yes. In some cases this could result in the wrong content
being exported to, or retrieved from the remote.

Sponsored-by: Nicholas Golder-Manning on Patreon
This commit is contained in:
Joey Hess 2023-03-28 15:21:10 -04:00
parent 390ed554e8
commit 02662f5292
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 18 additions and 7 deletions

View file

@ -10,6 +10,9 @@ git-annex (10.20230322) UNRELEASED; urgency=medium
* Windows: Support urls like "file:///c:/path"
* addurl, importfeed: Fix failure when annex.securehashesonly is set.
* Copy with a reflink when exporting a tree to a directory special remote.
* Fix bug that caused broken protocol to be used with external remotes
that use exporttree=yes. In some cases this could result in the wrong
content being exported to, or retrieved from the remote.
-- Joey Hess <id@joeyh.name> Thu, 23 Mar 2023 15:04:41 -0400

View file

@ -377,19 +377,27 @@ handleRequest external req mp responsehandler =
handleRequest' st external req mp responsehandler
handleRequestKey :: External -> (SafeKey -> Request) -> Key -> Maybe MeterUpdate -> ResponseHandler a -> Annex a
handleRequestKey external mkreq k mp responsehandler = case mkSafeKey k of
Right sk -> handleRequest external (mkreq sk) mp responsehandler
handleRequestKey external mkreq k mp responsehandler =
withSafeKey k $ \sk -> handleRequest external (mkreq sk) mp responsehandler
withSafeKey :: Key -> (SafeKey -> Annex a) -> Annex a
withSafeKey k a = case mkSafeKey k of
Right sk -> a sk
Left e -> giveup e
{- Export location is first sent in an EXPORT message before
- the main request. This is done because the ExportLocation can
- contain spaces etc. -}
handleRequestExport :: External -> ExportLocation -> (SafeKey -> Request) -> Key -> Maybe MeterUpdate -> ResponseHandler a -> Annex a
handleRequestExport external loc mkreq k mp responsehandler = do
withExternalState external $ \st -> do
checkPrepared st external
sendMessage st (EXPORT loc)
handleRequestKey external mkreq k mp responsehandler
handleRequestExport external loc mkreq k mp responsehandler =
withSafeKey k $ \sk ->
-- Both the EXPORT and subsequent request must be sent to the
-- same external process, so run both with the same external
-- state.
withExternalState external $ \st -> do
checkPrepared st external
sendMessage st (EXPORT loc)
handleRequest' st external (mkreq sk) mp responsehandler
handleRequest' :: ExternalState -> External -> Request -> Maybe MeterUpdate -> ResponseHandler a -> Annex a
handleRequest' st external req mp responsehandler