スクリプトのお勉強 技術

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

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

執筆者:

関連記事

PythonでAESを使用して暗号/復号する

1.つづき Pythonで、PKCS#12の公開鍵で暗号、秘密鍵で復号するプログラムの続きです。 今回はAESで暗号化/復号を行い、通信しながらRSA暗号/復号,AES暗号/復号を組み合わせたいと思い …

Ruby(Rails)で最小限にREST APIを立ち上げる

簡単にREST APIを立ち上げたいなーと思うときが仕事であります。別にRubyでなくてもいいのですが、一応前提がRubyであることにします。 仕事で必要になるには 現在の仕事を鑑みると、最低限以下の …

Svelte(Carbon Components Svelte) + Python(FastAPI)でWebアプリを作る

Svelte用のサンプルとして、Carbon Components SvelteのTreeViewを試用してファイルツリーを表示し、各データはAPIとして読み出し、編集するWebアプリケーションを実装 …

言語別ログイン機能パスワード保存処理方針

ちょっと前に、ログイン機能を作成した際、パスワードを暗号化するか、という議論を目にしたことがありました。 昔だと、「パスワードを暗号化しない」方で実装していましたが、最近はセキュリティが当たり前になっ …

(小ネタ) python3 date_range + step付き

ちょっと前に同じような感じのネタを。。 したような気がするのだが、まぉおいておこう。。 素のPython3で、日付にてfor文を回す方法 日付で分割して処理をしたいと思うときがあります。例えば、202 …

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