diff options
Diffstat (limited to 'Git')
-rw-r--r-- | Git/DiffTree.hs | 64 | ||||
-rw-r--r-- | Git/LsFiles.hs | 18 | ||||
-rw-r--r-- | Git/LsTree.hs | 3 |
3 files changed, 83 insertions, 2 deletions
diff --git a/Git/DiffTree.hs b/Git/DiffTree.hs new file mode 100644 index 000000000..7281255f5 --- /dev/null +++ b/Git/DiffTree.hs @@ -0,0 +1,64 @@ +{- git diff-tree interface + - + - Copyright 2012 Joey Hess <joey@kitenet.net> + - + - Licensed under the GNU GPL version 3 or higher. + -} + +module Git.DiffTree ( + DiffTreeItem(..), + diffTree, + parseDiffTree +) where + +import Numeric +import System.Posix.Types + +import Common +import Git +import Git.Sha +import Git.Command +import qualified Git.Filename + +data DiffTreeItem = DiffTreeItem + { srcmode :: FileMode + , dstmode :: FileMode + , srcsha :: Sha -- nullSha if file was added + , dstsha :: Sha -- nullSha if file was deleted + , status :: String + , file :: FilePath + } deriving Show + +{- Diffs two tree Refs. -} +diffTree :: Ref -> Ref -> Repo -> IO ([DiffTreeItem], IO Bool) +diffTree src dst repo = do + (diff, cleanup) <- pipeNullSplit [Params "diff-tree -z --raw --no-renames -l0", Param (show src), Param (show dst)] repo + return (parseDiffTree diff, cleanup) + +{- Parses diff-tree output. -} +parseDiffTree :: [String] -> [DiffTreeItem] +parseDiffTree l = go l [] + where + go [] c = c + go (info:f:rest) c = go rest (mk info f : c) + go (s:[]) _ = error $ "diff-tree parse error " ++ s + + mk info f = DiffTreeItem + { srcmode = readmode srcm + , dstmode = readmode dstm + , srcsha = fromMaybe (error "bad srcsha") $ extractSha ssha + , dstsha = fromMaybe (error "bad dstsha") $ extractSha dsha + , status = s + , file = Git.Filename.decode f + } + where + readmode = fst . Prelude.head . readOct + + -- info = :<srcmode> SP <dstmode> SP <srcsha> SP <dstsha> SP <status> + -- All fields are fixed, so we can pull them out of + -- specific positions in the line. + (srcm, past_srcm) = splitAt 7 $ drop 1 info + (dstm, past_dstm) = splitAt 7 past_srcm + (ssha, past_ssha) = splitAt shaSize past_dstm + (dsha, past_dsha) = splitAt shaSize $ drop 1 past_ssha + s = drop 1 past_dsha diff --git a/Git/LsFiles.hs b/Git/LsFiles.hs index 6d42d77ed..45e105a3b 100644 --- a/Git/LsFiles.hs +++ b/Git/LsFiles.hs @@ -10,7 +10,7 @@ module Git.LsFiles ( notInRepo, staged, stagedNotDeleted, - changedUnstaged, + stagedDetails, typeChanged, typeChangedStaged, Conflicting(..), @@ -53,6 +53,22 @@ staged' ps l = pipeNullSplit $ prefix ++ ps ++ suffix prefix = [Params "diff --cached --name-only -z"] suffix = Param "--" : map File l +{- Returns details about files that are staged in the index + - (including the Sha of their staged contents), + - as well as files not yet in git. -} +stagedDetails :: [FilePath] -> Repo -> IO ([(FilePath, Maybe Sha)], IO Bool) +stagedDetails l repo = do + (ls, cleanup) <- pipeNullSplit params repo + return (map parse ls, cleanup) + where + params = [Params "ls-files --others --exclude-standard --stage -z --"] ++ + map File l + parse s + | null file = (s, Nothing) + | otherwise = (file, extractSha $ take shaSize $ drop 7 metadata) + where + (metadata, file) = separate (== '\t') s + {- Returns a list of files that have unstaged changes. -} changedUnstaged :: [FilePath] -> Repo -> IO ([FilePath], IO Bool) changedUnstaged l = pipeNullSplit params diff --git a/Git/LsTree.hs b/Git/LsTree.hs index 611793c40..c61ae7fab 100644 --- a/Git/LsTree.hs +++ b/Git/LsTree.hs @@ -19,6 +19,7 @@ import System.Posix.Types import Common import Git import Git.Command +import Git.Sha import qualified Git.Filename data TreeItem = TreeItem @@ -53,5 +54,5 @@ parseLsTree l = TreeItem -- specific positions in the line. (m, past_m) = splitAt 7 l (t, past_t) = splitAt 4 past_m - (s, past_s) = splitAt 40 $ Prelude.tail past_t + (s, past_s) = splitAt shaSize $ Prelude.tail past_t f = Prelude.tail past_s |