git-annex/Git/Status.hs
Joey Hess f2b6ebd502 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.
2015-09-22 17:32:28 -04:00

76 lines
1.8 KiB
Haskell

{- 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