more work on applySimCommand

When using an existing repo, copy over all of its config into the sim.

Added CommandTrustLevel.

Start at creating a git clone for a simulated repo, but it's not done
yet.
This commit is contained in:
Joey Hess 2024-09-06 12:53:51 -04:00
parent def8095e5f
commit 8d707c4821
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38

View file

@ -9,22 +9,26 @@
module Annex.Sim where module Annex.Sim where
import Annex.Common
import Utility.DataUnits import Utility.DataUnits
import Types.NumCopies import Types.NumCopies
import Types.RepoSize import Types.Group
import Types.Key
import Types.UUID
import Types.StandardGroups import Types.StandardGroups
import Annex (Annex) import Types.TrustLevel
import Git.Types
import Git
import Backend.Hash (genTestKey) import Backend.Hash (genTestKey)
import Annex.UUID import Annex.UUID
import Annex.FileMatcher import Annex.FileMatcher
import Utility.FileSystemEncoding import Logs.Group
import Logs.Trust
import Logs.PreferredContent
import Logs.Remote
import Logs.MaxSize
import qualified Remote import qualified Remote
import System.Random import System.Random
import Data.Word import Data.Word
import Data.Maybe
import qualified Data.Map.Strict as M import qualified Data.Map.Strict as M
import qualified Data.Set as S import qualified Data.Set as S
import qualified Data.ByteString as B import qualified Data.ByteString as B
@ -42,29 +46,29 @@ stepSimulation st = undefined -- XXX TODO
data SimState = SimState data SimState = SimState
{ simRepos :: M.Map RepoName UUID { simRepos :: M.Map RepoName UUID
, simRepoState :: M.Map RepoName SimRepoState , simRepoState :: M.Map RepoName SimRepoState
, simSpecialRemotes :: M.Map RepoName UUID
, simConnections :: M.Map RepoName (S.Set RepoName) , simConnections :: M.Map RepoName (S.Set RepoName)
, simFiles :: M.Map FilePath Key , simFiles :: M.Map FilePath Key
, simRng :: StdGen , simRng :: StdGen
, simTrustLevels :: M.Map RepoName TrustLevel
, simNumCopies :: NumCopies , simNumCopies :: NumCopies
, simGroups :: M.Map RepoName (S.Set GroupName) , simGroups :: M.Map RepoName (S.Set Group)
, simWanted :: M.Map RepoName PreferredContentExpression , simWanted :: M.Map RepoName PreferredContentExpression
, simRequired :: M.Map RepoName PreferredContentExpression , simRequired :: M.Map RepoName PreferredContentExpression
, simGroupWanted :: M.Map GroupName PreferredContentExpression , simGroupWanted :: M.Map Group PreferredContentExpression
, simMaxSize :: M.Map RepoName MaxSize , simMaxSize :: M.Map RepoName MaxSize
, simRebalance :: Bool , simRebalance :: Bool
, simExistingRepoByName :: ExistingRepoByName , simGetExistingRepoByName :: GetExistingRepoByName
} }
deriving (Show) deriving (Show)
emptySimState :: Int -> ExistingRepoByName -> SimState emptySimState :: Int -> GetExistingRepoByName -> SimState
emptySimState rngseed repobyname = SimState emptySimState rngseed repobyname = SimState
{ simRepos = mempty { simRepos = mempty
, simSpecialRemotes = mempty
, simRepoState = mempty , simRepoState = mempty
, simConnections = mempty , simConnections = mempty
, simFiles = mempty , simFiles = mempty
, simRng = mkStdGen rngseed , simRng = mkStdGen rngseed
, simTrustLevels = mempty
, simNumCopies = configuredNumCopies 1 , simNumCopies = configuredNumCopies 1
, simGroups = mempty , simGroups = mempty
, simWanted = mempty , simWanted = mempty
@ -72,18 +76,16 @@ emptySimState rngseed repobyname = SimState
, simGroupWanted = mempty , simGroupWanted = mempty
, simMaxSize = mempty , simMaxSize = mempty
, simRebalance = False , simRebalance = False
, simExistingRepoByName = repobyname , simGetExistingRepoByName = repobyname
} }
-- State that can vary between different repos in the simulation. -- State that can vary between different repos in the simulation.
data SimRepoState = SimRepoState data SimRepoState = SimRepoState
{ simLocations :: M.Map Key (S.Set RepoName) { simLocations :: M.Map Key (S.Set RepoName)
, simIsSpecialRemote :: Bool
} }
deriving (Show, Eq) deriving (Show, Eq)
emptySimRepoState :: SimRepoState
emptySimRepoState = SimRepoState mempty
setPresentKey :: RepoName -> Key -> SimRepoState -> SimRepoState setPresentKey :: RepoName -> Key -> SimRepoState -> SimRepoState
setPresentKey repo k rst = rst setPresentKey repo k rst = rst
{ simLocations = { simLocations =
@ -93,9 +95,6 @@ setPresentKey repo k rst = rst
newtype RepoName = RepoName { fromRepoName :: String } newtype RepoName = RepoName { fromRepoName :: String }
deriving (Show, Eq, Ord) deriving (Show, Eq, Ord)
newtype GroupName = GroupName { fromGroupName :: String }
deriving (Show, Eq, Ord)
data SimCommand data SimCommand
= CommandInit RepoName = CommandInit RepoName
| CommandInitRemote RepoName | CommandInitRemote RepoName
@ -109,11 +108,12 @@ data SimCommand
| CommandPresent RepoName FilePath | CommandPresent RepoName FilePath
| CommandNotPresent RepoName FilePath | CommandNotPresent RepoName FilePath
| CommandNumCopies Int | CommandNumCopies Int
| CommandGroup RepoName GroupName | CommandTrustLevel RepoName String
| CommandUngroup RepoName GroupName | CommandGroup RepoName Group
| CommandUngroup RepoName Group
| CommandWanted RepoName PreferredContentExpression | CommandWanted RepoName PreferredContentExpression
| CommandRequired RepoName PreferredContentExpression | CommandRequired RepoName PreferredContentExpression
| CommandGroupWanted GroupName PreferredContentExpression | CommandGroupWanted Group PreferredContentExpression
| CommandMaxSize RepoName MaxSize | CommandMaxSize RepoName MaxSize
| CommandRebalance Bool | CommandRebalance Bool
deriving (Show) deriving (Show)
@ -125,22 +125,16 @@ applySimCommand
applySimCommand (CommandInit reponame) st = applySimCommand (CommandInit reponame) st =
checkNonexistantRepo reponame st $ checkNonexistantRepo reponame st $
let (u, st') = genSimUUID st reponame let (u, st') = genSimUUID st reponame
in Right $ Right $ st' in Right $ Right $ addRepo reponame (newSimRepoConfig u False) st'
{ simRepos = M.insert reponame u (simRepos st')
}
applySimCommand (CommandInitRemote reponame) st = applySimCommand (CommandInitRemote reponame) st =
checkNonexistantRepo reponame st $ checkNonexistantRepo reponame st $
let (u, st') = genSimUUID st reponame let (u, st') = genSimUUID st reponame
in Right $ Right $ st' in Right $ Right $ addRepo reponame (newSimRepoConfig u True) st'
{ simSpecialRemotes = M.insert reponame u (simSpecialRemotes st')
}
applySimCommand (CommandUse reponame s) st = applySimCommand (CommandUse reponame s) st =
case existingRepoByName (simExistingRepoByName st) s of case getExistingRepoByName (simGetExistingRepoByName st) s of
(u:[], _) -> checkNonexistantRepo reponame st $ Right existingrepo -> checkNonexistantRepo reponame st $
Right $ Right $ st Right $ Right $ addRepo reponame existingrepo st
{ simSpecialRemotes = M.insert reponame u (simSpecialRemotes st) Left msg -> Left $ "Unable to use a repository \""
}
(_, msg) -> Left $ "Unable to use a repository \""
++ fromRepoName reponame ++ fromRepoName reponame
++ "\" in the simulation because " ++ msg ++ "\" in the simulation because " ++ msg
applySimCommand (CommandConnect repo remote) st = applySimCommand (CommandConnect repo remote) st =
@ -167,11 +161,11 @@ applySimCommand (CommandAdd file sz repo) st = checkKnownRepo repo st $
let (k, st') = genSimKey sz st let (k, st') = genSimKey sz st
in Right $ Right $ st' in Right $ Right $ st'
{ simFiles = M.insert file k (simFiles st') { simFiles = M.insert file k (simFiles st')
, simRepoState = , simRepoState = case M.lookup repo (simRepoState st') of
let rst = fromMaybe emptySimRepoState $ Just rst -> M.insert repo
M.lookup repo (simRepoState st') (setPresentKey repo k rst)
rst' = setPresentKey repo k rst (simRepoState st')
in M.insert repo rst' (simRepoState st') Nothing -> error "no simRepoState in applySimCommand CommandAdd"
} }
applySimCommand (CommandStep n) st applySimCommand (CommandStep n) st
| n > 0 = applySimCommand | n > 0 = applySimCommand
@ -208,15 +202,22 @@ applySimCommand (CommandNotPresent repo file) st = checkKnownRepo repo st $
applySimCommand (CommandNumCopies n) st = Right $ Right $ st applySimCommand (CommandNumCopies n) st = Right $ Right $ st
{ simNumCopies = configuredNumCopies n { simNumCopies = configuredNumCopies n
} }
applySimCommand (CommandGroup repo group) st = checkKnownRepo repo st $ applySimCommand (CommandTrustLevel repo s) st = checkKnownRepo repo st $
case readTrustLevel s of
Just trustlevel -> Right $ Right $ st
{ simTrustLevels = M.insert repo trustlevel
(simTrustLevels st)
}
Nothing -> Left $ "Unknown trust level \"" ++ s ++ "\"."
applySimCommand (CommandGroup repo groupname) st = checkKnownRepo repo st $
Right $ Right $ st Right $ Right $ st
{ simGroups = M.insertWith S.union repo { simGroups = M.insertWith S.union repo
(S.singleton group) (S.singleton groupname)
(simGroups st) (simGroups st)
} }
applySimCommand (CommandUngroup repo group) st = checkKnownRepo repo st $ applySimCommand (CommandUngroup repo groupname) st = checkKnownRepo repo st $
Right $ Right $ st Right $ Right $ st
{ simGroups = M.adjust (S.delete group) repo (simGroups st) { simGroups = M.adjust (S.delete groupname) repo (simGroups st)
} }
applySimCommand (CommandWanted repo expr) st = checkKnownRepo repo st $ applySimCommand (CommandWanted repo expr) st = checkKnownRepo repo st $
checkValidPreferredContentExpression expr $ Right $ st checkValidPreferredContentExpression expr $ Right $ st
@ -226,9 +227,9 @@ applySimCommand (CommandRequired repo expr) st = checkKnownRepo repo st $
checkValidPreferredContentExpression expr $ Right $ st checkValidPreferredContentExpression expr $ Right $ st
{ simRequired = M.insert repo expr (simRequired st) { simRequired = M.insert repo expr (simRequired st)
} }
applySimCommand (CommandGroupWanted group expr) st = applySimCommand (CommandGroupWanted groupname expr) st =
checkValidPreferredContentExpression expr $ Right $ st checkValidPreferredContentExpression expr $ Right $ st
{ simGroupWanted = M.insert group expr (simGroupWanted st) { simGroupWanted = M.insert groupname expr (simGroupWanted st)
} }
applySimCommand (CommandMaxSize repo sz) st = checkKnownRepo repo st $ applySimCommand (CommandMaxSize repo sz) st = checkKnownRepo repo st $
Right $ Right $ st Right $ Right $ st
@ -285,12 +286,113 @@ simUUIDNameSpace :: U.UUID
simUUIDNameSpace = U5.generateNamed U5.namespaceURL $ simUUIDNameSpace = U5.generateNamed U5.namespaceURL $
B.unpack "http://git-annex.branchable.com/git-annex-sim/" B.unpack "http://git-annex.branchable.com/git-annex-sim/"
newtype ExistingRepoByName = ExistingRepoByName newtype GetExistingRepoByName = GetExistingRepoByName
{ existingRepoByName :: String -> ([UUID], String) { getExistingRepoByName :: String -> Either String SimRepoConfig
} }
instance Show ExistingRepoByName where instance Show GetExistingRepoByName where
show _ = "ExistingRepoByName" show _ = "GetExistingRepoByName"
mkExistingRepoByName :: Annex ExistingRepoByName data SimRepoConfig = SimRepoConfig
mkExistingRepoByName = ExistingRepoByName <$> Remote.nameToUUID'' { simRepoUUID :: UUID
, simRepoIsSpecialRemote :: Bool
, simRepoGroups :: S.Set Group
, simRepoTrustLevel :: TrustLevel
, simRepoPreferredContent :: Maybe PreferredContentExpression
, simRepoRequiredContent :: Maybe PreferredContentExpression
, simRepoGroupPreferredContent :: M.Map Group PreferredContentExpression
, simRepoMaxSize :: Maybe MaxSize
}
deriving (Show)
newSimRepoConfig :: UUID -> Bool -> SimRepoConfig
newSimRepoConfig u isspecialremote = SimRepoConfig
{ simRepoUUID = u
, simRepoIsSpecialRemote = isspecialremote
, simRepoGroups = mempty
, simRepoTrustLevel = def
, simRepoPreferredContent = Nothing
, simRepoRequiredContent = Nothing
, simRepoGroupPreferredContent = mempty
, simRepoMaxSize = Nothing
}
addRepo :: RepoName -> SimRepoConfig -> SimState -> SimState
addRepo reponame simrepo st = st
{ simRepos = M.insert reponame (simRepoUUID simrepo) (simRepos st)
, simRepoState = M.insert reponame rst (simRepoState st)
, simConnections = M.insert reponame mempty (simConnections st)
, simGroups = M.insert reponame (simRepoGroups simrepo) (simGroups st)
, simTrustLevels = M.insert reponame
(simRepoTrustLevel simrepo)
(simTrustLevels st)
, simWanted = M.alter
(const $ simRepoPreferredContent simrepo)
reponame
(simWanted st)
, simRequired = M.alter
(const $ simRepoRequiredContent simrepo)
reponame
(simRequired st)
, simGroupWanted = M.union
(simRepoGroupPreferredContent simrepo)
(simGroupWanted st)
, simMaxSize = M.alter
(const $ simRepoMaxSize simrepo)
reponame
(simMaxSize st)
}
where
rst = SimRepoState
{ simLocations = mempty
, simIsSpecialRemote = simRepoIsSpecialRemote simrepo
}
mkGetExistingRepoByName :: Annex GetExistingRepoByName
mkGetExistingRepoByName = do
groupmap <- groupMap
trustmap <- trustMap
pcmap <- preferredContentMapRaw
rcmap <- requiredContentMapRaw
gpcmap <- groupPreferredContentMapRaw
maxsizes <- getMaxSizes
nametouuid <- Remote.nameToUUID''
remoteconfigmap <- readRemoteLog
return $ GetExistingRepoByName $ \name ->
case nametouuid name of
(u:[], _) -> Right $
let gs = fromMaybe S.empty $
M.lookup u (groupsByUUID groupmap)
in SimRepoConfig
{ simRepoUUID = u
, simRepoIsSpecialRemote =
M.member u remoteconfigmap
, simRepoGroups = gs
, simRepoTrustLevel =
lookupTrust' u trustmap
, simRepoPreferredContent =
M.lookup u pcmap
, simRepoRequiredContent =
M.lookup u rcmap
, simRepoGroupPreferredContent =
M.restrictKeys gpcmap gs
, simRepoMaxSize =
M.lookup u maxsizes
}
(_, msg) -> Left msg
cloneSimRepo :: RepoName -> UUID -> Repo -> FilePath -> IO ()
cloneSimRepo simreponame u parent dest = do
cloned <- boolSystem "git"
[ Param "clone"
, Param "--shared"
, Param "--quiet"
-- Avoid overhead of checking out the working tree.
-- Note that, on visiting the simulated repo,
-- the working tree needs to be reset.
, Param "--no-checkout"
, File (fromRawFilePath (repoPath parent))
, File dest
]
unless cloned $ giveup "git clone failed"
-- TODO delete origin remote from clone, to avoid foot-shooting