Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit be96fcf

Browse files
committed
Refactored code to be in line with suggestions
1 parent 0abcac7 commit be96fcf

File tree

2 files changed

+25
-48
lines changed

2 files changed

+25
-48
lines changed

src/Semantic/Git.hs

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,50 +30,39 @@ clone url path = sh $ do
3030
-- | git cat-file -p
3131
catFile :: FilePath -> OID -> IO Text
3232
catFile gitDir (OID oid) = sh $ do
33-
run "git" [pack ("--git-dir=" <> gitDir), "cat-file", "-p", oid]
33+
run "git" ["-C", pack gitDir, "cat-file", "-p", oid]
3434

3535
-- | git ls-tree -rz
3636
lsTree :: FilePath -> OID -> IO [TreeEntry]
37-
lsTree gitDir (OID sha) = sh $ do
38-
out <- run "git" [pack ("--git-dir=" <> gitDir), "ls-tree", "-rz", sha]
39-
pure $ parseEntries out
37+
lsTree gitDir (OID sha) = sh $ parseEntries <$> run "git" ["-C", pack gitDir, "ls-tree", "-rz", sha]
4038

4139
sh :: MonadIO m => Sh a -> m a
4240
sh = shelly . silently . onCommandHandles (initOutputHandles (`hSetBinaryMode` True))
4341

4442
-- | Parses an list of entries separated by \NUL, and on failure return []
4543
parseEntries :: Text -> [TreeEntry]
46-
parseEntries = either (const []) id . AP.parseOnly (AP.sepBy entryParser (AP.char '\NUL'))
44+
parseEntries text = case parseOnly everything text of
45+
Done "" ls -> ls
46+
other -> error ("There was an error parsing the Git output: " <> show other)
47+
where
48+
everything = AP.sepBy entryParser "\NUL" <* ("\NUL\n" <?> "End sequence") <* AP.endOfInput <?> "Everything"
49+
parseOnly p t = AP.feed (AP.parse p t) ""
4750

4851
-- | Parse the entire input with entryParser, and on failure return a default
4952
-- For testing purposes only
5053
parseEntry :: Text -> TreeEntry
51-
parseEntry = either (const nullTreeEntry) id . AP.parseOnly entryParser
54+
parseEntry = either (const nullTreeEntry) id . AP.parseOnly (entryParser <* AP.endOfInput)
5255

53-
-- | Parses an entry successfully, falling back to the failure case if necessary.
56+
-- | Parses a TreeEntry
5457
entryParser :: Parser TreeEntry
55-
entryParser = AP.choice [entrySuccessParser, entryDefaultParser]
56-
57-
-- | Attoparsec parser for a block af text ending with \NUL
58-
-- in order to consume invalid input
59-
entryDefaultParser :: Parser TreeEntry
60-
entryDefaultParser = do
61-
_ <- AP.takeWhile (/= '\NUL')
62-
pure $ nullTreeEntry
63-
64-
-- | Attoparsec parser for a single line of git ls-tree -rz output
65-
entrySuccessParser :: Parser TreeEntry
66-
entrySuccessParser = do
67-
mode <- takeWhileToNul (/= ' ')
68-
_ <- AP.char ' '
69-
ty <- takeWhileToNul (/= ' ')
70-
_ <- AP.char ' '
71-
oid <- takeWhileToNul (/= '\t')
72-
_ <- AP.char '\t'
73-
path <- takeWhileToNul (const True)
74-
pure $ TreeEntry (objectMode mode) (objectType ty) (OID oid) (unpack path)
58+
entryParser = TreeEntry
59+
<$> modeParser <* (" " <?> "First Space")
60+
<*> typeParser <* (" " <?> "Second Space")
61+
<*> (OID <$> AP.takeWhile (AP.inClass "0123456789abcdef") <?> "OID Parser") <* ("\t" <?> "Tab")
62+
<*> (unpack <$> AP.takeWhile (/= '\NUL') <?> "Filepath") <?> "Entry Parser"
7563
where
76-
takeWhileToNul f = AP.takeWhile (\x -> f x && x /= '\NUL')
64+
typeParser = AP.choice [BlobObject <$ "blob", TreeObject <$ "tree"] <?> "Type Parser"
65+
modeParser = AP.choice [NormalMode <$ "100644", ExecutableMode <$ "100755", SymlinkMode <$ "120000", TreeMode <$ "040000"] <?> "Mode Parser"
7766

7867
newtype OID = OID Text
7968
deriving (Eq, Show, Ord)
@@ -86,24 +75,12 @@ data ObjectMode
8675
| OtherMode
8776
deriving (Eq, Show)
8877

89-
objectMode :: Text -> ObjectMode
90-
objectMode "100644" = NormalMode
91-
objectMode "100755" = ExecutableMode
92-
objectMode "120000" = SymlinkMode
93-
objectMode "040000" = TreeMode
94-
objectMode _ = OtherMode
95-
9678
data ObjectType
9779
= BlobObject
9880
| TreeObject
9981
| OtherObjectType
10082
deriving (Eq, Show)
10183

102-
objectType :: Text -> ObjectType
103-
objectType "blob" = BlobObject
104-
objectType "tree" = TreeObject
105-
objectType _ = OtherObjectType
106-
10784
data TreeEntry
10885
= TreeEntry
10986
{ treeEntryMode :: ObjectMode

test/Semantic/Spec.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@ spec = parallel $ do
2626
output <- fmap runBuilder . runTaskOrDie $ parseTermBuilder TermSExpression [methodsBlob]
2727
output `shouldBe` "(Statements\n (Method\n (Empty)\n (Identifier)\n (Statements)))\n"
2828

29-
describe "gitParsing" $ do
29+
describe "git ls-tree parsing" $ do
3030
it "parses a git output string" $ do
31-
let input = "100644 tree ThisIsTheOid\t/this/is/the/path"
32-
let expected = TreeEntry NormalMode TreeObject (OID "ThisIsTheOid") "/this/is/the/path"
31+
let input = "100644 tree abcdef\t/this/is/the/path"
32+
let expected = TreeEntry NormalMode TreeObject (OID "abcdef") "/this/is/the/path"
3333
parseEntry input `shouldBe` expected
3434

35-
it "parses nonsense into a default value" $ do
36-
let input = "iel jgh\nf2 8i4p\r8f2y4fpoxin u3y2 unz"
37-
let expected = TreeEntry OtherMode OtherObjectType (OID mempty) mempty
35+
it "allows whitespace in the path" $ do
36+
let input = "100644 tree 12345\t/this\n/is\t/the /path\r"
37+
let expected = TreeEntry NormalMode TreeObject (OID "12345") "/this\n/is\t/the /path\r"
3838
parseEntry input `shouldBe` expected
3939

4040
it "parses many outputs separated by \\NUL" $ do
41-
let input = "100644 tree ThisIsTheOid\t/this/is/the/path\NULiel jgh\nf2 8i4p\r8f2y4fpoxin u3y2 unz\NUL120000 blob 17776\t/dev/urandom"
42-
let expected = [ TreeEntry NormalMode TreeObject (OID "ThisIsTheOid") "/this/is/the/path", TreeEntry OtherMode OtherObjectType (OID mempty) mempty, TreeEntry SymlinkMode BlobObject (OID "17776") "/dev/urandom"]
41+
let input = "100644 tree abcdef\t/this/is/the/path\NUL120000 blob 17776\t/dev/urandom\NUL\n"
42+
let expected = [ TreeEntry NormalMode TreeObject (OID "abcdef") "/this/is/the/path", TreeEntry SymlinkMode BlobObject (OID "17776") "/dev/urandom"]
4343
parseEntries input `shouldBe` expected
4444

4545
where

0 commit comments

Comments
 (0)