11 return os.popen (x).read ()
17 class PatchFailed(Exception):
21 def __init__ (self, dict):
26 self.__dict__[v] = dict[v]
28 self.date = ' '.join (self.date.split (' ')[:-1])
29 self.date = time.strptime (self.date, '%a %b %d %H:%M:%S %Y')
31 m = re.search ('(.*)<(.*)>', self.author)
32 self.email = m.group (2).strip ()
33 self.name = m.group (1).strip ()
34 self.diff = read_pipe ('git show %s' % self.committish)
36 def touched_files (self):
39 files.append (x.group (1))
42 re.sub ('\n--- a/([^\n]+)\n',
44 re.sub('\n--- /dev/null\n\\+\\+\\+ b/([^\n]+)',
50 return self.touched_files () <> []
52 def apply (self, add_del_files):
53 def note_add_file (x):
54 add_del_files.append (('add', x.group (1)))
57 def note_del_file (x):
58 add_del_files.append (('del', x.group (1)))
61 re.sub('\n--- /dev/null\n\\+\\+\\+ b/([^\n]+)',
62 note_add_file, self.diff)
64 re.sub('\n--- a/([^\n]+)\n\\+\\+\\+ /dev/null',
65 note_del_file, self.diff)
67 p = os.popen ('patch -f -p1 ', 'w')
71 raise PatchFailed, self.committish
74 def parse_commit_log (log):
75 committish = re.search ('^([^\n]+)', log).group (1)
76 author = re.search ('\nAuthor:\s+([^\n]+)', log).group (1)
77 date_match = re.search ('\nDate:\s+([^\n]+)', log)
78 date = date_match.group (1)
79 log = log[date_match.end (1):]
81 message = re.sub ("\n *", '', log)
82 message = message.strip ()
84 c = Commit (locals ())
87 def parse_add_changes (from_commit, max_count=0):
94 opt = '--max-count=%d' % max_count
97 log = read_pipe ('git log %(opt)s %(from_commit)s%(rest)s' % locals ())
99 log = log[len ('commit '):]
105 commits = map (parse_commit_log, re.split ('\ncommit ', log))
112 return '%d-%02d-%02d %s <%s>\n' % (commit.date[:3] + (commit.name, commit.email))
114 def changelog_body (commit):
116 s += ''.join ('\n* %s: ' % f for f in commit.touched_files())
117 s += '\n' + commit.message
119 s = s.replace ('\n', '\n\t')
124 p = optparse.OptionParser (usage="usage git-update-changelog.py [options]",
126 Apply GIT patches and update change log.
128 Run this file from the CVS directory, with --git-dir
130 p.add_option ("--start",
134 help="start of log messages to merge.")
136 p.add_option ("--git-dir",
140 help="the GIT directory to merge.")
142 (options, args) = p.parse_args ()
144 log = open ('ChangeLog').read ()
147 os.environ['GIT_DIR'] = options.gitdir
151 if not options.start:
152 print 'Must set start committish.'
155 commits = parse_add_changes (options.start)
159 commits += parse_add_changes (a, max_count=1)
167 first = header (commits[0]) + '\n'
168 if first == log[:len (first)]:
169 log = log[len (first):]
174 collated_message = ''
178 commits = commits[1:]
180 if not c.has_patch ():
181 print 'patchless commit (merge?)'
184 print 'patch ', c.committish
186 c.apply (file_adddel)
190 if c.touched_files () == ['ChangeLog']:
194 and c.author != last_commit.author
195 and c.date[:3] != last_commit.date[:3]):
197 new_log += header (last_commit)
199 collated_log = changelog_body (c) + collated_log
202 collated_message += c.message + '\n'
206 for (op, f) in file_adddel:
208 system ('cvs remove %(f)s' % locals ())
210 system ('cvs add %(f)s' % locals ())
213 collated_log = header (last_commit) + collated_log + '\n'
215 log = collated_log + log
218 os.unlink ('ChangeLog~')
222 os.rename ('ChangeLog', 'ChangeLog~')
223 open ('ChangeLog', 'w').write (log)
225 open ('.msg','w').write (collated_message)
226 print '\nCommit message\n**\n%s\n**\n' % collated_message
227 print '\nRun:\n\n\tcvs commit -F .msg\n\n'
231 print 'Commits left to do:'
232 print ' '.join ([c.committish for c in commits])