annotate hgext/hooklib/changeset_obsoleted.py @ 44440:4cabeea6d214

hgext: start building a library for simple hooks Many workflows depend on hooks to enforce certain policies, e.g. to prevent forced pushes. The Mercurial Guide includes some cases and Google can help finding others, but it can save users a lot of time if hg itself has a couple of examples for further customization. Differential Revision: https://phab.mercurial-scm.org/D6825
author Joerg Sonnenberger <joerg@bec.de>
date Sat, 07 Sep 2019 14:50:39 +0200
parents
children 04ef381000a8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44440
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
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
125 def hook(ui, repo, hooktype, node=None, **kwargs):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
126 if hooktype != b"pretxnclose":
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
127 raise error.Abort(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
128 _(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
129 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
130 for rev in obsutil.getobsoleted(repo, repo.currenttransaction()):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
131 _report_commit(ui, repo, repo.unfiltered()[rev])