Skip to content

Commit

Permalink
Branch is a strong data type
Browse files Browse the repository at this point in the history
  • Loading branch information
olivierverdier committed Jan 31, 2015
1 parent 5bbc322 commit e054212
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 42 deletions.
32 changes: 24 additions & 8 deletions src/BranchParse.hs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module BranchParse where

import Control.Applicative ((<$>), (<*>), (<*), (*>), (<$))
import Control.Applicative ((<$>), (<*>), (<*), (*>), (<$), pure)
import Text.Parsec (digit, string, char, eof, anyChar,
many, many1, manyTill, noneOf, between,
parse, ParseError, (<|>), try)
import Text.Parsec.String (Parser)
import Test.QuickCheck (Arbitrary(arbitrary), oneof, getPositive)
import Test.QuickCheck (Arbitrary(arbitrary), oneof, getPositive, suchThat)
import Data.List (isPrefixOf, isSuffixOf, isInfixOf)

{-
The idea is to parse the first line of the git status command.
Expand All @@ -32,15 +33,30 @@ instance Arbitrary Distance where
where
pos = getPositive <$> arbitrary

type Branch = String
{- Branch type -}

newtype Branch = MkBranch String deriving (Show, Eq)

isValidBranch :: String -> Bool
isValidBranch b = not . or $ [null,
(' ' `elem`),
(".." `isInfixOf`),
("." `isPrefixOf`),
("." `isSuffixOf`)]
<*> pure b

instance Arbitrary Branch where
arbitrary = MkBranch <$> arbitrary `suchThat` isValidBranch


type BranchInfo = ((Maybe Branch, Maybe Branch), Maybe Distance)

noBranchInfo :: BranchInfo
noBranchInfo = ((Nothing, Nothing), Nothing)

newRepo :: Parser BranchInfo
newRepo =
fmap (\ branch -> ((Just branch, Nothing), Nothing))
fmap (\ branch -> ((Just $ MkBranch branch, Nothing), Nothing))
$ string "Initial commit on " *> many anyChar <* eof

noBranch :: Parser BranchInfo
Expand All @@ -49,24 +65,24 @@ noBranch =
<$ manyTill anyChar (try $ string " (no branch)") <* eof

trackedBranch :: Parser Branch
trackedBranch = manyTill anyChar (try $ string "...")
trackedBranch = MkBranch <$> manyTill anyChar (try $ string "...")

branchRemoteTracking :: Parser BranchInfo
branchRemoteTracking =
(\ branch tracking behead -> ((Just branch, Just tracking), Just behead))
(\ branch tracking behead -> ((Just branch, Just $ MkBranch tracking), Just behead))
<$> trackedBranch
<*> many (noneOf " ") <* char ' '
<*> inBrackets

branchRemote :: Parser BranchInfo
branchRemote =
(\ branch tracking -> ((Just branch, Just tracking), Nothing))
(\ branch tracking -> ((Just branch, Just $ MkBranch tracking), Nothing))
<$> trackedBranch
<*> many (noneOf " ") <* eof

branchOnly :: Parser BranchInfo
branchOnly =
(\ branch -> ((Just branch, Nothing), Nothing))
(\ branch -> ((Just $ MkBranch branch, Nothing), Nothing))
<$> many (noneOf " ") <* eof

branchParser :: Parser BranchInfo
Expand Down
4 changes: 2 additions & 2 deletions src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import System.Process (readProcessWithExitCode)
import System.Exit (ExitCode(ExitSuccess))
import Data.Maybe (fromMaybe)
import Control.Applicative ((<$>), (<*>))
import BranchParse (Branch, BranchInfo, branchInfo, Distance, pairFromDistance)
import BranchParse (Branch(MkBranch), BranchInfo, branchInfo, Distance, pairFromDistance)
import StatusParse (Status(MakeStatus), processStatus)
import Data.List (intercalate)

Expand Down Expand Up @@ -60,7 +60,7 @@ branchOrHash :: Maybe Branch -> IO String
branchOrHash branch =
case branch of
Nothing -> makeHashWith ':' <$> gitrevparse
Just bn -> return bn
Just (MkBranch bn) -> return bn

allInfo :: (BranchInfo, Status Int) -> (IO String, Numbers)
allInfo (((branch, _), behead), stat) = (branchOrHash branch, showBranchNumbers behead ++ showStatusNumbers stat)
Expand Down
47 changes: 15 additions & 32 deletions src/TestBranchParse.hs
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
import BranchParse (BranchInfo, branchInfo, Distance)
import Test.QuickCheck (Arbitrary(arbitrary), property, stdArgs, maxSuccess, quickCheckWith, suchThat)
import Data.List (isPrefixOf, isSuffixOf, isInfixOf)
import Control.Applicative ((<$>), (<*>), pure)

{- ValidBranch type -}

newtype ValidBranch = MkBranch String deriving (Show, Eq)

isValidBranch :: String -> Bool
isValidBranch b = not . or $ [null,
(' ' `elem`),
(".." `isInfixOf`),
("." `isPrefixOf`),
("." `isSuffixOf`)]
<*> pure b

instance Arbitrary ValidBranch where
arbitrary = MkBranch <$> arbitrary `suchThat` isValidBranch
import BranchParse (BranchInfo, branchInfo, Distance, Branch(MkBranch))
import Test.QuickCheck (property, stdArgs, maxSuccess, quickCheckWith)


{- Helper to tackle the Either type -}
Expand All @@ -30,34 +13,34 @@ checkRight b s = expectRight b $ branchInfo s

{- Test -}

propNoBranch :: ValidBranch -> Bool
propNoBranch :: Branch -> Bool
propNoBranch (MkBranch s) =
checkRight
((Nothing, Nothing), Nothing)
$ s ++ " (no branch)"

propNewRepo :: ValidBranch -> Bool
propNewRepo (MkBranch s) =
propNewRepo :: Branch -> Bool
propNewRepo b@(MkBranch s) =
checkRight
((Just s, Nothing), Nothing)
((Just b, Nothing), Nothing)
$ "Initial commit on " ++ s

propBranchOnly :: ValidBranch -> Bool
propBranchOnly (MkBranch s) =
propBranchOnly :: Branch -> Bool
propBranchOnly b@(MkBranch s) =
checkRight
((Just s, Nothing), Nothing)
((Just b, Nothing), Nothing)
s

propBranchRemote :: ValidBranch -> ValidBranch -> Bool
propBranchRemote (MkBranch b) (MkBranch t) =
propBranchRemote :: Branch -> Branch -> Bool
propBranchRemote b'@(MkBranch b) t'@(MkBranch t) =
checkRight
((Just b, Just t), Nothing)
((Just b', Just t'), Nothing)
$ b ++"..." ++ t

propBranchRemoteTracking :: ValidBranch -> ValidBranch -> Distance -> Bool
propBranchRemoteTracking (MkBranch b) (MkBranch t) distance =
propBranchRemoteTracking :: Branch -> Branch -> Distance -> Bool
propBranchRemoteTracking b'@(MkBranch b) t'@(MkBranch t) distance =
checkRight
((Just b, Just t), Just distance)
((Just b', Just t'), Just distance)
$ b ++ "..." ++ t ++ " " ++ show distance

main :: IO()
Expand Down

0 comments on commit e054212

Please sign in to comment.