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例外を発生する場合があります。通常ではエラーは出ませんが。
のような例外処理をしておいたほうがいいでしょう。
特に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リポジトリ作成コマンド手順