summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-09-28 14:03:59 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-09-28 14:03:59 -0400
commit93807564d00b3f64ad2353731fffb5c45ef8c01a (patch)
tree395928f7291625f05084ff971362775505b27afd
parentd7d9e9aca08b752cc2e04809edc654be39413665 (diff)
add ls-tree interface
This parser should be fast. I hope.
-rw-r--r--Git/LsTree.hs48
1 files changed, 48 insertions, 0 deletions
diff --git a/Git/LsTree.hs b/Git/LsTree.hs
new file mode 100644
index 000000000..8b530d2ad
--- /dev/null
+++ b/Git/LsTree.hs
@@ -0,0 +1,48 @@
+{- git ls-tree interface
+ -
+ - Copyright 2011 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.LsTree (
+ lsTree
+) where
+
+import Numeric
+import Control.Applicative
+import Data.Char
+
+import Git
+import Utility.SafeCommand
+
+type Treeish = String
+
+data TreeItem = TreeItem
+ { mode :: Int
+ , objtype :: String
+ , sha :: String
+ , file :: FilePath
+ } deriving Show
+
+{- Lists the contents of a Treeish -}
+lsTree :: Repo -> Treeish -> IO [TreeItem]
+lsTree repo t = map parseLsTree <$>
+ pipeNullSplit repo [Params "ls-tree --full-tree -z -r --", File t]
+
+{- Parses a line of ls-tree output.
+ - (The --long format is not currently supported.) -}
+parseLsTree :: String -> TreeItem
+parseLsTree l = TreeItem m o s f
+ where
+ -- l = <mode> SP <type> SP <sha> TAB <file>
+ -- Since everything until the file is fixed-width,
+ -- do not need to split on words.
+ (m, past_m) = head $ readOct l
+ (o, past_o) = splitAt 4 $ space past_m
+ (s, past_s) = splitAt shaSize $ space past_o
+ f = decodeGitFile $ space past_s
+ space s@(sp:rest)
+ | isSpace sp = rest
+ | otherwise = error $
+ "ls-tree parse error at '" ++ s ++ "' in " ++ l