v6 git-annex unlock
authorJoey Hess <joeyh@joeyh.name>
Thu, 10 Dec 2015 20:12:05 +0000 (16:12 -0400)
committerJoey Hess <joeyh@joeyh.name>
Thu, 10 Dec 2015 20:12:48 +0000 (16:12 -0400)
Note that the implementation uses replaceFile, so that the actual
replacement of the work tree file is atomic. This seems a good property to
have!

It would be possible for unlock in v6 mode to be run on files that do not
have their content present. However, that would be a behavior change from
before, and I don't see any immediate need to support it, so I didn't
implement it.

Command/Unlock.hs
debian/changelog
doc/git-annex-lock.mdwn
doc/git-annex-unlock.mdwn
doc/todo/smudge.mdwn

index d1b1d0e90ef1d0e8ed414996484ca044b89f8ae8..1cfd4a0b2b86e669457b8c752db545973178eda9 100644 (file)
@@ -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,9 @@ import Common.Annex
 import Command
 import Annex.Content
 import Annex.CatFile
+import Annex.Version
+import Annex.Link
+import Annex.ReplaceFile
 import Utility.CopyFile
 
 cmd :: Command
@@ -26,14 +29,45 @@ mkcmd n d = notDirect $ withGlobalOptions annexedMatchingOptions $
 seek :: CmdParams -> CommandSeek
 seek = withFilesInGit $ whenAnnexed start
 
-{- The unlock subcommand replaces the symlink with a copy of the file's
- - content. -}
+{- Before v6, the unlock subcommand replaces the symlink with a copy of
+ - the file's content. In v6 and above, it converts the file from a symlink
+ - to a pointer. -}
 start :: FilePath -> Key -> CommandStart
-start file key = do
-       showStart "unlock" file
+start file key = ifM (isJust <$> isAnnexLink file)
+       ( do
+               showStart "unlock" file
+               ifM (inAnnex key)
+                       ( ifM versionSupportsUnlockedPointers
+                               ( next $ performNew file key
+                               , startOld file key 
+                               )
+                       , do
+                               warning "content not present; cannot unlock"
+                               next $ next $ return False
+                       )
+       , stop
+       )
+
+performNew :: FilePath -> Key -> CommandPerform
+performNew dest key = do
+       src <- calcRepo (gitAnnexLocation key)
+       replaceFile dest $ \tmp -> do
+               r <- linkAnnex' key src tmp
+               case r of
+                       LinkAnnexOk -> return ()
+                       _ -> error "linkAnnex failed"
+       next $ cleanupNew dest key
+
+cleanupNew ::  FilePath -> Key -> CommandCleanup
+cleanupNew dest key = do
+       stagePointerFile dest =<< hashPointerFile key
+       return True
+
+startOld :: FilePath -> Key -> CommandStart
+startOld file key = 
        ifM (inAnnex key)
                ( ifM (isJust <$> catKeyFileHEAD file)
-                       ( next $ perform file key
+                       ( next $ performOld file key
                        , do
                                warning "this has not yet been committed to git; cannot unlock it"
                                next $ next $ return False
@@ -43,8 +77,8 @@ start file key = do
                        next $ next $ return False
                )
 
-perform :: FilePath -> Key -> CommandPerform
-perform dest key = ifM (checkDiskSpace Nothing key 0 True)
+performOld :: FilePath -> Key -> CommandPerform
+performOld dest key = ifM (checkDiskSpace Nothing key 0 True)
        ( do
                src <- calcRepo $ gitAnnexLocation key
                tmpdest <- fromRepo $ gitAnnexTmpObjectLocation key
index e3ee9a34ad8c763dc0bd0bfcf6a0b3cfefaafd72..1b645fd063b38d9e9ba5674e4a7fde3f87aadafa 100644 (file)
@@ -9,6 +9,8 @@ git-annex (6.20151225) unstable; urgency=medium
   * init: Configure .git/info/attributes to use git-annex as a smudge
     filter. Note that this changes the default behavior of git add in a
     newly initialized repository; it will add files to the annex.
+  * unlock, lock: In v6 mode, unlocking a file changes it from a symlink to a
+    pointer file, and this change can be committed to the git repository.
  
  -- Joey Hess <id@joeyh.name>  Tue, 08 Dec 2015 11:14:03 -0400
 
index 4bf279fb224430fdc97c232c8f2be7abeec44813..b9e5d345032bc3459a5363229b718253d1a29188 100644 (file)
@@ -9,7 +9,7 @@ git annex lock `[path ...]`
 # DESCRIPTION
 
 Use this to undo an unlock command if you don't want to modify
-the files, or have made modifications you want to discard.
+the files any longer, or have made modifications you want to discard.
 
 # OPTIONS
 
index ac8c2118551af649792e7f089276424e4a58dfcb..1231468364551e7ae402b3d557a597e9e18a9604 100644 (file)
@@ -11,8 +11,16 @@ git annex unlock `[path ...]`
 Normally, the content of annexed files is protected from being changed.
 Unlocking an annexed file allows it to be modified. This replaces the
 symlink for each specified file with a copy of the file's content.
-You can then modify it and `git annex add` (or `git commit`) to inject
-it back into the annex.
+You can then modify it and `git annex add` (or `git commit`) to save your
+changes.
+
+In repositories with annex.version 5 or earlier, unlocking a file is local
+to the repository, and is temporary. With version 6, unlocking a file
+changes how it is stored in the git repository (from a symlink to a pointer
+file), so you can commit it like any other change. Also in version 6, you
+can use `git add` to add a fie to the annex in unlocked form. This allows
+workflows where a file starts out unlocked, is modified as necessary, and
+is locked once it reaches its final version.
 
 # OPTIONS
 
index dd990afc71e4c25e87e627aaca9eb44ca669d9ef..72e062ff4ba0c6d8fc04de04f5ed865411ca01b2 100644 (file)
@@ -325,6 +325,9 @@ files to be unlocked, while the indirect upgrades don't touch the files.
 
 #### implementation todo list
 
+* Dropping a smudged file causes git status to show it as modified, 
+  because the timestamp has changed. Avoid this by preserving timestamp
+  of smudged files when manipulating.
 * linkAnnex should check disk reserve when it falls back to copying the
   file.
 * Reconcile staged changes into the associated files database, whenever
@@ -337,10 +340,6 @@ files to be unlocked, while the indirect upgrades don't touch the files.
   (when not in direct mode).
   However, beware over-optimisation breaking the assistant or perhaps other
   long-lived processes.
-* Convert `git annex unlock` to stage a pointer file, and hard link to the
-  annexed object (or write pointer file if annexed object not present).
-  - Also needs to thaw annex object file
-  - Also needs to update associated files db.
 * Convert `git annex lock` to verify that worktree file is not modified
   (same check used when updating pointer files to the content of a key),
   and then delete the worktree file and replace with an annex symlink.