スクリプトのお勉強 技術

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

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

執筆者:

関連記事

キーボード買った(Maestro2S 日本語配列)

キーボード購入 キーボードが完全にいかれたので新しいキーボードを買ってきました。 Maestro2S 日本語配列 Maestro2S 日本語配列 です。 画像 実は以前のキーボードとほぼ同じです。違う …

fastapi + SQLAlchemy で CRUDアプリケーションを作ってみる

概要 勉強用に、PythonでPostgresqlを制御しようと思います。の続きです。 前回でPostgreSQLと、データベース/テーブルまでは用意したので、今回はAPIを作成しようと思います。 実 …

svelteをチュートリアルしてみる

年末の休みは、svelteのチュートリアルをしてみました。なんとなくやはりそう?なので。 svelteとは Webアプリのフロントエンド(UI)用フレームワークです。要するにReactみたいなもんです …

Vue.js 導入編

1.はじめに 近年、web関係で「クライアントサイドJavaScript」というのがトレンドになっているそうです。 「クライアントサイドJavaScript」と、従来のWebアプリケーションとの違いは …

Pipenvでライブラリ(*.whl)をキャッシュする方法

仕事でWebアプリケーションを作成した場合、ガンガンとライブラリのバージョンを上げたりはしない場合があります。 そして、長期間放置されるタイプのWebアプリケーションの場合、使用しているライブラリが、 …

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