reinject: Added new mode which can reinject known files into the annex.

For example: git-annex reinject --known /mnt/backup/*
This commit is contained in:
Joey Hess 2016-04-22 13:49:32 -04:00
parent f9f2576203
commit 8ab27235ea
Failed to extract signature
5 changed files with 101 additions and 26 deletions

View file

@ -104,3 +104,5 @@ paramOptional :: String -> String
paramOptional s = s
paramPair :: String -> String -> String
paramPair a b = a ++ " " ++ b
paramOr :: String -> String -> String
paramOr a b = a ++ " | " ++ b

View file

@ -1,6 +1,6 @@
{- git-annex command
-
- Copyright 2011 Joey Hess <id@joeyh.name>
- Copyright 2011-2016 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@ -10,30 +10,63 @@ module Command.Reinject where
import Command
import Logs.Location
import Annex.Content
import Backend
import Types.KeySource
cmd :: Command
cmd = command "reinject" SectionUtility
"sets content of annexed file"
(paramPair "SRC" "DEST") (withParams seek)
"inject content of file back into annex"
(paramRepeating (paramPair "SRC" "DEST")
`paramOr` "--known " ++ paramRepeating "SRC")
(seek <$$> optParser)
seek :: CmdParams -> CommandSeek
seek = withWords start
data ReinjectOptions = ReinjectOptions
{ params :: CmdParams
, knownOpt :: Bool
}
start :: [FilePath] -> CommandStart
start (src:dest:[])
optParser :: CmdParamsDesc -> Parser ReinjectOptions
optParser desc = ReinjectOptions
<$> cmdParams desc
<*> switch
( long "known"
<> help "inject all known files"
<> hidden
)
seek :: ReinjectOptions -> CommandSeek
seek os
| knownOpt os = withStrings startKnown (params os)
| otherwise = withWords startSrcDest (params os)
startSrcDest :: [FilePath] -> CommandStart
startSrcDest (src:dest:[])
| src == dest = stop
| otherwise =
ifAnnexed src
(error $ "cannot used annexed file as src: " ++ src)
go
where
go = do
| otherwise = notAnnexed src $ do
showStart "reinject" dest
next $ whenAnnexed (perform src) dest
start _ = error "specify a src file and a dest file"
next $ ifAnnexed dest
(perform src)
stop
startSrcDest _ = error "specify a src file and a dest file"
perform :: FilePath -> FilePath -> Key -> CommandPerform
perform src _dest key = ifM move
startKnown :: FilePath -> CommandStart
startKnown src = notAnnexed src $ do
showStart "reinject" src
mkb <- genKey (KeySource src src Nothing) Nothing
case mkb of
Nothing -> error "Failed to generate key"
Just (key, _) -> ifM (isKnownKey key)
( next $ perform src key
, do
warning "Not known content; skipping"
next $ next $ return True
)
notAnnexed :: FilePath -> CommandStart -> CommandStart
notAnnexed src = ifAnnexed src (error $ "cannot used annexed file as src: " ++ src)
perform :: FilePath -> Key -> CommandPerform
perform src key = ifM move
( next $ cleanup key
, error "failed"
)

View file

@ -19,6 +19,7 @@ module Logs.Location (
logChange,
loggedLocations,
loggedLocationsHistorical,
isKnownKey,
checkDead,
setDead,
loggedKeys,
@ -65,6 +66,13 @@ getLoggedLocations getter key = do
config <- Annex.getGitConfig
map toUUID <$> getter (locationLogFile config key)
{- Is there a location log for the key? True even for keys with no
- remaining locations. -}
isKnownKey :: Key -> Annex Bool
isKnownKey key = do
config <- Annex.getGitConfig
not . null <$> readLog (locationLogFile config key)
{- For a key to be dead, all locations that have location status for the key
- must have InfoDead set. -}
checkDead :: Key -> Annex Bool

View file

@ -1,32 +1,62 @@
# NAME
git-annex reinject - sets content of annexed file
git-annex reinject - inject content of file back into annex
# SYNOPSIS
git annex reinject `src dest`
git annex reinject `[src dest]`
git annex reinject --known `[src]`
# DESCRIPTION
Moves the src file into the annex as the content of the dest file,
which should be an already annexed file whose content is not present.
Moves the content of the src file or files into the annex.
Only known file contents will be reinjected. Any unknown src files will
be left unchanged.
This can be useful if you have obtained the content of a file from
elsewhere and want to put it in the local annex.
elsewhere and want to put it in the local annex. For example, if a file's
content has been lost and you have a backup, you can restore the backup and
reinject it into your local repository.
Verifies that the src file's content matches with the content that the dest
file is expected to have, and refuses to reinject it otherwise.
Example:
There are two ways to use this command. Specifying a src file and the name
of a dest file (located inside the repository's working tree)
injects the src file as the content of the dest file.
git annex reinject /tmp/foo.iso foo.iso
Or the `--known` option can be used to reinject all known src files, without
needing to specify the dest file.
git annex reinject --known /tmp/*.iso
# OPTIONS
* `--known`
With this option, each specified src file is hashed using the default
key-value backend (or the one specified with `--backend`), and if git-annex
has a record of the file having been in the annex before, the content is
reinjected.
Note that this will reinject old versions of files that have been
modified or deleted from the current git branch.
Use [[git-annex-unused]](1) to detect when such old and potentially
unused files have been reinjected.
* `--backend`
Specify the key-value backend to use when checking if a file is known
with the `--known` option.
# SEE ALSO
[[git-annex]](1)
[[git-annex-add]](1)
[[git-annex-unused]](1)
[[git-annex-fsck]](1)
# AUTHOR

View file

@ -3,3 +3,5 @@ There's `git annex reinject <src> <dst>` for re-adding one file's contents to th
None of the `git annex import` modes work properly in this case. By default, importing adds another, unnecessary copy of the imported file (which I have to `rm` after importing). The `--clean-duplicates` mode seems close, but it insists on verifying the content in other repositories rather than just reinjecting it locally. (Let's assume that the main reason I'm trying to reinject is that I cannot access other repos.)
So I'm hoping for something like `git annex import --reinject <src>...`. Or are there other existing ways to achieve the same? I couldn't find any.
> implemented `git annex reinject --known` [[done]] --[[Joey]]