lockContent for S3 (with versioning=yes) and git-lfs

Made several special remotes support locking content on them while
dropping, which allows dropping from another special remote when the
content will only remain on a special remote of these types.

In both cases, verify the content is present actively, because it's
certianly possible for things other than git-annex to have removed it.

Worth thinking about what to do if at some later point, git-lfs gains
support for dropping content, and a content locking operation.
That would probably need a transition; first would need to make lockContent
use the locking operation. Then, once enough time had passed that we can
assume any git-annex operating on the git-lfs remote had that change,
git-annex could finally allow dropping from git-lfs.

Or, it could be that git-lfs gains support for dropping content, but not
locking it. In that case, it seems this commit would need to be reverted,
and then wait long enough for that git-annex to be everywhere, and only
then can git-annex safely support dropping from git-lfs.

So, the assumption made in this commit could lead to bother later.. But I
think it's actually highly unlikely git-lfs does ever support dropping;
it's outside their centralized model. Probably. :) Worth keeping in mind as
the same assumption is made about other special remotes though.

This commit was sponsored by Ethan Aubin.
This commit is contained in:
Joey Hess 2020-06-26 13:46:42 -04:00
parent a59e95a82d
commit 3175015d1b
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 34 additions and 5 deletions

View file

@ -13,6 +13,10 @@ git-annex (8.20200618) UNRELEASED; urgency=medium
* importfeed: Added some additional --template variables: * importfeed: Added some additional --template variables:
itempubyear, itempubmonth, itempubday, itempubhour, itempubyear, itempubmonth, itempubday, itempubhour,
itempubminute, itempubsecond. itempubminute, itempubsecond.
* Made several special remotes support locking content on them while
dropping, which allows dropping from another special remote when
the content will only remain on a special remote of these types:
S3 (with versioning=yes), git-lfs
-- Joey Hess <id@joeyh.name> Thu, 18 Jun 2020 12:21:14 -0400 -- Joey Hess <id@joeyh.name> Thu, 18 Jun 2020 12:21:14 -0400

View file

@ -16,6 +16,7 @@ import Annex.Url
import Types.Key import Types.Key
import Types.Creds import Types.Creds
import Types.ProposedAccepted import Types.ProposedAccepted
import Types.NumCopies
import qualified Annex import qualified Annex
import qualified Git import qualified Git
import qualified Git.Types as Git import qualified Git.Types as Git
@ -100,9 +101,9 @@ gen r u rc gc rs = do
(retrieve rs h) (retrieve rs h)
(remove h) (remove h)
(checkKey rs h) (checkKey rs h)
(this c cst) (this c cst h)
where where
this c cst = Remote this c cst h = Remote
{ uuid = u { uuid = u
, cost = cst , cost = cst
, name = Git.repoDescribe r , name = Git.repoDescribe r
@ -114,7 +115,7 @@ gen r u rc gc rs = do
-- is checked on download -- is checked on download
, retrievalSecurityPolicy = RetrievalAllKeysSecure , retrievalSecurityPolicy = RetrievalAllKeysSecure
, removeKey = removeKeyDummy , removeKey = removeKeyDummy
, lockContent = Nothing , lockContent = Just $ lockKey (this c cst h) rs h
, checkPresent = checkPresentDummy , checkPresent = checkPresentDummy
, checkPresentCheap = False , checkPresentCheap = False
, exportActions = exportUnsupported , exportActions = exportUnsupported
@ -132,7 +133,7 @@ gen r u rc gc rs = do
-- content cannot be removed from a git-lfs repo -- content cannot be removed from a git-lfs repo
, appendonly = True , appendonly = True
, mkUnavailable = return Nothing , mkUnavailable = return Nothing
, getInfo = gitRepoInfo (this c cst) , getInfo = gitRepoInfo (this c cst h)
, claimUrl = Nothing , claimUrl = Nothing
, checkUrl = Nothing , checkUrl = Nothing
, remoteStateHandle = rs , remoteStateHandle = rs
@ -493,6 +494,16 @@ retrieve rs h = fileRetriever $ \dest k p -> getLFSEndpoint LFS.RequestDownload
uo <- getUrlOptions uo <- getUrlOptions
liftIO $ downloadConduit p req dest uo liftIO $ downloadConduit p req dest uo
-- Since git-lfs does not support removing content, nothing needs to be
-- done to lock content in the remote, except for checking that the content
-- is actually present.
lockKey :: Remote -> RemoteStateHandle -> TVar LFSHandle -> Key -> (VerifiedCopy -> Annex a) -> Annex a
lockKey r rs h key callback =
ifM (checkKey rs h key)
( withVerifiedCopy LockedCopy (uuid r) (return True) callback
, giveup $ "content seems to be missing from " ++ name r
)
checkKey :: RemoteStateHandle -> TVar LFSHandle -> CheckPresent checkKey :: RemoteStateHandle -> TVar LFSHandle -> CheckPresent
checkKey rs h key = getLFSEndpoint LFS.RequestDownload h >>= \case checkKey rs h key = getLFSEndpoint LFS.RequestDownload h >>= \case
Nothing -> giveup "unable to connect to git-lfs endpoint" Nothing -> giveup "unable to connect to git-lfs endpoint"

View file

@ -58,6 +58,7 @@ import Logs.Web
import Logs.MetaData import Logs.MetaData
import Types.MetaData import Types.MetaData
import Types.ProposedAccepted import Types.ProposedAccepted
import Types.NumCopies
import Utility.Metered import Utility.Metered
import Utility.DataUnits import Utility.DataUnits
import Annex.Content import Annex.Content
@ -199,7 +200,7 @@ gen r u rc gc rs = do
-- secure. -- secure.
, retrievalSecurityPolicy = RetrievalAllKeysSecure , retrievalSecurityPolicy = RetrievalAllKeysSecure
, removeKey = removeKeyDummy , removeKey = removeKeyDummy
, lockContent = Nothing , lockContent = lockContentS3 hdl this rs c info
, checkPresent = checkPresentDummy , checkPresent = checkPresentDummy
, checkPresentCheap = False , checkPresentCheap = False
, exportActions = ExportActions , exportActions = ExportActions
@ -427,6 +428,19 @@ remove hv r info k = withS3HandleOrFail (uuid r) hv $ \h -> do
S3.DeleteObject (T.pack $ bucketObject info k) (bucket info) S3.DeleteObject (T.pack $ bucketObject info k) (bucket info)
return () return ()
lockContentS3 :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> Maybe (Key -> (VerifiedCopy -> Annex a) -> Annex a)
lockContentS3 hv r rs c info
-- When versioning is enabled, content is never removed from the
-- remote, so nothing needs to be done to lock the content there,
-- beyond a sanity check that the content is in fact present.
| versioning info = Just $ \k callback -> do
checkVersioning info rs k
ifM (checkKey hv r rs c info k)
( withVerifiedCopy LockedCopy (uuid r) (return True) callback
, giveup $ "content seems to be missing from " ++ name r ++ " despite S3 versioning being enabled"
)
| otherwise = Nothing
checkKey :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> CheckPresent checkKey :: S3HandleVar -> Remote -> RemoteStateHandle -> ParsedRemoteConfig -> S3Info -> CheckPresent
checkKey hv r rs c info k = withS3Handle hv $ \case checkKey hv r rs c info k = withS3Handle hv $ \case
Just h -> do Just h -> do