aboutsummaryrefslogtreecommitdiff
path: root/Command/Unannex.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Command/Unannex.hs')
-rw-r--r--Command/Unannex.hs79
1 files changed, 51 insertions, 28 deletions
diff --git a/Command/Unannex.hs b/Command/Unannex.hs
index 1f2978430..3fe4cf69c 100644
--- a/Command/Unannex.hs
+++ b/Command/Unannex.hs
@@ -1,6 +1,6 @@
{- git-annex command
-
- - Copyright 2010-2013 Joey Hess <joey@kitenet.net>
+ - Copyright 2010-2013 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -16,18 +16,51 @@ import qualified Annex
import Annex.Content
import Annex.Content.Direct
import qualified Git.Command
-import qualified Git.LsFiles as LsFiles
+import qualified Git.Branch
+import qualified Git.Ref
+import qualified Git.DiffTree as DiffTree
import Utility.CopyFile
+import Command.PreCommit (lockPreCommitHook)
-def :: [Command]
-def = [command "unannex" paramPaths seek SectionUtility
+cmd :: [Command]
+cmd = [withOptions annexedMatchingOptions $
+ command "unannex" paramPaths seek SectionUtility
"undo accidential add command"]
seek :: CommandSeek
-seek = withFilesInGit $ whenAnnexed start
+seek = wrapUnannex . (withFilesInGit $ whenAnnexed start)
-start :: FilePath -> (Key, Backend) -> CommandStart
-start file (key, _) = stopUnless (inAnnex key) $ do
+wrapUnannex :: Annex a -> Annex a
+wrapUnannex a = ifM isDirect
+ ( a
+ {- Run with the pre-commit hook disabled, to avoid confusing
+ - behavior if an unannexed file is added back to git as
+ - a normal, non-annexed file and then committed.
+ - Otherwise, the pre-commit hook would think that the file
+ - has been unlocked and needs to be re-annexed.
+ -
+ - At the end, make a commit removing the unannexed files.
+ -}
+ , ifM cleanindex
+ ( lockPreCommitHook $ commit `after` a
+ , error "Cannot proceed with uncommitted changes staged in the index. Recommend you: git commit"
+ )
+ )
+ where
+ commit = inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit
+ [ Param "-q"
+ , Param "--allow-empty"
+ , Param "--no-verify"
+ , Param "-m", Param "content removed from git annex"
+ ]
+ cleanindex = do
+ (diff, cleanup) <- inRepo $ DiffTree.diffIndex Git.Ref.headRef
+ if null diff
+ then void (liftIO cleanup) >> return True
+ else void (liftIO cleanup) >> return False
+
+start :: FilePath -> Key -> CommandStart
+start file key = stopUnless (inAnnex key) $ do
showStart "unannex" file
next $ ifM isDirect
( performDirect file key
@@ -36,38 +69,28 @@ start file (key, _) = stopUnless (inAnnex key) $ do
performIndirect :: FilePath -> Key -> CommandPerform
performIndirect file key = do
liftIO $ removeFile file
-
- -- git rm deletes empty directory without --cached
inRepo $ Git.Command.run [Params "rm --cached --force --quiet --", File file]
-
- -- If the file was already committed, it is now staged for removal.
- -- Commit that removal now, to avoid later confusing the
- -- pre-commit hook, if this file is later added back to
- -- git as a normal non-annexed file, to thinking that the
- -- file has been unlocked and needs to be re-annexed.
- (s, reap) <- inRepo $ LsFiles.staged [file]
- unless (null s) $
- inRepo $ Git.Command.run
- [ Param "commit"
- , Param "-q"
- , Param "--no-verify"
- , Param "-m", Param "content removed from git annex"
- , Param "--", File file
- ]
- void $ liftIO reap
-
next $ cleanupIndirect file key
cleanupIndirect :: FilePath -> Key -> CommandCleanup
cleanupIndirect file key = do
src <- calcRepo $ gitAnnexLocation key
ifM (Annex.getState Annex.fast)
- ( hardlinkfrom src
+ ( do
+ -- Only make a hard link if the annexed file does not
+ -- already have other hard links pointing at it.
+ -- This avoids unannexing (and uninit) ending up
+ -- hard linking files together, which would be
+ -- surprising.
+ s <- liftIO $ getFileStatus src
+ if linkCount s > 1
+ then copyfrom src
+ else hardlinkfrom src
, copyfrom src
)
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