summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--morphlib/gitdir.py32
-rw-r--r--morphlib/gitdir_tests.py5
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)])