annex.addunlocked

* add, addurl, import, importfeed: When in a v6 repository on a crippled
  filesystem, add files unlocked.
* annex.addunlocked: New configuration setting, makes files always be
  added unlocked. (v6 only)
This commit is contained in:
Joey Hess 2016-02-16 14:43:43 -04:00
parent adc27f081a
commit 15148ee9eb
Failed to extract signature
8 changed files with 116 additions and 39 deletions

View file

@ -1,6 +1,6 @@
{- git-annex content ingestion {- git-annex content ingestion
- -
- Copyright 2010-2015 Joey Hess <id@joeyh.name> - Copyright 2010-2016 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU GPL version 3 or higher. - Licensed under the GNU GPL version 3 or higher.
-} -}
@ -11,14 +11,17 @@ module Annex.Ingest (
LockedDown(..), LockedDown(..),
LockDownConfig(..), LockDownConfig(..),
lockDown, lockDown,
ingestAdd,
ingest, ingest,
finishIngestDirect, finishIngestDirect,
finishIngestUnlocked, finishIngestUnlocked,
cleanOldKeys, cleanOldKeys,
addLink, addLink,
makeLink, makeLink,
addUnlocked,
restoreFile, restoreFile,
forceParams, forceParams,
addAnnexedFile,
) where ) where
import Annex.Common import Annex.Common
@ -29,6 +32,7 @@ import Annex.Content.Direct
import Annex.Perms import Annex.Perms
import Annex.Link import Annex.Link
import Annex.MetaData import Annex.MetaData
import Annex.Version
import Logs.Location import Logs.Location
import qualified Annex import qualified Annex
import qualified Annex.Queue import qualified Annex.Queue
@ -111,11 +115,30 @@ lockDown' cfg file = ifM (pure (not (hardlinkFileTmp cfg)) <||> crippledFileSyst
, inodeCache = cache , inodeCache = cache
} }
{- Ingests a locked down file into the annex. {- Ingests a locked down file into the annex. Updates the work tree and
- - index. -}
- The file may be added to the git repository as a locked or an unlocked ingestAdd :: Maybe LockedDown -> Annex (Maybe Key)
- file. When unlocked, the work tree file is left alone. When locked, ingestAdd Nothing = return Nothing
- the work tree file is deleted, in preparation for adding the symlink. ingestAdd ld@(Just (LockedDown cfg source)) = do
(mk, mic) <- ingest ld
case mk of
Nothing -> return Nothing
Just k -> do
let f = keyFilename source
if lockingFile cfg
then do
liftIO $ nukeFile f
addLink f k mic
else ifM isDirect
( do
l <- calcRepo $ gitAnnexLink f k
stageSymlink f =<< hashSymlink l
, stagePointerFile f =<< hashPointerFile k
)
return (Just k)
{- Ingests a locked down file into the annex. Does not update the working
- tree or the index.
-} -}
ingest :: Maybe LockedDown -> Annex (Maybe Key, Maybe InodeCache) ingest :: Maybe LockedDown -> Annex (Maybe Key, Maybe InodeCache)
ingest Nothing = return (Nothing, Nothing) ingest Nothing = return (Nothing, Nothing)
@ -141,7 +164,6 @@ ingest (Just (LockedDown cfg source)) = withTSDelta $ \delta -> do
golocked key mcache s = do golocked key mcache s = do
catchNonAsync (moveAnnex key $ contentLocation source) catchNonAsync (moveAnnex key $ contentLocation source)
(restoreFile (keyFilename source) key) (restoreFile (keyFilename source) key)
liftIO $ nukeFile $ keyFilename source
populateAssociatedFiles key source populateAssociatedFiles key source
success key mcache s success key mcache s
@ -295,3 +317,50 @@ forceParams = ifM (Annex.getState Annex.force)
( return [Param "-f"] ( return [Param "-f"]
, return [] , return []
) )
{- Whether a file should be added unlocked or not. Default is to not,
- unless symlinks are not supported. annex.addunlocked can override that. -}
addUnlocked :: Annex Bool
addUnlocked = isDirect <||>
(versionSupportsUnlockedPointers <&&>
((not . coreSymlinks <$> Annex.getGitConfig) <||>
(annexAddUnlocked <$> Annex.getGitConfig)
)
)
{- Adds a file to the work tree for the key, and stages it in the index.
- The content of the key may be provided in a temp file, which will be
- moved into place. -}
addAnnexedFile :: FilePath -> Key -> Maybe FilePath -> Annex ()
addAnnexedFile file key mtmp = ifM (addUnlocked <&&> not <$> isDirect)
( do
stagePointerFile file =<< hashPointerFile key
Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
case mtmp of
Just tmp -> do
moveAnnex key tmp
linkunlocked
Nothing -> ifM (inAnnex key)
( linkunlocked
, writepointer
)
, do
addLink file key Nothing
whenM isDirect $ do
void $ addAssociatedFile key file
case mtmp of
Just tmp -> do
{- For moveAnnex to work in direct mode, the
- symlink must already exist, so flush the queue. -}
whenM isDirect $
Annex.Queue.flush
moveAnnex key tmp
Nothing -> return ()
)
where
writepointer = liftIO $ writeFile file (formatPointer key)
linkunlocked = do
r <- linkFromAnnex key file
case r of
LinkAnnexFailed -> writepointer
_ -> return ()

View file

@ -12,12 +12,10 @@ import Annex.Ingest
import Logs.Location import Logs.Location
import Annex.Content import Annex.Content
import Annex.Content.Direct import Annex.Content.Direct
import Annex.Link
import qualified Annex import qualified Annex
import qualified Annex.Queue import qualified Annex.Queue
import qualified Database.Keys import qualified Database.Keys
import Config import Config
import Utility.InodeCache
import Annex.FileMatcher import Annex.FileMatcher
import Annex.Version import Annex.Version
@ -99,48 +97,42 @@ start file = ifAnnexed file addpresent add
( do ( do
ms <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file ms <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file
case ms of case ms of
Just s | isSymbolicLink s -> fixup key Just s | isSymbolicLink s -> fixuplink key
_ -> ifM (sameInodeCache file =<< Database.Keys.getInodeCaches key) _ -> ifM (sameInodeCache file =<< Database.Keys.getInodeCaches key)
( stop, add ) ( stop, add )
, ifM isDirect , ifM isDirect
( do ( do
ms <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file ms <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file
case ms of case ms of
Just s | isSymbolicLink s -> fixup key Just s | isSymbolicLink s -> fixuplink key
_ -> ifM (goodContent key file) _ -> ifM (goodContent key file)
( stop , add ) ( stop , add )
, fixup key , fixuplink key
) )
) )
fixup key = do fixuplink key = do
-- the annexed symlink is present but not yet added to git -- the annexed symlink is present but not yet added to git
showStart "add" file showStart "add" file
liftIO $ removeFile file liftIO $ removeFile file
whenM isDirect $ next $ next $ do
void $ addAssociatedFile key file addLink file key Nothing
next $ next $ cleanup file key Nothing =<< inAnnex key cleanup key =<< inAnnex key
perform :: FilePath -> CommandPerform perform :: FilePath -> CommandPerform
perform file = do perform file = do
lockingfile <- not <$> isDirect lockingfile <- not <$> addUnlocked
let cfg = LockDownConfig let cfg = LockDownConfig
{ lockingFile = lockingfile { lockingFile = lockingfile
, hardlinkFileTmp = True , hardlinkFileTmp = True
} }
lockDown cfg file >>= ingest >>= go lockDown cfg file >>= ingestAdd >>= finish
where where
go (Just key, cache) = next $ cleanup file key cache True finish (Just key) = next $ cleanup key True
go (Nothing, _) = stop finish Nothing = stop
cleanup :: FilePath -> Key -> Maybe InodeCache -> Bool -> CommandCleanup cleanup :: Key -> Bool -> CommandCleanup
cleanup file key mcache hascontent = do cleanup key hascontent = do
maybeShowJSON [("key", key2file key)] maybeShowJSON [("key", key2file key)]
ifM (isDirect <&&> pure hascontent)
( do
l <- calcRepo $ gitAnnexLink file key
stageSymlink file =<< hashSymlink l
, addLink file key mcache
)
when hascontent $ when hascontent $
logStatus key InfoPresent logStatus key InfoPresent
return True return True

View file

@ -12,7 +12,6 @@ import Network.URI
import Command import Command
import Backend import Backend
import qualified Annex import qualified Annex
import qualified Annex.Queue
import qualified Annex.Url as Url import qualified Annex.Url as Url
import qualified Backend.URL import qualified Backend.URL
import qualified Remote import qualified Remote
@ -24,8 +23,6 @@ import Annex.UUID
import Logs.Web import Logs.Web
import Types.KeySource import Types.KeySource
import Types.UrlContents import Types.UrlContents
import Config
import Annex.Content.Direct
import Annex.FileMatcher import Annex.FileMatcher
import Logs.Location import Logs.Location
import Utility.Metered import Utility.Metered
@ -363,13 +360,7 @@ cleanup u url file key mtmp = case mtmp of
when (isJust mtmp) $ when (isJust mtmp) $
logStatus key InfoPresent logStatus key InfoPresent
setUrlPresent u key url setUrlPresent u key url
addLink file key Nothing addAnnexedFile file key mtmp
whenM isDirect $ do
void $ addAssociatedFile key file
{- For moveAnnex to work in direct mode, the symlink
- must already exist, so flush the queue. -}
Annex.Queue.flush
maybe noop (moveAnnex key) mtmp
nodownload :: URLString -> Url.UrlInfo -> FilePath -> Annex (Maybe Key) nodownload :: URLString -> Url.UrlInfo -> FilePath -> Annex (Maybe Key)
nodownload url urlinfo file nodownload url urlinfo file

View file

@ -69,6 +69,7 @@ data GitConfig = GitConfig
, annexVerify :: Bool , annexVerify :: Bool
, annexPidLock :: Bool , annexPidLock :: Bool
, annexPidLockTimeout :: Seconds , annexPidLockTimeout :: Seconds
, annexAddUnlocked :: Bool
, coreSymlinks :: Bool , coreSymlinks :: Bool
, coreSharedRepository :: SharedRepository , coreSharedRepository :: SharedRepository
, gcryptId :: Maybe String , gcryptId :: Maybe String
@ -118,6 +119,7 @@ extractGitConfig r = GitConfig
, annexPidLock = getbool (annex "pidlock") False , annexPidLock = getbool (annex "pidlock") False
, annexPidLockTimeout = Seconds $ fromMaybe 300 $ , annexPidLockTimeout = Seconds $ fromMaybe 300 $
getmayberead (annex "pidlocktimeout") getmayberead (annex "pidlocktimeout")
, annexAddUnlocked = getbool (annex "addunlocked") False
, coreSymlinks = getbool "core.symlinks" True , coreSymlinks = getbool "core.symlinks" True
, coreSharedRepository = getSharedRepository r , coreSharedRepository = getSharedRepository r
, gcryptId = getmaybe "core.gcrypt-id" , gcryptId = getmaybe "core.gcrypt-id"

6
debian/changelog vendored
View file

@ -14,6 +14,12 @@ git-annex (6.20160212) UNRELEASED; urgency=medium
* When initializing a v6 repo on a crippled filesystem, don't force it * When initializing a v6 repo on a crippled filesystem, don't force it
into direct mode. into direct mode.
* Windows: Fix v6 unlocked files to actually work. * Windows: Fix v6 unlocked files to actually work.
* add, addurl, import, importfeed: When in a v6 repository on a crippled
filesystem, add files unlocked.
* annex.addunlocked: New configuration setting, makes files always be
added unlocked. (v6 only)
* Improve format of v6 unlocked pointer files to support keys containing
slashes.
-- Joey Hess <id@joeyh.name> Fri, 12 Feb 2016 14:03:46 -0400 -- Joey Hess <id@joeyh.name> Fri, 12 Feb 2016 14:03:46 -0400

View file

@ -21,7 +21,8 @@ to the git repository, instead of to the annex.
Large files are added to the annex in locked form, which prevents further Large files are added to the annex in locked form, which prevents further
modification of their content unless unlocked by [[git-annex-unlock]](1). modification of their content unless unlocked by [[git-annex-unlock]](1).
(This is not the case however when a repository is in direct mode.) (This is not the case however when a repository is in a filesystem not
supporting symlinks, or is in direct mode.)
To add a file to the annex in unlocked form, `git add` can be used instead To add a file to the annex in unlocked form, `git add` can be used instead
(that only works when the repository has annex.version 6 or higher). (that only works when the repository has annex.version 6 or higher).

View file

@ -823,6 +823,15 @@ Here are all the supported configuration settings.
should be checked into git by `git annex add`. Defaults to true; should be checked into git by `git annex add`. Defaults to true;
set to false to instead make small files be skipped. set to false to instead make small files be skipped.
* `annex.addunlocked`
Set to true to make commands like `git-annex add` that add files to the
repository add them in unlocked form. The default is to add files in
locked form. This only has effect in version 6 repositories.
When a repository has core.symlinks set to false, it implicitly
sets annex.addunlocked to true.
* `annex.numcopies` * `annex.numcopies`
This is a deprecated setting. You should instead use the This is a deprecated setting. You should instead use the

View file

@ -88,6 +88,13 @@ git-annex converts between the content of the big file and a pointer file,
which is what gets committed to git. All the regular git-annex commands which is what gets committed to git. All the regular git-annex commands
(get, drop, etc) can be used on unlocked files too. (get, drop, etc) can be used on unlocked files too.
[[!template id=note text="""
By default, git-annex commands will add files in locked mode,
unless used on a filesystem that does not support symlinks, when unlocked
mode is used. To make them always use unlocked mode, run:
`git config annex.addunlocked true`
"""]]
A v6 repository can contain both locked and unlocked files. You can switch A v6 repository can contain both locked and unlocked files. You can switch
a file back and forth using the `git annex lock` and `git annex unlock` a file back and forth using the `git annex lock` and `git annex unlock`
commands. This changes what's stored in git between a git-annex symlink commands. This changes what's stored in git between a git-annex symlink