Files
sics/site_ansto/instrument/util/gitrefer.py
2014-09-08 11:37:10 +10:00

161 lines
6.0 KiB
Python
Executable File

#!/usr/bin/python
# vim: tabstop=8 softtabstop=4 shiftwidth=4 nocindent smartindent
import os, sys
import sqlite3
import datetime
import subprocess
import shlex
import argparse
import string
def get_hash_from_file(filename):
"""Generate the git hash of a file"""
global debug
cmd = "git hash-object " + filename
hashtxt, err = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
hashtxt = hashtxt.splitlines()
err = err.splitlines()
if debug:
for line in hashtxt:
print " Txt: %s" % line
for line in err:
print " Err: %s" % line
obj_hash = hashtxt[0].strip()
if Verbose:
print "Hash:", obj_hash, filename
return obj_hash
def do_one_way(the_hashes):
global conn
global curs
conn = sqlite3.connect("gitxref.sqlite")
curs = conn.cursor()
blob_map = {}
commit_map = {}
select = "select blob_hash, blob_name, c.commit_hash, timestamp, message "+\
"from blob_tab b, commit_tab c "+\
"where b.blob_hash == :1 and b.commit_hash == c.commit_hash "+\
"order by timestamp"
for one_hash in the_hashes:
curs.execute(select, (one_hash,))
old_hash = None
for blob_hash, blob_name, commit_hash, timestamp, message in curs.fetchall():
if blob_hash != old_hash:
if Verbose:
print "File:", blob_hash, blob_name
old_hash = blob_hash
if blob_hash not in blob_map:
blob_map[blob_hash] = (blob_name, set())
blob_map[blob_hash][1].add(commit_hash)
if commit_hash not in commit_map:
commit_map[commit_hash] = (timestamp, message, set())
commit_map[commit_hash][2].add(blob_hash)
if len(message) > 60:
message = message[:57] + "..."
timestamp = datetime.datetime.fromtimestamp(timestamp)
if Verbose:
print " Commit:", commit_hash, timestamp, message
commit_union = set(commit_map.keys())
junk = sorted(commit_map.keys(),\
key=lambda x: (len(commit_map[x][2]), -commit_map[x][0]),\
reverse=True)
for blob_key in blob_map.keys():
blob_name, commit_set = blob_map[blob_key]
commit_union.intersection_update(commit_set)
if len(commit_union) == 0:
print "Recalculating commit_map"
for commit_key in sorted(commit_map.keys(), key=lambda x: len(commit_map[x][2]), reverse=True):
timestamp, message, blobs = commit_map[commit_key]
if len(commit_union) == 0:
blob_union = set(blobs)
if len(blob_union.intersection(blobs)) < len(blob_union):
break;
commit_union.add(commit_key)
if 1 in Summary:
print "Summary1: Files with Commits"
for blob_key in blob_map.keys():
blob_name, commit_set = blob_map[blob_key]
print blob_key +":", blob_name, len(commit_set)
if 2 in Summary:
print "Summary2: Commits with most files"
for commit_key in sorted(commit_union, key=lambda x: commit_map[x][0]):
timestamp, message, blobs = commit_map[commit_key]
timestamp = datetime.datetime.fromtimestamp(timestamp)
if len(message) > 50:
message = message[:47] + "..."
print " Commit:", commit_key, timestamp, len(blobs), message
if 3 in Summary:
print "Summary3: Commits with files"
for commit_key in sorted(commit_map.keys(), key=lambda x: commit_map[x][0]):
timestamp, message, blobs = commit_map[commit_key]
timestamp = datetime.datetime.fromtimestamp(timestamp)
if len(message) > 60:
message = message[:57] + "..."
print " Commit:", commit_key, timestamp, len(blobs), message
if 4 in Summary:
print "Summary4: Files not in Summary 2"
for blob_key in blob_map.keys():
blob_name, commit_set = blob_map[blob_key]
if len(commit_union.intersection(commit_set)) == 0:
print "\n"+blob_key +":", blob_name, len(commit_set), commit_set
if 5 in Summary:
print "Summary5: Files without Commits"
for hash_key in [x for x in hash_map.keys() if x not in blob_map]:
print hash_key, hash_map[hash_key]
def do_args():
global hash_map, args
the_hashes = []
hash_map = {}
for filename in args.filenames:
if '.' in filename:
one_hash = get_hash_from_file(filename)
hash_map[one_hash] = filename
the_hashes.append(one_hash)
elif all(a in string.hexdigits for a in filename):
the_hashes.append(filename)
do_one_way(the_hashes)
def main_program():
global debug, Verbose, Summary
global hash_map, args
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", help="Add debugging output", action="store_true")
parser.add_argument("-p", "--profile", help="Add profile output", action="store_true")
parser.add_argument("-v", "--verbose", help="Add verbose output", action="store_true")
parser.add_argument("-s", "--summary", \
default = "2", \
help="select summary")
parser.add_argument("filenames", metavar="file", help="existing filename(s)", nargs="+")
args = parser.parse_args()
if args.debug:
debug = True
else:
debug = False
if args.verbose:
Verbose = True
else:
Verbose = False
if Verbose or debug:
print args
Summary = set()
for rng in [x.strip() for x in args.summary.split(',')]:
if '-' in rng:
lo, hi = rng.split('-')
if lo.isdigit() and hi.isdigit():
for idx in range(int(lo), int(hi)+1):
Summary.add(idx)
else:
if rng.isdigit():
Summary.add(int(rng))
print "Summary:", Summary
if args.profile:
import cProfile
cProfile.run('do_args()')
else:
do_args()
if __name__ == "__main__":
main_program();