summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Command/Status.hs92
-rw-r--r--Git/Status.hs76
-rw-r--r--debian/changelog1
-rw-r--r--doc/git-annex-status.mdwn6
-rw-r--r--doc/todo/make_status_show_staged_files.mdwn2
5 files changed, 121 insertions, 56 deletions
diff --git a/Command/Status.hs b/Command/Status.hs
index 5cb971b84..35195fec6 100644
--- a/Command/Status.hs
+++ b/Command/Status.hs
@@ -1,6 +1,6 @@
{- git-annex command
-
- - Copyright 2013 Joey Hess <id@joeyh.name>
+ - Copyright 2013-2015 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -12,9 +12,9 @@ import Command
import Annex.CatFile
import Annex.Content.Direct
import Config
-import qualified Git.LsFiles as LsFiles
+import Git.Status
import qualified Git.Ref
-import qualified Git
+import Git.FilePath
cmd :: Command
cmd = notBareRepo $ noCommit $ noMessages $ withGlobalOptions [jsonOption] $
@@ -24,67 +24,51 @@ cmd = notBareRepo $ noCommit $ noMessages $ withGlobalOptions [jsonOption] $
seek :: CmdParams -> CommandSeek
seek = withWords start
-
-start :: [FilePath] -> CommandStart
-start [] = do
- -- Like git status, when run without a directory, behave as if
- -- given the path to the top of the repository.
- top <- fromRepo Git.repoPath
- d <- liftIO $ relPathCwdToFile top
- start' [d]
-start locs = start' locs
-start' :: [FilePath] -> CommandStart
-start' locs = do
- (l, cleanup) <- inRepo $ LsFiles.modifiedOthers locs
+start :: [FilePath] -> CommandStart
+start locs = do
+ (l, cleanup) <- inRepo $ getStatus locs
getstatus <- ifM isDirect
( return statusDirect
- , return $ Just <$$> statusIndirect
+ , return $ \s -> pure (Just s)
)
- forM_ l $ \f -> maybe noop (showFileStatus f) =<< getstatus f
+ forM_ l $ \s -> maybe noop displayStatus =<< getstatus s
void $ liftIO cleanup
stop
-data Status
- = NewFile
- | DeletedFile
- | ModifiedFile
+displayStatus :: Status -> Annex ()
+-- renames not shown in this simplified status
+displayStatus (Renamed _ _) = noop
+displayStatus s = do
+ let c = statusChar s
+ absf <- fromRepo $ fromTopFilePath (statusFile s)
+ f <- liftIO $ relPathCwdToFile absf
+ unlessM (showFullJSON [("status", [c]), ("file", f)]) $
+ liftIO $ putStrLn $ [c] ++ " " ++ f
-showStatus :: Status -> String
-showStatus NewFile = "?"
-showStatus DeletedFile = "D"
-showStatus ModifiedFile = "M"
-
-showFileStatus :: FilePath -> Status -> Annex ()
-showFileStatus f s = unlessM (showFullJSON [("status", ss), ("file", f)]) $
- liftIO $ putStrLn $ ss ++ " " ++ f
+-- Git thinks that present direct mode files are typechanged;
+-- check their content to see if they are modified or not.
+statusDirect :: Status -> Annex (Maybe Status)
+statusDirect (TypeChanged t) = do
+ absf <- fromRepo $ fromTopFilePath t
+ f <- liftIO $ relPathCwdToFile absf
+ v <- liftIO (catchMaybeIO $ getFileStatus f)
+ case v of
+ Nothing -> return $ Just $ Deleted t
+ Just s
+ | not (isSymbolicLink s) ->
+ checkkey f s =<< catKeyFile f
+ | otherwise -> Just <$> checkNew f t
where
- ss = showStatus s
-
-statusDirect :: FilePath -> Annex (Maybe Status)
-statusDirect f = checkstatus =<< liftIO (catchMaybeIO $ getFileStatus f)
- where
- checkstatus Nothing = return $ Just DeletedFile
- checkstatus (Just s)
- -- Git thinks that present direct mode files are modifed,
- -- so have to check.
- | not (isSymbolicLink s) = checkkey s =<< catKeyFile f
- | otherwise = Just <$> checkNew f
-
- checkkey s (Just k) = ifM (sameFileStatus k f s)
+ checkkey f s (Just k) = ifM (sameFileStatus k f s)
( return Nothing
- , return $ Just ModifiedFile
+ , return $ Just $ Modified t
)
- checkkey _ Nothing = Just <$> checkNew f
-
-statusIndirect :: FilePath -> Annex Status
-statusIndirect f = ifM (liftIO $ isJust <$> catchMaybeIO (getFileStatus f))
- ( checkNew f
- , return DeletedFile
- )
+ checkkey f _ Nothing = Just <$> checkNew f t
+statusDirect s = pure (Just s)
-checkNew :: FilePath -> Annex Status
-checkNew f = ifM (isJust <$> catObjectDetails (Git.Ref.fileRef f))
- ( return ModifiedFile
- , return NewFile
+checkNew :: FilePath -> TopFilePath -> Annex Status
+checkNew f t = ifM (isJust <$> catObjectDetails (Git.Ref.fileRef f))
+ ( return (Modified t)
+ , return (Untracked t)
)
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
diff --git a/debian/changelog b/debian/changelog
index 5ebbfcd18..aa3675cdc 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,6 +13,7 @@ git-annex (5.20150917) UNRELEASED; urgency=medium
* Fix a crash at direct mode merge time when .git/index doesn't exist
yet. Triggered by eg, git-annex sync --no-commit in a fresh clone of
a repository.
+ * status: Show added but not yet committed files.
-- Joey Hess <id@joeyh.name> Wed, 16 Sep 2015 12:23:33 -0400
diff --git a/doc/git-annex-status.mdwn b/doc/git-annex-status.mdwn
index 7ad967bde..19bd6fab5 100644
--- a/doc/git-annex-status.mdwn
+++ b/doc/git-annex-status.mdwn
@@ -9,8 +9,10 @@ git annex status `[path ...]`
# DESCRIPTION
Similar to `git status --short`, this command displays the status of the files
-in the working tree. Shows files that are not checked into git, files that have
-been deleted, and files that have been modified.
+in the working tree.
+
+Show files that are not checked into git (?), deleted (D),
+modified (M), added but not committed (A), and type changed/unlocked (T).
Particularly useful in direct mode.
diff --git a/doc/todo/make_status_show_staged_files.mdwn b/doc/todo/make_status_show_staged_files.mdwn
index cd2de5bce..4d418bc11 100644
--- a/doc/todo/make_status_show_staged_files.mdwn
+++ b/doc/todo/make_status_show_staged_files.mdwn
@@ -21,3 +21,5 @@ Using the `git status` command directly will show the added files
### What version of git-annex are you using? On what operating system?
git-annex version: 5.20141024-g613f396
+
+> [[done]] --[[Joey]]