Details
Details
- Reviewers
- None
- Group Reviewers
hg-reviewers - Commits
- rHGd26a6706b070: notify: add option for deterministic message-id generation
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
hg-reviewers |
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | hgext/notify.py (29 lines) | |||
M | tests/test-notify.t (16 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
f08004c14fd1 | 69195b6f8f97 | Joerg Sonnenberger | Sep 7 2019, 6:49 AM |
notify.strip | notify.strip | ||||
Number of leading slashes to strip from url paths. By default, notifications | Number of leading slashes to strip from url paths. By default, notifications | ||||
reference repositories with their absolute path. ``notify.strip`` lets you | reference repositories with their absolute path. ``notify.strip`` lets you | ||||
turn them into relative paths. For example, ``notify.strip=3`` will change | turn them into relative paths. For example, ``notify.strip=3`` will change | ||||
``/long/path/repository`` into ``repository``. Default: 0. | ``/long/path/repository`` into ``repository``. Default: 0. | ||||
notify.domain | notify.domain | ||||
Default email domain for sender or recipients with no explicit domain. | Default email domain for sender or recipients with no explicit domain. | ||||
It is also used for the domain part of the ``Message-Id`` when using | |||||
``notify.messageidseed``. | |||||
notify.messageidseed | |||||
Create deterministic ``Message-Id`` headers for the mails based on the seed | |||||
and the revision identifier of the first commit in the changeset. | |||||
notify.style | notify.style | ||||
Style file to use when formatting emails. | Style file to use when formatting emails. | ||||
notify.template | notify.template | ||||
Template to use when formatting emails. | Template to use when formatting emails. | ||||
notify.incoming | notify.incoming | ||||
references. See also ``notify.strip``. | references. See also ``notify.strip``. | ||||
''' | ''' | ||||
from __future__ import absolute_import | from __future__ import absolute_import | ||||
import email.errors as emailerrors | import email.errors as emailerrors | ||||
import email.parser as emailparser | import email.parser as emailparser | ||||
import fnmatch | import fnmatch | ||||
import hashlib | |||||
import socket | import socket | ||||
import time | import time | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
logcmdutil, | logcmdutil, | ||||
default=None, | default=None, | ||||
) | ) | ||||
configitem('notify', 'diffstat', | configitem('notify', 'diffstat', | ||||
default=True, | default=True, | ||||
) | ) | ||||
configitem('notify', 'domain', | configitem('notify', 'domain', | ||||
default=None, | default=None, | ||||
) | ) | ||||
configitem('notify', 'messageidseed', | |||||
default=None, | |||||
) | |||||
configitem('notify', 'fromauthor', | configitem('notify', 'fromauthor', | ||||
default=None, | default=None, | ||||
) | ) | ||||
configitem('notify', 'incoming', | configitem('notify', 'incoming', | ||||
default=None, | default=None, | ||||
) | ) | ||||
configitem('notify', 'maxdiff', | configitem('notify', 'maxdiff', | ||||
default=300, | default=300, | ||||
self.root = self.strip(self.repo.root) | self.root = self.strip(self.repo.root) | ||||
self.domain = self.ui.config('notify', 'domain') | self.domain = self.ui.config('notify', 'domain') | ||||
self.mbox = self.ui.config('notify', 'mbox') | self.mbox = self.ui.config('notify', 'mbox') | ||||
self.test = self.ui.configbool('notify', 'test') | self.test = self.ui.configbool('notify', 'test') | ||||
self.charsets = mail._charsets(self.ui) | self.charsets = mail._charsets(self.ui) | ||||
self.subs = self.subscribers() | self.subs = self.subscribers() | ||||
self.merge = self.ui.configbool('notify', 'merge') | self.merge = self.ui.configbool('notify', 'merge') | ||||
self.showfunc = self.ui.configbool('notify', 'showfunc') | self.showfunc = self.ui.configbool('notify', 'showfunc') | ||||
self.messageidseed = self.ui.config('notify', 'messageidseed') | |||||
if self.showfunc is None: | if self.showfunc is None: | ||||
self.showfunc = self.ui.configbool('diff', 'showfunc') | self.showfunc = self.ui.configbool('diff', 'showfunc') | ||||
mapfile = None | mapfile = None | ||||
template = (self.ui.config('notify', hooktype) or | template = (self.ui.config('notify', hooktype) or | ||||
self.ui.config('notify', 'template')) | self.ui.config('notify', 'template')) | ||||
if not template: | if not template: | ||||
mapfile = self.ui.config('notify', 'style') | mapfile = self.ui.config('notify', 'style') | ||||
sender = self.ui.config('email', 'from') or self.ui.username() | sender = self.ui.config('email', 'from') or self.ui.username() | ||||
if '@' not in sender or '@localhost' in sender: | if '@' not in sender or '@localhost' in sender: | ||||
sender = self.fixmail(sender) | sender = self.fixmail(sender) | ||||
msg[r'From'] = encoding.strfromlocal( | msg[r'From'] = encoding.strfromlocal( | ||||
mail.addressencode(self.ui, sender, self.charsets, self.test)) | mail.addressencode(self.ui, sender, self.charsets, self.test)) | ||||
msg[r'X-Hg-Notification'] = r'changeset %s' % ctx | msg[r'X-Hg-Notification'] = r'changeset %s' % ctx | ||||
if not msg[r'Message-Id']: | if not msg[r'Message-Id']: | ||||
msg[r'Message-Id'] = encoding.strfromlocal( | msg[r'Message-Id'] = messageid(ctx, self.domain, self.messageidseed) | ||||
'<hg.%s.%d.%d@%s>' % (ctx, int(time.time()), | |||||
hash(self.repo.root), | |||||
encoding.strtolocal(socket.getfqdn()))) | |||||
msg[r'To'] = encoding.strfromlocal(', '.join(sorted(subs))) | msg[r'To'] = encoding.strfromlocal(', '.join(sorted(subs))) | ||||
msgtext = encoding.strtolocal(msg.as_string()) | msgtext = encoding.strtolocal(msg.as_string()) | ||||
if self.test: | if self.test: | ||||
self.ui.write(msgtext) | self.ui.write(msgtext) | ||||
if not msgtext.endswith('\n'): | if not msgtext.endswith('\n'): | ||||
self.ui.write('\n') | self.ui.write('\n') | ||||
else: | else: | ||||
data += ui.popbuffer() | data += ui.popbuffer() | ||||
fromauthor = ui.config('notify', 'fromauthor') | fromauthor = ui.config('notify', 'fromauthor') | ||||
if author and fromauthor: | if author and fromauthor: | ||||
data = '\n'.join(['From: %s' % author, data]) | data = '\n'.join(['From: %s' % author, data]) | ||||
if count: | if count: | ||||
n.send(ctx, count, data) | n.send(ctx, count, data) | ||||
def messageid(ctx, domain, messageidseed): | |||||
if domain and messageidseed: | |||||
host = domain | |||||
else: | |||||
host = encoding.strtolocal(socket.getfqdn()) | |||||
if messageidseed: | |||||
messagehash = hashlib.sha512(ctx.hex() + messageidseed) | |||||
messageid = '<hg.%s@%s>' % (messagehash.hexdigest()[:64], host) | |||||
else: | |||||
messageid = '<hg.%s.%d.%d@%s>' % (ctx, int(time.time()), | |||||
hash(ctx.repo().root), host) | |||||
return encoding.strfromlocal(messageid) |
notify.strip | notify.strip | ||||
Number of leading slashes to strip from url paths. By default, notifications | Number of leading slashes to strip from url paths. By default, notifications | ||||
reference repositories with their absolute path. "notify.strip" lets you | reference repositories with their absolute path. "notify.strip" lets you | ||||
turn them into relative paths. For example, "notify.strip=3" will change | turn them into relative paths. For example, "notify.strip=3" will change | ||||
"/long/path/repository" into "repository". Default: 0. | "/long/path/repository" into "repository". Default: 0. | ||||
notify.domain | notify.domain | ||||
Default email domain for sender or recipients with no explicit domain. | Default email domain for sender or recipients with no explicit domain. It is | ||||
also used for the domain part of the "Message-Id" when using | |||||
"notify.messageidseed". | |||||
notify.messageidseed | |||||
Create deterministic "Message-Id" headers for the mails based on the seed | |||||
and the revision identifier of the first commit in the changeset. | |||||
notify.style | notify.style | ||||
Style file to use when formatting emails. | Style file to use when formatting emails. | ||||
notify.template | notify.template | ||||
Template to use when formatting emails. | Template to use when formatting emails. | ||||
notify.incoming | notify.incoming | ||||
> [notify] | > [notify] | ||||
> maxsubject = 200 | > maxsubject = 200 | ||||
> EOF | > EOF | ||||
the python call below wraps continuation lines, which appear on Mac OS X 10.5 because | the python call below wraps continuation lines, which appear on Mac OS X 10.5 because | ||||
of the very long subject line | of the very long subject line | ||||
pull (minimal config) | pull (minimal config) | ||||
$ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py | $ hg --traceback --cwd b --config notify.domain=example.com --config notify.messageidseed=example pull ../a | "$PYTHON" $TESTTMP/filter.py | ||||
pulling from ../a | pulling from ../a | ||||
searching for changes | searching for changes | ||||
adding changesets | adding changesets | ||||
adding manifests | adding manifests | ||||
adding file changes | adding file changes | ||||
added 1 changesets with 2 changes to 2 files | added 1 changesets with 2 changes to 2 files | ||||
new changesets 00a13f371396 | new changesets 00a13f371396 | ||||
MIME-Version: 1.0 | MIME-Version: 1.0 | ||||
Content-Type: text/plain; charset="us-ascii" | Content-Type: text/plain; charset="us-ascii" | ||||
Content-Transfer-Encoding: 7bit | Content-Transfer-Encoding: 7bit | ||||
Date: * (glob) | Date: * (glob) | ||||
Subject: changeset in $TESTTMP/b: b | Subject: changeset in $TESTTMP/b: b | ||||
From: test | From: test@example.com | ||||
X-Hg-Notification: changeset 00a13f371396 | X-Hg-Notification: changeset 00a13f371396 | ||||
Message-Id: <*> (glob) | Message-Id: <hg.ba3098a36bd4c297288d16788623a841f81f618ea961a0f0fd65de7eb1191b66@example.com> | ||||
To: baz, foo@bar | To: baz@example.com, foo@bar | ||||
changeset 00a13f371396 in $TESTTMP/b | changeset 00a13f371396 in $TESTTMP/b | ||||
details: $TESTTMP/b?cmd=changeset;node=00a13f371396 | details: $TESTTMP/b?cmd=changeset;node=00a13f371396 | ||||
description: b | description: b | ||||
diffs (12 lines): | diffs (12 lines): | ||||
diff -r 0cd96de13884 -r 00a13f371396 a | diff -r 0cd96de13884 -r 00a13f371396 a |