-
Notifications
You must be signed in to change notification settings - Fork 3
/
git-fancy-branch-list
executable file
·131 lines (113 loc) · 3.86 KB
/
git-fancy-branch-list
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python3
"""
Show remote and local branch sorted by last commit time, using colors to indicate Githash.
If '-g' is provided, show branches that are identical to ones in remote.
Remote branches can be filtered by configuring fancy-branch-list.prefix, e.g.:
git config fancy-branch-list.prefix origin/dan/
"""
import os
import sys
import datetime
import time
from dateutil import parser
f = os.popen("git config fancy-branch-list.prefix", "r")
remote_prefix = f.read().strip()
f.close()
cmd = (
"""git for-each-ref "$@" --sort=-committerdate refs/heads/ refs/remotes/"""
+ remote_prefix +
""" --format="%(committerdate) ;; %(refname) ;; %(objectname) ;; %(subject)" """
)
branch_list = os.popen(cmd, "r").read()
def color24(r, g, b1):
return "\x1b[38;2;%d;%d;%dm" % (r, g, b1)
def backcolor24(r, g, b1):
return "\x1b[48;2;%d;%d;%dm" % (r, g, b1)
def colorreset():
return "\x1b[0;m"
def pretty_date(diff):
"""
Get a datetime object or a int() Epoch timestamp and return a
pretty string like 'an hour ago', 'Yesterday', '3 months ago',
'just now', etc
"""
second_diff = int(diff)
day_diff = int(diff / 86400)
if day_diff < 0:
return ''
if day_diff == 0:
if second_diff < 10:
return "just now"
if second_diff < 60:
return str(second_diff) + " seconds ago"
if second_diff < 120:
return "a minute ago"
if second_diff < 3600:
return str(int(second_diff / 60)) + " minutes ago"
if second_diff < 7200:
return "an hour ago"
if second_diff < 86400:
return str(int((second_diff / 3600))) + " hours ago"
if day_diff == 1:
return "Yesterday"
if day_diff < 7:
return str(day_diff) + " days ago"
if day_diff < 31:
return str(int(day_diff / 7)) + " weeks ago"
if day_diff < 365:
return str(int(day_diff / 30)) + " months ago"
return str(int(day_diff / 365)) + " years ago"
lst = []
nb = 0
branch_type = {}
branch_hash = {}
for line in branch_list.splitlines():
(ts, b, h, s) = line.split(' ;; ')
place = " "
is_remote = False
if b.startswith('refs/heads/'):
b = b[len('refs/heads/'):]
if b.startswith('refs/remotes/origin/'):
b = b[len('refs/remotes/origin/'):]
place = "(remote)"
is_remote = True
if b not in branch_type:
if is_remote:
branch_type[b] = "remote-single"
else:
branch_type[b] = "local-single"
else:
if branch_hash[b] == h:
branch_type[b] = "remote-and-local-ident"
else:
if branch_type[b] == "remote-single":
if not is_remote:
branch_type[b] = "remote-and-local-older"
else:
if is_remote:
branch_type[b] = "local-and-remote-older"
branch_hash[b] = h
lst.append((ts, b, h, s, place))
nb = max(nb, len(b))
branchDictTypes = {
"local-single" : color24( 95, 185, 235),
"remote-single" : color24(168, 168, 255),
"local-and-remote-older" : color24(255, 255, 55),
"remote-and-local-ident" : color24( 0, 255, 0),
"remote-and-local-older" : color24(255, 50, 50),
}
show_remote_and_local_ident = '-g' in sys.argv
lst.reverse()
for (ts, b, h, s, place) in lst:
h = h[:12]
if branch_type[b] == "remote-and-local-ident" and not show_remote_and_local_ident:
continue
branch_color = branchDictTypes[branch_type[b]]
back_color = ''
ts_v = parser.parse(ts)
age = (time.time() - time.mktime(ts_v.timetuple()))
if age > 86400 * 31:
back_color = backcolor24(40, 40, 40)
print(("%s %s %-16s %s %s %s%-" + str(nb) + "s%s %s") % (
back_color, parser.parse(ts), pretty_date(age),
h, place, branch_color, b, colorreset(), s))