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 | ||||