スクリプトのお勉強 技術

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リポジトリ作成コマンド手順

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

執筆者:

関連記事

Go言語でtarアーカイブコマンド作成

今所属している会社で1バイナリでとりあえず済ませる簡単ツールはgo言語で書くことが多いようです。 私はそれほどgo言語が好きというわけでもありませんが、勉強がてら、ディレクトリからtarアーカイブする …

小ネタ: Python のdataclass でNone or “”を使わないJSONデータを定義する

PythonをREST APIのクライアントとして作成する際、dataclassesを使用しようと思いました。型が見た瞬間分かるし、しっかりしているからです。 でも、そのREST API は&#822 …

コンピュータ系の人のためのCoinhive最高裁の読み方(なぜ無罪だったか)

以下ですべて断定してますが、そもそもからしてすべて想定です。私は法律家ではないので。 前回の記事で、Coinhiveの高裁判決について書きました。 今回は、無罪と決まったCoinhiveの最高裁判決を …

「Python3 メモ」 独自例外クラスからの値取得/変数の内容取得

忙しい。。 この時期でなぜか忙しく、ブログ書いてる暇ない。。のでメモ書き程度。そして、内容をよく忘れるやつ。。 python3の独自例外クラス 例外クラスからの値取得方法をいつも忘れます。ある関数or …

poetry installでJSONDecodeError

小ネタです。OSをアップデートしたので、その他もいろいろアップデートしようとしたらエラーになったので、メモとして書いておきます。 WSL2のUbuntuを 22.04 LTSにアップデート は、さほど …

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