X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=buildscripts%2Fgit-update-changelog.py;h=09f0d16b7afebad8214b9463cef4076fdc5f1301;hb=4e6d37762f033a5d89afc0b0848ef42914f7318f;hp=d1492cf5d882d74204499bb94a428d7370f30c80;hpb=c22bd1864da3f35016624fac4241bdea484bc64d;p=lilypond.git diff --git a/buildscripts/git-update-changelog.py b/buildscripts/git-update-changelog.py index d1492cf5d8..09f0d16b7a 100644 --- a/buildscripts/git-update-changelog.py +++ b/buildscripts/git-update-changelog.py @@ -9,6 +9,7 @@ import optparse def read_pipe (x): print 'pipe', x return os.popen (x).read () + def system (x): print x return os.system (x) @@ -16,6 +17,15 @@ def system (x): class PatchFailed(Exception): pass +def sign (x): + if x < 0: + return -1 + if x > 0: + return 1 + + return 0 + + class Commit: def __init__ (self, dict): for v in ('message', @@ -31,6 +41,46 @@ class Commit: self.email = m.group (2).strip () self.name = m.group (1).strip () self.diff = read_pipe ('git show %s' % self.committish) + def compare (self, other): + return sign (time.mktime (self.date) - time.mktime (other.date)) + + + def check_diff_chunk (self, filename, chunk): + removals = [] + def note_removal (m): + removals.append (m.group (1)) + + re.sub ('\n-([^\n]+)', note_removal, chunk) + + if removals == []: + return True + if not os.path.exists (filename): + return False + + contents = open (filename).read () + for r in removals: + if r not in contents: + return False + + return True + + def check_diff (self): + chunks = re.split ('\ndiff --git ', self.diff) + + ok = True + for c in chunks: + m = re.search ('^a/([^ ]+)', c) + if not m: + continue + + file = m.group (1) + + c = re.sub('\n--- [^\n]+', '', c) + ok = ok and self.check_diff_chunk (file, c) + if not ok: + break + + return ok def touched_files (self): files = [] @@ -45,6 +95,9 @@ class Commit: return files + def has_patch (self): + return self.touched_files () <> [] + def apply (self, add_del_files): def note_add_file (x): add_del_files.append (('add', x.group (1))) @@ -80,9 +133,17 @@ def parse_commit_log (log): c = Commit (locals ()) return c -def parse_add_changes (from_commit): - - log = read_pipe ('git log %(from_commit)s..' % locals ()) +def parse_add_changes (from_commit, max_count=0): + opt = '' + rest = '..' + if max_count: + + # fixme. + assert max_count == 1 + opt = '--max-count=%d' % max_count + rest = '' + + log = read_pipe ('git log %(opt)s %(from_commit)s%(rest)s' % locals ()) log = log[len ('commit '):] log = log.strip () @@ -100,7 +161,7 @@ def header (commit): return '%d-%02d-%02d %s <%s>\n' % (commit.date[:3] + (commit.name, commit.email)) def changelog_body (commit): - + s = '' s += ''.join ('\n* %s: ' % f for f in commit.touched_files()) s += '\n' + commit.message @@ -109,17 +170,19 @@ def changelog_body (commit): return s def main (): - p = optparse.OptionParser (usage="usage git-update-changelog.py [options]", + p = optparse.OptionParser (usage="usage git-update-changelog.py [options] [commits]", description=""" Apply GIT patches and update change log. -Run this file from the CVS directory, with --git-dir +Run this file from the CVS directory, with commits from the repository in --git-dir. + """) p.add_option ("--start", action='store', default='', + metavar="FIRST", dest="start", - help="start of log messages to merge.") + help="all commits starting with FIRST (exclusive).") p.add_option ("--git-dir", action='store', @@ -131,14 +194,21 @@ Run this file from the CVS directory, with --git-dir log = open ('ChangeLog').read () - if not options.start: - print 'Must set start committish.' - sys.exit (1) - if options.gitdir: os.environ['GIT_DIR'] = options.gitdir - - commits = parse_add_changes (options.start) + + + if not args: + if not options.start: + print 'Must set start committish.' + sys.exit (1) + + commits = parse_add_changes (options.start) + else: + commits = [] + for a in args: + commits += parse_add_changes (a, max_count=1) + if not commits: return @@ -149,10 +219,40 @@ Run this file from the CVS directory, with --git-dir if first == log[:len (first)]: log = log[len (first):] - file_adddel = [] - final_log = '' + try: + previously_done = dict((c, 1) for c in open ('.git-commits-done').read ().split ('\n')) + except IOError: + previously_done = {} + + commits = [c for c in commits if not previously_done.has_key (c.committish)] + commits = sorted (commits, cmp=Commit.compare) + + system ('cvs up') - for c in commits: + file_adddel = [] + collated_log = '' + collated_message = '' + commits_done = [] + while commits: + c = commits[0] + + if not c.has_patch (): + print 'patchless commit (merge?)' + continue + + ok = c.check_diff () + + if not ok: + print "Patch doesn't seem to apply" + print 'skipping', c.committish + print 'message:', c.message + + break + + + commits = commits[1:] + commits_done.append (c) + print 'patch ', c.committish try: c.apply (file_adddel) @@ -168,21 +268,23 @@ Run this file from the CVS directory, with --git-dir new_log += header (last_commit) - new_log = changelog_body (c) + new_log + collated_log = changelog_body (c) + collated_log last_commit = c - final_log += self.message + '\n' - + collated_message += c.message + '\n' + + for (op, f) in file_adddel: if op == 'del': system ('cvs remove %(f)s' % locals ()) if op == 'add': system ('cvs add %(f)s' % locals ()) - new_log = header (last_commit) + new_log + '\n' + if last_commit: + collated_log = header (last_commit) + collated_log + '\n' - log = new_log + log + log = collated_log + log try: os.unlink ('ChangeLog~') @@ -192,8 +294,16 @@ Run this file from the CVS directory, with --git-dir os.rename ('ChangeLog', 'ChangeLog~') open ('ChangeLog', 'w').write (log) - open ('.msg','w').write (final_log) - print 'cvs commit -F .msg ' + open ('.msg','w').write (collated_message) + print '\nCommit message\n**\n%s\n**\n' % collated_message + print '\nRun:\n\n\tcvs commit -F .msg\n\n' + print '\n\techo %s >> .git-commits-done\n\n' % ' '.join ([c.committish + for c in commits_done]) + + + if commits: + print 'Commits left to do:' + print ' '.join ([c.committish for c in commits]) main ()