From 7bc8c2bfebab6d67071219bd1f31d95163d44e8a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 23 Sep 2024 13:09:35 -0400 Subject: [PATCH] sim visit as first-class command Allows using it in a sim file. --- Annex/Sim.hs | 32 +++++++++++++++++++++++++++++++- Annex/Sim/File.hs | 4 ++++ Command/Sim.hs | 23 ----------------------- doc/git-annex-sim.mdwn | 23 +++++++++++++---------- 4 files changed, 48 insertions(+), 34 deletions(-) diff --git a/Annex/Sim.hs b/Annex/Sim.hs index 988fc2a825..7e2f6a8071 100644 --- a/Annex/Sim.hs +++ b/Annex/Sim.hs @@ -35,6 +35,7 @@ import Logs.MaxSize import Logs.Difference import Logs.UUID import Logs.Location +import Utility.Env import qualified Annex import qualified Remote import qualified Git.Construct @@ -222,6 +223,7 @@ data SimCommand | CommandGroupWanted Group PreferredContentExpression | CommandMaxSize RepoName MaxSize | CommandRebalance Bool + | CommandVisit RepoName [String] | CommandComment String | CommandBlank deriving (Show, Read) @@ -278,6 +280,32 @@ applySimCommand (CommandNotPresent repo file) st _ = checkKnownRepo repo st $ \u present = Left $ "Expected " ++ fromRawFilePath file ++ " not to be present in " ++ fromRepoName repo ++ ", but it is present." +applySimCommand c@(CommandVisit repo cmdparams) st _ = + checkKnownRepo repo st $ \u -> Right $ Left $ do + st' <- liftIO $ updateSimRepos st + let dir = simRepoDirectory st' u + unlessM (liftIO $ doesDirectoryExist dir) $ + giveup "Simulated repository unavailable." + (cmd, params) <- case cmdparams of + (cmd:params) -> return (cmd, params) + [] -> do + showLongNote "Starting a shell in the simulated repository." + shellcmd <- liftIO $ fromMaybe "sh" <$> getEnv "SHELL" + return (shellcmd, []) + exitcode <- liftIO $ + safeSystem' cmd (map Param params) + (\p -> p { cwd = Just dir }) + when (null cmdparams) $ + showLongNote "Finished visit to simulated repository." + if null cmdparams + then return st' + else if exitcode == ExitSuccess + then return $ addHistory st' c + else do + showLongNote $ UnquotedString $ + "Command " ++ unwords cmdparams ++ + " exited nonzero." + liftIO $ exitWith exitcode applySimCommand cmd st repobyname = let st' = flip addHistory cmd $ st { simVectorClock = @@ -455,6 +483,7 @@ applySimCommand' (CommandRebalance b) st _ = } applySimCommand' (CommandComment _) st _ = Right $ Right st applySimCommand' CommandBlank st _ = Right $ Right st +applySimCommand' (CommandVisit _ _) _ _ = error "applySimCommand' CommandVisit" applySimCommand' (CommandPresent _ _) _ _ = error "applySimCommand' CommandPresent" applySimCommand' (CommandNotPresent _ _) _ _ = error "applySimCommand' CommandNotPresent" @@ -716,7 +745,8 @@ checkKnownRepo :: RepoName -> SimState SimRepo -> (UUID -> Either String a) -> E checkKnownRepo reponame st a = case M.lookup reponame (simRepos st) of Just u -> a u Nothing -> Left $ "No repository in the simulation is named \"" - ++ fromRepoName reponame ++ "\"." + ++ fromRepoName reponame ++ "\". Choose from: " + ++ unwords (map fromRepoName $ M.keys (simRepos st)) checkKnownRemote :: RemoteName -> RepoName -> UUID -> SimState SimRepo -> (UUID -> Either String a) -> Either String a checkKnownRemote remotename reponame u st a = diff --git a/Annex/Sim/File.hs b/Annex/Sim/File.hs index eee9f4d955..9362713c94 100644 --- a/Annex/Sim/File.hs +++ b/Annex/Sim/File.hs @@ -80,6 +80,8 @@ generateSimFile = unlines . map unwords . go ["maxsize", repo, showsize (fromMaxSize maxsize)] : go rest go (CommandRebalance b : rest) = ["rebalance", if b then "on" else "off"] : go rest + go (CommandVisit (RepoName repo) cmdparams : rest) = + (["visit", repo] ++ cmdparams) : go rest go (CommandComment s : rest) = [s] : go rest go (CommandBlank : rest) = @@ -184,6 +186,8 @@ parseSimCommand ("maxsize":repo:size:[]) = parseSimCommand ("rebalance":onoff:[]) = case isTrueFalse onoff of Just b -> Right $ CommandRebalance b Nothing -> Left $ "Unable to parse rebalance value \"" ++ onoff ++ "\"" +parseSimCommand ("visit":repo:cmdparams) = + Right $ CommandVisit (RepoName repo) cmdparams parseSimCommand ws = parseError ws parseSimAction :: [String] -> Either String SimAction diff --git a/Command/Sim.hs b/Command/Sim.hs index b0c60d83f1..d184d3a3b5 100644 --- a/Command/Sim.hs +++ b/Command/Sim.hs @@ -13,10 +13,8 @@ import Command import Annex.Sim import Annex.Sim.File import Annex.Perms -import Utility.Env import System.Random -import qualified Data.Map as M cmd :: Command cmd = command "sim" SectionTesting @@ -31,27 +29,6 @@ seek ("end":[]) = do whenM (liftIO $ doesDirectoryExist simdir) $ do liftIO $ removeDirectoryRecursive simdir showLongNote $ UnquotedString "Sim ended." -seek ("visit":reponame:[]) = do - simdir <- fromRepo gitAnnexSimDir - liftIO (restoreSim simdir) >>= \case - Left err -> giveup err - Right st -> case M.lookup (RepoName reponame) (simRepos st) of - Just u -> do - let dir = simRepoDirectory st u - unlessM (liftIO $ doesDirectoryExist dir) $ - giveup "Simulated repository unavailable." - showLongNote "Starting a shell in the simulated repository." - shellcmd <- liftIO $ fromMaybe "sh" <$> getEnv "SHELL" - exitcode <- liftIO $ - safeSystem' shellcmd [] - (\p -> p { cwd = Just dir }) - showLongNote "Finished visit to simulated repository." - liftIO $ exitWith exitcode - Nothing -> giveup $ unwords - [ "There is no simulated repository with that name." - , "Choose from:" - , unwords $ map fromRepoName $ M.keys (simRepos st) - ] seek ("show":[]) = do simdir <- fromRepo gitAnnexSimDir liftIO (restoreSim simdir) >>= \case diff --git a/doc/git-annex-sim.mdwn b/doc/git-annex-sim.mdwn index 602a9ff0aa..5888e8286a 100644 --- a/doc/git-annex-sim.mdwn +++ b/doc/git-annex-sim.mdwn @@ -8,8 +8,6 @@ git annex sim start [my.sim] git annex sim command -git annex sim visit repo - git annex sim show git annex sim end @@ -32,14 +30,6 @@ simulation, and the results of the simulation. Use "git-annex sim show" to display the log. This allows re-running the same simulation later, as well as analyzing the results of the simulation. -While a simulation is running, the command "git annex sim visit repo", where -"repo" is the name of one of the repositories in the simulation, will spawn -a subshell in a git repository whose git-annex branch contains the state of -that simulated repository. This allows running any git-annex command, such -as `git-annex whereis` to examine the state of the simulation. -You should avoid making any changes to git-annex state. -Exit the subshell to end the visit. - Use "git annex sim end" to finish the simulation, and clean up. # THE SIM FILE @@ -109,6 +99,19 @@ as passed to "git annex sim" while a simulation is running. The repository to use can be specified by remote name, uuid, etc. Example: "use myrepo here" +* `visit repo [command]` + + Runs the specified shell command inside the simulated repository, + and waits for it to exit. + + When no shell command is specified, it runs an interactive shell. + + The command is run in a git repository whosegit-annex branch contains + the state of that simulated repository. This allows running any + git-annex commands, such as `git-annex whereis` to examine the + state of the simulation. You should avoid making any changes to + git-annex state. + * `connect repo [<-|->|<->] repo [...]` Add a connection between two or more repositories. The arrow indicates