{- git-annex command - - Copyright 2014 Joey Hess - - Licensed under the GNU GPL version 3 or higher. -} module Command.MetaData where import Common.Annex import Command import Annex.MetaData import Logs.MetaData import qualified Data.Set as S import Data.Time.Clock.POSIX cmd :: Command cmd = withGlobalOptions ([jsonOption] ++ annexedMatchingOptions) $ command "metadata" SectionMetaData "sets or gets metadata of a file" paramPaths (seek <$$> optParser) data MetaDataOptions = MetaDataOptions { forFiles :: CmdParams , getSet :: GetSet , keyOptions :: Maybe KeyOptions } data GetSet = Get MetaField | Set [ModMeta] optParser :: CmdParamsDesc -> Parser MetaDataOptions optParser desc = MetaDataOptions <$> cmdParams desc <*> ((Get <$> getopt) <|> (Set <$> many modopts)) <*> optional (parseKeyOptions False) where getopt = option (eitherReader mkMetaField) ( long "get" <> short 'g' <> metavar paramField <> help "get single metadata field" ) modopts = option (eitherReader parseModMeta) ( long "set" <> short 's' <> metavar "FIELD[+-]=VALUE" <> help "set or unset metadata value" ) <|> (AddMeta tagMetaField . toMetaValue <$> strOption ( long "tag" <> short 't' <> metavar "TAG" <> help "set a tag" )) <|> (AddMeta tagMetaField . mkMetaValue (CurrentlySet False) <$> strOption ( long "untag" <> short 'u' <> metavar "TAG" <> help "remove a tag" )) seek :: MetaDataOptions -> CommandSeek seek o = do now <- liftIO getPOSIXTime let seeker = case getSet o of Get _ -> withFilesInGit Set _ -> withFilesInGitNonRecursive withKeyOptions (keyOptions o) False (startKeys now o) (seeker $ whenAnnexed $ start now o) (forFiles o) start :: POSIXTime -> MetaDataOptions -> FilePath -> Key -> CommandStart start now o file = start' (Just file) now o startKeys :: POSIXTime -> MetaDataOptions -> Key -> CommandStart startKeys = start' Nothing start' :: AssociatedFile -> POSIXTime -> MetaDataOptions -> Key -> CommandStart start' afile now o k = case getSet o of Set ms -> do showStart' "metadata" k afile next $ perform now ms k Get f -> do l <- S.toList . currentMetaDataValues f <$> getCurrentMetaData k liftIO $ forM_ l $ putStrLn . fromMetaValue stop perform :: POSIXTime -> [ModMeta] -> Key -> CommandPerform perform _ [] k = next $ cleanup k perform now ms k = do oldm <- getCurrentMetaData k let m = combineMetaData $ map (modMeta oldm) ms addMetaData' k m now next $ cleanup k cleanup :: Key -> CommandCleanup cleanup k = do l <- map unwrapmeta . fromMetaData <$> getCurrentMetaData k maybeShowJSON l showLongNote $ unlines $ concatMap showmeta l return True where unwrapmeta (f, v) = (fromMetaField f, map fromMetaValue (S.toList v)) showmeta (f, vs) = map ((f ++ "=") ++) vs