#!/usr/bin/env python print "NOT DONE -- just for testing" sys.exit(1) ################################################################## # # This is a script that takes as input a branch and a path and outputs # -- *very* efficiently via one git call -- two JSON strings. The # first contains information about all relevant commits, and the # second gives for each file at least its status code and last commit # to touch it. # # The path is *NOT* recursively walked, since it is important that # the size of the output stay manageable. # # The information about given in each list may grow as our needs # expand. # ################################################################## import json, os, subprocess, sys, uuid if len(sys.argv) < 2: print "Usage: %s <path> [branch]"%(sys.argv[0]) sys.exit(1) path = sys.argv[1] if not os.path.exists(path): print "path %s does not exist"%path sys.exit(1) if len(sys.argv) >= 3: branch = sys.argv[2] else: branch = "" logs = {} files = {} def set_file(obj, components, commit): if len(components) == 1: c = components[0] if c not in obj: # only record this the *first* time we see a file obj[c] = commit else: if not obj.has_key(components[0]): obj[components[0]] = {} set_file(obj[components[0]], components[1:], commit) # recurse def dir_exists(commits, files, d=None): """ Return a dictionary directory_name:true/false, where the value is true if the directory contains any non-deleted files and false otherwise. """ if d is None: d = {} for path, val in files.iteritems(): if isinstance(val, dict): # a directory d[path] = os.path.exists(path) dir_exists(commits, val, d) return d def go(): format = "--pretty=format:!%H|%an <%ae>|%ad|%s|" field_sep = str(uuid.uuid4()) commit_sep = str(uuid.uuid4()) format = format.replace('|',field_sep).replace("!",commit_sep) file_list = [os.path.listdir(path) log = subprocess.Popen(['git', 'log', '--name-status', format, branch, "--"] + file_list, stdin=subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE).stdout.read() commits = log.split(commit_sep) v = {} d = {} files[branch] = d commit_list = [] for entry in commits: if len(entry.strip()) == 0 : continue commit, author, date, message, modified_files= entry.split(field_sep) # modified_files = list of pairs (filename, status) modified_files = [(str(x[2:]).replace('\\\\"','"').replace('\\"',''),x[0]) for x in modified_files.splitlines() if x] meta = {'author':author, 'date':date, 'message':message, 'modified_files':dict(modified_files)} v[commit] = meta commit_list.append(commit) commit_id = commit for filename, status in modified_files: set_file(d, filename.split('/'), commit_id) logs[branch] = {'commit_list':commit_list, 'commits':v, 'dir_exists':dir_exists(v, d)} print json.dumps(logs, separators=(',',':')) print json.dumps(files, separators=(',',':'))