Do not preserve permissions and acls when copying files from one local git repository to another. Timestamps are still preserved as long as cp --preserve=timestamps is supported.

This avoids cp -a overriding the default mode acls that the user might have
set in a git repository.

With GNU cp, this behavior change should not be a breaking change, because
git-anex also uses rsync sometimes in the same situation, and has only ever
preserved timestamps when using rsync.

Systems without GNU cp will no longer use cp -a, but instead just cp.
So, timestamps will no longer be preserved. Preserving timestamps when
copying between repos is not guaranteed anyway.

Closes: #729757
This commit is contained in:
Joey Hess 2014-08-26 17:06:43 -07:00
parent 06b51f67ac
commit 6eb5c3f479
11 changed files with 28 additions and 16 deletions

View file

@ -580,7 +580,7 @@ preseedTmp key file = go =<< inAnnex key
( return True
, do
s <- calcRepo $ gitAnnexLocation key
liftIO $ copyFileExternal s file
liftIO $ copyFileExternal CopyTimeStamps s file
)
{- Blocks writing to an annexed file, and modifies file permissions to

View file

@ -210,7 +210,7 @@ addContentWhenNotPresent key contentfile associatedfile = do
v <- isAnnexLink associatedfile
when (Just key == v) $
replaceFile associatedfile $
liftIO . void . copyFileExternal contentfile
liftIO . void . copyFileExternal CopyAllMetaData contentfile
updateInodeCache key associatedfile
{- Some filesystems get new inodes each time they are mounted.

View file

@ -357,7 +357,7 @@ toDirectGen k f = do
`catchIO` (\_ -> freezeContent loc)
fromdirect loc = do
replaceFile f $
liftIO . void . copyFileExternal loc
liftIO . void . copyFileExternal CopyAllMetaData loc
updateInodeCache k f
{- Removes a direct mode file, while retaining its content in the annex

View file

@ -23,6 +23,7 @@ tests =
, TestCase "git version" getGitVersion
, testCp "cp_a" "-a"
, testCp "cp_p" "-p"
, testCp "cp_preserve_timestamps" "--preserve=timestamps"
, testCp "cp_reflink_auto" "--reflink=auto"
, TestCase "xargs -0" $ requireCmd "xargs_0" "xargs -0 </dev/null"
, TestCase "rsync" $ requireCmd "rsync" "rsync --version >/dev/null"

View file

@ -90,7 +90,7 @@ start mode (srcfile, destfile) =
handleexisting =<< liftIO (catchMaybeIO $ getSymbolicLinkStatus destfile)
liftIO $ createDirectoryIfMissing True (parentDir destfile)
liftIO $ if mode == Duplicate || mode == SkipDuplicates
then void $ copyFileExternal srcfile destfile
then void $ copyFileExternal CopyAllMetaData srcfile destfile
else moveFile srcfile destfile
Command.Add.perform destfile
handleexisting Nothing = noop

View file

@ -136,7 +136,7 @@ test st r k =
, check "retrieveKeyFile resume from end" $ do
loc <- Annex.calcRepo (gitAnnexLocation k)
tmp <- prepTmp k
void $ liftIO $ copyFileExternal loc tmp
void $ liftIO $ copyFileExternal CopyAllMetaData loc tmp
lockContent k removeAnnex
get
, check "fsck downloaded object" fsck

View file

@ -89,7 +89,7 @@ cleanupIndirect file key = do
)
where
copyfrom src =
thawContent file `after` liftIO (copyFileExternal src file)
thawContent file `after` liftIO (copyFileExternal CopyAllMetaData src file)
hardlinkfrom src =
#ifndef mingw32_HOST_OS
-- creating a hard link could fall; fall back to copying

View file

@ -46,7 +46,7 @@ perform dest key = do
tmpdest <- fromRepo $ gitAnnexTmpObjectLocation key
liftIO $ createDirectoryIfMissing True (parentDir tmpdest)
showAction "copying"
ifM (liftIO $ copyFileExternal src tmpdest)
ifM (liftIO $ copyFileExternal CopyAllMetaData src tmpdest)
( do
liftIO $ do
removeFile dest

View file

@ -543,7 +543,7 @@ rsyncOrCopyFile rsyncparams src dest p =
docopy = liftIO $ bracket
(forkIO $ watchfilesize zeroBytesProcessed)
(void . tryIO . killThread)
(const $ copyFileExternal src dest)
(const $ copyFileExternal CopyTimeStamps src dest)
watchfilesize oldsz = do
threadDelay 500000 -- 0.5 seconds
v <- catchMaybeIO $

View file

@ -1,6 +1,6 @@
{- file copying
-
- Copyright 2010-2013 Joey Hess <joey@kitenet.net>
- Copyright 2010-2014 Joey Hess <joey@kitenet.net>
-
- License: BSD-2-clause
-}
@ -9,16 +9,20 @@
module Utility.CopyFile (
copyFileExternal,
createLinkOrCopy
createLinkOrCopy,
CopyMetaData(..)
) where
import Common
import qualified Build.SysConfig as SysConfig
data CopyMetaData = CopyTimeStamps | CopyAllMetaData
deriving (Eq)
{- The cp command is used, because I hate reinventing the wheel,
- and because this allows easy access to features like cp --reflink. -}
copyFileExternal :: FilePath -> FilePath -> IO Bool
copyFileExternal src dest = do
copyFileExternal :: CopyMetaData -> FilePath -> FilePath -> IO Bool
copyFileExternal meta src dest = do
whenM (doesFileExist dest) $
removeFile dest
boolSystem "cp" $ params ++ [File src, File dest]
@ -26,12 +30,16 @@ copyFileExternal src dest = do
#ifndef __ANDROID__
params = map snd $ filter fst
[ (SysConfig.cp_reflink_auto, Param "--reflink=auto")
, (SysConfig.cp_a, Param "-a")
, (SysConfig.cp_p && not SysConfig.cp_a, Param "-p")
, (allmeta && SysConfig.cp_a, Param "-a")
, (allmeta && SysConfig.cp_p && not SysConfig.cp_a
, Param "-p")
, (not allmeta && SysConfig.cp_preserve_timestamps
, Param "--preserve=timestamps")
]
#else
params = []
#endif
allmeta = meta == CopyAllMetaData
{- Create a hard link if the filesystem allows it, and fall back to copying
- the file. -}
@ -42,7 +50,7 @@ createLinkOrCopy src dest = go `catchIO` const fallback
go = do
createLink src dest
return True
fallback = copyFileExternal src dest
fallback = copyFileExternal CopyAllMetaData src dest
#else
createLinkOrCopy = copyFileExternal
createLinkOrCopy = copyFileExternal CopyAllMetaData
#endif

3
debian/changelog vendored
View file

@ -8,6 +8,9 @@ git-annex (5.20140818) UNRELEASED; urgency=medium
Closes: #758630
* Fix handing of autocorrection when running outside a git repository.
* Fix stub git-annex test support when built without tasty.
* Do not preserve permissions and acls when copying files from
one local git repository to another. Timestamps are still preserved
as long as cp --preserve=timestamps is supported. Closes: #729757
-- Joey Hess <joeyh@debian.org> Tue, 19 Aug 2014 12:52:41 -0400