First stab at annotating 'pu'
[trackgit.git] / notes.py
blob6f3804c56ddc7059ee2f2bf62f47cbf39d52c1a8
1 import os
2 import sys
3 import time
4 import re
5 from collections import defaultdict
6 from sqlalchemy.orm import join
8 import db
9 from git import git
11 NOTES_INDEX = '.git/git-notes-index'
12 notes_env = {
13 'GIT_INDEX_FILE': NOTES_INDEX,
15 NOTES_REF = 'refs/heads/mailnotes'
17 def write_notes(commit_sha1, notes):
18 blob_sha1 = git('hash-object', '-w', '--stdin', input=notes)[0]
19 git('update-index', '--add', '--cacheinfo', '0644', blob_sha1, commit_sha1, env=notes_env)
21 def finalize_notes():
22 previous, ret = git('rev-parse', NOTES_REF)
23 if ret != 0:
24 args = []
25 previous_arg = []
26 else:
27 args = ['-p', previous.strip()]
28 previous_arg = [previous.strip()]
29 tree_sha1 = git('write-tree', env=notes_env)[0].strip()
30 head_sha1 = git('commit-tree', tree_sha1, *args,
31 input='Mass annotation by notes.py')[0].strip()
32 git('update-ref', '-m', 'Mass annotation by notes.py',
33 NOTES_REF, head_sha1, *previous_arg)
35 def compute_notes(session, commit, mail):
36 notes = []
37 notes.append('Mail-From: %s\n' % mail.author)
38 notes.append('Message-Id: %s\n' % mail.message_id)
39 notes.append('Posted-Date: %s\n'
40 % time.strftime("%c", time.localtime(mail.post_date)))
41 if mail.in_reply_to:
42 notes.append('In-Reply-To: %s\n' % mail.in_reply_to)
43 if mail.references:
44 notes.append('References:\n')
45 for r in mail.references:
46 notes.append('\t%s\n' % r.message_id)
47 if len(mail.patch)>0 and mail.patch[0].extra_notes:
48 notes.append('Extra-notes:\n')
49 for line in str(mail.patch[0].extra_notes).splitlines():
50 notes.append('\t%s\n' % line)
51 return notes
53 _merge_re = re.compile("^([a-f0-9]{40}) Merge branch '([^']+)'")
54 def _redo_pu(session, notes):
55 pu_ref = git('rev-parse', 'origin/pu')[0].strip()
56 pu_topic = session.query(db.Topic).filter(db.Topic.name == 'pu').first()
57 if pu_topic:
58 notes[pu_ref].append(pu_topic.cooking_notes)
59 for line in git('log', '--first-parent', '--pretty=tformat:%H %s',
60 'origin/next..origin/pu', ret_pipe=True):
61 m = _merge_re.match(line)
62 if not m:
63 continue
64 sha1 = m.group(1)
65 branch = m.group(2)
66 t = session.query(db.Topic).filter(db.Topic.name == branch).first()
67 if t:
68 notes[sha1].append(t.cooking_notes)
70 def _redo_patches(session, notes):
71 for cmt, mail in (session.query(db.Commit, db.Mail)
72 .select_from(join(db.Mail, db.Commit,
73 db.Mail.patch_id==db.Commit.patch_id))
74 .filter(db.Commit.upstream==True)
75 .filter(db.Mail.has_patch==True)):
76 nts = compute_notes(session, cmt, mail)
77 if not nts:
78 continue
79 if notes[cmt.sha1]:
80 notes[cmt.sha1].append('\n')
81 notes[cmt.sha1].extend(nts)
82 sys.stdout.write('\r%6d' % count)
83 sys.stdout.flush()
84 count = count + 1
85 count = 0
86 sys.stdout.write('\n')
88 def _redo_all():
89 session = db.Session()
90 count = 0
91 notes = defaultdict(list)
92 _redo_patches(session, notes)
93 _redo_pu(session, notes)
94 os.unlink(NOTES_INDEX)
95 for cmt, nts in notes.iteritems():
96 sys.stdout.write('\r%6d' % count)
97 sys.stdout.flush()
98 write_notes(cmt, ''.join(nts))
99 count = count + 1
100 sys.stdout.write('\n')
101 finalize_notes()
103 if __name__ == '__main__':
104 if len(sys.argv) > 1:
105 session = db.Session()
106 cmt = session.query(db.Commit).filter(db.Commit.sha1==sys.argv[1]).one()
107 print compute_notes(session, cmt)
108 else:
109 _redo_all()