Patch en pièce jointe pour la notification Darcs

Cette modification permet d'envoyer le patch en pièce jointe (inline) au lieu de le mettre directement dans le corps du message

darcs-hash:20071214223740-ffbb2-96d9400a9935026956c93c1b35933d9a49b12d85.gz
This commit is contained in:
Nicolas Dandrimont 2007-12-14 23:37:40 +01:00
parent 6458f06ce2
commit 8b3d4f05e6

View file

@ -5,6 +5,7 @@
# --------------------- # ---------------------
# #
# Copyright (C) 2007 Jeremie Dimino <jeremie@dimino.org> # Copyright (C) 2007 Jeremie Dimino <jeremie@dimino.org>
# Copyright (C) 2007 Nicolas Dandrimont <Nicolas.Dandrimont@crans.org>
# #
# This file is free software; you can redistribute it and/or modify # This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -30,13 +31,17 @@ import commands, os, sys, email
try: try:
from lxml import etree from lxml import etree
except: except:
sys.stderr.write("darcs_send_changes recquiert le paquet python-lxml.\n") sys.stderr.write("darcs_send_changes requiert le paquet python-lxml.\n")
sys.stderr.flush() sys.stderr.flush()
sys.exit(1) sys.exit(1)
sys.path.append("/usr/scripts/gestion") sys.path.append("/usr/scripts/gestion")
from affich_tools import cprint, encoding from affich_tools import cprint, encoding
from unicode2ascii import unicode2ascii from unicode2ascii import unicode2ascii
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders
def to_utf8(str): def to_utf8(str):
""" Decode un str ou un unicode vers un str en UTF-8. """ """ Decode un str ou un unicode vers un str en UTF-8. """
@ -84,60 +89,64 @@ def get_patches_properties(from_hash):
props.append(get_patch_properties(change.attrib['hash'])) props.append(get_patch_properties(change.attrib['hash']))
return props return props
DEFAULT_TEMPLATE = """From: %(author)s
To: %(recipient)s
Subject: Darcs record (%(shortrepo)s): %(name)s
Mail-Followup-To: %(recipient)s
Mail-Reply-To: %(author)s
X-CVSinfo: CRANS
X-DarcsInfo: CRANS-%(shortrepo)s
%(changes)s
%(diff)s
"""
CONF_PATH = "_darcs/third-party/darcs-send-changes" CONF_PATH = "_darcs/third-party/darcs-send-changes"
TEMPLATE_FILE = CONF_PATH + "/email-template"
LAST_SEEN_FILE = CONF_PATH + "/last-seen" LAST_SEEN_FILE = CONF_PATH + "/last-seen"
def send_changes(smtp, recipient, patch_props, template=DEFAULT_TEMPLATE): def send_changes(smtp, recipient, patch_props):
""" Formatte et envoie un mail avec les modifications sur le dernier """ Formate et envoie un mail avec les modifications sur le dernier
patch appliqué au dépot. patch appliqué au dépot.
recipient est une liste des destinataires du mail. recipient est une liste des destinataires du mail.
template est une chaîne de format python qui Les différents templates sont des chaînes de format python qui peuvent
peut contenir les variables suivantes: contenir les variables suivantes:
* author, date, hash, name, comment * author, date, hash, name, comment
* repo: le dépot (hote + chemin) * repo: le dépot (hote + chemin)
* shortrepo: basename(chemin du dépot) * shortrepo: basename(chemin du dépot)
* changes: la sortie de darcs changes --summary * changes: la sortie de darcs changes --summary
* diff: la sortie de darcs diff --unified a partir du premier diff * diff: la sortie de darcs diff --unified a partir du premier diff
* recipient: les destinataires du mail * recipient: les destinataires du mail
si template est None, DEFAULT_TEMPLATE est utilisé.
""" """
patch_props["recipient"] = ", ".join(recipient) from_template = "%(author)s"
subject_template = "Darcs record (%(shortrepo)s): %(name)s"
message_template = "%(changes)s"
diff_template = "%(diff)s"
# On met toutes valeurs en string, en UTF-8 # On met toutes valeurs en string, en UTF-8
for key, val in patch_props.items(): for key, val in patch_props.items():
patch_props[key] = to_utf8(val) patch_props[key] = to_utf8(val)
template = to_utf8(template or DEFAULT_TEMPLATE) mail = MIMEMultipart()
mail = email.message_from_string(template % patch_props)
# On met le titre en ascii sinon c'est atroce pour le filtrage # On met le titre en ascii sinon c'est atroce pour le filtrage
# automatique # automatique
subject = mail['Subject'] subject = subject_template % patch_props
if subject: if subject:
subject = unicode2ascii(subject.decode("UTF-8")) subject = unicode2ascii(subject.decode("UTF-8"))
mail.replace_header('Subject', subject) mail['Subject'] = subject_template % patch_props
mail['From'] = from_template % patch_props
mail['To'] = ", ".join(recipient)
mail['Date'] = formatdate(localtime=True)
mail['Mail-Followup-To'] = ", ".join(recipient)
mail['Mail-Reply-To'] = from_template % patch_props
mail['X-CVSinfo'] = "CRANS"
mail['X-DarcsInfo'] = "CRANS-%(shortrepo)s" % patch_props
texte = MIMEText(message_template % patch_props, "UTF-8")
texte.set_charset("UTF-8")
mail.attach(texte)
patch = MIMEText(diff_template % patch_props, "UTF-8")
patch.set_type('text/x-patch')
patch.set_charset("UTF-8")
patch.add_header('Content-Disposition', 'inline', filename='%(hash)s.diff' % patch_props)
mail.attach(patch)
if not mail['Content-Transfer-Encoding']: if not mail['Content-Transfer-Encoding']:
mail['Content-Transfer-Encoding'] = '8bit' mail['Content-Transfer-Encoding'] = '8bit'
charset = mail.get_charset()
if not charset:
charset = "UTF-8"
mail.set_charset("UTF-8") mail.set_charset("UTF-8")
rawmail = mail.as_string()
if charset != "UTF-8":
rawmail = rawmail.decode("UTF-8").encode(charset)
for to in recipient: for to in recipient:
smtp.sendmail(patch_props['author'], to, rawmail) smtp.sendmail(patch_props['author'], to, mail.as_string())
def __usage(err=None): def __usage(err=None):
if err: cprint("%s\n" % err) if err: cprint("%s\n" % err)
@ -153,10 +162,9 @@ Les options disponibles sont:
-h, --help affiche cette aide -h, --help affiche cette aide
-s, --smtp <serveur> spécifie le serveur smtp à utiliser -s, --smtp <serveur> spécifie le serveur smtp à utiliser
-r, --repo <chemin> spécifie l'emplacement du dépôt -r, --repo <chemin> spécifie l'emplacement du dépôt
-t, --template <fichier> fichier a utiliser comme template
-f, --from <hash> hash du premier patch de la série a envoyer -f, --from <hash> hash du premier patch de la série a envoyer
Si aucun destinataires n'est donné, roots@crans.org est utilisé. Si aucun destinataire n'est donné, roots@crans.org est utilisé.
""" % { 'name': os.path.basename(sys.argv[0]) }) """ % { 'name': os.path.basename(sys.argv[0]) })
sys.exit(0) sys.exit(0)
@ -165,11 +173,10 @@ if __name__ == "__main__":
smtp = 'localhost' smtp = 'localhost'
repo = None repo = None
template = None
from_hash = None from_hash = None
try: try:
options, arg = getopt.getopt(sys.argv[1:], 'hs:r:t:f:', [ 'help', 'smtp=', 'repo=', 'template=', 'from=']) options, arg = getopt.getopt(sys.argv[1:], 'hs:r:f:', [ 'help', 'smtp=', 'repo=', 'from='])
except getopt.error, msg: except getopt.error, msg:
__usage(unicode(msg)) __usage(unicode(msg))
for opt, val in options: for opt, val in options:
@ -179,8 +186,6 @@ if __name__ == "__main__":
smtp = val smtp = val
elif opt in [ '-r', '--repo' ]: elif opt in [ '-r', '--repo' ]:
repo = val repo = val
elif opt in [ '-t', '--template' ]:
template = val
elif opt in [ '-f', '--from' ]: elif opt in [ '-f', '--from' ]:
from_hash = val from_hash = val
else: else:
@ -197,12 +202,7 @@ if __name__ == "__main__":
if not os.path.exists('_darcs') and os.getcwd() == '/': if not os.path.exists('_darcs') and os.getcwd() == '/':
cprint("Pas de dépôt darcs trouvé") cprint("Pas de dépôt darcs trouvé")
sys.exit(1) sys.exit(1)
if not template and os.path.exists(TEMPLATE_FILE):
template = TEMPLATE_FILE
if template:
f = open(template)
template = f.read()
f.close()
if not from_hash: if not from_hash:
if os.path.exists(LAST_SEEN_FILE): if os.path.exists(LAST_SEEN_FILE):
f = open(LAST_SEEN_FILE) f = open(LAST_SEEN_FILE)
@ -216,7 +216,7 @@ if __name__ == "__main__":
sys.exit(0) sys.exit(0)
for patch in patches: for patch in patches:
cprint("Envoi du patch %s a %s." % (patch['hash'], ", ".join(recipient))) cprint("Envoi du patch %s a %s." % (patch['hash'], ", ".join(recipient)))
send_changes(smtplib.SMTP(smtp), recipient, patch, template) send_changes(smtplib.SMTP(smtp), recipient, patch)
if not os.path.exists(CONF_PATH): if not os.path.exists(CONF_PATH):
p = "" p = ""
for comp in CONF_PATH.split('/'): for comp in CONF_PATH.split('/'):