httpalso: support exporttree=yes

Also tested what happens if the other special remote has importtree=yes
and exporttree=yes, and in that case, download via httpalso works too,
without needing to implement any importtree methods here.

It might be possible to make it automatically set exporttree=yes if the
--sameas does. Didn't try, will probably be layering issues.

Or perhaps it should be inherited by sameas like some
other configs? But then, wouldn't it also make sense to inherit
importree=yes? But as shown here, it's not needed by this kind of
remote.
This commit is contained in:
Joey Hess 2020-09-02 11:14:50 -04:00
parent 8656afd3e1
commit 854cd2ad47
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 52 additions and 19 deletions

View file

@ -10,6 +10,7 @@ module Remote.HttpAlso (remote) where
import Annex.Common import Annex.Common
import Types.Remote import Types.Remote
import Types.ProposedAccepted import Types.ProposedAccepted
import Types.Export
import Remote.Helper.Messages import Remote.Helper.Messages
import Remote.Helper.ExportImport import Remote.Helper.ExportImport
import Remote.Helper.Special import Remote.Helper.Special
@ -37,7 +38,7 @@ remote = RemoteType
(FieldDesc "(required) url to the remote content") (FieldDesc "(required) url to the remote content")
] ]
, setup = httpAlsoSetup , setup = httpAlsoSetup
, exportSupported = exportUnsupported , exportSupported = exportIsSupported
, importSupported = importUnsupported , importSupported = importUnsupported
} }
@ -56,17 +57,24 @@ gen r u rc gc rs = do
{ uuid = u { uuid = u
, cost = cst , cost = cst
, name = Git.repoDescribe r , name = Git.repoDescribe r
, storeKey = uploadKey , storeKey = cannotModify
, retrieveKeyFile = downloadKey url ll , retrieveKeyFile = downloadKey url ll
, retrieveKeyFileCheap = Nothing , retrieveKeyFileCheap = Nothing
-- HttpManagerRestricted is used here, so this is -- HttpManagerRestricted is used here, so this is
-- secure. -- secure.
, retrievalSecurityPolicy = RetrievalAllKeysSecure , retrievalSecurityPolicy = RetrievalAllKeysSecure
, removeKey = dropKey , removeKey = cannotModify
, lockContent = Nothing , lockContent = Nothing
, checkPresent = checkKey url ll (this url ll c cst) , checkPresent = checkKey url ll (this url ll c cst)
, checkPresentCheap = False , checkPresentCheap = False
, exportActions = exportUnsupported , exportActions = ExportActions
{ storeExport = cannotModify
, retrieveExport = retriveExportHttpAlso url
, removeExport = cannotModify
, checkPresentExport = checkPresentExportHttpAlso url
, removeExportDirectory = Nothing
, renameExport = cannotModify
}
, importActions = importUnsupported , importActions = importUnsupported
, whereisKey = Nothing , whereisKey = Nothing
, remoteFsck = Nothing , remoteFsck = Nothing
@ -86,6 +94,9 @@ gen r u rc gc rs = do
, remoteStateHandle = rs , remoteStateHandle = rs
} }
cannotModify :: a
cannotModify = giveup "httpalso special remote is read only"
httpAlsoSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID) httpAlsoSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
httpAlsoSetup _ Nothing _ _ _ = httpAlsoSetup _ Nothing _ _ _ =
error "Must use --sameas when initializing a httpalso remote." error "Must use --sameas when initializing a httpalso remote."
@ -99,23 +110,30 @@ httpAlsoSetup _ (Just u) _ c gc = do
downloadKey :: Maybe URLString -> LearnedLayout -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> Annex Verification downloadKey :: Maybe URLString -> LearnedLayout -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> Annex Verification
downloadKey baseurl ll key _af dest p = do downloadKey baseurl ll key _af dest p = do
unlessM (urlAction baseurl ll key go) $ unlessM (keyUrlAction baseurl ll key (downloadKey' key dest p)) $
giveup "download failed" giveup "download failed"
return UnVerified return UnVerified
where
go url = Url.withUrlOptions $ downloadUrl key p [url] dest
uploadKey :: Key -> AssociatedFile -> MeterUpdate -> Annex () downloadKey' :: Key -> FilePath -> MeterUpdate -> URLString -> Annex Bool
uploadKey _ _ _ = giveup "upload to httpalso special remote not supported" downloadKey' key dest p url =
Url.withUrlOptions $ downloadUrl key p [url] dest
dropKey :: Key -> Annex () retriveExportHttpAlso :: Maybe URLString -> Key -> ExportLocation -> FilePath -> MeterUpdate -> Annex ()
dropKey _ = giveup "removal from httpalso special remote not supported" retriveExportHttpAlso baseurl key loc dest p =
unlessM (exportLocationUrlAction baseurl loc (downloadKey' key dest p)) $
giveup "download failed"
checkKey :: Maybe URLString -> LearnedLayout -> Remote -> Key -> Annex Bool checkKey :: Maybe URLString -> LearnedLayout -> Remote -> Key -> Annex Bool
checkKey baseurl ll r key = do checkKey baseurl ll r key = do
showChecking r showChecking r
urlAction baseurl ll key $ \url -> keyUrlAction baseurl ll key (checkKey' key)
Url.withUrlOptions $ Url.checkBoth url (fromKey keySize key)
checkKey' :: Key -> URLString -> Annex Bool
checkKey' key url = Url.withUrlOptions $ Url.checkBoth url (fromKey keySize key)
checkPresentExportHttpAlso :: Maybe URLString -> Key -> ExportLocation -> Annex Bool
checkPresentExportHttpAlso baseurl key loc =
exportLocationUrlAction baseurl loc (checkKey' key)
type LearnedLayout = TVar (Maybe [Key -> URLString]) type LearnedLayout = TVar (Maybe [Key -> URLString])
@ -125,8 +143,8 @@ newLearnedLayout = newTVarIO Nothing
-- Learns which layout the special remote uses, so the once any -- Learns which layout the special remote uses, so the once any
-- action on an url succeeds, subsequent calls will continue to use that -- action on an url succeeds, subsequent calls will continue to use that
-- layout (or related layouts). -- layout (or related layouts).
urlAction :: Maybe URLString -> LearnedLayout -> Key -> (URLString -> Annex Bool) -> Annex Bool keyUrlAction :: Maybe URLString -> LearnedLayout -> Key -> (URLString -> Annex Bool) -> Annex Bool
urlAction (Just baseurl) ll key a = liftIO (readTVarIO ll) >>= \case keyUrlAction (Just baseurl) ll key a = liftIO (readTVarIO ll) >>= \case
Just learned -> go False [learned] Just learned -> go False [learned]
Nothing -> go True (supportedLayouts baseurl) Nothing -> go True (supportedLayouts baseurl)
where where
@ -144,9 +162,16 @@ urlAction (Just baseurl) ll key a = liftIO (readTVarIO ll) >>= \case
return True return True
, go' learn rest (layout:prevs) , go' learn rest (layout:prevs)
) )
keyUrlAction Nothing _ _ _ = noBaseUrlError
exportLocationUrlAction :: Maybe URLString -> ExportLocation -> (URLString -> Annex Bool) -> Annex Bool
exportLocationUrlAction (Just baseurl) loc a =
a (baseurl P.</> fromRawFilePath (fromExportLocation loc))
exportLocationUrlAction Nothing _ _ = noBaseUrlError
-- cannot normally happen -- cannot normally happen
urlAction Nothing _ _ _ = giveup "no url configured for httpalso special remote" noBaseUrlError :: Annex a
noBaseUrlError = giveup "no url configured for httpalso special remote"
-- Different ways that keys can be laid out in the special remote, -- Different ways that keys can be laid out in the special remote,
-- with the more common first. -- with the more common first.

View file

@ -29,7 +29,8 @@ type Template = String
{- Runs an action like writeFile, writing to a temp file first and {- Runs an action like writeFile, writing to a temp file first and
- then moving it into place. The temp file is stored in the same - then moving it into place. The temp file is stored in the same
- directory as the final file to avoid cross-device renames. -} - directory as the final file to avoid cross-device renames.
-}
viaTmp :: (MonadMask m, MonadIO m) => (FilePath -> v -> m ()) -> FilePath -> v -> m () viaTmp :: (MonadMask m, MonadIO m) => (FilePath -> v -> m ()) -> FilePath -> v -> m ()
viaTmp a file content = bracketIO setup cleanup use viaTmp a file content = bracketIO setup cleanup use
where where

View file

@ -26,3 +26,8 @@ for a list of known working combinations.
* `url` - The http or https url to where the content is stored by the * `url` - The http or https url to where the content is stored by the
other special remote. other special remote.
* `exporttree` - If the other special remote has `exporttree=yes` set,
it also needs to be set when initializing the httpalso remote.
Setting this does not allow trees to be exported to the httpalso remote,
because it's read-only. But it does let exported files be downloaded
from it.

View file

@ -58,4 +58,4 @@ If you find combinations that work, please edit this page to list them.
* httpalso and directory * httpalso and directory
* httpalso and rsync * httpalso and rsync
* httpalso and rclone (any layout except for frankencase) * httpalso and rclone (any layout except for frankencase)
* httpalso and any special remote that uses exporttree=yes

View file

@ -2,3 +2,5 @@ The http special remote doesn't currently support being used with a
--sameas remote that uses exporttree=yes. --sameas remote that uses exporttree=yes.
It seems like this should be fairly easy to implement. --[[Joey]] It seems like this should be fairly easy to implement. --[[Joey]]
> [[done]] --[[Joey]]