#!/usr/bin/env python ''' This script attempts to extract what options have been added since the specified revision (usually a tag, but any revision that git recognizes may be provided). It accepts an optional second revision to use as the cut-off. The default is your LOCAL "master". Thus, you should ensure that this is up to date before running this script. This script works by extracting the set of options before and after every commit that affected ':src/options.h' and computing the differences. It should, therefore, be fairly robust (for example, options that moved around won't show up). However, if an option is removed and subsequently re-added, or if an option was added and subsequently removed, the resulting records will need to be reconciled manually. ''' import argparse import git import os import re import sys import time re_option = re.compile(r'extern (Bounded)?Option<[^>]+>') # ----------------------------------------------------------------------------- def extract_options(repo, blob_id): from git.util import hex_to_bin blob = git.Blob(repo, hex_to_bin(blob_id)) content = blob.data_stream.stream options = set() for line in iter(content.readline, b''): line = line.decode('utf-8').strip() if re_option.match(line): line = content.readline().decode('utf-8').strip() options.add(line.split(';')[0]) return options # ============================================================================= class Changeset(object): # ------------------------------------------------------------------------- def __init__(self, repo, sha): self.sha = sha self.added_options = set() self.removed_options = set() commit = repo.commit(sha) ad = time.gmtime(commit.authored_date) self.date = time.strftime('%b %d %Y', ad).replace(' 0', ' ') info = repo.git.log('-1', '--raw', '--abbrev=40', '--pretty=', sha, '--', ':src/options.h').split(' ') if len(info) < 5: return old_options = extract_options(repo, info[2]) new_options = extract_options(repo, info[3]) self.added_options = new_options.difference(old_options) self.removed_options = old_options.difference(new_options) # ----------------------------------------------------------------------------- def main(): parser = argparse.ArgumentParser( description='Generate changelog for new options') root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) parser.add_argument('--repo', type=str, default=root, help='Path to uncrustify git repository') parser.add_argument('since', type=str, help='Revision (tag) of previous uncrustify version') parser.add_argument('until', type=str, default='master', nargs='?', help='Revision (tag) of next uncrustify version') args = parser.parse_args() repo = git.Repo(args.repo) revs = repo.git.log('--pretty=%H', '--reverse', '{}..{}'.format(args.since, args.until), '--', ':src/options.h').split('\n') if revs == ['']: print('No changes were found') return 1 changes = [] for r in revs: c = Changeset(repo, r) if len(c.added_options) or len(c.removed_options): changes.append(c) for c in changes: print(c.sha) for o in c.added_options: print(' Added : {:36} {}'.format(o, c.date)) for o in c.removed_options: print(' Removed : {:36} {}'.format(o, c.date)) return 0 # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if __name__ == '__main__': sys.exit(main())