hard links on windows

* annex.thin and annex.hardlink are now supported on Windows.
* unannex --fast now makes hard links on Windows.
This commit is contained in:
Joey Hess 2016-04-08 15:25:32 -04:00
parent 251405eca2
commit cf06dac2b8
Failed to extract signature
8 changed files with 29 additions and 26 deletions

View file

@ -594,14 +594,10 @@ linkOrCopy' canhardlink key src dest = catchBoolIO $
where
hardlink = do
s <- getstat
#ifndef mingw32_HOST_OS
if linkCount s > 1
then copy s
else liftIO (createLink src dest >> return True)
`catchIO` const (copy s)
#else
copy s
#endif
copy = checkedCopyFile' key src dest
getstat = liftIO $ getFileStatus src

View file

@ -5,8 +5,6 @@
- Licensed under the GNU GPL version 3 or higher.
-}
{-# LANGUAGE CPP #-}
module Command.Unannex where
import Command
@ -107,15 +105,11 @@ cleanupIndirect file key = do
copyfrom src =
thawContent file `after` liftIO (copyFileExternal CopyAllMetaData src file)
hardlinkfrom src =
#ifndef mingw32_HOST_OS
-- creating a hard link could fall; fall back to copying
ifM (liftIO $ catchBoolIO $ createLink src file >> return True)
( return True
, copyfrom src
)
#else
copyfrom src
#endif
performDirect :: FilePath -> Key -> CommandPerform
performDirect file key = do

View file

@ -695,7 +695,6 @@ mkCopier :: Bool -> [CommandParam] -> Annex Copier
mkCopier remotewanthardlink rsyncparams = do
let copier = \src dest p check -> unVerified $
rsyncOrCopyFile rsyncparams src dest p <&&> check
#ifndef mingw32_HOST_OS
localwanthardlink <- wantHardLink
let linker = \src dest -> createLink src dest >> return True
ifM (pure (remotewanthardlink || localwanthardlink) <&&> not <$> isDirect)
@ -706,6 +705,3 @@ mkCopier remotewanthardlink rsyncparams = do
)
, return copier
)
#else
return $ if remotewanthardlink then copier else copier
#endif

View file

@ -49,13 +49,9 @@ copyFileExternal meta src dest = do
{- Create a hard link if the filesystem allows it, and fall back to copying
- the file. -}
createLinkOrCopy :: FilePath -> FilePath -> IO Bool
#ifndef mingw32_HOST_OS
createLinkOrCopy src dest = go `catchIO` const fallback
where
go = do
createLink src dest
return True
fallback = copyFileExternal CopyAllMetaData src dest
#else
createLinkOrCopy = copyFileExternal CopyAllMetaData
#endif

View file

@ -1,6 +1,6 @@
{- POSIX files (and compatablity wrappers).
-
- This is like System.PosixCompat.Files, except with a fixed rename.
- This is like System.PosixCompat.Files, but with a few fixes.
-
- Copyright 2014 Joey Hess <id@joeyh.name>
-
@ -21,6 +21,7 @@ import System.PosixCompat.Files as X hiding (rename)
import System.Posix.Files (rename)
#else
import qualified System.Win32.File as Win32
import qualified System.Win32.HardLink as Win32
#endif
{- System.PosixCompat.Files.rename on Windows calls renameFile,
@ -32,3 +33,10 @@ import qualified System.Win32.File as Win32
rename :: FilePath -> FilePath -> IO ()
rename src dest = Win32.moveFileEx src dest Win32.mOVEFILE_REPLACE_EXISTING
#endif
{- System.PosixCompat.Files.createLink throws an error, but windows
- does support hard links. -}
#ifdef mingw32_HOST_OS
createLink :: FilePath -> FilePath -> IO ()
createLink = Win32.createHardLink
#endif

2
debian/changelog vendored
View file

@ -14,6 +14,8 @@ git-annex (6.20160319) UNRELEASED; urgency=medium
* log --raw-date: Use to display seconds from unix epoch.
* v6: Close pointer file handles more quickly, to avoid problems on Windows.
* sync: Show output of git commit.
* annex.thin and annex.hardlink are now supported on Windows.
* unannex --fast now makes hard links on Windows.
-- Joey Hess <id@joeyh.name> Wed, 23 Mar 2016 11:42:36 -0400

View file

@ -280,9 +280,20 @@ into adjusted view worktrees.]
to checkout the adjusted branch some other way. Maybe generalize so this
more efficient checkout is available as a git-annex command?
* There are potentially races in code that assumes a branch like
master is not being changed by someone else. In particular,
propigateAdjustedCommits rebases the adjusted branch on top of master.
That is called by sync. The assumption is that any changes in master
have already been handled by updateAdjustedBranch. But, if another remote
pushed a new master at just the right time, the adjusted branch could be
rebased on top of a master that it doesn't incorporate, which is wrong.
master is not being changed by someone else.
In particular, propigateAdjustedCommits rebases the adjusted branch on
top of master. That is called by sync. The assumption is that any changes
in master have already been handled by updateAdjustedBranch. But, if
another remote pushed a new master at just the right time, the adjusted
branch could be rebased on top of a master that it doesn't incorporate,
which is wrong.
Best fix seems to be to use a hidden ref, like refs/annex/adjusted/master
and copy master's ref to it when entering the view branch. Then, make
all adjustments via that ref, and propigate back to refs/heads/master.
It's fine to overwrite changes that were pushed to master when
propigating from the adjusted branch. Synced changes also go to
synced/master so won't be lost. Pushes not made using git-annex sync
of master are not really desired, just a possibility.

View file

@ -143,7 +143,7 @@ match the new setting:
git annex fix
Note that setting annex.thin only has any effect on systems that support
hard links. Ie, not Windows, and not FAT filesystems.
hard links. It is supported on Windows, but not on FAT filesystems.
## tradeoffs