##// END OF EJS Templates
hooklib: force an exception wrapped by errors.Abort to bytestr...
Matt Harbison -
r50760:5392bf25 default
parent child Browse files
Show More
@@ -1,143 +1,146 b''
1 1 # Copyright 2020 Joerg Sonnenberger <joerg@bec.de>
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5 """changeset_obsoleted is a hook to send a mail when an
6 6 existing draft changeset is obsoleted by an obsmarker without successor.
7 7
8 8 Correct message threading requires the same messageidseed to be used for both
9 9 the original notification and the new mail.
10 10
11 11 Usage:
12 12 [notify]
13 13 messageidseed = myseed
14 14
15 15 [hooks]
16 16 txnclose.changeset_obsoleted = \
17 17 python:hgext.hooklib.changeset_obsoleted.hook
18 18 """
19 19
20 20
21 21 import email.errors as emailerrors
22 22 import email.utils as emailutils
23 23
24 24 from mercurial.i18n import _
25 25 from mercurial import (
26 26 encoding,
27 27 error,
28 28 formatter,
29 29 logcmdutil,
30 30 mail,
31 31 obsutil,
32 32 pycompat,
33 33 registrar,
34 34 )
35 from mercurial.utils import dateutil
35 from mercurial.utils import (
36 dateutil,
37 stringutil,
38 )
36 39 from .. import notify
37 40
38 41 configtable = {}
39 42 configitem = registrar.configitem(configtable)
40 43
41 44 configitem(
42 45 b'notify_obsoleted',
43 46 b'domain',
44 47 default=None,
45 48 )
46 49 configitem(
47 50 b'notify_obsoleted',
48 51 b'messageidseed',
49 52 default=None,
50 53 )
51 54 configitem(
52 55 b'notify_obsoleted',
53 56 b'template',
54 57 default=b'''Subject: changeset abandoned
55 58
56 59 This changeset has been abandoned.
57 60 ''',
58 61 )
59 62
60 63
61 64 def _report_commit(ui, repo, ctx):
62 65 domain = ui.config(b'notify_obsoleted', b'domain') or ui.config(
63 66 b'notify', b'domain'
64 67 )
65 68 messageidseed = ui.config(
66 69 b'notify_obsoleted', b'messageidseed'
67 70 ) or ui.config(b'notify', b'messageidseed')
68 71 template = ui.config(b'notify_obsoleted', b'template')
69 72 spec = formatter.literal_templatespec(template)
70 73 templater = logcmdutil.changesettemplater(ui, repo, spec)
71 74 ui.pushbuffer()
72 75 n = notify.notifier(ui, repo, b'incoming')
73 76
74 77 subs = set()
75 78 for sub, spec in n.subs:
76 79 if spec is None:
77 80 subs.add(sub)
78 81 continue
79 82 revs = repo.revs(b'%r and %d:', spec, ctx.rev())
80 83 if len(revs):
81 84 subs.add(sub)
82 85 continue
83 86 if len(subs) == 0:
84 87 ui.debug(
85 88 b'notify_obsoleted: no subscribers to selected repo and revset\n'
86 89 )
87 90 return
88 91
89 92 templater.show(
90 93 ctx,
91 94 changes=ctx.changeset(),
92 95 baseurl=ui.config(b'web', b'baseurl'),
93 96 root=repo.root,
94 97 webroot=n.root,
95 98 )
96 99 data = ui.popbuffer()
97 100
98 101 try:
99 102 msg = mail.parsebytes(data)
100 103 except emailerrors.MessageParseError as inst:
101 raise error.Abort(inst)
104 raise error.Abort(stringutil.forcebytestr(inst))
102 105
103 106 msg['In-reply-to'] = notify.messageid(ctx, domain, messageidseed)
104 107 msg['Message-Id'] = notify.messageid(
105 108 ctx, domain, messageidseed + b'-obsoleted'
106 109 )
107 110 msg['Date'] = encoding.strfromlocal(
108 111 dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2")
109 112 )
110 113 if not msg['From']:
111 114 sender = ui.config(b'email', b'from') or ui.username()
112 115 if b'@' not in sender or b'@localhost' in sender:
113 116 sender = n.fixmail(sender)
114 117 msg['From'] = mail.addressencode(ui, sender, n.charsets, n.test)
115 118 msg['To'] = ', '.join(sorted(subs))
116 119
117 120 msgtext = msg.as_bytes()
118 121 if ui.configbool(b'notify', b'test'):
119 122 ui.write(msgtext)
120 123 if not msgtext.endswith(b'\n'):
121 124 ui.write(b'\n')
122 125 else:
123 126 ui.status(_(b'notify_obsoleted: sending mail for %d\n') % ctx.rev())
124 127 mail.sendmail(
125 128 ui, emailutils.parseaddr(msg['From'])[1], subs, msgtext, mbox=n.mbox
126 129 )
127 130
128 131
129 132 def has_successor(repo, rev):
130 133 return any(
131 134 r for r in obsutil.allsuccessors(repo.obsstore, [rev]) if r != rev
132 135 )
133 136
134 137
135 138 def hook(ui, repo, hooktype, node=None, **kwargs):
136 139 if hooktype != b"txnclose":
137 140 raise error.Abort(
138 141 _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)
139 142 )
140 143 for rev in obsutil.getobsoleted(repo, changes=kwargs['changes']):
141 144 ctx = repo.unfiltered()[rev]
142 145 if not has_successor(repo, ctx.node()):
143 146 _report_commit(ui, repo, ctx)
@@ -1,135 +1,138 b''
1 1 # Copyright 2020 Joerg Sonnenberger <joerg@bec.de>
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5 """changeset_published is a hook to send a mail when an
6 6 existing draft changeset is moved to the public phase.
7 7
8 8 Correct message threading requires the same messageidseed to be used for both
9 9 the original notification and the new mail.
10 10
11 11 Usage:
12 12 [notify]
13 13 messageidseed = myseed
14 14
15 15 [hooks]
16 16 txnclose-phase.changeset_published = \
17 17 python:hgext.hooklib.changeset_published.hook
18 18 """
19 19
20 20
21 21 import email.errors as emailerrors
22 22 import email.utils as emailutils
23 23
24 24 from mercurial.i18n import _
25 25 from mercurial import (
26 26 encoding,
27 27 error,
28 28 formatter,
29 29 logcmdutil,
30 30 mail,
31 31 pycompat,
32 32 registrar,
33 33 )
34 from mercurial.utils import dateutil
34 from mercurial.utils import (
35 dateutil,
36 stringutil,
37 )
35 38 from .. import notify
36 39
37 40 configtable = {}
38 41 configitem = registrar.configitem(configtable)
39 42
40 43 configitem(
41 44 b'notify_published',
42 45 b'domain',
43 46 default=None,
44 47 )
45 48 configitem(
46 49 b'notify_published',
47 50 b'messageidseed',
48 51 default=None,
49 52 )
50 53 configitem(
51 54 b'notify_published',
52 55 b'template',
53 56 default=b'''Subject: changeset published
54 57
55 58 This changeset has been published.
56 59 ''',
57 60 )
58 61
59 62
60 63 def _report_commit(ui, repo, ctx):
61 64 domain = ui.config(b'notify_published', b'domain') or ui.config(
62 65 b'notify', b'domain'
63 66 )
64 67 messageidseed = ui.config(
65 68 b'notify_published', b'messageidseed'
66 69 ) or ui.config(b'notify', b'messageidseed')
67 70 template = ui.config(b'notify_published', b'template')
68 71 spec = formatter.literal_templatespec(template)
69 72 templater = logcmdutil.changesettemplater(ui, repo, spec)
70 73 ui.pushbuffer()
71 74 n = notify.notifier(ui, repo, b'incoming')
72 75
73 76 subs = set()
74 77 for sub, spec in n.subs:
75 78 if spec is None:
76 79 subs.add(sub)
77 80 continue
78 81 revs = repo.revs(b'%r and %d:', spec, ctx.rev())
79 82 if len(revs):
80 83 subs.add(sub)
81 84 continue
82 85 if len(subs) == 0:
83 86 ui.debug(
84 87 b'notify_published: no subscribers to selected repo and revset\n'
85 88 )
86 89 return
87 90
88 91 templater.show(
89 92 ctx,
90 93 changes=ctx.changeset(),
91 94 baseurl=ui.config(b'web', b'baseurl'),
92 95 root=repo.root,
93 96 webroot=n.root,
94 97 )
95 98 data = ui.popbuffer()
96 99
97 100 try:
98 101 msg = mail.parsebytes(data)
99 102 except emailerrors.MessageParseError as inst:
100 raise error.Abort(inst)
103 raise error.Abort(stringutil.forcebytestr(inst))
101 104
102 105 msg['In-reply-to'] = notify.messageid(ctx, domain, messageidseed)
103 106 msg['Message-Id'] = notify.messageid(
104 107 ctx, domain, messageidseed + b'-published'
105 108 )
106 109 msg['Date'] = encoding.strfromlocal(
107 110 dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2")
108 111 )
109 112 if not msg['From']:
110 113 sender = ui.config(b'email', b'from') or ui.username()
111 114 if b'@' not in sender or b'@localhost' in sender:
112 115 sender = n.fixmail(sender)
113 116 msg['From'] = mail.addressencode(ui, sender, n.charsets, n.test)
114 117 msg['To'] = ', '.join(sorted(subs))
115 118
116 119 msgtext = msg.as_bytes()
117 120 if ui.configbool(b'notify', b'test'):
118 121 ui.write(msgtext)
119 122 if not msgtext.endswith(b'\n'):
120 123 ui.write(b'\n')
121 124 else:
122 125 ui.status(_(b'notify_published: sending mail for %d\n') % ctx.rev())
123 126 mail.sendmail(
124 127 ui, emailutils.parseaddr(msg['From'])[1], subs, msgtext, mbox=n.mbox
125 128 )
126 129
127 130
128 131 def hook(ui, repo, hooktype, node=None, **kwargs):
129 132 if hooktype != b"txnclose-phase":
130 133 raise error.Abort(
131 134 _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)
132 135 )
133 136 ctx = repo.unfiltered()[node]
134 137 if kwargs['oldphase'] == b'draft' and kwargs['phase'] == b'public':
135 138 _report_commit(ui, repo, ctx)
General Comments 0
You need to be logged in to leave comments. Login now