diff options
author | Joey Hess <joey@kitenet.net> | 2010-10-25 18:32:29 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2010-10-25 18:32:29 -0400 |
commit | d0a9cdadafca1ee0da100a993b23e8a063f86bf8 (patch) | |
tree | 46d6955950bafc004fdc47c3db499e5e2a4849fb | |
parent | 8beed17168aab12bb4045b6d8635b37503d5099b (diff) |
add dropkey subcommand and --quiet
Needed for better git annex move --from
-rw-r--r-- | Commands.hs | 51 | ||||
-rw-r--r-- | Core.hs | 14 | ||||
-rw-r--r-- | GitRepo.hs | 2 | ||||
-rw-r--r-- | Remotes.hs | 54 | ||||
-rw-r--r-- | TypeInternals.hs | 9 | ||||
-rw-r--r-- | Types.hs | 1 | ||||
-rw-r--r-- | doc/git-annex.mdwn | 12 |
7 files changed, 87 insertions, 56 deletions
diff --git a/Commands.hs b/Commands.hs index cf0516463..2b8da585e 100644 --- a/Commands.hs +++ b/Commands.hs @@ -61,7 +61,8 @@ doSubCmd cmdname start param = do {- A subcommand can broadly want one of several kinds of input parameters. - This allows a first stage of filtering before starting a subcommand. -} -data SubCmdWants = FilesInGit | FilesNotInGit | FilesMissing | Description +data SubCmdWants = FilesInGit | FilesNotInGit | FilesMissing + | Description | Keys data SubCommand = Command { subcmdname :: String, @@ -87,6 +88,8 @@ subCmds = [ "fix up files' symlinks to point to annexed content") , (Command "fromkey" fromKeyStart FilesMissing "adds a file using a specific key") + , (Command "dropkey" fromKeyStart Keys + "drops cached content for specified keys") ] -- Each dashed command-line option results in generation of an action @@ -95,6 +98,8 @@ options :: [OptDescr (Annex ())] options = [ Option ['f'] ["force"] (NoArg (storebool "force" True)) "allow actions that may lose annexed data" + , Option ['q'] ["quiet"] (NoArg (storebool "quiet" True)) + "avoid verbose output" , Option ['b'] ["backend"] (ReqArg (storestring "backend") "NAME") "specify default key-value backend to use" , Option ['k'] ["key"] (ReqArg (storestring "key") "KEY") @@ -127,6 +132,7 @@ usage = usageInfo header options ++ "\nSubcommands:\n" ++ cmddescs {- Generate descriptions of wanted parameters for subcommands. -} descWanted :: SubCmdWants -> String descWanted Description = "DESCRIPTION" +descWanted Keys = "KEY ..." descWanted _ = "PATH ..." {- Finds the type of parameters a subcommand wants, from among the passed @@ -147,6 +153,7 @@ findWanted FilesMissing params repo = do if (e) then return False else return True findWanted Description params _ = do return $ [unwords params] +findWanted Keys params _ = return params {- Parses command line and returns two lists of actions to be - run in the Annex monad. The first actions configure it @@ -243,9 +250,9 @@ dropStart file = isAnnexed file $ \(key, backend) -> do inbackend <- Backend.hasKey key if (not inbackend) then return Nothing - else return $ Just $ dropPerform file key backend -dropPerform :: FilePath -> Key -> Backend -> Annex (Maybe SubCmdCleanup) -dropPerform file key backend = do + else return $ Just $ dropPerform key backend +dropPerform :: Key -> Backend -> Annex (Maybe SubCmdCleanup) +dropPerform key backend = do success <- Backend.removeKey backend key if (success) then return $ Just $ dropCleanup key @@ -262,6 +269,29 @@ dropCleanup key = do return True else return True +{- Drops cached content for a key. -} +dropKeyStart :: String -> Annex (Maybe SubCmdPerform) +dropKeyStart keyname = do + backends <- Backend.list + let key = genKey (backends !! 0) keyname + present <- inAnnex key + force <- Annex.flagIsSet "force" + if (not present) + then return Nothing + else if (not force) + then error "dropkey is can cause data loss; use --force if you're sure you want to do this" + else return $ Just $ dropKeyPerform key +dropKeyPerform :: Key -> Annex (Maybe SubCmdCleanup) +dropKeyPerform key = do + g <- Annex.gitRepo + let loc = annexLocation g key + liftIO $ removeFile loc + return $ Just $ dropKeyCleanup key +dropKeyCleanup :: Key -> Annex Bool +dropKeyCleanup key = do + logStatus key ValueMissing + return True + {- Fixes the symlink to an annexed file. -} fixStart :: FilePath -> Annex (Maybe SubCmdPerform) fixStart file = isAnnexed file $ \(key, backend) -> do @@ -423,11 +453,14 @@ moveFromPerform file key = do return $ Just $ moveFromCleanup remote key moveFromCleanup :: Git.Repo -> Key -> Annex Bool moveFromCleanup remote key = do - Remotes.removeRemoteFile remote $ annexLocation remote key - -- Record that the key is not on the remote. - u <- getUUID remote - liftIO $ logChange remote key u ValueMissing - Remotes.updateRemoteLogStatus remote key + -- Force drop content from the remote. + Remotes.runCmd remote "git-annex" ["dropkey", "--quiet", "--force", + "--backend=" ++ (backendName key), + keyName key] + -- Record locally that the key is not on the remote. + remoteuuid <- getUUID remote + g <- Annex.gitRepo + liftIO $ logChange g key remoteuuid ValueMissing return True -- helpers @@ -115,22 +115,26 @@ getViaTmp key action = do return False {- Output logging -} +verbose :: Annex () -> Annex () +verbose a = do + q <- Annex.flagIsSet "quiet" + if (q) then return () else a showStart :: String -> String -> Annex () -showStart command file = do +showStart command file = verbose $ do liftIO $ putStr $ command ++ " " ++ file ++ " " liftIO $ hFlush stdout showNote :: String -> Annex () -showNote s = do +showNote s = verbose $ do liftIO $ putStr $ "(" ++ s ++ ") " liftIO $ hFlush stdout showLongNote :: String -> Annex () -showLongNote s = do +showLongNote s = verbose $ do liftIO $ putStr $ "\n" ++ (indent s) where indent s = join "\n" $ map (\l -> " " ++ l) $ lines s showEndOk :: Annex () -showEndOk = do +showEndOk = verbose $ do liftIO $ putStrLn "ok" showEndFail :: Annex () -showEndFail = do +showEndFail = verbose $ do liftIO $ putStrLn "\nfailed" diff --git a/GitRepo.hs b/GitRepo.hs index 553e91fec..ee1bdba34 100644 --- a/GitRepo.hs +++ b/GitRepo.hs @@ -156,7 +156,7 @@ workTree repo = - name to use to refer to the file relative to a git repository's top. - This is the same form displayed and used by git. -} relative :: Repo -> String -> String -relative repo file = drop (length absrepo) absfile +relative repo file = assertLocal repo $ drop (length absrepo) absfile where -- normalize both repo and file, so that repo -- will be substring of file diff --git a/Remotes.hs b/Remotes.hs index c9c65babe..985199e1c 100644 --- a/Remotes.hs +++ b/Remotes.hs @@ -8,11 +8,11 @@ module Remotes ( commandLineRemote, copyFromRemote, copyToRemote, - removeRemoteFile, - updateRemoteLogStatus + runCmd ) where -import Control.Exception +import IO (bracket_) +import Control.Exception hiding (bracket_) import Control.Monad.State (liftIO) import Control.Monad (filterM) import qualified Data.Map as Map @@ -20,9 +20,9 @@ import Data.String.Utils import Data.Either.Utils import System.Cmd.Utils import System.Directory +import System.Posix.Directory import List import Maybe -import IO (hPutStrLn) import Types import qualified GitRepo as Git @@ -221,39 +221,19 @@ copyToRemote r key = do sshlocation = (Git.urlHost r) ++ ":" ++ file file = error "TODO" -{- Removes a file from a remote. -} -removeRemoteFile :: Git.Repo -> FilePath -> Annex () -removeRemoteFile r file = do +{- Runs a command in a remote. -} +runCmd :: Git.Repo -> String -> [String] -> Annex Bool +runCmd r command params = do if (not $ Git.repoIsUrl r) - then liftIO $ removeFile file + then do + cwd <- liftIO $ getCurrentDirectory + liftIO $ bracket_ (changeWorkingDirectory (Git.workTree r)) + (\_ -> changeWorkingDirectory cwd) $ + boolSystem command params else if (Git.repoIsSsh r) then do - ok <- liftIO $ boolSystem "ssh" - [Git.urlHost r, "rm -f " ++ - (shellEscape file)] - if (ok) - then return () - else error "failed to remove file from remote" - else error "removing file from non-ssh repo not supported" - -{- Update's a remote's location log for a key, by merging the local - - location log into it. -} -updateRemoteLogStatus :: Git.Repo -> Key -> Annex () -updateRemoteLogStatus r key = do - -- To merge, just append data to the remote's - -- log. Since the log is timestamped, the presumably newer - -- information from the local will superscede the older - -- information in the remote's log. - -- TODO: remote log locking - let mergecmd = "cat >> " ++ (shellEscape $ logFile r key) ++ " && " ++ - "cd " ++ (shellEscape $ Git.workTree r) ++ " && " ++ - "git add " ++ (shellEscape $ stateLoc) - let shellcmd = if (not $ Git.repoIsUrl r) - then pOpen WriteToPipe "sh" ["-c", mergecmd] - else if (Git.repoIsSsh r) - then pOpen WriteToPipe "ssh" [Git.urlHost r, mergecmd] - else error "updating non-ssh repo not supported" - g <- Annex.gitRepo - liftIO $ shellcmd $ \h -> do - lines <- readLog $ logFile g key - hPutStrLn h $ unlines $ map show lines + liftIO $ boolSystem "ssh" [Git.urlHost r, + "cd " ++ (shellEscape $ Git.workTree r) ++ + " && " ++ command ++ " " ++ + unwords params] + else error "running command in non-ssh repo not supported" diff --git a/TypeInternals.hs b/TypeInternals.hs index 6d1c72d2e..188f5e534 100644 --- a/TypeInternals.hs +++ b/TypeInternals.hs @@ -31,12 +31,12 @@ data AnnexState = AnnexState { type Annex = StateT AnnexState IO -- annexed filenames are mapped through a backend into keys -type KeyFrag = String +type KeyName = String type BackendName = String -data Key = Key (BackendName, KeyFrag) deriving (Eq) +data Key = Key (BackendName, KeyName) deriving (Eq) -- constructs a key in a backend -genKey :: Backend -> KeyFrag -> Key +genKey :: Backend -> KeyName -> Key genKey b f = Key (name b,f) -- show a key to convert it to a string; the string includes the @@ -51,9 +51,10 @@ instance Read Key where b = l !! 0 k = join ":" $ drop 1 l --- pulls the backend name out backendName :: Key -> BackendName backendName (Key (b,k)) = b +keyName :: Key -> KeyName +keyName (Key (b,k)) = k -- this structure represents a key-value backend data Backend = Backend { @@ -7,6 +7,7 @@ module Types ( Key, genKey, backendName, + keyName, FlagName, Flag(..) ) where diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn index 522be7570..e7057afee 100644 --- a/doc/git-annex.mdwn +++ b/doc/git-annex.mdwn @@ -116,6 +116,13 @@ Many git-annex subcommands will stage changes for later `git commit` by you. git annex fromkey --backend=URL --key=http://www.archive.org/somefile somefile +* dropkey [key ...] + + Drops the cached data for the specified keys from this repository. + + This can be used to drop content for arbitrary keys, which do not need + to have a file in the git repository pointing at them. + # OPTIONS * --force @@ -123,6 +130,11 @@ Many git-annex subcommands will stage changes for later `git commit` by you. Force unsafe actions, such as dropping a file's content when no other source of it can be verified to still exist. Use with care. +* --quiet + + Avoid the default verbose logging of what is done; only show errors + and progress displays. + * --backend=name Specify the default key-value backend to use, adding it to the front |