Supports indirect mode on encfs in paranoia mode, and other filesystems that do not support hard links, but do support symlinks and other POSIX filesystem features.
This commit is contained in:
parent
9cf6d8130c
commit
a64106dcef
6 changed files with 65 additions and 45 deletions
|
@ -80,20 +80,21 @@ start file = ifAnnexed file addpresent add
|
||||||
|
|
||||||
{- The file that's being added is locked down before a key is generated,
|
{- The file that's being added is locked down before a key is generated,
|
||||||
- to prevent it from being modified in between. It's hard linked into a
|
- to prevent it from being modified in between. It's hard linked into a
|
||||||
- temporary location, and its writable bits are removed. It could still be
|
- temporary location (to prevent it being replaced with another file),
|
||||||
- written to by a process that already has it open for writing.
|
- and its writable bits are removed. It could still be written to by a
|
||||||
|
- process that already has it open for writing.
|
||||||
|
-
|
||||||
|
- On a crippled filesystem, no lock down is done; the file can be modified
|
||||||
|
- at any time, and the no hard link is made.
|
||||||
|
-
|
||||||
|
- On a filesystem without hard links, but not otherwise crippled,
|
||||||
|
- no hard link is made, but the write bit is still removed.
|
||||||
-
|
-
|
||||||
- Lockdown can fail if a file gets deleted, and Nothing will be returned.
|
- Lockdown can fail if a file gets deleted, and Nothing will be returned.
|
||||||
-}
|
-}
|
||||||
lockDown :: FilePath -> Annex (Maybe KeySource)
|
lockDown :: FilePath -> Annex (Maybe KeySource)
|
||||||
lockDown file = ifM (crippledFileSystem)
|
lockDown file = ifM (crippledFileSystem)
|
||||||
( liftIO $ catchMaybeIO $ do
|
( liftIO $ catchMaybeIO nohardlink
|
||||||
cache <- genInodeCache file
|
|
||||||
return $ KeySource
|
|
||||||
{ keyFilename = file
|
|
||||||
, contentLocation = file
|
|
||||||
, inodeCache = cache
|
|
||||||
}
|
|
||||||
, do
|
, do
|
||||||
tmp <- fromRepo gitAnnexTmpDir
|
tmp <- fromRepo gitAnnexTmpDir
|
||||||
createAnnexDirectory tmp
|
createAnnexDirectory tmp
|
||||||
|
@ -102,14 +103,24 @@ lockDown file = ifM (crippledFileSystem)
|
||||||
(tmpfile, h) <- openTempFile tmp (takeFileName file)
|
(tmpfile, h) <- openTempFile tmp (takeFileName file)
|
||||||
hClose h
|
hClose h
|
||||||
nukeFile tmpfile
|
nukeFile tmpfile
|
||||||
createLink file tmpfile
|
withhardlink tmpfile `catchIO` const nohardlink
|
||||||
cache <- genInodeCache tmpfile
|
|
||||||
return $ KeySource
|
|
||||||
{ keyFilename = file
|
|
||||||
, contentLocation = tmpfile
|
|
||||||
, inodeCache = cache
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
where
|
||||||
|
nohardlink = do
|
||||||
|
cache <- genInodeCache file
|
||||||
|
return $ KeySource
|
||||||
|
{ keyFilename = file
|
||||||
|
, contentLocation = file
|
||||||
|
, inodeCache = cache
|
||||||
|
}
|
||||||
|
withhardlink tmpfile = do
|
||||||
|
createLink file tmpfile
|
||||||
|
cache <- genInodeCache tmpfile
|
||||||
|
return $ KeySource
|
||||||
|
{ keyFilename = file
|
||||||
|
, contentLocation = tmpfile
|
||||||
|
, inodeCache = cache
|
||||||
|
}
|
||||||
|
|
||||||
{- Ingests a locked down file into the annex.
|
{- Ingests a locked down file into the annex.
|
||||||
-
|
-
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
module Command.ReKey where
|
module Command.ReKey where
|
||||||
|
|
||||||
import System.PosixCompat.Files
|
|
||||||
|
|
||||||
import Common.Annex
|
import Common.Annex
|
||||||
import Command
|
import Command
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
|
@ -17,7 +15,6 @@ import Annex.Content
|
||||||
import qualified Command.Add
|
import qualified Command.Add
|
||||||
import Logs.Web
|
import Logs.Web
|
||||||
import Logs.Location
|
import Logs.Location
|
||||||
import Config
|
|
||||||
import Utility.CopyFile
|
import Utility.CopyFile
|
||||||
|
|
||||||
def :: [Command]
|
def :: [Command]
|
||||||
|
@ -49,18 +46,14 @@ perform file oldkey newkey = do
|
||||||
return True
|
return True
|
||||||
next $ cleanup file oldkey newkey
|
next $ cleanup file oldkey newkey
|
||||||
|
|
||||||
{- Make a hard link to the old key content, to avoid wasting disk space. -}
|
{- Make a hard link to the old key content (when supported),
|
||||||
|
- to avoid wasting disk space. -}
|
||||||
linkKey :: Key -> Key -> Annex Bool
|
linkKey :: Key -> Key -> Annex Bool
|
||||||
linkKey oldkey newkey = getViaTmpUnchecked newkey $ \tmp -> do
|
linkKey oldkey newkey = getViaTmpUnchecked newkey $ \tmp -> do
|
||||||
src <- calcRepo $ gitAnnexLocation oldkey
|
src <- calcRepo $ gitAnnexLocation oldkey
|
||||||
ifM (liftIO $ doesFileExist tmp)
|
liftIO $ ifM (doesFileExist tmp)
|
||||||
( return True
|
( return True
|
||||||
, ifM crippledFileSystem
|
, createLinkOrCopy src tmp
|
||||||
( liftIO $ copyFileExternal src tmp
|
|
||||||
, do
|
|
||||||
liftIO $ createLink src tmp
|
|
||||||
return True
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cleanup :: FilePath -> Key -> Key -> CommandCleanup
|
cleanup :: FilePath -> Key -> Key -> CommandCleanup
|
||||||
|
|
2
Init.hs
2
Init.hs
|
@ -140,8 +140,6 @@ probeCrippledFileSystem = do
|
||||||
probe f = catchBoolIO $ do
|
probe f = catchBoolIO $ do
|
||||||
let f2 = f ++ "2"
|
let f2 = f ++ "2"
|
||||||
nukeFile f2
|
nukeFile f2
|
||||||
createLink f f2
|
|
||||||
nukeFile f2
|
|
||||||
createSymbolicLink f f2
|
createSymbolicLink f f2
|
||||||
nukeFile f2
|
nukeFile f2
|
||||||
preventWrite f
|
preventWrite f
|
||||||
|
|
|
@ -264,7 +264,7 @@ rsyncRemote o callback params = do
|
||||||
-
|
-
|
||||||
- This would not be necessary if the hash directory structure used locally
|
- This would not be necessary if the hash directory structure used locally
|
||||||
- was always the same as that used on the rsync remote. So if that's ever
|
- was always the same as that used on the rsync remote. So if that's ever
|
||||||
- unified, this gets nicer. Especially in the crippled filesystem case.
|
- unified, this gets nicer.
|
||||||
- (When we have the right hash directory structure, we can just
|
- (When we have the right hash directory structure, we can just
|
||||||
- pass --include=X --include=X/Y --include=X/Y/file --exclude=*)
|
- pass --include=X --include=X/Y --include=X/Y/file --exclude=*)
|
||||||
-}
|
-}
|
||||||
|
@ -272,20 +272,11 @@ rsyncSend :: RsyncOpts -> MeterUpdate -> Key -> Bool -> FilePath -> Annex Bool
|
||||||
rsyncSend o callback k canrename src = withRsyncScratchDir $ \tmp -> do
|
rsyncSend o callback k canrename src = withRsyncScratchDir $ \tmp -> do
|
||||||
let dest = tmp </> Prelude.head (keyPaths k)
|
let dest = tmp </> Prelude.head (keyPaths k)
|
||||||
liftIO $ createDirectoryIfMissing True $ parentDir dest
|
liftIO $ createDirectoryIfMissing True $ parentDir dest
|
||||||
ok <- if canrename
|
ok <- liftIO $ if canrename
|
||||||
then do
|
then do
|
||||||
liftIO $ renameFile src dest
|
renameFile src dest
|
||||||
return True
|
return True
|
||||||
else ifM crippledFileSystem
|
else createLinkOrCopy src dest
|
||||||
( liftIO $ copyFileExternal src dest
|
|
||||||
, do
|
|
||||||
#ifndef __WINDOWS__
|
|
||||||
liftIO $ createLink src dest
|
|
||||||
return True
|
|
||||||
#else
|
|
||||||
liftIO $ copyFileExternal src dest
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
ps <- sendParams
|
ps <- sendParams
|
||||||
if ok
|
if ok
|
||||||
then rsyncRemote o (Just callback) $ ps ++
|
then rsyncRemote o (Just callback) $ ps ++
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
{- git-annex file copying
|
{- file copying
|
||||||
-
|
-
|
||||||
- Copyright 2010,2012 Joey Hess <joey@kitenet.net>
|
- Copyright 2010-2013 Joey Hess <joey@kitenet.net>
|
||||||
-
|
-
|
||||||
- Licensed under the GNU GPL version 3 or higher.
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Utility.CopyFile (copyFileExternal) where
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
|
module Utility.CopyFile (
|
||||||
|
copyFileExternal,
|
||||||
|
createLinkOrCopy
|
||||||
|
) where
|
||||||
|
|
||||||
import Common
|
import Common
|
||||||
import qualified Build.SysConfig as SysConfig
|
import qualified Build.SysConfig as SysConfig
|
||||||
|
@ -23,3 +28,17 @@ copyFileExternal src dest = do
|
||||||
, (SysConfig.cp_a, Param "-a")
|
, (SysConfig.cp_a, Param "-a")
|
||||||
, (SysConfig.cp_p && not SysConfig.cp_a, Param "-p")
|
, (SysConfig.cp_p && not SysConfig.cp_a, Param "-p")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
{- Create a hard link if the filesystem allows it, and fall back to copying
|
||||||
|
- the file. -}
|
||||||
|
createLinkOrCopy :: FilePath -> FilePath -> IO Bool
|
||||||
|
#ifndef __WINDOWS__
|
||||||
|
createLinkOrCopy src dest = go `catchIO` const fallback
|
||||||
|
where
|
||||||
|
go = do
|
||||||
|
createLink src dest
|
||||||
|
return True
|
||||||
|
fallback = copyFileExternal src dest
|
||||||
|
#else
|
||||||
|
createLinkOrCopy = copyFileExternal
|
||||||
|
#endif
|
||||||
|
|
8
debian/changelog
vendored
8
debian/changelog
vendored
|
@ -1,3 +1,11 @@
|
||||||
|
git-annex (4.20130602) UNRELEASED; urgency=low
|
||||||
|
|
||||||
|
* Supports indirect mode on encfs in paranoia mode, and other
|
||||||
|
filesystems that do not support hard links, but do support
|
||||||
|
symlinks and other POSIX filesystem features.
|
||||||
|
|
||||||
|
-- Joey Hess <joeyh@debian.org> Mon, 10 Jun 2013 12:52:44 -0400
|
||||||
|
|
||||||
git-annex (4.20130601) unstable; urgency=medium
|
git-annex (4.20130601) unstable; urgency=medium
|
||||||
|
|
||||||
* XMPP: Git push over xmpp made much more robust.
|
* XMPP: Git push over xmpp made much more robust.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue