10 return os.popen (x).read ()
15 class PatchFailed(Exception):
19 def __init__ (self, dict):
24 self.__dict__[v] = dict[v]
26 # Sat Oct 28 18:52:30 2006 +0200
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)
35 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]+)',
49 def apply (self, add_del_files):
50 def note_add_file (x):
51 add_del_files.append (('add', x.group (1)))
54 def note_del_file (x):
55 add_del_files.append (('del', x.group (1)))
59 re.sub('\n--- /dev/null\n\\+\\+\\+ b/([^\n]+)',
60 note_add_file, self.diff)
62 re.sub('\n--- a/([^\n]+)\n\\+\\+\\+ /dev/null',
63 note_del_file, self.diff)
65 p = os.popen ('patch -f -p1 ', 'w')
69 raise PatchFailed, self.committish
72 def parse_commit_log (log):
73 committish = re.search ('^([^\n]+)', log).group (1)
74 author = re.search ('\nAuthor:\s+([^\n]+)', log).group (1)
75 date_match = re.search ('\nDate:\s+([^\n]+)', log)
76 date = date_match.group (1)
77 log = log[date_match.end (1):]
79 message = re.sub ("\n *", '', log)
80 message = message.strip ()
82 c = Commit (locals ())
85 def parse_add_changes (from_commit):
87 log = read_pipe ('git log %(from_commit)s..' % locals ())
89 log = log[len ('commit '):]
95 commits = map (parse_commit_log, re.split ('\ncommit ', log))
102 return '%d-%02d-%02d %s <%s>\n' % (commit.date[:3] + (commit.name, commit.email))
104 def changelog_body (commit):
107 s += "\ngit commit %s\n" % commit.committish
108 s += ''.join ('\n* %s: ' % f for f in commit.touched_files())
109 s += '\n' + commit.message
111 s = s.replace ('\n', '\n\t')
115 def find_last_checked_in_commit (log):
116 m = re.match ('^(\\d+-\\d+-\\d+)[^\n]+\n*\tgit commit ([a-f0-9]+)', log)
119 return (m.group (1), m.group (2))
127 p = optparse.OptionParser (usage="usage git-update-changelog.py [options]",
129 Apply GIT patches and update change log.
131 Run this file from the CVS directory, with --git-dir
133 p.add_option ("--start",
137 help="start of log messages to merge.")
139 p.add_option ("--git-dir",
143 help="the GIT directory to merge.")
145 (options, args) = p.parse_args ()
147 log = open ('ChangeLog').read ()
149 if not options.start:
150 (time, id) = find_last_checked_in_commit (log)
153 print 'processing commits from ', id, options.start
156 os.environ['GIT_DIR'] = options.gitdir
158 commits = parse_add_changes (options.start)
165 first = header (commits[0]) + '\n'
166 if first == log[:len (first)]:
167 log = log[len (first):]
171 print 'patch ', c.committish
173 c.apply (file_adddel)
177 if c.touched_files () == ['ChangeLog']:
181 and c.author != last_commit.author
182 and c.date[:3] != last_commit.date[:3]):
184 new_log += header (last_commit)
186 new_log += changelog_body (c)
189 for (op, f) in file_adddel:
191 system ('cvs remove %(f)s' % locals ())
193 system ('cvs add %(f)s' % locals ())
195 new_log = header (last_commit) + new_log + '\n'
200 os.unlink ('ChangeLog~')
204 os.rename ('ChangeLog', 'ChangeLog~')
205 open ('ChangeLog', 'w').write (log)