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.
This commit is contained in:
parent
178826c4cb
commit
f2b6ebd502
5 changed files with 121 additions and 56 deletions
76
Git/Status.hs
Normal file
76
Git/Status.hs
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue