git-annex/Command/Import.hs
Joey Hess b46afa29ac implement import --deduplicate and import --clean-duplicates
Note that --deduplicate currently checksums each file twice,
once to see if it's a known key, and once when importing it.

Perhaps this could be revisited and the extra checksum gotten rid of,
at the cost of not locking down the file when adding it.
2013-08-20 11:00:52 -04:00

104 lines
2.8 KiB
Haskell

{- git-annex command
-
- Copyright 2012-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Command.Import where
import System.PosixCompat.Files
import Common.Annex
import Command
import qualified Annex
import qualified Command.Add
import qualified Option
import Utility.CopyFile
import Backend
import Remote
import Types.KeySource
def :: [Command]
def = [withOptions opts $ notBareRepo $ command "import" paramPaths seek
SectionCommon "move and add files from outside git working copy"]
opts :: [Option]
opts =
[ duplicateOption
, deduplicateOption
, cleanDuplicatesOption
]
duplicateOption :: Option
duplicateOption = Option.flag [] "duplicate" "do not delete outside files"
deduplicateOption :: Option
deduplicateOption = Option.flag [] "deduplicate" "do not add files whose content has been seen"
cleanDuplicatesOption :: Option
cleanDuplicatesOption = Option.flag [] "clean-duplicates" "delete outside duplicate files (import nothing)"
data DuplicateMode = Default | Duplicate | DeDuplicate | CleanDuplicates
deriving (Eq)
getDuplicateMode :: Annex DuplicateMode
getDuplicateMode = gen
<$> getflag duplicateOption
<*> getflag deduplicateOption
<*> getflag cleanDuplicatesOption
where
getflag = Annex.getFlag . Option.name
gen False False False = Default
gen True False False = Duplicate
gen False True False = DeDuplicate
gen False False True = CleanDuplicates
gen _ _ _ = error "bad combination of --duplicate, --deduplicate, --clean-duplicates"
seek :: [CommandSeek]
seek = [withValue getDuplicateMode $ \mode -> withPathContents $ start mode]
start :: DuplicateMode -> (FilePath, FilePath) -> CommandStart
start mode (srcfile, destfile) =
ifM (liftIO $ isRegularFile <$> getSymbolicLinkStatus srcfile)
( do
showStart "import" destfile
next $ perform mode srcfile destfile
, stop
)
perform :: DuplicateMode -> FilePath -> FilePath -> CommandPerform
perform mode srcfile destfile =
case mode of
DeDuplicate -> ifM isdup
( deletedup
, go
)
CleanDuplicates -> ifM isdup
( deletedup
, next $ return True
)
_ -> go
where
isdup = do
backend <- chooseBackend destfile
let ks = KeySource srcfile srcfile Nothing
v <- genKey ks backend
case v of
Just (k, _) -> not . null <$> keyLocations k
_ -> return False
deletedup = do
showNote "duplicate"
liftIO $ removeFile srcfile
next $ return True
go = do
whenM (liftIO $ doesFileExist destfile) $
unlessM (Annex.getState Annex.force) $
error $ "not overwriting existing " ++ destfile ++
" (use --force to override)"
liftIO $ createDirectoryIfMissing True (parentDir destfile)
liftIO $ if mode == Duplicate
then void $ copyFileExternal srcfile destfile
else moveFile srcfile destfile
Command.Add.perform destfile