From aa0141a047a60ccbf0e474e531f2b8519934c2e9 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Sat, 8 Dec 2007 23:32:43 +0100 Subject: [PATCH] Script pour envoyer le dernier commit dans darcs par mail. darcs-hash:20071208223243-af139-7ce74d950e424a60ee130344a952245f0a823d27.gz --- gestion/darcs_send_changes.py | 172 ++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100755 gestion/darcs_send_changes.py diff --git a/gestion/darcs_send_changes.py b/gestion/darcs_send_changes.py new file mode 100755 index 00000000..d63ca426 --- /dev/null +++ b/gestion/darcs_send_changes.py @@ -0,0 +1,172 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# darcs_send_changes.py +# --------------------- +# +# Copyright (C) 2007 Jeremie Dimino +# +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + + +""" +Envoie un mail détaillant le dernier patch appliqué à un dépot. +""" + +import commands, os, sys, email, re, cStringIO + +try: + from lxml import etree +except: + sys.stderr.write("darcs_send_changes recquiert le paquet python-lxml.\n") + sys.stderr.flush() + sys.exit(1) + +sys.path.append("/usr/scripts/gestion") +from affich_tools import cprint +from unicode2ascii import unicode2ascii + +def darcs(args): + """ Invoque darcs et renvoie sa sortie. """ + return commands.getoutput("darcs " + args) + +def get_patch_properties(): + """ Récupère les informations a propos du dernier patch. """ + prop = etree.XML(darcs("changes --last 1 --xml-output"))[0] + diff = darcs("diff --last 1 --unified") + diff = diff[diff.find('\ndiff ')+1:] + cwd = os.getcwd() + return { 'author': prop.attrib['author'], + 'repo': "%s:%s" % (commands.getoutput('hostname -s'), cwd), + 'shortrepo': os.path.basename(cwd), + 'date': prop.attrib['local_date'], + 'hash': prop.attrib['hash'], + 'name': prop.findtext('name'), + 'comment': prop.findtext('comment'), + 'diff': diff, + 'changes': darcs('changes --last 1 --summary') } + +DEFAULT_TEMPLATE = """From: %(author)s +To: %(recipient)s +Subject: Darcs record (%(shortrepo)s): %(name)s + +%(changes)s + +%(diff)s +""" +TEMPLATE_FILE = "_darcs/third-party/darcs-send-changes/email-template" + +__darcs_escaped_re = re.compile('\\[_\\\\[0-9a-f][0-9a-f]_\\]') +def darcs_unescape(str): + """ Converti les séquences d'échappement de darcs en charactère unicode. """ + start = 0 + newstr = cStringIO.StringIO() + s = __darcs_escaped_re.search(str, start) + while s: + newstr.write(str[start:s.start()]) + newstr.write(chr(int(str[s.start()+3:s.start()+5], 16))) + start = s.end() + s = __darcs_escaped_re.search(str, start) + newstr.write(str[start:]) + return newstr.getvalue() + +def send_changes(smtp, recipient, patch_props, template=DEFAULT_TEMPLATE): + """ Formatte et envoie un mail avec les modifications sur le dernier +patch appliqué au dépot. +recipient est une liste des destinataires du mail. + +template est une chaîne de format python qui +peut contenir les variables suivantes: +* author, date, hash, name, comment +* repo: le dépot (hote + chemin) +* shortrepo: basename(chemin du dépot) +* changes: la sortie de darcs changes --summary +* diff: la sortie de darcs diff --unified a partir du premier diff +* recipient: les destinataires du mail + +si template est None, DEFAULT_TEMPLATE est utilisé. +""" + patch_props["recipient"] = ", ".join(recipient) + rawmail = darcs_unescape((template or DEFAULT_TEMPLATE) % patch_props) + mail = email.message_from_string(rawmail) + if not mail['Content-Transfer-Encoding']: + mail['Content-Transfer-Encoding'] = 'quoted-printable' + if not mail.get_charset(): + mail.set_charset("UTF-8") + # On met le titre en ascii sinon c'est atroce pour le filtrage + # automatique + subject = unicode2ascii(mail['Subject'].decode("UTF-8")) + mail.replace_header('Subject', subject) + rawmail = mail.as_string() + for to in recipient: + smtp.sendmail(patch_props['author'], to, rawmail) + +def __usage(err=None): + if err: cprint("%s\n" % err) + cprint("""Usage: %(name)s [OPTIONS] destinataires +pour en savoir plus faites « %(name)s --help » +""" % { 'name': os.path.basename(sys.argv[0]) }) + sys.exit(2) + +def __help(): + cprint("""Usage: %(name)s [options] destinataires + +Les options disponibles sont: + -h, --help affiche cette aide + -s, --smtp spécifie le serveur smtp à utiliser + -r, --repo spécifie l'emplacement du dépôt + -t, --template fichier a utiliser comme template + +Si aucun destinataires n'est donné, roots@crans.org est utilisé. +""" % { 'name': os.path.basename(sys.argv[0]) }) + sys.exit(0) + +if __name__ == "__main__": + import smtplib, getopt + + smtp = 'localhost' + repo = None + template = None + + try: + options, arg = getopt.getopt(sys.argv[1:], 'hs:r:t:', [ 'help', 'smtp=', 'repo=', 'template=']) + except getopt.error, msg: + __usage(unicode(msg)) + for opt, val in options: + if opt in [ '-h', '--help' ]: + __help() + elif opt in [ '-s', '--smtp' ]: + smtp = val + elif opt in [ '-r', '--repo' ]: + repo = val + elif opt in [ '-t', '--template' ]: + template = val + else: + __usage("option inconnue « %s »'" % opt) + recipient = arg + if len(recipient) == 0: + recipient = [ 'roots@crans.org' ] + + if repo: + os.chdir(repo) + if not template and os.path.exists(TEMPLATE_FILE): + template = TEMPLATE_FILE + if template: + f = open(template) + template = f.read() + f.close() + + cprint("Envoie du patch a " + ", ".join(recipient)) + send_changes(smtplib.SMTP(smtp), recipient, get_patch_properties(), template)