@@ -17,62 +17,74 @@ module Semantic.Git
17
17
18
18
import Prologue
19
19
20
- import Data.Attoparsec.Text (Parser )
21
- import Data.Attoparsec.Text as AP
20
+ import Data.Attoparsec.ByteString (Parser )
21
+ import Data.Attoparsec.ByteString as AP
22
+ import Data.ByteString (ByteString )
23
+ import Data.ByteString.Internal (w2c )
24
+ import qualified Data.ByteString.UTF8 as UTF8
25
+ import qualified Data.ByteString as B
22
26
import qualified Data.ByteString.Streaming as ByteStream
27
+ import qualified Data.Attoparsec.ByteString.Streaming as AP.Streaming
23
28
import Data.Char
24
29
import Data.Either (fromRight )
25
30
import Data.Text as Text
26
- import Shelly hiding ( FilePath )
31
+ import Text.Parser.Combinators ( sepEndBy )
27
32
import qualified Streaming.Process
28
- import qualified System.Process as Process ( proc )
33
+ import qualified System.Process as Process
29
34
import qualified Source.Source as Source
30
35
31
36
-- | git clone --bare
32
37
clone :: Text -> FilePath -> IO ()
33
- clone url path = sh $ do
34
- run_ " git " [" clone" , " --bare" , url, pack path]
38
+ clone url path = Process. callProcess " git "
39
+ [" clone" , " --bare" , Text. unpack url, path]
35
40
36
41
-- | Runs @git cat-file -p@. Throws 'ProcessExitedUnsuccessfully' if the
37
42
-- underlying git command returns a nonzero exit code. Loads the contents
38
43
-- of the file into memory all at once and strictly.
39
44
catFile :: FilePath -> OID -> IO Source. Source
40
45
catFile gitDir (OID oid) =
41
- let process = Process. proc " git" [" -C" , gitDir, " cat-file" , " -p" , Text. unpack oid]
46
+ let process = Process. proc " git" [" -C" , gitDir, " cat-file" , " -p" , UTF8. toString oid]
42
47
consumeStdout stream = Streaming.Process. withProcessOutput stream ByteStream. toStrict_
43
48
in Source. fromUTF8 <$> Streaming.Process. withStreamProcess process consumeStdout
44
49
45
50
-- | git ls-tree -rz
46
51
lsTree :: FilePath -> OID -> IO [TreeEntry ]
47
- lsTree gitDir (OID sha) = sh $ parseEntries <$> run " git" [" -C" , pack gitDir, " ls-tree" , " -rz" , sha]
52
+ lsTree gitDir (OID sha) =
53
+ let process = Process. proc " git" [" -C" , gitDir, " ls-tree" , " -rz" , UTF8. toString sha]
54
+ allEntries = (entryParser `sepEndBy` AP. word8 0 ) <* AP. endOfInput
55
+ ignoreFailures = fmap (fromRight [] . fst )
56
+ in Streaming.Process. withStreamProcess process $
57
+ \ stream -> Streaming.Process. withProcessOutput stream (ignoreFailures . AP.Streaming. parse allEntries)
48
58
49
- sh :: MonadIO m => Sh a -> m a
50
- sh = shelly . silently
51
59
52
60
-- | Parses an list of entries separated by \NUL, and on failure return []
53
- parseEntries :: Text -> [TreeEntry ]
61
+ parseEntries :: ByteString -> [TreeEntry ]
54
62
parseEntries = fromRight [] . AP. parseOnly everything
55
63
where
56
- everything = AP. sepBy entryParser " \NUL " <* " \NUL\n " <* AP. endOfInput
64
+ everything = AP. sepBy entryParser ( AP. word8 0 )
57
65
58
66
-- | Parse the entire input with entryParser, and on failure return a default
59
67
-- For testing purposes only
60
- parseEntry :: Text -> Either String TreeEntry
68
+ parseEntry :: ByteString -> Either String TreeEntry
61
69
parseEntry = AP. parseOnly (entryParser <* AP. endOfInput)
62
70
63
71
-- | Parses a TreeEntry
64
72
entryParser :: Parser TreeEntry
65
73
entryParser = TreeEntry
66
- <$> modeParser <* AP. char ' '
67
- <*> typeParser <* AP. char ' '
68
- <*> oidParser <* AP. char ' \t '
69
- <*> (unpack <$> AP. takeWhile (/= ' \NUL ' ))
74
+ <$> modeParser <* AP. word8 space
75
+ <*> typeParser <* AP. word8 space
76
+ <*> oidParser <* AP. word8 tab
77
+ <*> (UTF8. toString <$> AP. takeWhile (/= nul ))
70
78
where
71
- typeParser = AP. choice [BlobObject <$ " blob" , TreeObject <$ " tree" , OtherObjectType <$ AP. takeWhile isAlphaNum]
72
- modeParser = AP. choice [NormalMode <$ " 100644" , ExecutableMode <$ " 100755" , SymlinkMode <$ " 120000" , TreeMode <$ " 040000" , OtherMode <$ AP. takeWhile isAlphaNum]
73
- oidParser = OID <$> AP. takeWhile isHexDigit
79
+ char = fromIntegral @ Int @ Word8 . ord
80
+ space = char ' '
81
+ tab = char ' \t '
82
+ nul = char ' \NUL '
83
+ typeParser = AP. choice [BlobObject <$ " blob" , TreeObject <$ " tree" , OtherObjectType <$ AP. takeWhile (isAlphaNum . w2c)]
84
+ modeParser = AP. choice [NormalMode <$ " 100644" , ExecutableMode <$ " 100755" , SymlinkMode <$ " 120000" , TreeMode <$ " 040000" , OtherMode <$ AP. takeWhile (isAlphaNum . w2c)]
85
+ oidParser = OID <$> AP. takeWhile (isHexDigit . w2c)
74
86
75
- newtype OID = OID Text
87
+ newtype OID = OID ByteString
76
88
deriving (Eq , Show , Ord )
77
89
78
90
data ObjectMode
0 commit comments