スクリプトのお勉強 技術

Pythonからsvnしてみる

投稿日:

SVN: レガシーシステムの一つ。。

私の関わってるシステムでは、いまだにsvnレポジトリがあります。
pythonで処理する必要性が生じましたが、そういえばどう処理していいもんか、完全に忘れました。

思い出しがてら、軽くサンプルを作ってみようと思います。

ワーキングディレクトリがすでにある前提で、そこにファイル追加/コミットするサンプルを作成します。

何故か知りませんが、検索しても出てこなかったので書いておきます。

環境

  • OS: ubuntu:22.04 LTS
  • Python3: 3.10.4
  • poetry: 1.1.8
  • svn: 1.14.1 (apt installしたプログラム)

で動作させてます。

まずはテスト用リポジトリとワーキングコピー作成

gitを便利に使ってると、リポジトリとワーキングコピーが違うものであることを忘れます。。

gitでもできるんですが、しないですよね??ね???(忘れてた人。。)

以下のコマンドでテスト用のリポジトリとワーキングコピーを作成します。

### リポジトリ作成
$ svnadmin create /home/tanino/github/python-svn/testrepo
### ワーキングコピー用ディレクトリの作成
$ mkdir /home/tanino/github/python-svn/repos
### 初期のインポート用データ作成
$ mkdir /home/tanino/github/python-svn/importdata
$ mkdir -p /home/tanino/github/python-svn/importdata/system/common
$ echo "test" > /home/tanino/github/python-svn/importdata/system/common/d1
$ cd /home/tanino/github/python-svn/importdata
### データのインポート
$ svn import file:///home/tanino/github/python-svn/testrepo -m "new commit"
Adding         system
Adding         system/common
Adding         system/common/d1
Committing transaction...
Committed revision 1.
$ cd /home/tanino/github/python-svn/repos
### ワーキングコピー作成
$ svn checkout file:///home/tanino/github/python-svn/testrepo .
A    system
A    system/common
A    system/common/d1
Checked out revision 1.

サンプルプログラム

サンプルプログラムの前に、以下でsvnライブラリをインストールしてください。

$ pip install svn

サンプルプログラムが以下です。
bin/svn_ope.pyとして以下を保存します。

import os
import svn.local


class Svnrepo:

    def __init__(self):
        self.work_copy = "/home/tanino/github/python-svn/repos"
        self.repo_client = svn.local.LocalClient(self.work_copy)

    def exists(self, work_dir, filename):
        status = self.repo_client.list(False, work_dir)
        for st in status:
            if st == filename:
                return True

        return False

    def add(self, work_dir, filename):
        self.repo_client.add(os.path.join(self.work_copy, work_dir, filename))

    def commit(self, message, work_dir, filename):
        self.repo_client.commit(message, [os.path.join(self.work_copy,
                                                       work_dir,
                                                       filename)])

        self.repo_client.update()


def main():
    outdir = "system/common"
    outfile = "c1"

    r = Svnrepo()

    with open(os.path.join(r.work_copy, outdir, outfile), "a") as f:
        f.write("data1")

    if r.exists(outdir, outfile) is False:
        r.add(outdir, outfile)

    import datetime
    now = datetime.datetime.now()
    r.commit(f"commit message {now}", outdir, outfile)


if __name__ == "__main__":
    main()

プログラム自体は簡単なものです。

ワーキングコピー(“system/common”)に”c1″というファイルを追記し、起動するたびに最初はaddしてコミットし、以降はコミットするプログラムです

ただし、エラー処理していないので、SVN例外を発生する場合があります。通常ではエラーは出ませんが。

https://github.com/dsoprea/PySvn/blob/master/svn/exception.py

のような例外処理をしておいたほうがいいでしょう。

特にadd()が面倒です。既にファイルがリポジトリに格納されている場合、add()すると例外が発生します。
既にリポジトリに追加済みかどうか判定するのにlist()から取得していますが、もっといい方法があるかもしれません。

とりあえずadd()して例外が発生しても無視するやり方もあるかもしれませんが、なんとなく嫌だったので採用しませんでした。

起動結果

起動すると以下のようにコミットログができることがわかります。

$ python3 bin/svn_ope.py
$ cd system/common
$ svn log
------------------------------------------------------------------------
r2 | tanino | 2023-03-12 10:17:58 +0900 (Sun, 12 Mar 2023) | 1 line

commit message 2023-03-12 10:17:58.131565
------------------------------------------------------------------------
r1 | tanino | 2023-03-12 10:00:06 +0900 (Sun, 12 Mar 2023) | 1 line

new commit

なお、commit()の対象ファイルに変化がない場合、commit()を呼び出してもコミットログは生成されません。
それはそれで良いかと思いますが、どちらだろうと思ったらそうなってました。

終わりに

テストプログラム自体はあっさり動作しました。

add()判定(exists)がすこし手間取りましたが、とりあえず動作したようです。

なにかの参考にしてください。

参考

  • http://svn.linux-dvr.biz/archives/85
    svnリポジトリ作成コマンド手順

-スクリプトのお勉強, 技術

執筆者:

関連記事

PyWebIOでform 入力+ REST API呼び出しを作ってみる

仕事柄、簡単なWebアプリを作りたいと思うことはよくあり、その場合はその場で直せるスクリプトで書きたいとよく思うものです。 すごーく簡単なフォームを非常に簡単に使いたいので、まずは簡単に作れるフレーム …

SNMPTrap を Kafka に転送するツール:snmptrap-kafka-forwarder の紹介

はじめに こんにちは!今回は、ネットワーク監視の世界で古くから使われている SNMPTrap を、モダンなデータ基盤である Apache Kafka に連携するための便利なツール「snmptrap-k …

悪いほうが良い? でも限度があるよね。。

自分のその時の状態によって結論が変わる https://tech.nikkeibp.co.jp/atcl/nxt/column/18/00620/040900010/を見て書こうと思いました。 今やっ …

Python3/ある日付から日付までの月/日/時間ごとの時刻を算出する

小ネタです。 要するに、時刻A と 時刻B を指定したときの、各時間間隔での時刻取得したかったです。 当初はdateutilを使う方法でなく、自前で実装しようと思ったのですが、面倒なことに気づきました …

Mojolicious XML-RPC Pluginの開発(2)

はじめに 「Mojolicious XML-RPC Pluginの開発」のその2です。 本内容では、前回の内容を踏まえ、XML-RPC実装を、Mojoliciousのプラグイン機能を使用して実装しよう …

google オプトアウト Click here to opt-out.