diff options
Diffstat (limited to 'Annex/Direct.hs')
-rw-r--r-- | Annex/Direct.hs | 75 |
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 |