lib/bpgit.py: add git status support
authorLuis R. Rodriguez <mcgrof@do-not-panic.com>
Mon, 21 Oct 2013 09:08:26 +0000 (11:08 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 21 Oct 2013 19:50:38 +0000 (21:50 +0200)
We use --porcelain given that this spits out the results
in an easy-to-parse format for scripts and will remain stable
across git versions and regardless of user configuration.

We will use this later.

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
lib/bpgit.py

index 9a3f430ba108b0125c328090b2a6fbfe71f82cc3..d2fb98628f41e8c3c81cbd7eb9acfd9c2ad852df 100644 (file)
@@ -27,6 +27,60 @@ def rev_parse(rev='HEAD', tree=None):
         raise SHAError()
     return sha
 
+def status(tree=None):
+    '''
+    For interpretation of the porcelain output refer to
+    the git status(1) man page. In summary the first column is the
+    index state, the second represents the working tree state and
+    the third column are files in cases of renames. This gives back
+    None in case no changes are present, otherwise it returns a list
+    of dict entries with key values: index, work_tree, and files. The
+    files are a list of all files found on that entry, in case of a rename
+    this would consist of a list of 2 files.
+
+    As an example if you had this on your git status:
+
+    R  udev/foo.sh -> poo/foo.sh
+    D  scripts/bar.sh
+    ?? .poo.py.swp
+
+    This would be transposed into the following dict:
+
+        results = status(tree=your_git_tree_path)
+        if not results:
+            return 0
+        for entry in results:
+            print entry
+
+    {'files': [' udev/foo.sh', 'poo/foo.sh'], 'index': 'R', 'work_tree': ' '}
+    {'files': [' scripts/bar.sh'], 'index': 'D', 'work_tree': ' '}
+    {'files': [' .poo.py.swp'], 'index': '?', 'work_tree': '?'}
+    '''
+    def split_status(entry):
+        if len(entry) == 0:
+            return None
+        if len(entry) == 1:
+            return dict(index=entry[0], work_tree=None, files=None)
+        if len(entry) == 2:
+            return dict(index=entry[0], work_tree=entry[1], files=None)
+        else:
+            return dict(index=entry[0], work_tree=entry[1],
+                        files=entry[2:].split(' -> '))
+
+    cmd = ['git', 'status', '--porcelain']
+
+    process = subprocess.Popen(cmd,
+            stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True,
+            universal_newlines=True, cwd=tree)
+    stdout = process.communicate()[0]
+    process.wait()
+    _check(process)
+
+    list_status = stdout.split('\n')
+    if (len(list_status) == 1 and list_status[0] == ''):
+        return None
+    return [split_status(entry) for entry in list_status]
+
 def describe(rev='HEAD', tree=None, extra_args=[]):
     cmd = ['git', 'describe', '--always']