module Mit.State where
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import Mit.Clock (getCurrentTime)
import Mit.Git
import Mit.Prelude
import Mit.Undo
import System.Directory (removeFile)
data MitState a = MitState
{ head :: a,
merging :: Maybe Text,
ranCommitAt :: Maybe Word64,
undos :: [Undo]
}
deriving stock (Eq, Show)
emptyMitState :: MitState ()
emptyMitState =
MitState {head = (), merging = Nothing, ranCommitAt = Nothing, undos = []}
deleteMitState :: Text -> IO ()
deleteMitState branch64 =
removeFile (mitfile branch64) `catch` \(_ :: IOException) -> pure ()
parseMitState :: Text -> Maybe (MitState Text)
parseMitState contents = do
[headLine, mergingLine, ranCommitAtLine, undosLine] <- Just (Text.lines contents)
["head", head] <- Just (Text.words headLine)
merging <-
case Text.words mergingLine of
["merging"] -> Just Nothing
["merging", branch] -> Just (Just branch)
_ -> Nothing
ranCommitAt <-
case Text.words ranCommitAtLine of
["ran-commit-at"] -> Just Nothing
["ran-commit-at", text2word64 -> Just n] -> Just (Just n)
_ -> Nothing
undos <- Text.stripPrefix "undos " undosLine >>= parseUndos
pure MitState {head, merging, ranCommitAt, undos}
readMitState :: Text -> IO (MitState ())
readMitState branch64 = do
head <- gitHead
try (Text.readFile (mitfile branch64)) >>= \case
Left (_ :: IOException) -> pure emptyMitState
Right contents -> do
let maybeState = do
state <- parseMitState contents
guard (head == state.head)
pure state
case maybeState of
Nothing -> do
deleteMitState branch64
pure emptyMitState
Just state -> pure (state {head = ()} :: MitState ())
writeMitState :: Text -> MitState () -> IO ()
writeMitState branch64 state = do
head <- gitHead
let contents :: Text
contents =
Text.unlines
[ "head " <> head,
"merging " <> fromMaybe Text.empty state.merging,
"ran-commit-at " <> maybe Text.empty word642text state.ranCommitAt,
"undos " <> showUndos state.undos
]
Text.writeFile (mitfile branch64) contents `catch` \(_ :: IOException) -> pure ()
mitStateRanCommitAgo :: MitState a -> IO Word64
mitStateRanCommitAgo state =
case state.ranCommitAt of
Nothing -> pure maxBound
Just timestamp0 -> do
timestamp1 <- getCurrentTime
pure
if timestamp1 >= timestamp0
then timestamp1 - timestamp0
else maxBound -- weird unexpected case
mitfile :: Text -> FilePath
mitfile branch64 =
Text.unpack (gitdir <> "/.mit-" <> branch64)