def blame(cls, repo, commit, file): """ The blame information for the given file at the given commit Returns list: [git.Commit, list: [<line>]] A list of tuples associating a Commit object with a list of lines that changed within the given commit. The Commit objects will be given in order of appearance. """ data = repo.git.blame(commit, '--', file, p=True) commits = {} blames = [] info = None for line in data.splitlines(): parts = re.split(r'\s+', line, 1) if re.search(r'^[0-9A-Fa-f]{40}$', parts[0]): if re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$', line): m = re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$', line) id, origin_line, final_line, group_lines = m.groups() info = {'id': id} blames.append([None, []]) elif re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$', line): m = re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$', line) id, origin_line, final_line = m.groups() info = {'id': id} elif re.search(r'^(author|committer)', parts[0]): if re.search(r'^(.+)-mail$', parts[0]): m = re.search(r'^(.+)-mail$', parts[0]) info["%s_email" % m.groups()[0]] = parts[-1] elif re.search(r'^(.+)-time$', parts[0]): m = re.search(r'^(.+)-time$', parts[0]) info["%s_date" % m.groups()[0]] = time.gmtime(int(parts[-1])) elif re.search(r'^(author|committer)$', parts[0]): m = re.search(r'^(author|committer)$', parts[0]) info[m.groups()[0]] = parts[-1] elif re.search(r'^filename', parts[0]): info['filename'] = parts[-1] elif re.search(r'^summary', parts[0]): info['summary'] = parts[-1] elif parts[0] == '': if info: c = commits.has_key(info['id']) and commits[info['id']] if not c: c = Commit(repo, id=info['id'], author=Actor.from_string(info['author'] + ' ' + info['author_email']), authored_date=info['author_date'], committer=Actor.from_string(info['committer'] + ' ' + info['committer_email']), committed_date=info['committer_date'], message=info['summary']) commits[info['id']] = c m = re.search(r'^\t(.*)$', line) text, = m.groups() blames[-1][0] = c blames[-1][1].append( text ) info = None return blames
def actor(cls, line): """ Parse out the actor (author or committer) info Returns [Actor, gmtime(acted at time)] """ m = re.search(r'^.+? (.*) (\d+) .*$', line) actor, epoch = m.groups() return [Actor.from_string(actor), time.gmtime(int(epoch))]
def blame(cls, repo, commit, file): """ The blame information for the given file at the given commit Returns list: [git.Commit, list: [<line>]] A list of tuples associating a Commit object with a list of lines that changed within the given commit. The Commit objects will be given in order of appearance. """ data = repo.git.blame(commit, '--', file, p=True) commits = {} blames = [] info = None for line in data.splitlines(): parts = re.split(r'\s+', line, 1) if re.search(r'^[0-9A-Fa-f]{40}$', parts[0]): if re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$', line): m = re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$', line) id, origin_line, final_line, group_lines = m.groups() info = {'id': id} blames.append([None, []]) elif re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$', line): m = re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$', line) id, origin_line, final_line = m.groups() info = {'id': id} elif re.search(r'^(author|committer)', parts[0]): if re.search(r'^(.+)-mail$', parts[0]): m = re.search(r'^(.+)-mail$', parts[0]) info["%s_email" % m.groups()[0]] = parts[-1] elif re.search(r'^(.+)-time$', parts[0]): m = re.search(r'^(.+)-time$', parts[0]) info["%s_date" % m.groups()[0]] = time.gmtime( int(parts[-1])) elif re.search(r'^(author|committer)$', parts[0]): m = re.search(r'^(author|committer)$', parts[0]) info[m.groups()[0]] = parts[-1] elif re.search(r'^filename', parts[0]): info['filename'] = parts[-1] elif re.search(r'^summary', parts[0]): info['summary'] = parts[-1] elif parts[0] == '': if info: c = commits.has_key(info['id']) and commits[info['id']] if not c: c = Commit( repo, id=info['id'], author=Actor.from_string(info['author'] + ' ' + info['author_email']), authored_date=info['author_date'], committer=Actor.from_string( info['committer'] + ' ' + info['committer_email']), committed_date=info['committer_date'], message=info['summary']) commits[info['id']] = c m = re.search(r'^\t(.*)$', line) text, = m.groups() blames[-1][0] = c blames[-1][1].append(text) info = None return blames