Fix pu notes into working shape
[trackgit.git] / notes.py
blob87cf9cd249d5c02e15a911f1d78b9c6db52b091f
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(str(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 and t.cooking_notes:
68 notes[sha1].append(str(t.cooking_notes))
70 def _redo_patches(session, notes):
71 count = 0
72 for cmt, mail in (session.query(db.Commit, db.Mail)
73 .select_from(join(db.Mail, db.Commit,
74 db.Mail.patch_id==db.Commit.patch_id))
75 .filter(db.Commit.upstream==True)
76 .filter(db.Mail.has_patch==True)):
77 nts = compute_notes(session, cmt, mail)
78 if not nts:
79 continue
80 if notes[cmt.sha1]:
81 notes[cmt.sha1].append('\n')
82 notes[cmt.sha1].extend(nts)
83 sys.stdout.write('\r%6d' % count)
84 sys.stdout.flush()
85 count = count + 1
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 count = 0
96 for cmt, nts in notes.iteritems():
97 sys.stdout.write('\r%6d' % count)
98 sys.stdout.flush()
99 write_notes(cmt, ''.join(nts))
100 count = count + 1
101 sys.stdout.write('\n')
102 finalize_notes()
104 if __name__ == '__main__':
105 if len(sys.argv) > 1:
106 session = db.Session()
107 cmt = session.query(db.Commit).filter(db.Commit.sha1==sys.argv[1]).one()
108 print compute_notes(session, cmt)
109 else:
110 _redo_all()