import Types.Group
import Types.StandardGroups
import Types.TrustLevel
+import Types.Difference
import Git.Types
import Git
import Backend.Hash (genTestKey)
import Annex.UUID
import Annex.FileMatcher
+import Annex.Init
+import Annex.Startup
import Logs.Group
import Logs.Trust
import Logs.PreferredContent
import Logs.Remote
import Logs.MaxSize
+import Logs.Difference
+import qualified Annex
import qualified Remote
+import qualified Git.Construct
+import qualified Git.Remote.Remove
import System.Random
import Data.Word
}
deriving (Show)
-emptySimState :: Int -> GetExistingRepoByName -> SimState
-emptySimState rngseed repobyname = SimState
+emptySimState :: StdGen -> GetExistingRepoByName -> SimState
+emptySimState rng repobyname = SimState
{ simRepos = mempty
, simRepoState = mempty
, simConnections = mempty
, simFiles = mempty
- , simRng = mkStdGen rngseed
+ , simRng = rng
, simTrustLevels = mempty
, simNumCopies = configuredNumCopies 1
, simGroups = mempty
data SimRepoState = SimRepoState
{ simLocations :: M.Map Key (S.Set RepoName)
, simIsSpecialRemote :: Bool
+ , simRepo :: Maybe SimRepo
}
- deriving (Show, Eq)
+
+instance Show SimRepoState where
+ show _ = "SimRepoState"
setPresentKey :: RepoName -> Key -> SimRepoState -> SimRepoState
setPresentKey repo k rst = rst
rst = SimRepoState
{ simLocations = mempty
, simIsSpecialRemote = simRepoIsSpecialRemote simrepo
+ , simRepo = Nothing
}
mkGetExistingRepoByName :: Annex GetExistingRepoByName
}
(_, msg) -> Left msg
-cloneSimRepo :: RepoName -> UUID -> Repo -> FilePath -> IO ()
-cloneSimRepo simreponame u parent dest = do
+-- Information about a git repository that is cloned and used to represent
+-- a repository in the simulation
+data SimRepo = SimRepo
+ { simRepoGitRepo :: Repo
+ , simRepoAnnex :: (Annex.AnnexState, Annex.AnnexRead)
+ , simRepoCurrState :: SimState
+ }
+
+cloneSimRepo :: RepoName -> UUID -> Repo -> FilePath -> SimState -> IO SimRepo
+cloneSimRepo simreponame u parent dest st = do
cloned <- boolSystem "git"
[ Param "clone"
, Param "--shared"
-- Note that, on visiting the simulated repo,
-- the working tree needs to be reset.
, Param "--no-checkout"
+ -- Make sure the origin gets that name.
+ , Param "--origin", Param "origin"
, File (fromRawFilePath (repoPath parent))
, File dest
]
- unless cloned $ giveup "git clone failed"
- -- TODO delete origin remote from clone, to avoid foot-shooting
+ unless cloned $
+ giveup "git clone failed"
+ simrepo <- Git.Construct.fromPath (toRawFilePath dest)
+ ast <- Annex.new simrepo
+ ((), ast') <- Annex.run ast $ doQuietAction $ do
+ -- Disconnect simulated repository from origin, so its
+ -- git-annex branch is not used, and also to prevent any
+ -- accidental foot shooting pushes to it.
+ inRepo $ Git.Remote.Remove.remove "origin"
+ storeUUID u
+ -- Prevent merging this simulated git-annex branch with
+ -- any real one. Writing to the git-annex branch here also
+ -- avoids checkSharedClone enabling the shared clone
+ -- setting, which is not wanted here.
+ recordDifferences simulationDifferences u
+ let desc = "simulated repository " ++ fromRepoName simreponame
+ initialize startupAnnex (Just desc) Nothing
+ updateSimRepoState st $ SimRepo
+ { simRepoGitRepo = simrepo
+ , simRepoAnnex = ast'
+ , simRepoCurrState = emptySimState
+ (simRng st)
+ (simGetExistingRepoByName st)
+ }
+
+updateSimRepoState :: SimState -> SimRepo -> IO SimRepo
+updateSimRepoState st sr = do
+ ((), ast) <- Annex.run (simRepoAnnex sr) $ doQuietAction $ do
+ let oldst = simRepoCurrState sr
+ -- simTrustLevels st
+ error "TODO diff and update everything" -- XXX
+ return $ sr
+ { simRepoAnnex = ast
+ , simRepoCurrState = st
+ }
+
+simulationDifferences :: Differences
+simulationDifferences = mkDifferences $ S.singleton Simulation
{- git-annex repository differences
-
- - Copyright 2015 Joey Hess <id@joeyh.name>
+ - Copyright 2015-2024 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
= ObjectHashLower
| OneLevelObjectHash
| OneLevelBranchHash
+ | Simulation
deriving (Show, Read, Eq, Ord, Enum, Bounded)
-- This type is used internally for efficient checking for differences,
{ objectHashLower :: Bool
, oneLevelObjectHash :: Bool
, oneLevelBranchHash :: Bool
+ , simulation :: Bool
}
| UnknownDifferences
[ objectHashLower
, oneLevelObjectHash
, oneLevelBranchHash
+ , simulation
]
appendDifferences :: Differences -> Differences -> Differences
{ objectHashLower = objectHashLower a || objectHashLower b
, oneLevelObjectHash = oneLevelObjectHash a || oneLevelObjectHash b
, oneLevelBranchHash = oneLevelBranchHash a || oneLevelBranchHash b
+ , simulation = simulation a || simulation b
}
appendDifferences _ _ = UnknownDifferences
(<>) = appendDifferences
instance Monoid Differences where
- mempty = Differences False False False
+ mempty = Differences False False False False
readDifferences :: String -> Differences
readDifferences = maybe UnknownDifferences mkDifferences . readish
getDifferences r = mkDifferences $ S.fromList $
mapMaybe getmaybe [minBound .. maxBound]
where
- getmaybe d = case Git.Config.isTrueFalse' =<< Git.Config.getMaybe (differenceConfigKey d) r of
+ getmaybe d = case Git.Config.isTrueFalse' =<< flip Git.Config.getMaybe r =<< differenceConfigKey d of
Just True -> Just d
_ -> Nothing
-differenceConfigKey :: Difference -> ConfigKey
+differenceConfigKey :: Difference -> Maybe ConfigKey
differenceConfigKey ObjectHashLower = tunable "objecthashlower"
differenceConfigKey OneLevelObjectHash = tunable "objecthash1"
differenceConfigKey OneLevelBranchHash = tunable "branchhash1"
+differenceConfigKey Simulation = Nothing
differenceConfigVal :: Difference -> String
differenceConfigVal _ = Git.Config.boolConfig True
-tunable :: B.ByteString -> ConfigKey
-tunable k = ConfigKey ("annex.tune." <> k)
+tunable :: B.ByteString -> Maybe ConfigKey
+tunable k = Just $ ConfigKey ("annex.tune." <> k)
hasDifference :: Difference -> Differences -> Bool
hasDifference _ UnknownDifferences = False
hasDifference ObjectHashLower ds = objectHashLower ds
hasDifference OneLevelObjectHash ds = oneLevelObjectHash ds
hasDifference OneLevelBranchHash ds = oneLevelBranchHash ds
+hasDifference Simulation ds = simulation ds
listDifferences :: Differences -> [Difference]
listDifferences d@(Differences {}) = map snd $
[ (objectHashLower, ObjectHashLower)
, (oneLevelObjectHash, OneLevelObjectHash)
, (oneLevelBranchHash, OneLevelBranchHash)
+ , (simulation, Simulation)
]
listDifferences UnknownDifferences = []
{ objectHashLower = check ObjectHashLower
, oneLevelObjectHash = check OneLevelObjectHash
, oneLevelBranchHash = check OneLevelBranchHash
+ , simulation = check Simulation
}
where
check f = f `S.member` s