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

Commit e431922

Browse files
committed
Cleaned up parser
1 parent 28c26d0 commit e431922

File tree

2 files changed

+14
-17
lines changed

2 files changed

+14
-17
lines changed

src/Semantic/Git.hs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Semantic.Git
1818
import Control.Monad.IO.Class
1919
import Data.Attoparsec.Text (Parser)
2020
import Data.Attoparsec.Text as AP
21+
import Data.Char
2122
import Data.Text as Text
2223
import Shelly hiding (FilePath)
2324
import System.IO (hSetBinaryMode)
@@ -41,28 +42,26 @@ sh = shelly . silently . onCommandHandles (initOutputHandles (`hSetBinaryMode` T
4142

4243
-- | Parses an list of entries separated by \NUL, and on failure return []
4344
parseEntries :: Text -> [TreeEntry]
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)
45+
parseEntries = either (const []) id . AP.parseOnly everything
4746
where
48-
everything = AP.sepBy entryParser "\NUL" <* ("\NUL\n" <?> "End sequence") <* AP.endOfInput <?> "Everything"
49-
parseOnly p t = AP.feed (AP.parse p t) ""
47+
everything = AP.sepBy entryParser "\NUL" <* "\NUL\n" <* AP.endOfInput
5048

5149
-- | Parse the entire input with entryParser, and on failure return a default
5250
-- For testing purposes only
53-
parseEntry :: Text -> TreeEntry
54-
parseEntry = either (const nullTreeEntry) id . AP.parseOnly (entryParser <* AP.endOfInput)
51+
parseEntry :: Text -> Either String TreeEntry
52+
parseEntry = AP.parseOnly (entryParser <* AP.endOfInput)
5553

5654
-- | Parses a TreeEntry
5755
entryParser :: Parser TreeEntry
5856
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"
57+
<$> modeParser <* AP.char ' '
58+
<*> typeParser <* AP.char ' '
59+
<*> oidParser <* AP.char '\t'
60+
<*> (unpack <$> AP.takeWhile (/= '\NUL'))
6361
where
64-
typeParser = AP.choice [BlobObject <$ "blob", TreeObject <$ "tree"] <?> "Type Parser"
65-
modeParser = AP.choice [NormalMode <$ "100644", ExecutableMode <$ "100755", SymlinkMode <$ "120000", TreeMode <$ "040000"] <?> "Mode Parser"
62+
typeParser = AP.choice [BlobObject <$ "blob", TreeObject <$ "tree"]
63+
modeParser = AP.choice [NormalMode <$ "100644", ExecutableMode <$ "100755", SymlinkMode <$ "120000", TreeMode <$ "040000"]
64+
oidParser = OID <$> AP.takeWhile isHexDigit
6665

6766
newtype OID = OID Text
6867
deriving (Eq, Show, Ord)
@@ -89,5 +88,3 @@ data TreeEntry
8988
, treeEntryPath :: FilePath
9089
} deriving (Eq, Show)
9190

92-
nullTreeEntry :: TreeEntry
93-
nullTreeEntry = TreeEntry OtherMode OtherObjectType (OID mempty) mempty

test/Semantic/Spec.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ spec = parallel $ do
2929
describe "git ls-tree parsing" $ do
3030
it "parses a git output string" $ do
3131
let input = "100644 tree abcdef\t/this/is/the/path"
32-
let expected = TreeEntry NormalMode TreeObject (OID "abcdef") "/this/is/the/path"
32+
let expected = Right $ TreeEntry NormalMode TreeObject (OID "abcdef") "/this/is/the/path"
3333
parseEntry input `shouldBe` expected
3434

3535
it "allows whitespace in the path" $ do
3636
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"
37+
let expected = Right $ 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

0 commit comments

Comments
 (0)