summaryrefslogtreecommitdiff
path: root/Annex/Direct.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Annex/Direct.hs')
-rw-r--r--Annex/Direct.hs75
1 files changed, 48 insertions, 27 deletions
diff --git a/Annex/Direct.hs b/Annex/Direct.hs
index 02766ab18..2f583fd94 100644
--- a/Annex/Direct.hs
+++ b/Annex/Direct.hs
@@ -170,23 +170,23 @@ mergeDirectCleanup d oldsha newsha = do
makeabs <- flip fromTopFilePath <$> gitRepo
let fsitems = zip (map (makeabs . DiffTree.file) items) items
forM_ fsitems $
- go DiffTree.srcsha DiffTree.srcmode moveout moveout_raw
+ go makeabs DiffTree.srcsha DiffTree.srcmode moveout moveout_raw
forM_ fsitems $
- go DiffTree.dstsha DiffTree.dstmode movein movein_raw
+ go makeabs DiffTree.dstsha DiffTree.dstmode movein movein_raw
void $ liftIO cleanup
liftIO $ removeDirectoryRecursive d
where
- go getsha getmode a araw (f, item)
+ go makeabs getsha getmode a araw (f, item)
| getsha item == nullSha = noop
| otherwise = void $
- tryAnnex . maybe (araw f item) (\k -> void $ a k f)
+ tryAnnex . maybe (araw item makeabs f) (\k -> void $ a item makeabs k f)
=<< catKey (getsha item) (getmode item)
- moveout = removeDirect
+ moveout _ _ = removeDirect
{- Files deleted by the merge are removed from the work tree.
- Empty work tree directories are removed, per git behavior. -}
- moveout_raw f _item = liftIO $ do
+ moveout_raw _ _ f = liftIO $ do
nukeFile f
void $ tryIO $ removeDirectory $ parentDir f
@@ -198,39 +198,60 @@ mergeDirectCleanup d oldsha newsha = do
-
- Otherwise, create the symlink and then if possible, replace it
- with the content. -}
- movein k f = unlessM (goodContent k f) $ do
- preserveUnannexed f
+ movein item makeabs k f = unlessM (goodContent k f) $ do
+ preserveUnannexed item makeabs f oldsha
l <- inRepo $ gitAnnexLink f k
replaceFile f $ makeAnnexLink l
toDirect k f
{- Any new, modified, or renamed files were written to the temp
- directory by the merge, and are moved to the real work tree. -}
- movein_raw f item = do
- preserveUnannexed f
+ movein_raw item makeabs f = do
+ preserveUnannexed item makeabs f oldsha
liftIO $ do
createDirectoryIfMissing True $ parentDir f
void $ tryIO $ rename (d </> getTopFilePath (DiffTree.file item)) f
- {- If the file is present in the work tree, but did not exist in
- - the oldsha branch, preserve this local, unannexed file. -}
- preserveUnannexed f = whenM unannexed $
- whenM (isNothing <$> catFileDetails oldsha f) $
- liftIO $ findnewname (0 :: Int)
- where
- exists = isJust <$$> catchMaybeIO . getSymbolicLinkStatus
+{- If the file that's being moved in is already present in the work
+ - tree, but did not exist in the oldsha branch, preserve this
+ - local, unannexed file (or directory), as "variant-local".
+ -
+ - It's also possible that the file that's being moved in
+ - is in a directory that collides with an exsting, non-annexed
+ - file (not a directory), which should be preserved.
+ -}
+preserveUnannexed :: DiffTree.DiffTreeItem -> (TopFilePath -> FilePath) -> FilePath -> Ref -> Annex ()
+preserveUnannexed item makeabs absf oldsha = do
+ whenM (liftIO (collidingitem absf) <&&> unannexed absf) $
+ liftIO $ findnewname absf 0
+ checkdirs (DiffTree.file item)
+ where
+ checkdirs from = do
+ let p = parentDir (getTopFilePath from)
+ let d = asTopFilePath p
+ unless (null p) $ do
+ let absd = makeabs d
+ whenM (liftIO (colliding_nondir absd) <&&> unannexed absd) $
+ liftIO $ findnewname absd 0
+ checkdirs d
+
+ collidingitem f = isJust
+ <$> catchMaybeIO (getSymbolicLinkStatus f)
+ colliding_nondir f = maybe False (not . isDirectory)
+ <$> catchMaybeIO (getSymbolicLinkStatus f)
- unannexed = liftIO (exists f)
- <&&> (isNothing <$> isAnnexLink f)
+ unannexed f = (isNothing <$> isAnnexLink f)
+ <&&> (isNothing <$> catFileDetails oldsha f)
- findnewname n = do
- let localf = mkVariant f
- ("local" ++ if n > 0 then show n else "")
- ifM (exists localf)
- ( findnewname (n+1)
- , rename f localf
- `catchIO` const (findnewname (n+1))
- )
+ findnewname :: FilePath -> Int -> IO ()
+ findnewname f n = do
+ let localf = mkVariant f
+ ("local" ++ if n > 0 then show n else "")
+ ifM (collidingitem localf)
+ ( findnewname f (n+1)
+ , rename f localf
+ `catchIO` const (findnewname f (n+1))
+ )
{- If possible, converts a symlink in the working tree into a direct
- mode file. If the content is not available, leaves the symlink