Josip Sokcevic | 4de5dea | 2022-03-23 21:15:14 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
iannucci@chromium.org | a112f03 | 2014-03-13 07:47:50 +0000 | [diff] [blame] | 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 | |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 6 | """ |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 7 | usage: git map [-h] [--help] [<args>] |
| 8 | |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 9 | Enhances `git log --graph` view with information on commit branches + tags that |
| 10 | point to them. Items are colorized as follows: |
| 11 | |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 12 | * Cyan - Currently checked out branch |
| 13 | * Green - Local branch |
| 14 | * Red - Remote branches |
| 15 | * Magenta - Tags |
iannucci@chromium.org | c050a5b | 2014-03-26 06:18:50 +0000 | [diff] [blame] | 16 | * White - Merge Base Markers |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 17 | * Blue background - The currently checked out commit |
| 18 | """ |
iannucci@chromium.org | c050a5b | 2014-03-26 06:18:50 +0000 | [diff] [blame] | 19 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 20 | import os |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 21 | import sys |
| 22 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 23 | import git_common |
| 24 | import setup_color |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 25 | import subprocess2 |
| 26 | |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 27 | from third_party import colorama |
| 28 | |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 29 | |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 30 | RESET = colorama.Fore.RESET + colorama.Back.RESET + colorama.Style.RESET_ALL |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 31 | BRIGHT = colorama.Style.BRIGHT |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 32 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 33 | BLUE_BACK = colorama.Back.BLUE + BRIGHT |
| 34 | BRIGHT_RED = colorama.Fore.RED + BRIGHT |
| 35 | CYAN = colorama.Fore.CYAN + BRIGHT |
| 36 | GREEN = colorama.Fore.GREEN + BRIGHT |
| 37 | MAGENTA = colorama.Fore.MAGENTA + BRIGHT |
| 38 | RED = colorama.Fore.RED |
| 39 | WHITE = colorama.Fore.WHITE + BRIGHT |
| 40 | YELLOW = colorama.Fore.YELLOW |
iannucci@chromium.org | c050a5b | 2014-03-26 06:18:50 +0000 | [diff] [blame] | 41 | |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 42 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 43 | def _print_help(outbuf): |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 44 | names = { |
| 45 | 'Cyan': CYAN, |
| 46 | 'Green': GREEN, |
| 47 | 'Magenta': MAGENTA, |
| 48 | 'Red': RED, |
| 49 | 'White': WHITE, |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 50 | 'Blue background': BLUE_BACK, |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 51 | } |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 52 | msg = '' |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 53 | for line in __doc__.splitlines(): |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 54 | for name, color in names.items(): |
| 55 | if name in line: |
| 56 | msg += line.replace('* ' + name, color + '* ' + name + RESET) + '\n' |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 57 | break |
| 58 | else: |
| 59 | msg += line + '\n' |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 60 | outbuf.write(msg.encode('utf-8', 'replace')) |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 61 | |
| 62 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 63 | def _color_branch(branch, all_branches, all_tags, current): |
Aravind Vasudevan | c5f0cbb | 2022-01-24 23:56:57 +0000 | [diff] [blame] | 64 | if branch in (current, 'HEAD -> ' + current): |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 65 | color = CYAN |
| 66 | current = None |
| 67 | elif branch in all_branches: |
| 68 | color = GREEN |
| 69 | all_branches.remove(branch) |
| 70 | elif branch in all_tags: |
| 71 | color = MAGENTA |
| 72 | elif branch.startswith('tag: '): |
| 73 | color = MAGENTA |
| 74 | branch = branch[len('tag: '):] |
| 75 | else: |
| 76 | color = RED |
| 77 | return color + branch + RESET |
| 78 | |
| 79 | |
| 80 | def _color_branch_list(branch_list, all_branches, all_tags, current): |
| 81 | if not branch_list: |
| 82 | return '' |
| 83 | colored_branches = (GREEN + ', ').join( |
| 84 | _color_branch(branch, all_branches, all_tags, current) |
| 85 | for branch in branch_list if branch != 'HEAD') |
| 86 | return (GREEN + '(' + colored_branches + GREEN + ') ' + RESET) |
| 87 | |
| 88 | |
| 89 | def _parse_log_line(line): |
| 90 | graph, branch_list, commit_date, subject = ( |
| 91 | line.decode('utf-8', 'replace').strip().split('\x00')) |
| 92 | branch_list = [] if not branch_list else branch_list.split(', ') |
| 93 | commit = graph.split()[-1] |
| 94 | graph = graph[:-len(commit)] |
| 95 | return graph, commit, branch_list, commit_date, subject |
| 96 | |
| 97 | |
| 98 | def main(argv, outbuf): |
| 99 | if '-h' in argv or '--help' in argv: |
| 100 | _print_help(outbuf) |
anatoly techtonik | c878ba6 | 2017-04-03 06:08:38 +0300 | [diff] [blame] | 101 | return 0 |
| 102 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 103 | map_extra = git_common.get_config_list('depot_tools.map_extra') |
| 104 | cmd = [ |
| 105 | git_common.GIT_EXE, 'log', git_common.root(), |
| 106 | '--graph', '--branches', '--tags', '--color=always', '--date=short', |
| 107 | '--pretty=format:%H%x00%D%x00%cd%x00%s' |
| 108 | ] + map_extra + argv |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 109 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 110 | log_proc = subprocess2.Popen(cmd, stdout=subprocess2.PIPE, shell=False) |
| 111 | |
| 112 | current = git_common.current_branch() |
| 113 | all_tags = set(git_common.tags()) |
| 114 | all_branches = set(git_common.branches()) |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 115 | if current in all_branches: |
| 116 | all_branches.remove(current) |
iannucci@chromium.org | c050a5b | 2014-03-26 06:18:50 +0000 | [diff] [blame] | 117 | |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 118 | merge_base_map = {} |
| 119 | for branch in all_branches: |
| 120 | merge_base = git_common.get_or_create_merge_base(branch) |
| 121 | if merge_base: |
| 122 | merge_base_map.setdefault(merge_base, set()).add(branch) |
| 123 | |
| 124 | for merge_base, branches in merge_base_map.items(): |
| 125 | merge_base_map[merge_base] = ', '.join(branches) |
| 126 | |
| 127 | try: |
| 128 | for line in log_proc.stdout: |
| 129 | if b'\x00' not in line: |
| 130 | outbuf.write(line) |
| 131 | continue |
| 132 | |
| 133 | graph, commit, branch_list, commit_date, subject = _parse_log_line(line) |
| 134 | |
| 135 | if 'HEAD' in branch_list: |
| 136 | graph = graph.replace('*', BLUE_BACK + '*') |
| 137 | |
| 138 | line = '{graph}{commit}\t{branches}{date} ~ {subject}'.format( |
| 139 | graph=graph, |
| 140 | commit=BRIGHT_RED + commit[:10] + RESET, |
| 141 | branches=_color_branch_list( |
| 142 | branch_list, all_branches, all_tags, current), |
| 143 | date=YELLOW + commit_date + RESET, |
| 144 | subject=subject) |
| 145 | |
| 146 | if commit in merge_base_map: |
| 147 | line += ' <({})'.format(WHITE + merge_base_map[commit] + RESET) |
| 148 | |
| 149 | line += os.linesep |
| 150 | outbuf.write(line.encode('utf-8', 'replace')) |
| 151 | except (BrokenPipeError, KeyboardInterrupt): |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 152 | pass |
iannucci@chromium.org | 8bc9b5c | 2014-03-12 01:36:18 +0000 | [diff] [blame] | 153 | return 0 |
| 154 | |
| 155 | |
| 156 | if __name__ == '__main__': |
Edward Lemur | b800fde | 2020-01-10 23:04:44 +0000 | [diff] [blame] | 157 | setup_color.init() |
| 158 | with git_common.less() as less_input: |
| 159 | sys.exit(main(sys.argv[1:], less_input)) |