スクリプトのお勉強 技術

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

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

執筆者:

関連記事

小ネタ: JavaScriptにてBase64エンコード/デコードする方法

小ネタです。JavaScriptにてBase64エンコード/デコードをしようとして、意外と詰まったので、メモ的に方法を書いておきます。 結論: js-base64ライブラリを使用する これだけです。。 …

Dockerを使用してGo言語の開発環境を構築する

なんとなくGolangのブロジェクトに機能追加しようと思いました。 Golangの開発用に、Dockerfile等を準備する手順を書いておこうと思います。 サンプルにnfpm サンプルとして、Fork …

@nifty auひかり タイプVからタイプGに変えてみた

家のインターネットはいままで、光回線ではありましたが、昔のVSDLのままでした。auひかりでいう、マンション タイプVというやつです。 それを近年、リモートワークが増えていることや、半導体需要がなんと …

yoyo-migrationsを使ってみる

勉強用に、PythonでPostgresqlを制御しようと思います。 その前に、Postgresqlの設定と、マイグレーションをしようかと思います。まずyoyo-migrationsを使用します。 y …

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

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

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