Advertisement
Guest User

Untitled

a guest
Nov 18th, 2019
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.93 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # Interactive git checkout.
  3.  
  4. import os
  5. import sys
  6. import subprocess
  7. import unittest
  8.  
  9. from collections import namedtuple
  10. from StringIO import StringIO
  11. from subprocess import call
  12.  
  13.  
  14. DETACHED_HEAD_BRANCH_NAME = '(no branch) - detached HEAD'
  15.  
  16.  
  17. # Keep data about branches.
  18. BranchesInfo = namedtuple('BranchesInfo', [
  19. 'all_branches', # list of strings
  20. 'current_branch', # string
  21. 'current_index', # number
  22. ])
  23.  
  24.  
  25. def get_git_branches():
  26. "Returns git branch output."
  27. command = ['git', 'branch', '--no-color']
  28. return subprocess.check_output(command)
  29.  
  30.  
  31. def git_checkout(branch):
  32. "Returns git checkout output."
  33. command = ['git', 'checkout', branch]
  34. return subprocess.check_output(command)
  35.  
  36.  
  37. def branches_menu(branches_info):
  38. "Returns a simple menu as string."
  39. s = StringIO()
  40. s.write('\nCurrent branch: %s\n\n' % branches_info.current_branch)
  41. for i, branch in enumerate(branches_info.all_branches):
  42. s.write('%s %s\n' % (i, branch))
  43. return s.getvalue()
  44.  
  45.  
  46. def parse_git_branches(output):
  47. "Returns an instance of BranchesInfo class."
  48. all_branches = []
  49. current_branch = ''
  50. current_index = -1
  51. i = -1
  52. for line in output.splitlines():
  53. parts = line.split()
  54. if not parts:
  55. continue # skip empty lines
  56. i += 1
  57. if line == '* (no branch)': # detached HEAD
  58. current_index = i
  59. current_branch = DETACHED_HEAD_BRANCH_NAME
  60. all_branches.append(DETACHED_HEAD_BRANCH_NAME)
  61. continue
  62.  
  63. all_branches.append(parts[-1])
  64. if parts[0] == '*':
  65. current_index = i
  66. current_branch = parts[-1]
  67.  
  68. return BranchesInfo(all_branches, current_branch, current_index)
  69.  
  70.  
  71. class TestParseGitBranches(unittest.TestCase):
  72.  
  73. def test_normal_output(self):
  74. output = 'master\n test\n* new-features\n'
  75. b = parse_git_branches(output)
  76. self.assertEqual(b.current_branch, 'new-features')
  77. self.assertEqual(b.current_index, 2)
  78. self.assertEqual(b.all_branches[0], 'master')
  79. self.assertEqual(b.all_branches[1], 'test')
  80. self.assertEqual(b.all_branches[2], 'new-features')
  81.  
  82. def test_detached_head(self):
  83. output = '* (no branch)\n master\n'
  84. b = parse_git_branches(output)
  85. self.assertEqual(b.current_branch, DETACHED_HEAD_BRANCH_NAME)
  86. self.assertEqual(b.current_index, 0)
  87. self.assertEqual(b.all_branches[0], DETACHED_HEAD_BRANCH_NAME )
  88. self.assertEqual(b.all_branches[1], 'master')
  89.  
  90.  
  91. class TestBranchesMenu(unittest.TestCase):
  92.  
  93. def test_menu(self):
  94. all_branches = ['master', 'docs', 'test']
  95. b = BranchesInfo(all_branches, 'docs', 1)
  96. self.assertEqual(branches_menu(b), '''
  97. Current branch: docs
  98.  
  99. 0 master
  100. 1 docs
  101. 2 test
  102. ''')
  103.  
  104.  
  105. def runTests():
  106. all_test_cases = [TestParseGitBranches, TestBranchesMenu]
  107. loader = unittest.TestLoader()
  108. all_suites = [loader.loadTestsFromTestCase(t) for t in all_test_cases]
  109. all_tests = unittest.TestSuite(all_suites)
  110. result = unittest.TextTestRunner().run(all_tests)
  111. if result.wasSuccessful():
  112. return 0
  113. return 1
  114.  
  115.  
  116. def main(args):
  117. program_args = args[1:]
  118.  
  119. if '--test' in program_args:
  120. return runTests()
  121.  
  122. if len(program_args) > 0:
  123. return call(['git', 'checkout'] + program_args)
  124.  
  125. output = get_git_branches()
  126. branches_info = parse_git_branches(output)
  127. print(branches_menu(branches_info))
  128. try:
  129. choice = raw_input('Select a branch by number: ')
  130. branch = branches_info.all_branches[int(choice)]
  131. print(git_checkout(branch))
  132. except KeyboardInterrupt:
  133. print('\nCanceled.')
  134. except:
  135. print('Invalid input. Checkout fail.')
  136. return 1
  137. return 0
  138.  
  139.  
  140. if __name__ == '__main__':
  141. sys.exit(main(sys.argv))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement