Skip to content

Commit 5315960

Browse files
committed
Add chart "commits_day" and option -s/--sort-max
New chart "commits_day" shows commits by day (by default the 20 last days with at least one commit). Two charts have been renamed: - commits_hour -> commits_hour_day - commits_day -> commits_day_week New command line option -s/--sort-max: keep max entries in chart and sort them by value. Option -m/--max has been renamed to -d/--max-diff and is now used as well for the new chart "commits_day".
1 parent 1780aa4 commit 5315960

2 files changed

Lines changed: 63 additions & 31 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
It can build following charts, as SVG or PNG:
66

77
* authors (pie chart)
8-
* commits by hour, day of week, month of year, year, year/month (bar charts)
8+
* commits by hour of day, day, day of week, month of year, year, year/month
9+
(bar charts)
910
* commits by hour of week (dot chart)
1011
* files by type (pie chart)
1112

gitchart.py

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
# name | chart | description | expected (stdin)
2626
# -------------------+-------+---------------------------+-----------------
2727
# authors | pie | git authors | -
28-
# commits_hour | bar | commits by hour of day | -
28+
# commits_hour_day | bar | commits by hour of day | -
2929
# commits_hour_week | dot | commits by hour of week | -
30-
# commits_day | bar | commits by day of week | -
30+
# commits_day | bar | commits by day | -
31+
# commits_day_week | bar | commits by day of week | -
3132
# commits_month | bar | commits by month of year | -
3233
# commits_year | bar | commits by year | -
3334
# commits_year_month | bar | commits by year/month | -
@@ -47,17 +48,18 @@
4748
import sys
4849
import traceback
4950

50-
VERSION = '0.7'
51+
VERSION = '0.8'
5152

5253

5354
class GitChart:
5455
"""Generate a git stat chart."""
5556

5657
charts = {
5758
'authors': 'Authors',
58-
'commits_hour': 'Commits by hour of day',
59+
'commits_hour_day': 'Commits by hour of day',
5960
'commits_hour_week': 'Commits by hour of week',
60-
'commits_day': 'Commits by day of week',
61+
'commits_day': 'Commits by day',
62+
'commits_day_week': 'Commits by day of week',
6163
'commits_month': 'Commits by month of year',
6264
'commits_year': 'Commits by year',
6365
'commits_year_month': 'Commits by year/month',
@@ -80,12 +82,13 @@ class GitChart:
8082
'#ff00cc', '#899ca1', '#bf4646'))
8183

8284
def __init__(self, chart_name, title=None, repository='.', output=None,
83-
max_entries=20, in_data=None):
85+
max_diff=20, sort_max=0, in_data=None):
8486
self.chart_name = chart_name
8587
self.title = title if title is not None else self.charts[chart_name]
8688
self.repository = repository
8789
self.output = output
88-
self.max_entries = max_entries
90+
self.max_diff = max_diff
91+
self.sort_max = sort_max
8992
self.in_data = in_data
9093

9194
def _git_command(self, command1, command2=None):
@@ -107,16 +110,35 @@ def _git_command(self, command1, command2=None):
107110
cwd=self.repository)
108111
return p.communicate()[0].decode('utf-8').strip().split('\n')
109112

110-
def _generate_bar_chart(self, data, sorted_keys=None, x_labels=None,
111-
x_label_rotation=0):
113+
def _generate_bar_chart(self, data, sorted_keys=None, max_keys=0,
114+
max_x_labels=0, x_label_rotation=0):
112115
"""Generate a bar chart."""
113116
bar_chart = pygal.Bar(style=self.style, show_legend=False,
114117
x_label_rotation=x_label_rotation,
115118
label_font_size=12)
116119
bar_chart.title = self.title
117-
if not sorted_keys:
120+
# sort and keep max entries (if asked)
121+
if self.sort_max != 0:
122+
sorted_keys = sorted(data, key=data.get, reverse=self.sort_max < 0)
123+
keep = -1 * self.sort_max
124+
if keep > 0:
125+
sorted_keys = sorted_keys[:keep]
126+
else:
127+
sorted_keys = sorted_keys[keep:]
128+
elif not sorted_keys:
118129
sorted_keys = sorted(data)
119-
bar_chart.x_labels = x_labels if x_labels else sorted_keys
130+
if max_keys != 0:
131+
sorted_keys = sorted_keys[-1 * max_keys:]
132+
bar_chart.x_labels = sorted_keys[:]
133+
if max_x_labels > 0 and len(bar_chart.x_labels) > max_x_labels:
134+
# reduce number of x labels for readibility: keep only one label
135+
# on N, starting from the end
136+
n = max(2, (len(bar_chart.x_labels) // max_x_labels) * 2)
137+
count = 0
138+
for i in range(len(bar_chart.x_labels) - 1, -1, -1):
139+
if count % n != 0:
140+
bar_chart.x_labels[i] = ''
141+
count += 1
120142
bar_chart.add('', [data[n] for n in sorted_keys])
121143
self._render(bar_chart)
122144

@@ -134,7 +156,7 @@ def _chart_authors(self):
134156
for author in stdout:
135157
(number, name) = author.strip().split('\t', 1)
136158
count += 1
137-
if self.max_entries <= 0 or count <= self.max_entries:
159+
if self.max_diff <= 0 or count <= self.max_diff:
138160
pie_chart.add(name + ' ({0})'.format(number), int(number))
139161
else:
140162
count_others += 1
@@ -145,7 +167,7 @@ def _chart_authors(self):
145167
self._render(pie_chart)
146168
return True
147169

148-
def _chart_commits_hour(self):
170+
def _chart_commits_hour_day(self):
149171
"""Generate bar chart with commits by hour of day."""
150172
# format of lines in stdout: 2013-03-15 18:27:55 +0100
151173
stdout = self._git_command(['git', 'log', '--date=iso',
@@ -175,6 +197,18 @@ def _chart_commits_hour_week(self):
175197
return True
176198

177199
def _chart_commits_day(self):
200+
"""Generate bar chart with commits by day."""
201+
# format of lines in stdout: 2013-03-15
202+
stdout = self._git_command(['git', 'log', '--date=short',
203+
'--pretty=format:%ad'])
204+
commits = {}
205+
for line in stdout:
206+
commits[line] = commits.get(line, 0) + 1
207+
self._generate_bar_chart(commits, max_keys=self.max_diff,
208+
x_label_rotation=45)
209+
return True
210+
211+
def _chart_commits_day_week(self):
178212
"""Generate bar chart with commits by day of week."""
179213
# format of lines in stdout: Fri, 15 Mar 2013 18:27:55 +0100
180214
stdout = self._git_command(['git', 'log', '--date=rfc',
@@ -238,17 +272,7 @@ def _chart_commits_year_month(self):
238272
date += 89
239273
else:
240274
date += 1
241-
x_labels = sorted(commits)
242-
# if there are more than 20 commits, keep one x label on 10
243-
# (starting from the end)
244-
if len(commits) > 20:
245-
n = 0
246-
for i in range(len(x_labels) - 1, -1, -1):
247-
if n % 10 != 0:
248-
x_labels[i] = ''
249-
n += 1
250-
self._generate_bar_chart(commits, x_labels=x_labels,
251-
x_label_rotation=45)
275+
self._generate_bar_chart(commits, max_x_labels=30, x_label_rotation=45)
252276
return True
253277

254278
def _chart_commits_version(self):
@@ -290,7 +314,7 @@ def _chart_files_type(self):
290314
sum_others = 0
291315
for ext in sorted(extensions, key=extensions.get, reverse=True):
292316
count += 1
293-
if self.max_entries <= 0 or count <= self.max_entries:
317+
if self.max_diff <= 0 or count <= self.max_diff:
294318
pie_chart.add(ext + ' ({0})'.format(extensions[ext]),
295319
extensions[ext])
296320
else:
@@ -334,10 +358,17 @@ def main():
334358
help='override the default chart title')
335359
parser.add_argument('-r', '--repo', default='.',
336360
help='directory with git repository')
337-
parser.add_argument('-m', '--max', type=int, default=20,
361+
parser.add_argument('-d', '--max-diff', type=int, default=20,
338362
help='max different entries in chart: after this '
339-
'number, an entry is counted in "others" (only for '
340-
'charts "authors" and "files_type"), 0=unlimited')
363+
'number, an entry is counted in "others" (for charts '
364+
'authors and files_type); max number of days (for '
365+
'chart commits_day); 0=unlimited')
366+
parser.add_argument('-s', '--sort-max', type=int, default=0,
367+
help='keep max entries in chart and sort them by '
368+
'value; a negative number will reverse the sort '
369+
'(only for charts: commits_hour_day, commits_day, '
370+
'commits_day_week, commits_month, commits_year, '
371+
'commits_year_month, commits_version); 0=no sort/max')
341372
parser.add_argument('chart', metavar='chart',
342373
choices=sorted(GitChart.charts),
343374
help='name of chart, one of: ' +
@@ -362,8 +393,8 @@ def main():
362393
in_data += data.decode('utf-8')
363394

364395
# generate chart
365-
chart = GitChart(args.chart, args.title, args.repo, args.output, args.max,
366-
in_data)
396+
chart = GitChart(args.chart, args.title, args.repo, args.output,
397+
args.max_diff, args.sort_max, in_data)
367398
if chart.generate():
368399
sys.exit(0)
369400

0 commit comments

Comments
 (0)