gitstatus.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/env python2
  2. # -*- coding: UTF-8 -*-
  3. from subprocess import Popen, PIPE
  4. import re
  5. # change those symbols to whatever you prefer
  6. symbols = {
  7. 'ahead of': '↑',
  8. 'behind': '↓',
  9. 'staged': '♦',
  10. 'changed': '‣',
  11. 'untracked': '…',
  12. 'clean': '⚡',
  13. 'unmerged': '≠',
  14. 'sha1': ':'
  15. }
  16. output, error = Popen(
  17. ['git', 'status'], stdout=PIPE, stderr=PIPE, universal_newlines=True).communicate()
  18. if error:
  19. import sys
  20. sys.exit(0)
  21. lines = output.splitlines()
  22. behead_re = re.compile(
  23. r"^# Your branch is (ahead of|behind) '(.*)' by (\d+) commit")
  24. diverge_re = re.compile(r"^# and have (\d+) and (\d+) different")
  25. status = ''
  26. staged = re.compile(r'^# Changes to be committed:$', re.MULTILINE)
  27. changed = re.compile(r'^# Changed but not updated:$', re.MULTILINE)
  28. untracked = re.compile(r'^# Untracked files:$', re.MULTILINE)
  29. unmerged = re.compile(r'^# Unmerged paths:$', re.MULTILINE)
  30. def execute(*command):
  31. out, err = Popen(stdout=PIPE, stderr=PIPE, *command).communicate()
  32. if not err:
  33. nb = len(out.splitlines())
  34. else:
  35. nb = '?'
  36. return nb
  37. if staged.search(output):
  38. nb = execute(
  39. ['git', 'diff', '--staged', '--name-only', '--diff-filter=ACDMRT'])
  40. status += '%s%s' % (symbols['staged'], nb)
  41. if unmerged.search(output):
  42. nb = execute(['git', 'diff', '--staged', '--name-only', '--diff-filter=U'])
  43. status += '%s%s' % (symbols['unmerged'], nb)
  44. if changed.search(output):
  45. nb = execute(['git', 'diff', '--name-only', '--diff-filter=ACDMRT'])
  46. status += '%s%s' % (symbols['changed'], nb)
  47. if untracked.search(output):
  48. status += symbols['untracked']
  49. if status == '':
  50. status = symbols['clean']
  51. remote = ''
  52. bline = lines[0]
  53. if bline.find('Not currently on any branch') != -1:
  54. branch = symbols['sha1'] + Popen([
  55. 'git',
  56. 'rev-parse',
  57. '--short',
  58. 'HEAD'], stdout=PIPE).communicate()[0][:-1]
  59. else:
  60. branch = bline.split(' ')[-1]
  61. bstatusline = lines[1]
  62. match = behead_re.match(bstatusline)
  63. if match:
  64. remote = symbols[match.groups()[0]]
  65. remote += match.groups()[2]
  66. elif lines[2:]:
  67. div_match = diverge_re.match(lines[2])
  68. if div_match:
  69. remote = "{behind}{1}{ahead of}{0}".format(
  70. *div_match.groups(), **symbols)
  71. print('\n'.join([branch, remote, status]))