summaryrefslogtreecommitdiff
path: root/Command/Lock.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-12-11 10:42:18 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-12-11 10:42:18 -0400
commitd769454704555d7e969754de22e32fd7ed738aaa (patch)
treedddb324eee4df842b731e43047dc70b6190ba4e5 /Command/Lock.hs
parent9e0360d0343575a03dce9f90e7d72c0c56deed1a (diff)
wip
Diffstat (limited to 'Command/Lock.hs')
-rw-r--r--Command/Lock.hs90
1 files changed, 78 insertions, 12 deletions
diff --git a/Command/Lock.hs b/Command/Lock.hs
index 7711ec3b8..c425d7eb6 100644
--- a/Command/Lock.hs
+++ b/Command/Lock.hs
@@ -1,6 +1,6 @@
{- git-annex command
-
- - Copyright 2010 Joey Hess <id@joeyh.name>
+ - Copyright 2010,2015 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -11,6 +11,13 @@ import Common.Annex
import Command
import qualified Annex.Queue
import qualified Annex
+import Annex.Version
+import Annex.Content
+import Annex.Link
+import Annex.InodeSentinal
+import Utility.InodeCache
+import qualified Database.Keys
+import qualified Command.Add
cmd :: Command
cmd = notDirect $ withGlobalOptions annexedMatchingOptions $
@@ -19,18 +26,77 @@ cmd = notDirect $ withGlobalOptions annexedMatchingOptions $
paramPaths (withParams seek)
seek :: CmdParams -> CommandSeek
-seek ps = do
- withFilesUnlocked start ps
- withFilesUnlockedToBeCommitted start ps
+seek ps = ifM versionSupportsUnlockedPointers
+ ( withFilesInGit (whenAnnexed startNew) ps
+ , do
+ withFilesUnlocked startOld ps
+ withFilesUnlockedToBeCommitted startOld ps
+ )
-start :: FilePath -> CommandStart
-start file = do
+startNew :: FilePath -> Key -> CommandStart
+startNew file key = do
showStart "lock" file
- unlessM (Annex.getState Annex.force) $
- error "Locking this file would discard any changes you have made to it. Use 'git annex add' to stage your changes. (Or, use --force to override)"
- next $ perform file
+ go =<< isPointerFile file
+ where
+ go (Just key')
+ | key' == key = cont False
+ | otherwise = errorModified
+ go Nothing =
+ ifM (isUnmodified key file)
+ ( cont False
+ , ifM (Annex.getState Annex.force)
+ ( cont True
+ , errorModified
+ )
+ )
+ cont = next . performNew file key
-perform :: FilePath -> CommandPerform
-perform file = do
+performNew :: FilePath -> Key -> Bool -> CommandPerform
+performNew file key filemodified = do
+ -- If other files use this same key, and are unlocked,
+ -- the annex object file might be hard linked to those files.
+ -- It's also possible that the annex object file was
+ -- modified while the file was unlocked.
+ --
+ -- So, in order to lock the file's content, we need to break all
+ -- hard links to the annex object file, and if it's modified,
+ -- replace it with a copy of the content of one of the associated
+ -- files.
+ --
+ -- When the file being locked is unmodified, the annex object file
+ -- can just be linked to it. (Which might already be the case, but
+ -- do it again to be sure.)
+ --
+ -- When the file being locked is modified, find another associated
+ -- file that is unmodified, and copy it to the annex object file.
+ -- If there are no unmodified associated files, the content of
+ -- the key is lost.
+ --
+ -- If the filesystem doesn't support hard links, none of this
+ -- is a concern.
+ obj <- calcRepo (gitAnnexLocation key)
+
+ freezeContent obj
+ Command.Add.addLink file key
+ =<< withTSDelta (liftIO . genInodeCache file)
+ next $ cleanupNew file key
+
+cleanupNew :: FilePath -> Key -> CommandCleanup
+cleanupNew file key = do
+ Database.Keys.removeAssociatedFile key file
+ return True
+
+startOld :: FilePath -> CommandStart
+startOld file = do
+ showStart "lock" file
+ unlessM (Annex.getState Annex.force)
+ errorModified
+ next $ performOld file
+
+performOld :: FilePath -> CommandPerform
+performOld file = do
Annex.Queue.addCommand "checkout" [Param "--"] [file]
- next $ return True -- no cleanup needed
+ next $ return True
+
+errorModified :: a
+errorModified = error "Locking this file would discard any changes you have made to it. Use 'git annex add' to stage your changes. (Or, use --force to override)"