diff options
-rw-r--r-- | morphlib/gitdir.py | 32 | ||||
-rw-r--r-- | morphlib/gitdir_tests.py | 5 |
2 files changed, 37 insertions, 0 deletions
diff --git a/morphlib/gitdir.py b/morphlib/gitdir.py index c075f456..7ee64f36 100644 --- a/morphlib/gitdir.py +++ b/morphlib/gitdir.py @@ -16,6 +16,7 @@ # =*= License: GPL-2 =*= +import collections import cliapp import glob import os @@ -200,6 +201,37 @@ class GitDirectory(object): output = self._runcmd(['git', 'rev-parse', '--abbrev-ref', 'HEAD']) return output.strip() + def _get_status(self): + '''Runs git status and formats its output into something more useful. + + This runs git status such that unusual filenames are preserved + and returns its output in a sequence of (status_code, to_path, + from_path). + + from_path is None unless the status_code says there was a rename, + in which case it is the path it was renamed from. + + Untracked and ignored changes are also included in the output, + their status codes are '??' and '!!' respectively. + + ''' + status = self._runcmd(['git', 'status', '-z', '--ignored']) + tokens = collections.deque(status.split('\0')) + while True: + tok = tokens.popleft() + # Terminates with an empty token, since status ends with a \0 + if not tok: + return + + code = tok[:2] + to_path = tok[3:] + yield code, to_path, tokens.popleft() if code[0] == 'R' else None + + def get_uncommitted_changes(self): + for code, to_path, from_path in self._get_status(): + if code not in ('??', '!!'): + yield code, to_path, from_path + def init(dirname): '''Initialise a new git repository.''' diff --git a/morphlib/gitdir_tests.py b/morphlib/gitdir_tests.py index 84b8787a..803f1b3e 100644 --- a/morphlib/gitdir_tests.py +++ b/morphlib/gitdir_tests.py @@ -147,3 +147,8 @@ class GitDirectoryContentsTests(unittest.TestCase): gd.checkout('foo') self.assertEqual(gd.HEAD, 'foo') + + def test_uncommitted_changes(self): + gd = morphlib.gitdir.GitDirectory(self.dirname) + self.assertEqual(sorted(gd.get_uncommitted_changes()), + [(' D', 'foo', None)]) |