-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgit-visualize
executable file
·65 lines (59 loc) · 2.26 KB
/
git-visualize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/env python3
# show the entire history of a Git repo as a colored tree in the terminal
import re, signal, subprocess, sys
def process_lines(lines, out):
starred_col = None
for line in lines:
plain_line = re.sub(r"\x1b\[[\d;]*m", "", line)
m = re.match(r"(\| *)+$", plain_line)
if m:
if (starred_col is None
or plain_line[starred_col:starred_col + 1] == "|"):
continue
out.write(line)
plain_head, = re.match(r"([\|* ]*)", plain_line).groups()
starred_col = plain_head.index("*") if "*" in plain_head else None
git_version = subprocess.check_output(["git", "--version"],
universal_newlines=True)
git_version = re.search("(\d+)\.(\d+)\.(\d+)", git_version).groups()
git_version = tuple(map(int, git_version))
def col(s):
if s == "auto":
# %C(auto) is only supported on git >= 1.8.3
return "%C(auto)" if git_version >= (1, 8, 3) else ""
return "%C{}".format(s)
# the %n introduces a gap between each entry,
# but most of them gets removed by the filter
# except gaps that occur between disjoint components
fmt = "{}%h {}%ad{}{}%d %s%n".format(
col("auto"), col("green"), col("reset"), col("auto"))
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
args = sys.argv[1:] or ["--all"]
git = subprocess.Popen(["git", "log", "--color",
"--date=short", "--decorate", "--full-history",
"--graph", "--pretty=format:" + fmt] +
args,
stdout=subprocess.PIPE,
universal_newlines=True)
try:
less = subprocess.Popen(["less", "-R"],
stdin=subprocess.PIPE,
universal_newlines=True)
while True:
try:
process_lines(git.stdout, less.stdin)
less.stdin.close()
less.wait()
break
except KeyboardInterrupt:
# SIGINT is not fatal to less so we need to keep going
less.send_signal(getattr(signal, "SIGINT", signal.SIGTERM))
except:
less.stdin.close()
less.terminate()
less.wait()
raise
except:
git.terminate()
git.wait()
raise