Subversionのコミットメールをpythonで書いてみた

なぜpythonかと言うと、rubyは入っていないしperlは5.6でNet::SMTP使えないしsendmail行方不明だし・・・。pythonはcvs2svnで必要だったのでインストールしてもらっていたのでした。PERLも5.10をインストールして貰えばいいんですが、依頼をして待つ時間を考えるとpythonで書いた方が早いだろうと判断したからです。

動けばいいやーレベルで書いたので穴があるかもしれないです。ちなみにバージョンは2.6で確認しました。

●post-commit

#!/bin/bash

REPOSITORY="$1"
REVISION="$2"
MAILER="/data/svn/proj1/hooks/mail.py"

export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

$MAILER $REPOSITORY $REVISION

●mail.py

#!/usr/local/python/bin/python
# -*- coding: utf-8 -*-

import re
import sys
import os
import subprocess
import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate

SMTP_HOST = 'xxx.xxx.xxx.xxx'
SMTP_PORT = 25
SVNLOOK = '/usr/local/svn/bin/svnlook'
subject_prefix = "[svn][proj1]"
from_addr = 'no-reply@example.com'
to_addr = ["user1@example.com", "user2@example.com"]


def send(from_addr, to_addr, msg):
    s = smtplib.SMTP(SMTP_HOST, SMTP_PORT)
    s.sendmail(from_addr, to_addr, msg.as_string())
    s.close()

def create_message(from_addr, to_addr, subject, body, encoding):
    msg = MIMEText(body, 'plain', encoding)
    msg['Subject'] = Header(subject, encoding)
    msg['From'] = from_addr
    msg['To'] = ', '.join(to_addr)
    msg['Date'] = formatdate()
    return msg

if __name__ == '__main__':

    REPOS = sys.argv[1]
    REV = sys.argv[2]

    # exec svnlook
    p = subprocess.Popen(["%(SVNLOOK)s info %(REPOS)s -r %(REV)s" % locals()], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    lines1 = p.stdout.read().splitlines()
    AUTHOR = lines1.pop(0)
    DATE = lines1.pop(0)
    lines1.pop(0)
    LOG = "\n".join(lines1)

    # exec dirs-changes
    p = subprocess.Popen(["%(SVNLOOK)s dirs-changed %(REPOS)s -r %(REV)s" % locals()], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    dirchanged = ""
    for dir in sorted(p.stdout.read().splitlines(True)):
        dirchanged += "    " + dir

    # exec changed
    p = subprocess.Popen(["%(SVNLOOK)s changed %(REPOS)s -r %(REV)s" % locals()], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    r = re.compile('^(.).  (.*)$')
    adds = []
    dels = []
    mods = []
    for file in (p.stdout.read().splitlines(True)):
        (tmp, code, path, tmp) = r.split(file)
        if tmp == 'A':
            adds.append("    " + path)
        elif tmp == 'D':
            dels.append("    " + path)
        else:
            mods.append("    " + path)

    body  = "Author: " + AUTHOR + "\n"
    body += "Date: " + DATE + "\n"
    body += "New Revision: " + REV + "\n"
    body += "\n"
    body += "Log:\n"
    body += LOG
    body += "\n\n"
    body += "Direcoties:\n"
    body +=  dirchanged
    body += "\n"
    if len(adds) != 0:
        body += "Added:\n"
        body += "\n".join(sorted(adds))
    if len(dels) != 0:
        body += "Removed:\n"
        body += "\n".join(sorted(dels))
    if len(mods) != 0:
        body += "Modified:\n"
        body += "\n".join(sorted(mods))

    subject = subject_prefix + " r" + REV + " - " + AUTHOR + " -"
    msg = create_message(from_addr, to_addr, subject, body, 'UTF-8')
    send(from_addr, to_addr, msg)
新しいサイトもよろしくお願いします!