v6 git-annex unlock

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.
This commit is contained in:
Joey Hess 2015-12-10 16:12:05 -04:00
parent 9dffd3d255
commit e2c8dc6778
Failed to extract signature
5 changed files with 58 additions and 15 deletions

View 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

2
debian/changelog vendored
View 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

View 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

View 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

View 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.