Browse Source

runs with msysgit on Win32

Signed-off-by: Heikki Hokkanen <hoxu@users.sf.net>
Shixin Zeng 17 years ago
parent
commit
a01045f248
1 changed files with 51 additions and 19 deletions
  1. 51
    19
      gitstats

+ 51
- 19
gitstats View File

1
 #!/usr/bin/env python
1
 #!/usr/bin/env python
2
 # Copyright (c) 2007 Heikki Hokkanen <hoxu@users.sf.net>
2
 # Copyright (c) 2007 Heikki Hokkanen <hoxu@users.sf.net>
3
 # GPLv2
3
 # GPLv2
4
-import commands
4
+import subprocess
5
 import datetime
5
 import datetime
6
 import glob
6
 import glob
7
 import os
7
 import os
10
 import sys
10
 import sys
11
 import time
11
 import time
12
 
12
 
13
+GNUPLOT = 'c:/tools/gnuplot/bin/wgnuplot_pipes.exe'
13
 GNUPLOT_COMMON = 'set terminal png transparent\nset size 0.5,0.5\n'
14
 GNUPLOT_COMMON = 'set terminal png transparent\nset size 0.5,0.5\n'
14
 
15
 
15
 exectime_internal = 0.0
16
 exectime_internal = 0.0
16
 exectime_external = 0.0
17
 exectime_external = 0.0
17
 time_start = time.time()
18
 time_start = time.time()
18
 
19
 
19
-def getoutput(cmd, quiet = False):
20
+def getpipeoutput(cmds, quiet = False):
21
+	def beautify_name(cmds):
22
+		ret = cmds[0]
23
+		for x in cmds[1:]:
24
+			ret += ' | ' + x
25
+		return ret
26
+		
20
 	global exectime_external
27
 	global exectime_external
21
 	start = time.time()
28
 	start = time.time()
22
 	if not quiet:
29
 	if not quiet:
23
-		print '>> %s' % cmd,
30
+		print '>> ', beautify_name(cmds)
24
 		sys.stdout.flush()
31
 		sys.stdout.flush()
25
-	output = commands.getoutput(cmd)
32
+	p0 = subprocess.Popen(cmds[0], stdout = subprocess.PIPE)
33
+	p = p0
34
+	for x in cmds[1:]:
35
+		p = subprocess.Popen(x, stdin = p0.stdout, stdout = subprocess.PIPE)
36
+		p0 = p
37
+	output = p.communicate()[0]
26
 	end = time.time()
38
 	end = time.time()
27
 	if not quiet:
39
 	if not quiet:
28
-		print '\r[%.5f] >> %s' % (end - start, cmd)
40
+		print '\r[%.5f] >> %s' % (end - start, beautify_name(cmds))
29
 	exectime_external += (end - start)
41
 	exectime_external += (end - start)
30
-	return output
42
+	return output.rstrip('\n')
31
 
43
 
32
 def getkeyssortedbyvalues(dict):
44
 def getkeyssortedbyvalues(dict):
33
 	return map(lambda el : el[1], sorted(map(lambda el : (el[1], el[0]), dict.items())))
45
 	return map(lambda el : el[1], sorted(map(lambda el : (el[1], el[0]), dict.items())))
97
 	def collect(self, dir):
109
 	def collect(self, dir):
98
 		DataCollector.collect(self, dir)
110
 		DataCollector.collect(self, dir)
99
 
111
 
100
-		self.total_authors = int(getoutput('git-log |git-shortlog -s |wc -l'))
112
+		try:
113
+			self.total_authors = int(getpipeoutput(('git-log', 'git-shortlog -s', 'wc -l')))
114
+		except:
115
+			self.total_authors = 0
101
 		#self.total_lines = int(getoutput('git-ls-files -z |xargs -0 cat |wc -l'))
116
 		#self.total_lines = int(getoutput('git-ls-files -z |xargs -0 cat |wc -l'))
102
 
117
 
103
 		self.activity_by_hour_of_day = {} # hour -> commits
118
 		self.activity_by_hour_of_day = {} # hour -> commits
117
 
132
 
118
 		# tags
133
 		# tags
119
 		self.tags = {}
134
 		self.tags = {}
120
-		lines = getoutput('git-show-ref --tags').split('\n')
135
+		lines = getpipeoutput((('git-show-ref', '--tags'),)).split('\n')
121
 		for line in lines:
136
 		for line in lines:
122
 			if len(line) == 0:
137
 			if len(line) == 0:
123
 				continue
138
 				continue
124
-			(hash, tag) = line.split(' ')
139
+			print "line = ", line
140
+			splitted_str = line.split(' ')
141
+			print "splitted_str = ", splitted_str
142
+			(hash, tag) = splitted_str
143
+
125
 			tag = tag.replace('refs/tags/', '')
144
 			tag = tag.replace('refs/tags/', '')
126
-			output = getoutput('git-log "%s" --pretty=format:"%%at %%an" -n 1' % hash)
145
+			output = getpipeoutput((('git-log', '"%s" --pretty=format:"%%at %%an" -n 1' % hash),))
127
 			if len(output) > 0:
146
 			if len(output) > 0:
128
 				parts = output.split(' ')
147
 				parts = output.split(' ')
129
 				stamp = 0
148
 				stamp = 0
136
 
155
 
137
 		# Collect revision statistics
156
 		# Collect revision statistics
138
 		# Outputs "<stamp> <author>"
157
 		# Outputs "<stamp> <author>"
139
-		lines = getoutput('git-rev-list --pretty=format:"%at %an" HEAD |grep -v ^commit').split('\n')
158
+		lines = getpipeoutput(('git-rev-list --pretty=format:"%at %an" HEAD', 'grep -v ^commit')).split('\n')
140
 		for line in lines:
159
 		for line in lines:
141
 			# linux-2.6 says "<unknown>" for one line O_o
160
 			# linux-2.6 says "<unknown>" for one line O_o
142
 			parts = line.split(' ')
161
 			parts = line.split(' ')
144
 			try:
163
 			try:
145
 				stamp = int(parts[0])
164
 				stamp = int(parts[0])
146
 			except ValueError:
165
 			except ValueError:
166
+				print "lines = ", lines
167
+				print "line = ", line
168
+				raise
147
 				stamp = 0
169
 				stamp = 0
148
 			if len(parts) > 1:
170
 			if len(parts) > 1:
149
 				author = ' '.join(parts[1:])
171
 				author = ' '.join(parts[1:])
228
 		# TODO Optimize this, it's the worst bottleneck
250
 		# TODO Optimize this, it's the worst bottleneck
229
 		# outputs "<stamp> <files>" for each revision
251
 		# outputs "<stamp> <files>" for each revision
230
 		self.files_by_stamp = {} # stamp -> files
252
 		self.files_by_stamp = {} # stamp -> files
231
-		lines = getoutput('git-rev-list --pretty=format:"%at %H" HEAD |grep -v ^commit |while read line; do set $line; echo "$1 $(git-ls-tree -r "$2" |wc -l)"; done').split('\n')
253
+		lines = getpipeoutput(('git-rev-list --pretty=format:"%at %H" HEAD',
254
+				       'grep -v ^commit')).strip().split('\n')
255
+		#'sh while read line; do set $line; echo "$1 $(git-ls-tree -r "$2" |wc -l)"; done')).split('\n')
256
+		tmp = [None] * len(lines)
257
+		for idx in xrange(len(lines)):
258
+			(a, b) = lines[idx].split(" ")
259
+			tmp[idx] = a + getpipeoutput(('git-ls-tree -r ' + b, 'wc -l')).strip('\n')
260
+		lines = tmp
261
+
232
 		self.total_commits = len(lines)
262
 		self.total_commits = len(lines)
233
 		for line in lines:
263
 		for line in lines:
234
 			parts = line.split(' ')
264
 			parts = line.split(' ')
242
 
272
 
243
 		# extensions
273
 		# extensions
244
 		self.extensions = {} # extension -> files, lines
274
 		self.extensions = {} # extension -> files, lines
245
-		lines = getoutput('git-ls-files').split('\n')
275
+		lines = getpipeoutput(('git-ls-files',)).split('\n')
246
 		self.total_files = len(lines)
276
 		self.total_files = len(lines)
247
 		for line in lines:
277
 		for line in lines:
248
 			base = os.path.basename(line)
278
 			base = os.path.basename(line)
257
 			self.extensions[ext]['files'] += 1
287
 			self.extensions[ext]['files'] += 1
258
 			try:
288
 			try:
259
 				# Escaping could probably be improved here
289
 				# Escaping could probably be improved here
260
-				self.extensions[ext]['lines'] += int(getoutput('wc -l < %s' % re.sub(r'(\W)', r'\\\1', line), quiet = True))
290
+				self.extensions[ext]['lines'] += int(getpipeoutput(('wc -l "%s"' % line,)).split()[0])
261
 			except:
291
 			except:
262
 				print 'Warning: Could not count lines for file "%s"' % line
292
 				print 'Warning: Could not count lines for file "%s"' % line
263
 
293
 
266
 		#  N files changed, N insertions (+), N deletions(-)
296
 		#  N files changed, N insertions (+), N deletions(-)
267
 		# <stamp> <author>
297
 		# <stamp> <author>
268
 		self.changes_by_date = {} # stamp -> { files, ins, del }
298
 		self.changes_by_date = {} # stamp -> { files, ins, del }
269
-		lines = getoutput('git-log --shortstat --pretty=format:"%at %an"').split('\n')
299
+		lines = getpipeoutput(('git-log --shortstat --pretty=format:"%at %an"',)).split('\n')
270
 		lines.reverse()
300
 		lines.reverse()
271
 		files = 0; inserted = 0; deleted = 0; total_lines = 0
301
 		files = 0; inserted = 0; deleted = 0; total_lines = 0
272
 		for line in lines:
302
 		for line in lines:
330
 		return datetime.datetime.fromtimestamp(self.last_commit_stamp)
360
 		return datetime.datetime.fromtimestamp(self.last_commit_stamp)
331
 	
361
 	
332
 	def getTags(self):
362
 	def getTags(self):
333
-		lines = getoutput('git-show-ref --tags |cut -d/ -f3')
363
+		lines = getpipeoutput(('git-show-ref --tags',
364
+				       'cut -d/ -f3'))
334
 		return lines.split('\n')
365
 		return lines.split('\n')
335
 	
366
 	
336
 	def getTagDate(self, tag):
367
 	def getTagDate(self, tag):
349
 		return self.total_lines
380
 		return self.total_lines
350
 	
381
 	
351
 	def revToDate(self, rev):
382
 	def revToDate(self, rev):
352
-		stamp = int(getoutput('git-log --pretty=format:%%at "%s" -n 1' % rev))
383
+		stamp = int(getpipeoutput(('git-log --pretty=format:%%at "%s" -n 1' % rev,)))
353
 		return datetime.datetime.fromtimestamp(stamp).strftime('%Y-%m-%d')
384
 		return datetime.datetime.fromtimestamp(stamp).strftime('%Y-%m-%d')
354
 
385
 
355
 class ReportCreator:
386
 class ReportCreator:
375
 
406
 
376
 		# TODO copy the CSS if it does not exist
407
 		# TODO copy the CSS if it does not exist
377
 		if not os.path.exists(path + '/gitstats.css'):
408
 		if not os.path.exists(path + '/gitstats.css'):
378
-			shutil.copyfile('gitstats.css', path + '/gitstats.css')
409
+			basedir = os.path.dirname(os.path.abspath(__file__))
410
+			shutil.copyfile(basedir + '/gitstats.css', path + '/gitstats.css')
379
 			pass
411
 			pass
380
 
412
 
381
 		f = open(path + "/index.html", 'w')
413
 		f = open(path + "/index.html", 'w')
775
 		os.chdir(path)
807
 		os.chdir(path)
776
 		files = glob.glob(path + '/*.plot')
808
 		files = glob.glob(path + '/*.plot')
777
 		for f in files:
809
 		for f in files:
778
-			out = getoutput('gnuplot %s' % f)
810
+			out = getpipeoutput((GNUPLOT + ' "%s"' % f,))
779
 			if len(out) > 0:
811
 			if len(out) > 0:
780
 				print out
812
 				print out
781
 
813