annotate hgext/hooklib/changeset_obsoleted.py @ 45090:0ecb3b11fcad

rebase: correctly check for empty commit in in-memory mode The new code has a small overhead in the empty commit case, as a `memctx` object is always created, but I don’t think it’s justified here to duplicate code to optimize a relatively unlikely code path. Differential Revision: https://phab.mercurial-scm.org/D8732
author Manuel Jacob <me@manueljacob.de>
date Sat, 11 Jul 2020 03:10:23 +0200
parents 04ef381000a8
children 3c2fae87bd5a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44413
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
1 # Copyright 2020 Joerg Sonnenberger <joerg@bec.de>
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
2 #
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
3 # This software may be used and distributed according to the terms of the
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
4 # GNU General Public License version 2 or any later version.
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
5 """changeset_obsoleted is a hook to send a mail when an
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
6 existing draft changeset is obsoleted by an obsmarker without successor.
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
7
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
8 Correct message threading requires the same messageidseed to be used for both
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
9 the original notification and the new mail.
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
10
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
11 Usage:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
12 [notify]
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
13 messageidseed = myseed
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
14
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
15 [hooks]
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
16 pretxnclose.changeset_obsoleted = \
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
17 python:hgext.hooklib.changeset_obsoleted.hook
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
18 """
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
19
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
20 from __future__ import absolute_import
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
21
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
22 import email.errors as emailerrors
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
23 import email.utils as emailutils
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
24
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
25 from mercurial.i18n import _
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
26 from mercurial import (
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
27 encoding,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
28 error,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
29 logcmdutil,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
30 mail,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
31 obsutil,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
32 pycompat,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
33 registrar,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
34 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
35 from mercurial.utils import dateutil
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
36 from .. import notify
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
37
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
38 configtable = {}
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
39 configitem = registrar.configitem(configtable)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
40
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
41 configitem(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
42 b'notify_obsoleted', b'domain', default=None,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
43 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
44 configitem(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
45 b'notify_obsoleted', b'messageidseed', default=None,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
46 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
47 configitem(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
48 b'notify_obsoleted',
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
49 b'template',
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
50 default=b'''Subject: changeset abandoned
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
51
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
52 This changeset has been abandoned.
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
53 ''',
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
54 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
55
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
56
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
57 def _report_commit(ui, repo, ctx):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
58 domain = ui.config(b'notify_obsoleted', b'domain') or ui.config(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
59 b'notify', b'domain'
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
60 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
61 messageidseed = ui.config(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
62 b'notify_obsoleted', b'messageidseed'
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
63 ) or ui.config(b'notify', b'messageidseed')
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
64 template = ui.config(b'notify_obsoleted', b'template')
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
65 spec = logcmdutil.templatespec(template, None)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
66 templater = logcmdutil.changesettemplater(ui, repo, spec)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
67 ui.pushbuffer()
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
68 n = notify.notifier(ui, repo, b'incoming')
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
69
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
70 subs = set()
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
71 for sub, spec in n.subs:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
72 if spec is None:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
73 subs.add(sub)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
74 continue
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
75 revs = repo.revs(b'%r and %d:', spec, ctx.rev())
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
76 if len(revs):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
77 subs.add(sub)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
78 continue
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
79 if len(subs) == 0:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
80 ui.debug(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
81 b'notify_obsoleted: no subscribers to selected repo and revset\n'
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
82 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
83 return
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
84
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
85 templater.show(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
86 ctx,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
87 changes=ctx.changeset(),
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
88 baseurl=ui.config(b'web', b'baseurl'),
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
89 root=repo.root,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
90 webroot=n.root,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
91 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
92 data = ui.popbuffer()
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
93
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
94 try:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
95 msg = mail.parsebytes(data)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
96 except emailerrors.MessageParseError as inst:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
97 raise error.Abort(inst)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
98
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
99 msg['In-reply-to'] = notify.messageid(ctx, domain, messageidseed)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
100 msg['Message-Id'] = notify.messageid(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
101 ctx, domain, messageidseed + b'-obsoleted'
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
102 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
103 msg['Date'] = encoding.strfromlocal(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
104 dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2")
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
105 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
106 if not msg['From']:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
107 sender = ui.config(b'email', b'from') or ui.username()
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
108 if b'@' not in sender or b'@localhost' in sender:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
109 sender = n.fixmail(sender)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
110 msg['From'] = mail.addressencode(ui, sender, n.charsets, n.test)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
111 msg['To'] = ', '.join(sorted(subs))
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
112
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
113 msgtext = msg.as_bytes() if pycompat.ispy3 else msg.as_string()
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
114 if ui.configbool(b'notify', b'test'):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
115 ui.write(msgtext)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
116 if not msgtext.endswith(b'\n'):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
117 ui.write(b'\n')
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
118 else:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
119 ui.status(_(b'notify_obsoleted: sending mail for %d\n') % ctx.rev())
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
120 mail.sendmail(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
121 ui, emailutils.parseaddr(msg['From'])[1], subs, msgtext, mbox=n.mbox
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
122 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
123
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
124
45075
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
125 def has_successor(repo, rev):
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
126 return any(
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
127 r for r in obsutil.allsuccessors(repo.obsstore, [rev]) if r != rev
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
128 )
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
129
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
130
44413
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
131 def hook(ui, repo, hooktype, node=None, **kwargs):
45075
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
132 if hooktype != b"txnclose":
44413
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
133 raise error.Abort(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
134 _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
135 )
45075
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
136 for rev in obsutil.getobsoleted(repo, changes=kwargs['changes']):
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
137 ctx = repo.unfiltered()[rev]
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
138 if not has_successor(repo, ctx.node()):
04ef381000a8 hooklib: fix detection of successors for changeset_obsoleted
Joerg Sonnenberger <joerg@bec.de>
parents: 44413
diff changeset
139 _report_commit(ui, repo, ctx)