-
Notifications
You must be signed in to change notification settings - Fork 10
/
gitcount.py
executable file
·138 lines (111 loc) · 4 KB
/
gitcount.py
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
132
133
134
135
136
137
138
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
__version__ = '0.1.3'
from pipes import quote
from subprocess import Popen, PIPE
from datetime import date, timedelta
def count_git_log(range='', paths=None, options=None):
if options is None:
options = {}
options['oneline'] = True
shell_args = []
for k, v in list(options.items()):
if isinstance(v, bool) and v:
shell_args.append('--%s' % k.replace('_', '-'))
elif v:
shell_args.append('--%s=%s' % (k.replace('_', '-'), quote(v)))
if paths:
shell_args.append('-- %s' % paths)
popen = Popen('git log %s %s' %
(range, ' '.join(shell_args)), shell=True, stdout=PIPE)
if popen.wait():
return None
else:
return popen.stdout.read().count('\n')
DAY = timedelta(days=1)
WEEK = timedelta(weeks=1)
DATE_FORMAT = '%Y-%m-%d 00:00:00'
def count(author=None, period='weekly', first='monday', number=None, range='', paths=None, not_all=False, merges=False, **options):
'''It counts the commits in a Git repository.
-a, --author=<str> Specify an author.
-p, --period=<str> Specify the period: daily (d), weekly (w), monthly
(m) or yearly (y). Default is weekly.
-f, --first=<str> Specify the first day of weeks: monday (mon), sunday
(sun), saturday (sat). Default is monday.
-n, --number=<int> How many periods?
-r, --range=<str> Specify the range, ex. master..dev.
-t, --paths=<str> Specify the paths, ex. .gitignore.
--not-all Count the commits in current branch only.
--merges Include the merge commits.
The other arguments will be passed to the command, ``git log``.
'''
assert period[0] in 'dwmy', "option 'period' should be daily (d), weekly (w), monthly (m) or yearly (y)"
assert first[:3] in (
'mon', 'sun', 'sat'), "option 'first' should be monday (mon), sunday (sun), saturday (sat)"
today = date.today()
if period.startswith('d'):
until = today+DAY
if not number:
number = 14
elif period.startswith('w'):
until = today - today.weekday()*DAY + WEEK
if first[:3] == 'sun':
until -= DAY
elif first[:3] == 'sat':
until -= 2*DAY
if not number:
number = 8
elif period.startswith('m'):
until = date(
today.year+(today.month+1 > 12),
(today.month+1) % 12,
1
)
if not number:
number = 12
elif period.startswith('y'):
until = date(today.year+1, 1, 1)
if not number:
number = 5
options['author'] = author
options['all'] = not not_all
options['no_merges'] = not merges
while number > 0:
if period.startswith('d'):
since = until - DAY
elif period.startswith('w'):
since = until - WEEK
elif period.startswith('m'):
since = date(
until.year-(until.month-1 <= 0),
1 + ((12+(until.month-1)-1) % 12),
1
)
elif period.startswith('y'):
since = date(until.year-1, 1, 1)
options['since'] = since.strftime(DATE_FORMAT)
options['until'] = until.strftime(DATE_FORMAT)
count = count_git_log(range, paths, options)
if count is not None:
print('%s\t%s' % (since, count))
else:
return
until = since
number -= 1
def main():
try:
import clime
except ImportError:
clime = None
if clime and clime.__version__ >= '0.2':
clime.start({'count': count})
else:
import sys
print('It works better with Clime (>= 0.2). Visit http://clime.mosky.tw/ for more details.', file=sys.stderr)
if len(sys.argv) <= 1:
count()
else:
count(sys.argv[1])
if __name__ == '__main__':
main()