Merge branch 'checkout'
This commit is contained in:
commit
f5f472e855
15 changed files with 286 additions and 22 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
build/*
|
build/*
|
||||||
|
test
|
||||||
git-annex
|
git-annex
|
||||||
git-annex.1
|
git-annex.1
|
||||||
doc/.ikiwiki
|
doc/.ikiwiki
|
||||||
|
|
30
CmdLine.hs
30
CmdLine.hs
|
@ -30,10 +30,13 @@ import qualified Command.SetKey
|
||||||
import qualified Command.Fix
|
import qualified Command.Fix
|
||||||
import qualified Command.Init
|
import qualified Command.Init
|
||||||
import qualified Command.Fsck
|
import qualified Command.Fsck
|
||||||
|
import qualified Command.Unlock
|
||||||
|
import qualified Command.Lock
|
||||||
|
import qualified Command.PreCommit
|
||||||
|
|
||||||
subCmds :: [SubCommand]
|
subCmds :: [SubCommand]
|
||||||
subCmds =
|
subCmds =
|
||||||
[ SubCommand "add" path (withFilesNotInGit Command.Add.start)
|
[ SubCommand "add" path (withFilesToAdd Command.Add.start)
|
||||||
"add files to annex"
|
"add files to annex"
|
||||||
, SubCommand "get" path (withFilesInGit Command.Get.start)
|
, SubCommand "get" path (withFilesInGit Command.Get.start)
|
||||||
"make content of annexed files available"
|
"make content of annexed files available"
|
||||||
|
@ -41,12 +44,18 @@ subCmds =
|
||||||
"indicate content of files not currently wanted"
|
"indicate content of files not currently wanted"
|
||||||
, SubCommand "move" path (withFilesInGit Command.Move.start)
|
, SubCommand "move" path (withFilesInGit Command.Move.start)
|
||||||
"transfer content of files to/from another repository"
|
"transfer content of files to/from another repository"
|
||||||
|
, SubCommand "unlock" path (withFilesInGit Command.Unlock.start)
|
||||||
|
"unlock files for modification"
|
||||||
|
, SubCommand "edit" path (withFilesInGit Command.Unlock.start)
|
||||||
|
"same as unlock"
|
||||||
|
, SubCommand "lock" path (withFilesInGit Command.Lock.start)
|
||||||
|
"undo unlock command"
|
||||||
, SubCommand "init" desc (withDescription Command.Init.start)
|
, SubCommand "init" desc (withDescription Command.Init.start)
|
||||||
"initialize git-annex with repository description"
|
"initialize git-annex with repository description"
|
||||||
, SubCommand "unannex" path (withFilesInGit Command.Unannex.start)
|
, SubCommand "unannex" path (withFilesInGit Command.Unannex.start)
|
||||||
"undo accidential add command"
|
"undo accidential add command"
|
||||||
, SubCommand "pre-commit" path (withFilesToBeCommitted Command.Fix.start)
|
, SubCommand "pre-commit" path (withFilesToBeCommitted Command.PreCommit.start)
|
||||||
"fix up symlinks before they are committed"
|
"run by git pre-commit hook"
|
||||||
, SubCommand "fromkey" key (withFilesMissing Command.FromKey.start)
|
, SubCommand "fromkey" key (withFilesMissing Command.FromKey.start)
|
||||||
"adds a file using a specific key"
|
"adds a file using a specific key"
|
||||||
, SubCommand "dropkey" key (withKeys Command.DropKey.start)
|
, SubCommand "dropkey" key (withKeys Command.DropKey.start)
|
||||||
|
@ -106,13 +115,6 @@ usage = usageInfo header options ++ "\nSubcommands:\n" ++ cmddescs
|
||||||
|
|
||||||
{- These functions find appropriate files or other things based on a
|
{- These functions find appropriate files or other things based on a
|
||||||
user's parameters. -}
|
user's parameters. -}
|
||||||
withFilesNotInGit :: SubCmdSeekBackendFiles
|
|
||||||
withFilesNotInGit a params = do
|
|
||||||
repo <- Annex.gitRepo
|
|
||||||
files <- liftIO $ mapM (Git.notInRepo repo) params
|
|
||||||
let files' = foldl (++) [] files
|
|
||||||
pairs <- Backend.chooseBackends files'
|
|
||||||
return $ map a $ filter (\(f,_) -> notState f) pairs
|
|
||||||
withFilesInGit :: SubCmdSeekStrings
|
withFilesInGit :: SubCmdSeekStrings
|
||||||
withFilesInGit a params = do
|
withFilesInGit a params = do
|
||||||
repo <- Annex.gitRepo
|
repo <- Annex.gitRepo
|
||||||
|
@ -126,6 +128,14 @@ withFilesMissing a params = do
|
||||||
missing f = do
|
missing f = do
|
||||||
e <- doesFileExist f
|
e <- doesFileExist f
|
||||||
return $ not e
|
return $ not e
|
||||||
|
withFilesToAdd :: SubCmdSeekBackendFiles
|
||||||
|
withFilesToAdd a params = do
|
||||||
|
repo <- Annex.gitRepo
|
||||||
|
newfiles <- liftIO $ mapM (Git.notInRepo repo) params
|
||||||
|
unlockedfiles <- liftIO $ mapM (Git.typeChangedFiles repo) params
|
||||||
|
let files = foldl (++) [] $ newfiles ++ unlockedfiles
|
||||||
|
pairs <- Backend.chooseBackends files
|
||||||
|
return $ map a $ filter (\(f,_) -> notState f) pairs
|
||||||
withDescription :: SubCmdSeekStrings
|
withDescription :: SubCmdSeekStrings
|
||||||
withDescription a params = return [a $ unwords params]
|
withDescription a params = return [a $ unwords params]
|
||||||
withFilesToBeCommitted :: SubCmdSeekStrings
|
withFilesToBeCommitted :: SubCmdSeekStrings
|
||||||
|
|
50
Command/Lock.hs
Normal file
50
Command/Lock.hs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{- git-annex command
|
||||||
|
-
|
||||||
|
- Copyright 2010 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Command.Lock where
|
||||||
|
|
||||||
|
import Control.Monad.State (liftIO)
|
||||||
|
import System.Directory
|
||||||
|
import System.Posix.Files
|
||||||
|
|
||||||
|
import Types
|
||||||
|
import Command
|
||||||
|
import Messages
|
||||||
|
import qualified Annex
|
||||||
|
import qualified GitRepo as Git
|
||||||
|
|
||||||
|
{- Undo unlock -}
|
||||||
|
start :: SubCmdStartString
|
||||||
|
start file = do
|
||||||
|
locked <- isLocked file
|
||||||
|
if locked
|
||||||
|
then return Nothing
|
||||||
|
else do
|
||||||
|
showStart "lock" file
|
||||||
|
return $ Just $ perform file
|
||||||
|
|
||||||
|
perform :: FilePath -> SubCmdPerform
|
||||||
|
perform file = do
|
||||||
|
liftIO $ removeFile file
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
-- first reset the file to drop any changes checked into the index
|
||||||
|
liftIO $ Git.run g ["reset", "-q", "--", file]
|
||||||
|
-- checkout the symlink
|
||||||
|
liftIO $ Git.run g ["checkout", "--", file]
|
||||||
|
return $ Just $ return True -- no cleanup needed
|
||||||
|
|
||||||
|
{- Checks if a file is unlocked for edit.
|
||||||
|
-
|
||||||
|
- But, without the symlink to the annex, cannot tell for sure if the
|
||||||
|
- file was annexed before. So, check if git thinks the file's type has
|
||||||
|
- changed (from a symlink to a regular file). -}
|
||||||
|
isLocked :: FilePath -> Annex Bool
|
||||||
|
isLocked file = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
typechanged <- liftIO $ Git.typeChangedFiles g file
|
||||||
|
s <- liftIO $ getSymbolicLinkStatus file
|
||||||
|
return $ (not $ elem file typechanged) || isSymbolicLink s
|
40
Command/PreCommit.hs
Normal file
40
Command/PreCommit.hs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{- git-annex command
|
||||||
|
-
|
||||||
|
- Copyright 2010 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Command.PreCommit where
|
||||||
|
|
||||||
|
import Control.Monad.State (liftIO)
|
||||||
|
import Control.Monad (when, unless)
|
||||||
|
|
||||||
|
import Command
|
||||||
|
import qualified Annex
|
||||||
|
import qualified Backend
|
||||||
|
import qualified GitRepo as Git
|
||||||
|
import qualified Command.Fix
|
||||||
|
import qualified Command.Lock
|
||||||
|
import qualified Command.Add
|
||||||
|
|
||||||
|
{- Run by git pre-commit hook. -}
|
||||||
|
start :: SubCmdStartString
|
||||||
|
start file = do
|
||||||
|
-- If a file is unlocked for edit, add its new content to the
|
||||||
|
-- annex, -}
|
||||||
|
locked <- Command.Lock.isLocked file
|
||||||
|
when (not locked) $ do
|
||||||
|
pairs <- Backend.chooseBackends [file]
|
||||||
|
ok <- doSubCmd $ Command.Add.start $ pairs !! 0
|
||||||
|
unless (ok) $ do
|
||||||
|
error $ "failed to add " ++ file ++ "; canceling commit"
|
||||||
|
-- git commit will have staged the file's content;
|
||||||
|
-- drop that and stage the symlink
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
liftIO $ Git.run g ["reset", "-q", "--", file]
|
||||||
|
Annex.queueRun
|
||||||
|
|
||||||
|
-- Fix symlinks as they are committed, this ensures the
|
||||||
|
-- relative links are not broken when moved around.
|
||||||
|
Command.Fix.start file
|
39
Command/Unlock.hs
Normal file
39
Command/Unlock.hs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{- git-annex command
|
||||||
|
-
|
||||||
|
- Copyright 2010 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Command.Unlock where
|
||||||
|
|
||||||
|
import Control.Monad.State (liftIO)
|
||||||
|
import System.Directory
|
||||||
|
|
||||||
|
import Command
|
||||||
|
import qualified Annex
|
||||||
|
import Types
|
||||||
|
import Messages
|
||||||
|
import Locations
|
||||||
|
import Utility
|
||||||
|
import Core
|
||||||
|
|
||||||
|
{- The unlock subcommand replaces the symlink with a copy of the file's
|
||||||
|
- content. -}
|
||||||
|
start :: SubCmdStartString
|
||||||
|
start file = isAnnexed file $ \(key, _) -> do
|
||||||
|
showStart "unlock" file
|
||||||
|
return $ Just $ perform file key
|
||||||
|
|
||||||
|
perform :: FilePath -> Key -> SubCmdPerform
|
||||||
|
perform dest key = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
let src = annexLocation g key
|
||||||
|
liftIO $ removeFile dest
|
||||||
|
showNote "copying..."
|
||||||
|
ok <- liftIO $ boolSystem "cp" ["-p", src, dest]
|
||||||
|
if ok
|
||||||
|
then do
|
||||||
|
liftIO $ allowWrite dest
|
||||||
|
return $ Just $ return True
|
||||||
|
else error "cp failed!"
|
1
Core.hs
1
Core.hs
|
@ -173,6 +173,7 @@ moveAnnex key src = do
|
||||||
let dir = parentDir dest
|
let dir = parentDir dest
|
||||||
liftIO $ do
|
liftIO $ do
|
||||||
createDirectoryIfMissing True dir
|
createDirectoryIfMissing True dir
|
||||||
|
allowWrite dir -- in case the directory already exists
|
||||||
renameFile src dest
|
renameFile src dest
|
||||||
preventWrite dest
|
preventWrite dest
|
||||||
preventWrite dir
|
preventWrite dir
|
||||||
|
|
21
GitRepo.hs
21
GitRepo.hs
|
@ -39,6 +39,7 @@ module GitRepo (
|
||||||
checkAttr,
|
checkAttr,
|
||||||
decodeGitFile,
|
decodeGitFile,
|
||||||
encodeGitFile,
|
encodeGitFile,
|
||||||
|
typeChangedFiles,
|
||||||
|
|
||||||
prop_idempotent_deencode
|
prop_idempotent_deencode
|
||||||
) where
|
) where
|
||||||
|
@ -58,6 +59,7 @@ import Data.Char
|
||||||
import Data.Word (Word8)
|
import Data.Word (Word8)
|
||||||
import Codec.Binary.UTF8.String (encode)
|
import Codec.Binary.UTF8.String (encode)
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
import Data.List
|
||||||
|
|
||||||
import Utility
|
import Utility
|
||||||
|
|
||||||
|
@ -227,20 +229,31 @@ hPipeRead repo params = assertLocal repo $ do
|
||||||
- are checked into git at that location. -}
|
- are checked into git at that location. -}
|
||||||
inRepo :: Repo -> FilePath -> IO [FilePath]
|
inRepo :: Repo -> FilePath -> IO [FilePath]
|
||||||
inRepo repo l = pipeNullSplit repo
|
inRepo repo l = pipeNullSplit repo
|
||||||
["ls-files", "--cached", "--exclude-standard", "-z", l]
|
["ls-files", "--cached", "--exclude-standard", "-z", "--", l]
|
||||||
|
|
||||||
{- Passed a location, recursively scans for all files that are not checked
|
{- Passed a location, recursively scans for all files that are not checked
|
||||||
- into git, and not gitignored. -}
|
- into git, and not gitignored. -}
|
||||||
notInRepo :: Repo -> FilePath -> IO [FilePath]
|
notInRepo :: Repo -> FilePath -> IO [FilePath]
|
||||||
notInRepo repo l = pipeNullSplit repo
|
notInRepo repo l = pipeNullSplit repo
|
||||||
["ls-files", "--others", "--exclude-standard", "-z", l]
|
["ls-files", "--others", "--exclude-standard", "-z", "--", l]
|
||||||
|
|
||||||
{- Passed a location, returns a list of the files, staged for
|
{- Passed a location, returns a list of the files, staged for
|
||||||
- commit, that are being added, moved, or changed (but not deleted). -}
|
- commit, that are being added, moved, or changed (but not deleted). -}
|
||||||
stagedFiles :: Repo -> FilePath -> IO [FilePath]
|
stagedFiles :: Repo -> FilePath -> IO [FilePath]
|
||||||
stagedFiles repo l = pipeNullSplit repo
|
stagedFiles repo l = pipeNullSplit repo
|
||||||
["diff", "--cached", "--name-only", "--diff-filter=ACMRT", "-z",
|
["diff", "--cached", "--name-only", "--diff-filter=ACMRT", "-z",
|
||||||
"HEAD", l]
|
"--", l]
|
||||||
|
|
||||||
|
{- Passed a location, returns a list of the files whose type has changed. -}
|
||||||
|
typeChangedFiles :: Repo -> FilePath -> IO [FilePath]
|
||||||
|
typeChangedFiles repo l = do
|
||||||
|
changed <- pipeNullSplit repo $ start ++ end
|
||||||
|
changedCached <- pipeNullSplit repo $ start ++ ["--cached"] ++ end
|
||||||
|
-- a file can be found twice by the above, so nub
|
||||||
|
return $ nub $ changed ++ changedCached
|
||||||
|
where
|
||||||
|
start = ["diff", "--name-only", "--diff-filter=T", "-z"]
|
||||||
|
end = ["--", l]
|
||||||
|
|
||||||
{- Reads null terminated output of a git command (as enabled by the -z
|
{- Reads null terminated output of a git command (as enabled by the -z
|
||||||
- parameter), and splits it into a list of files. -}
|
- parameter), and splits it into a list of files. -}
|
||||||
|
|
11
Makefile
11
Makefile
|
@ -1,8 +1,10 @@
|
||||||
all: git-annex docs
|
all: git-annex docs
|
||||||
|
|
||||||
|
ghcmake=ghc -Wall -odir build -hidir build --make
|
||||||
|
|
||||||
git-annex:
|
git-annex:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
ghc -Wall -odir build -hidir build --make git-annex
|
$(ghcmake) git-annex
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -d $(DESTDIR)/usr/bin
|
install -d $(DESTDIR)/usr/bin
|
||||||
|
@ -17,7 +19,8 @@ IKIWIKI=ikiwiki
|
||||||
endif
|
endif
|
||||||
|
|
||||||
test:
|
test:
|
||||||
runghc test.hs
|
$(ghcmake) test
|
||||||
|
./test
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
./mdwn2man git-annex 1 doc/git-annex.mdwn > git-annex.1
|
./mdwn2man git-annex 1 doc/git-annex.mdwn > git-annex.1
|
||||||
|
@ -27,7 +30,7 @@ docs:
|
||||||
--disable-plugin=smiley
|
--disable-plugin=smiley
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build git-annex git-annex.1
|
rm -rf build git-annex git-annex.1 test
|
||||||
rm -rf doc/.ikiwiki html
|
rm -rf doc/.ikiwiki html
|
||||||
|
|
||||||
.PHONY: git-annex
|
.PHONY: git-annex test
|
||||||
|
|
10
debian/changelog
vendored
10
debian/changelog
vendored
|
@ -1,5 +1,12 @@
|
||||||
git-annex (0.04) UNRELEASED; urgency=low
|
git-annex (0.04) UNRELEASED; urgency=low
|
||||||
|
|
||||||
|
* Add unlock subcommand, which replaces the symlink with a copy of
|
||||||
|
the file's content in preparation of changing it. The "edit" subcommand
|
||||||
|
is an alias for unlock.
|
||||||
|
* Add lock subcommand.
|
||||||
|
* Unlocked files will now automatically be added back into the annex when
|
||||||
|
committed (and the updated symlink committed), by some magic in the
|
||||||
|
pre-commit hook.
|
||||||
* Add build dep on libghc6-testpack-dev.
|
* Add build dep on libghc6-testpack-dev.
|
||||||
* Add annex.version, which will be used to automate upgrades
|
* Add annex.version, which will be used to automate upgrades
|
||||||
between incompatable versions.
|
between incompatable versions.
|
||||||
|
@ -11,6 +18,9 @@ git-annex (0.04) UNRELEASED; urgency=low
|
||||||
* Annexed file contents are now made unwritable and put in unwriteable
|
* Annexed file contents are now made unwritable and put in unwriteable
|
||||||
directories, to avoid them accidentially being removed or modified.
|
directories, to avoid them accidentially being removed or modified.
|
||||||
(Thanks Josh Triplett for the idea.)
|
(Thanks Josh Triplett for the idea.)
|
||||||
|
* Avoid using runghc to run test suite as it is not available on all
|
||||||
|
architectures. Closes: #603006
|
||||||
|
* Missing build dep. Closes: #603016
|
||||||
|
|
||||||
-- Joey Hess <joeyh@debian.org> Mon, 08 Nov 2010 12:36:39 -0400
|
-- Joey Hess <joeyh@debian.org> Mon, 08 Nov 2010 12:36:39 -0400
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ can use different backends for different files.
|
||||||
* `SHA1` -- This backend stores the file's content in
|
* `SHA1` -- This backend stores the file's content in
|
||||||
`.git/annex/objects/`, with a name based on its sha1 checksum. This backend
|
`.git/annex/objects/`, with a name based on its sha1 checksum. This backend
|
||||||
allows modifications of files to be tracked. Its need to generate checksums
|
allows modifications of files to be tracked. Its need to generate checksums
|
||||||
can make it slower for large files. **Warning** this backend is not ready
|
can make it slower for large files.
|
||||||
for use.
|
for use.
|
||||||
* `URL` -- This backend downloads the file's content from an external URL.
|
* `URL` -- This backend downloads the file's content from an external URL.
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,19 @@ Many git-annex subcommands will stage changes for later `git commit` by you.
|
||||||
git-annex may refuse to drop content if the backend does not think
|
git-annex may refuse to drop content if the backend does not think
|
||||||
it is safe to do so, typically because of the setting of annex.numcopies.
|
it is safe to do so, typically because of the setting of annex.numcopies.
|
||||||
|
|
||||||
|
* unlock [path ...]
|
||||||
|
|
||||||
|
Normally, the content of annexed files is protected from being changed.
|
||||||
|
Unlocking a 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.
|
||||||
|
|
||||||
|
* edit [path ...]
|
||||||
|
|
||||||
|
This is an alias for the unlock subcommand. May be easier to remember,
|
||||||
|
if you think of this as allowing you to edit an annexed file.
|
||||||
|
|
||||||
* move [path ...]
|
* move [path ...]
|
||||||
|
|
||||||
When used with the --to option, moves the content of annexed files from
|
When used with the --to option, moves the content of annexed files from
|
||||||
|
@ -93,7 +106,11 @@ Many git-annex subcommands will stage changes for later `git commit` by you.
|
||||||
|
|
||||||
Initializes git-annex with a description of the git repository,
|
Initializes git-annex with a description of the git repository,
|
||||||
and sets up `.gitattributes` and the pre-commit hook.
|
and sets up `.gitattributes` and the pre-commit hook.
|
||||||
This is an optional, but recommended step.
|
|
||||||
|
* lock [path ...]
|
||||||
|
|
||||||
|
Use this to undo an unlock command if you don't want to modify
|
||||||
|
the files, or have made modifications you want to discard.
|
||||||
|
|
||||||
* unannex [path ...]
|
* unannex [path ...]
|
||||||
|
|
||||||
|
@ -110,7 +127,8 @@ Many git-annex subcommands will stage changes for later `git commit` by you.
|
||||||
* pre-commit [path ...]
|
* pre-commit [path ...]
|
||||||
|
|
||||||
Fixes up symlinks that are staged as part of a commit, to ensure they
|
Fixes up symlinks that are staged as part of a commit, to ensure they
|
||||||
point to annexed content.
|
point to annexed content. Also handles injecting changes to unlocked
|
||||||
|
files into the annex.
|
||||||
|
|
||||||
This is meant to be called from git's pre-commit hook. `git annex init`
|
This is meant to be called from git's pre-commit hook. `git annex init`
|
||||||
automatically creates a pre-commit hook using this.
|
automatically creates a pre-commit hook using this.
|
||||||
|
|
|
@ -3,3 +3,5 @@ This backend is not finished.
|
||||||
In particular, while files can be added using it, git-annex will not notice
|
In particular, while files can be added using it, git-annex will not notice
|
||||||
when their content changes, and will not create a new key for the new sha1
|
when their content changes, and will not create a new key for the new sha1
|
||||||
of the net content.
|
of the net content.
|
||||||
|
|
||||||
|
[[done]]; use unlock subcommand and commit changes with git
|
||||||
|
|
|
@ -3,3 +3,21 @@ file's content, with a copy of the file. Once you've checked a file out,
|
||||||
you can edit it, and `git commit` it. On commit, git-annex will detect
|
you can edit it, and `git commit` it. On commit, git-annex will detect
|
||||||
if the file has been changed, and if it has, `add` its content to the
|
if the file has been changed, and if it has, `add` its content to the
|
||||||
annex.
|
annex.
|
||||||
|
|
||||||
|
> Internally, this will need to store the original symlink to the file, in
|
||||||
|
> `.git/annex/checkedout/$filename`.
|
||||||
|
>
|
||||||
|
> * git-annex uncheckout moves that back
|
||||||
|
> * git-annex pre-commit hook checks each file being committed to see if
|
||||||
|
> it has a symlink there, and if so, removes the symlink and adds the new
|
||||||
|
> content to the annex.
|
||||||
|
>
|
||||||
|
> And it seems the file content should be copied, not moved or hard linked:
|
||||||
|
>
|
||||||
|
> * Makes sure other annexes can find it if transferring it from
|
||||||
|
> this annex.
|
||||||
|
> * Ensures it's always available for uncheckout.
|
||||||
|
> * Avoids the last copy of a file's content being lost when
|
||||||
|
> the checked out file is modified.
|
||||||
|
|
||||||
|
[[done]]
|
||||||
|
|
|
@ -139,6 +139,50 @@ But `other.iso` looks to have never been copied to anywhere else, so if
|
||||||
it's something you want to hold onto, you'd need to transfer it to
|
it's something you want to hold onto, you'd need to transfer it to
|
||||||
some other repository before dropping it.
|
some other repository before dropping it.
|
||||||
|
|
||||||
|
## modifying annexed files
|
||||||
|
|
||||||
|
Normally, the content of files in the annex is prevented from being modified.
|
||||||
|
|
||||||
|
# echo oops > my_cool_big_file
|
||||||
|
bash: my_cool_big_file: Permission deined
|
||||||
|
|
||||||
|
In order to modify a file, it should first be unlocked.
|
||||||
|
|
||||||
|
# git annex unlock my_cool_big_file
|
||||||
|
unlock my_cool_big_file (copying...) ok
|
||||||
|
|
||||||
|
They replaces the symlink that normally points at its content with a copy
|
||||||
|
of the content. You can then modify the file like any regular file. Because
|
||||||
|
it is a regular file.
|
||||||
|
|
||||||
|
If you decide you don't need to modify the file after all, or want to discard
|
||||||
|
modifications, just use `git annex lock`.
|
||||||
|
|
||||||
|
When you `git commit`, git-annex's pre-commit hook will automatically
|
||||||
|
notice that you are committing an unlocked file, and add its new content
|
||||||
|
to the annex. The file will be replaced with a symlink to the new content,
|
||||||
|
and this symlink is what gets committed to git in the end.
|
||||||
|
|
||||||
|
# echo "now smaller, but even cooler" > my_cool_big_file
|
||||||
|
# git commit my_cool_big_file -m "changed an annexed file"
|
||||||
|
add my_cool_big_file ok
|
||||||
|
[master 64cda67] changed an annexed file
|
||||||
|
2 files changed, 2 insertions(+), 1 deletions(-)
|
||||||
|
create mode 100644 .git-annex/SHA1:0b1d8616d0238cb9418a0e0a649bdad2e9e7faae.log
|
||||||
|
|
||||||
|
There is one problem with using `git commit` like this: Git wants to first
|
||||||
|
stage the entire contents of the file in its index. That can be slow for
|
||||||
|
big files (sorta why git-annex exists in the first place). So, the
|
||||||
|
automatic handling on commit is a nice safety feature, since it prevents
|
||||||
|
the file content being accidentially commited into git. But when working with
|
||||||
|
big files, it's faster to explicitly add them to the annex yourself
|
||||||
|
before committing.
|
||||||
|
|
||||||
|
# echo "now smaller, but even cooler yet" > my_cool_big_file
|
||||||
|
# git annex add my_cool_big_file
|
||||||
|
add my_cool_big_file ok
|
||||||
|
# git commit my_cool_big_file -m "changed an annexed file"
|
||||||
|
|
||||||
## using ssh remotes
|
## using ssh remotes
|
||||||
|
|
||||||
So far in this walkthrough, git-annex has been used with a remote
|
So far in this walkthrough, git-annex has been used with a remote
|
||||||
|
@ -216,3 +260,17 @@ that the URL is stable; no local backup is kept.
|
||||||
|
|
||||||
# git annex drop somefile
|
# git annex drop somefile
|
||||||
drop somefile (ok)
|
drop somefile (ok)
|
||||||
|
|
||||||
|
## using the SHA1 backend
|
||||||
|
|
||||||
|
Another handy alternative to the default [[backend|backends]] is the
|
||||||
|
SHA1 backend. This backend provides more git-style assurance that your data
|
||||||
|
has not been damanged. And the checksum means that when you add the same
|
||||||
|
content to the annex twice, only one copy need be stored in the backend.
|
||||||
|
|
||||||
|
The only reason it's not the default is that it needs to checksum
|
||||||
|
files when they're added to the annex, and this can slow things down
|
||||||
|
significantly for really big files. To make SHA1 the detault, just
|
||||||
|
add something like this to `.gitattributes`:
|
||||||
|
|
||||||
|
* git-annex-backend=SHA1
|
||||||
|
|
3
test.hs
3
test.hs
|
@ -1,15 +1,16 @@
|
||||||
-- TODO find a test harness that is actually in Debian and use it.
|
-- TODO find a test harness that is actually in Debian and use it.
|
||||||
|
|
||||||
import Test.QuickCheck
|
|
||||||
import Test.HUnit
|
import Test.HUnit
|
||||||
import Test.HUnit.Tools
|
import Test.HUnit.Tools
|
||||||
|
|
||||||
import GitRepo
|
import GitRepo
|
||||||
import Locations
|
import Locations
|
||||||
|
|
||||||
|
alltests :: [Test]
|
||||||
alltests = [
|
alltests = [
|
||||||
qctest "prop_idempotent_deencode" prop_idempotent_deencode,
|
qctest "prop_idempotent_deencode" prop_idempotent_deencode,
|
||||||
qctest "prop_idempotent_fileKey" prop_idempotent_fileKey
|
qctest "prop_idempotent_fileKey" prop_idempotent_fileKey
|
||||||
]
|
]
|
||||||
|
|
||||||
|
main :: IO (Counts, Int)
|
||||||
main = runVerboseTests (TestList alltests)
|
main = runVerboseTests (TestList alltests)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue