かーくがかーくよ

色々書くよ プログラミングとか漫画とかゲームとかが主

Windowsに入れたXonshをSVNの更新通知取得に使ってみたけど課題が多すぎる

はじめに

この記事はXonsh Advent Calendar 2017 19日目の記事です。

Python2系メインで使っている社内PCにXonshを導入してみた - かーくがかーくよの続き?です。

環境

やりたいこと

前回の記事ではとりあえず機械学習スクリプトの評価をXonshでやってみたんですがいくらなんでもそんなことXonshでやる必要ないし書き捨てのスクリプトでやることでもないだろ…普通にPythonでちゃんと書けよ…となったので、もう少し日頃から使いそうで、かつチャラっと書いても支障なさそうなことをやってみようと思いました。

さて、弊プロジェクトのソースコードSVNで管理されているのですが、ホストが社内になく、また私にはリポジトリの管理権限もありません。そのため、コミット通知をWebhook的に受け取ることができず、若干不便を感じています。

そこで、ログを上手いこと定期的に取得することで、擬似的にコミット通知を出すことができないか? と考えました。

作ってみる

下記のようなものを作ってみました。

import re
import time

re_svninfo = re.compile('^r(?P<rev>[0-9]+) \| (?P<name>.+) \| (?P<datetime>20\d\d-\d\d-\d\d \d\d:\d\d:\d\d) .* \(.*\) \| \d+ lines?$')

target_dir = $ARG1

last_log = $(svn log @(target_dir) -l 1).split('\n')
checked_rev = re_svninfo.match(last_log[1]).group('rev')

while(True):
    infos = []
    for line in $(svn log @(target_dir) -r @(checked_rev+':HEAD')).split('\n'):
        matcher = re_svninfo.match(line)
        if matcher:
            infos.append((matcher.group('rev'), matcher.group('name'), matcher.group('datetime')))

    for rev, name, datetime in infos:
        comment= $(svn log @(target_dir) -r @(rev)).split('\n')[2:-2]
        comment= '\n'.join([line for line in comment if line])
        print(rev, name, datetime, comment) 

    checked_rev = rev
    time.sleep(3000)

print(rev, name, datetime, comment)しているところでなんかこう、json投げたり、引数にして他のコマンド叩いたりとかできるといいな…といったところで。

なんか強引なループを書いていますね。cronで実行とも思ったのですが、社内のサーバに勝手に設置するのも憚られ、どうせデスクトップで実行するならこういうのでいいや、中断するときはKeyboardInterruptすればいいだろ、みたいな判断でした。

とりあえずここまでは動きます。動きますが…

問題点

日本語を扱えない(?)

日本語のコミットコメントをprintしようとするとUnicodeEncodeErrorを吐きます。正直これが一番痛いです。

サロゲートペアが含まれているのが駄目っぽいと見て、message.encode('utf-16', 'surrogatepass').encode('utf-16')なども試してみたのですがどうも上手くいきません。

stdoutには出せてるわけだからリダイレクトでtxtに吐き出せばもうちょっと使えるんじゃないか?と思ったのですが、今度は何故か[WinError 87] The parameter is incorrectを吐いてしまいます。

Xonshの標準出力の問題なのかCygwinと組み合わせていることによる問題なのかがいまいち分からない…

重い

何回もsvn logを呼んでいるせいか、やりたいことの単純さに対して随分レスポンスが遅い感じがします。

ただこれは単にロジックの手を抜いていることによる問題ですね。最後にチェックしたリビジョンからHEADまでのログを取得する際に、もっと上手くマッチングを取れば、リビジョン1つずつについてsvn logしなくても良くなるわけですから。

コミットコメントの行数まで与えられてるので、ここは今後いくらでも手の入れようがある気がします。しますが…

Pythonでよくない?

というか既にほぼPythonスクリプトじゃない?svn logコマンドしか呼んでないなら普通にPythonでsubprocess実行しても大差なくない?という気持ちになります。

なんか最初は正規表現の部分をシェルっぽく書けないかなあと思っていたのですが、~=による正規表現マッチングはどうやらXonshでは使えない?っぽいのですよね…

まとめ

Xonsh、面白そうなのですが、使いこなすには私の力量が不足しているような気がします。うーん。

日本語出力周りの問題がどうにかなれば、少なくとも今回の課題については一定の成果が上げられるような気がするのですが。

とりあえず今後もConEmuには残しておいて、気が向いたときにちまちま触ってみようかと思います。

面白いものに出会わせてくれたばんくし (@vaaaaanquish) | Twitterさんに感謝!