diff options
author | Joey Hess <joeyh@joeyh.name> | 2015-09-22 17:32:28 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2015-09-22 17:32:28 -0400 |
commit | 6dc0db8df4324497ce666231a1d458ac6ee6c9ee (patch) | |
tree | 3adccac08e5411413607d749859f5f6fbe2cc07f /Git | |
parent | 94e8b0e08e5a5f630eea17700294b1783b190e67 (diff) |
status: Show added but not yet committed files.
Seems easy, but git ls-files can't list the right subset of files.
So, I wrote a whole new parser for git status output, and converted the
status command to use that.
There are a few other small behavior changes. The order changed. Unlocked
files show as T. In indirect mode, deleted files were not shown before, and
that's fixed. Regular files checked directly into git and modified
were not shown before, and are now.
Diffstat (limited to 'Git')
-rw-r--r-- | Git/Status.hs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/Git/Status.hs b/Git/Status.hs new file mode 100644 index 000000000..4f9ad0265 --- /dev/null +++ b/Git/Status.hs @@ -0,0 +1,76 @@ +{- git status interface + - + - Copyright 2015 Joey Hess <id@joeyh.name> + - + - Licensed under the GNU GPL version 3 or higher. + -} + +module Git.Status where + +import Common +import Git +import Git.Command +import Git.FilePath + +data Status + = Modified TopFilePath + | Deleted TopFilePath + | Added TopFilePath + | Renamed TopFilePath TopFilePath + | TypeChanged TopFilePath + | Untracked TopFilePath + +statusChar :: Status -> Char +statusChar (Modified _) = 'M' +statusChar (Deleted _) = 'D' +statusChar (Added _) = 'A' +statusChar (Renamed _ _) = 'R' +statusChar (TypeChanged _) = 'T' +statusChar (Untracked _) = '?' + +statusFile :: Status -> TopFilePath +statusFile (Modified f) = f +statusFile (Deleted f) = f +statusFile (Added f) = f +statusFile (Renamed _oldf newf) = newf +statusFile (TypeChanged f) = f +statusFile (Untracked f) = f + +parseStatusZ :: [String] -> [Status] +parseStatusZ = go [] + where + go c [] = reverse c + go c (x:xs) = case x of + (sindex:sworktree:' ':f) -> + -- Look at both the index and worktree status, + -- preferring worktree. + case cparse sworktree <|> cparse sindex of + Just mks -> go (mks (asTopFilePath f) : c) xs + Nothing -> if sindex == 'R' + -- In -z mode, the name the + -- file was renamed to comes + -- first, and the next component + -- is the old filename. + then case xs of + (oldf:xs') -> go (Renamed (asTopFilePath oldf) (asTopFilePath f) : c) xs' + _ -> go c [] + else go c xs + _ -> go c xs + + cparse 'M' = Just Modified + cparse 'A' = Just Added + cparse 'D' = Just Deleted + cparse 'T' = Just TypeChanged + cparse '?' = Just Untracked + cparse _ = Nothing + +getStatus :: [FilePath] -> Repo -> IO ([Status], IO Bool) +getStatus l r = do + (ls, cleanup) <- pipeNullSplit params r + return (parseStatusZ ls, cleanup) + where + params = + [ Param "status" + , Param "-uall" + , Param "-z" + ] ++ map File l |