git_map.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/env python
  2. # Copyright 2014 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """
  6. Provides an augmented `git log --graph` view. In particular, it also annotates
  7. commits with branches + tags that point to them. Items are colorized as follows:
  8. * Cyan - Currently checked out branch
  9. * Green - Local branch
  10. * Red - Remote branches
  11. * Magenta - Tags
  12. * Blue background - The currently checked out commit
  13. """
  14. import sys
  15. import subprocess2
  16. from git_common import current_branch, branches, tags, config_list, GIT_EXE
  17. from third_party import colorama
  18. CYAN = colorama.Fore.CYAN
  19. GREEN = colorama.Fore.GREEN
  20. MAGENTA = colorama.Fore.MAGENTA
  21. RED = colorama.Fore.RED
  22. BLUEBAK = colorama.Back.BLUE
  23. BRIGHT = colorama.Style.BRIGHT
  24. RESET = colorama.Fore.RESET + colorama.Back.RESET + colorama.Style.RESET_ALL
  25. def main():
  26. map_extra = config_list('depot_tools.map_extra')
  27. fmt = '%C(red bold)%h%x09%Creset%C(green)%d%Creset %C(yellow)%ad%Creset ~ %s'
  28. log_proc = subprocess2.Popen(
  29. [GIT_EXE, 'log', '--graph', '--full-history', '--branches', '--tags',
  30. '--remotes', '--color=always', '--date=short', ('--pretty=format:' + fmt)
  31. ] + map_extra + sys.argv[1:],
  32. stdout=subprocess2.PIPE,
  33. shell=False)
  34. current = current_branch()
  35. all_branches = set(branches())
  36. if current in all_branches:
  37. all_branches.remove(current)
  38. all_tags = set(tags())
  39. try:
  40. for line in log_proc.stdout.xreadlines():
  41. start = line.find(GREEN+' (')
  42. end = line.find(')', start)
  43. if start != -1 and end != -1:
  44. start += len(GREEN) + 2
  45. branch_list = line[start:end].split(', ')
  46. branches_str = ''
  47. if branch_list:
  48. colored_branches = []
  49. head_marker = ''
  50. for b in branch_list:
  51. if b == "HEAD":
  52. head_marker = BLUEBAK+BRIGHT+'*'
  53. continue
  54. if b == current:
  55. colored_branches.append(CYAN+BRIGHT+b+RESET)
  56. current = None
  57. elif b in all_branches:
  58. colored_branches.append(GREEN+BRIGHT+b+RESET)
  59. all_branches.remove(b)
  60. elif b in all_tags:
  61. colored_branches.append(MAGENTA+BRIGHT+b+RESET)
  62. elif b.startswith('tag: '):
  63. colored_branches.append(MAGENTA+BRIGHT+b[5:]+RESET)
  64. else:
  65. colored_branches.append(RED+b)
  66. branches_str = '(%s) ' % ((GREEN+", ").join(colored_branches)+GREEN)
  67. line = "%s%s%s" % (line[:start-1], branches_str, line[end+5:])
  68. if head_marker:
  69. line = line.replace('*', head_marker, 1)
  70. sys.stdout.write(line)
  71. except (IOError, KeyboardInterrupt):
  72. pass
  73. finally:
  74. sys.stderr.close()
  75. sys.stdout.close()
  76. return 0
  77. if __name__ == '__main__':
  78. sys.exit(main())