5 from collections
import defaultdict
6 from sqlalchemy
.orm
import join
11 NOTES_INDEX
= '.git/git-notes-index'
13 'GIT_INDEX_FILE': NOTES_INDEX
,
15 NOTES_REF
= 'refs/heads/mailnotes'
17 _eol_space_re
= re
.compile('\s+$', re
.MULTILINE
)
18 def write_notes(commit_sha1
, notes
):
19 notes
= _eol_space_re
.sub('', notes
)
20 notes
= notes
.strip('\n')
21 blob_sha1
= git('hash-object', '-w', '--stdin', input=notes
)[0]
22 git('update-index', '--add', '--cacheinfo', '0644', blob_sha1
, commit_sha1
, env
=notes_env
)
25 previous
, ret
= git('rev-parse', NOTES_REF
)
30 args
= ['-p', previous
.strip()]
31 previous_arg
= [previous
.strip()]
32 tree_sha1
= git('write-tree', env
=notes_env
)[0].strip()
33 head_sha1
= git('commit-tree', tree_sha1
, *args
,
34 input='Mass annotation by notes.py')[0].strip()
35 git('update-ref', '-m', 'Mass annotation by notes.py',
36 NOTES_REF
, head_sha1
, *previous_arg
)
38 def split_and_tab(buf
):
40 for line
in str(buf
).splitlines():
41 ret
.append('\t%s\n' % line
)
44 def compute_notes(session
, commit
, mail
):
46 notes
.append('Mail-From: %s\n' % mail
.author
)
47 notes
.append('Message-Id: %s\n' % mail
.message_id
)
48 notes
.append('Posted-Date: %s\n'
49 % time
.strftime("%c", time
.localtime(mail
.post_date
)))
51 notes
.append('In-Reply-To: %s\n' % mail
.in_reply_to
)
53 notes
.append('References:\n')
54 for r
in mail
.references
:
55 notes
.append('\t%s\n' % r
.message_id
)
56 if len(mail
.patch
)>0 and mail
.patch
[0].extra_notes
:
57 notes
.append('Extra-notes:\n')
58 notes
.extend(split_and_tab(mail
.patch
[0].extra_notes
))
61 _merge_re
= re
.compile("^([a-f0-9]{40}) Merge branch '([^']+)'")
62 def _redo_pu(session
, notes
):
63 pu_ref
= git('rev-parse', 'origin/pu')[0].strip()
64 pu_topic
= session
.query(db
.Topic
).filter(db
.Topic
.name
== 'pu').first()
66 notes
[pu_ref
].append('Pu-Overview:\n')
67 notes
[pu_ref
].extend(split_and_tab(pu_topic
.cooking_notes
))
68 notes
[pu_ref
].append('\n')
69 for line
in git('log', '--first-parent', '--pretty=tformat:%H %s',
70 'origin/master..origin/pu', ret_pipe
=True):
71 m
= _merge_re
.match(line
)
76 t
= session
.query(db
.Topic
).filter(db
.Topic
.name
== branch
).first()
77 if t
and t
.cooking_notes
:
78 notes
[sha1
].append('Pu-Topic:\n')
79 notes
[sha1
].extend(split_and_tab(t
.cooking_notes
))
80 notes
[sha1
].append('\n')
82 def _redo_patches(session
, notes
):
84 for cmt
, mail
in (session
.query(db
.Commit
, db
.Mail
)
85 .select_from(join(db
.Mail
, db
.Commit
,
86 db
.Mail
.patch_id
==db
.Commit
.patch_id
))
87 .filter(db
.Commit
.upstream
==True)
88 .filter(db
.Mail
.has_patch
==True)):
89 nts
= compute_notes(session
, cmt
, mail
)
93 notes
[cmt
.sha1
].append('\n')
94 notes
[cmt
.sha1
].extend(nts
)
95 sys
.stdout
.write('\r%6d' % count
)
98 sys
.stdout
.write('\n')
101 session
= db
.Session()
103 notes
= defaultdict(list)
104 _redo_patches(session
, notes
)
105 _redo_pu(session
, notes
)
106 os
.unlink(NOTES_INDEX
)
108 for cmt
, nts
in notes
.iteritems():
109 sys
.stdout
.write('\r%6d' % count
)
111 write_notes(cmt
, ''.join(nts
))
113 sys
.stdout
.write('\n')
116 if __name__
== '__main__':
117 if len(sys
.argv
) > 1:
118 session
= db
.Session()
119 cmt
= session
.query(db
.Commit
).filter(db
.Commit
.sha1
==sys
.argv
[1]).one()
120 print compute_notes(session
, cmt
)