def _parsecatlog(self, data, rev): try: catlog = mail.parsebytes(data) # Commit date self.changes[rev].date = dateutil.datestr( dateutil.strdate(catlog['Standard-date'], b'%Y-%m-%d %H:%M:%S')) # Commit author self.changes[rev].author = self.recode(catlog['Creator']) # Commit description self.changes[rev].summary = b'\n\n'.join(( self.recode(catlog['Summary']), self.recode(catlog.get_payload()), )) self.changes[rev].summary = self.recode(self.changes[rev].summary) # Commit revision origin when dealing with a branch or tag if 'Continuation-of' in catlog: self.changes[rev].continuationof = self.recode( catlog['Continuation-of']) except Exception: raise error.Abort(_(b'could not parse cat-log of %s') % rev)
def _report_commit(ui, repo, ctx): domain = ui.config(b'notify_published', b'domain') or ui.config( b'notify', b'domain') messageidseed = ui.config(b'notify_published', b'messageidseed') or ui.config( b'notify', b'messageidseed') template = ui.config(b'notify_published', b'template') spec = formatter.literal_templatespec(template) templater = logcmdutil.changesettemplater(ui, repo, spec) ui.pushbuffer() n = notify.notifier(ui, repo, b'incoming') subs = set() for sub, spec in n.subs: if spec is None: subs.add(sub) continue revs = repo.revs(b'%r and %d:', spec, ctx.rev()) if len(revs): subs.add(sub) continue if len(subs) == 0: ui.debug( b'notify_published: no subscribers to selected repo and revset\n') return templater.show( ctx, changes=ctx.changeset(), baseurl=ui.config(b'web', b'baseurl'), root=repo.root, webroot=n.root, ) data = ui.popbuffer() try: msg = mail.parsebytes(data) except emailerrors.MessageParseError as inst: raise error.Abort(inst) msg['In-reply-to'] = notify.messageid(ctx, domain, messageidseed) msg['Message-Id'] = notify.messageid(ctx, domain, messageidseed + b'-published') msg['Date'] = encoding.strfromlocal( dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2")) if not msg['From']: sender = ui.config(b'email', b'from') or ui.username() if b'@' not in sender or b'@localhost' in sender: sender = n.fixmail(sender) msg['From'] = mail.addressencode(ui, sender, n.charsets, n.test) msg['To'] = ', '.join(sorted(subs)) msgtext = msg.as_bytes() if pycompat.ispy3 else msg.as_string() if ui.configbool(b'notify', b'test'): ui.write(msgtext) if not msgtext.endswith(b'\n'): ui.write(b'\n') else: ui.status(_(b'notify_published: sending mail for %d\n') % ctx.rev()) mail.sendmail(ui, emailutils.parseaddr(msg['From'])[1], subs, msgtext, mbox=n.mbox)
def send(self, ctx, count, data): '''send message.''' # Select subscribers by revset subs = set() for sub, spec in self.subs: if spec is None: subs.add(sub) continue revs = self.repo.revs(b'%r and %d:', spec, ctx.rev()) if len(revs): subs.add(sub) continue if len(subs) == 0: self.ui.debug( b'notify: no subscribers to selected repo and revset\n') return try: msg = mail.parsebytes(data) except emailerrors.MessageParseError as inst: raise error.Abort(inst) # store sender and subject sender = msg[r'From'] subject = msg[r'Subject'] if sender is not None: sender = mail.headdecode(sender) if subject is not None: subject = mail.headdecode(subject) del msg[r'From'], msg[r'Subject'] if not msg.is_multipart(): # create fresh mime message from scratch # (multipart templates must take care of this themselves) headers = msg.items() payload = msg.get_payload(decode=pycompat.ispy3) # for notification prefer readability over data precision msg = mail.mimeencode(self.ui, payload, self.charsets, self.test) # reinstate custom headers for k, v in headers: msg[k] = v msg[r'Date'] = encoding.strfromlocal( dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2")) # try to make subject line exist and be useful if not subject: if count > 1: subject = _(b'%s: %d new changesets') % (self.root, count) else: s = ctx.description().lstrip().split(b'\n', 1)[0].rstrip() subject = b'%s: %s' % (self.root, s) maxsubject = int(self.ui.config(b'notify', b'maxsubject')) if maxsubject: subject = stringutil.ellipsis(subject, maxsubject) msg[r'Subject'] = encoding.strfromlocal( mail.headencode(self.ui, subject, self.charsets, self.test)) # try to make message have proper sender if not sender: sender = self.ui.config(b'email', b'from') or self.ui.username() if b'@' not in sender or b'@localhost' in sender: sender = self.fixmail(sender) msg[r'From'] = encoding.strfromlocal( mail.addressencode(self.ui, sender, self.charsets, self.test)) msg[r'X-Hg-Notification'] = r'changeset %s' % ctx if not msg[r'Message-Id']: msg[r'Message-Id'] = messageid(ctx, self.domain, self.messageidseed) msg[r'To'] = encoding.strfromlocal(b', '.join(sorted(subs))) msgtext = msg.as_bytes() if pycompat.ispy3 else msg.as_string() if self.test: self.ui.write(msgtext) if not msgtext.endswith(b'\n'): self.ui.write(b'\n') else: self.ui.status( _(b'notify: sending %d subscribers %d changes\n') % (len(subs), count)) mail.sendmail( self.ui, emailutils.parseaddr(msg[r'From'])[1], subs, msgtext, mbox=self.mbox, )
def send(self, ctx, count, data): '''send message.''' # Select subscribers by revset subs = set() for sub, spec in self.subs: if spec is None: subs.add(sub) continue revs = self.repo.revs(b'%r and %d:', spec, ctx.rev()) if len(revs): subs.add(sub) continue if len(subs) == 0: self.ui.debug( b'notify: no subscribers to selected repo and revset\n') return try: msg = mail.parsebytes(data) except emailerrors.MessageParseError as inst: raise error.Abort(inst) # store sender and subject sender = msg['From'] subject = msg['Subject'] if sender is not None: sender = mail.headdecode(sender) if subject is not None: subject = mail.headdecode(subject) del msg['From'], msg['Subject'] if not msg.is_multipart(): # create fresh mime message from scratch # (multipart templates must take care of this themselves) headers = msg.items() payload = msg.get_payload(decode=pycompat.ispy3) # for notification prefer readability over data precision msg = mail.mimeencode(self.ui, payload, self.charsets, self.test) # reinstate custom headers for k, v in headers: msg[k] = v msg['Date'] = encoding.strfromlocal( dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2")) # try to make subject line exist and be useful if not subject: if count > 1: subject = _(b'%s: %d new changesets') % (self.root, count) else: s = ctx.description().lstrip().split(b'\n', 1)[0].rstrip() subject = b'%s: %s' % (self.root, s) maxsubject = int(self.ui.config(b'notify', b'maxsubject')) if maxsubject: subject = stringutil.ellipsis(subject, maxsubject) msg['Subject'] = mail.headencode(self.ui, subject, self.charsets, self.test) # try to make message have proper sender if not sender: sender = self.ui.config(b'email', b'from') or self.ui.username() if b'@' not in sender or b'@localhost' in sender: sender = self.fixmail(sender) msg['From'] = mail.addressencode(self.ui, sender, self.charsets, self.test) msg['X-Hg-Notification'] = 'changeset %s' % ctx if not msg['Message-Id']: msg['Message-Id'] = messageid(ctx, self.domain, self.messageidseed) if self.reply: unfi = self.repo.unfiltered() has_node = unfi.changelog.index.has_node predecessors = [ unfi[ctx2] for ctx2 in obsutil.allpredecessors( unfi.obsstore, [ctx.node()]) if ctx2 != ctx.node() and has_node(ctx2) ] if predecessors: # There is at least one predecessor, so which to pick? # Ideally, there is a unique root because changesets have # been evolved/rebased one step at a time. In this case, # just picking the oldest known changeset provides a stable # base. It doesn't help when changesets are folded. Any # better solution would require storing more information # in the repository. pred = min(predecessors, key=lambda ctx: ctx.rev()) msg['In-Reply-To'] = messageid(pred, self.domain, self.messageidseed) msg['To'] = ', '.join(sorted(subs)) msgtext = msg.as_bytes() if pycompat.ispy3 else msg.as_string() if self.test: self.ui.write(msgtext) if not msgtext.endswith(b'\n'): self.ui.write(b'\n') else: self.ui.status( _(b'notify: sending %d subscribers %d changes\n') % (len(subs), count)) mail.sendmail( self.ui, emailutils.parseaddr(msg['From'])[1], subs, msgtext, mbox=self.mbox, )