bzrlib: bazaarをPythonから操作する

分散VCSのbazaarは、Pythonで作成されています。

普通はbzrコマンドで操作するのですが、これをbzrlibを使ってPythonから直に操作してみます。

コマンドライン機能の発行

from bzrlib import commands

repos_location = "/home/bellbind/bzr/hello"

# import os; os.system("bzr log %s" % repos_location)
# commands.main(["bzr", "log", repos_location])
# commands.run_bzr(["log", repos_location])
commands.get_cmd_object("log").run_argv_aliases([repos_location])

コメントアウトしてあるものは、ほぼすべて同じ結果を出すものです。

以下のようStringIOを使うことで、コマンドの結果を文字列として取り出せるようです。

from StringIO import StringIO
from bzrlib import commands

repos_location = "/home/bellbind/bzr/hello"

cmd = commands.get_cmd_object("log")
out = StringIO()
cmd.outf = out
cmd.run(location=repos_location)
print out.getvalue()

リポジトリ情報の取得

from datetime import datetime
from StringIO import StringIO
from bzrlib.branch import Branch
from bzrlib import diff

repos_dir = "/home/bellbind/bzr/hello"
branch = Branch.open(repos_dir)

# all_ids = branch.get_revision_history() # id list from old to new
target_id = branch.get_rev_id(branch.revno())

# show change info
revision = branch.repository.get_revision(target_id)
print revision.committer
print revision.message
print revision.timestamp # float
print revision.timezone # int
date = datetime.fromtimestamp(revision.timestamp)
print date # local time

# show change file lists
delta = branch.repository.get_revision_delta(target_id)
print delta.added # list for (path, id, kind)
print delta.removed # list for (path, id, kind)
print delta.modified # list for (path, id, kind, is_text_modified, is_meta_modified)

# show diff
target = branch.repository.revision_tree(target_id)
prev_id = branch.get_rev_id(branch.revision_id_to_revno(target_id) - 1)
prev = branch.repository.revision_tree(prev_id)
out = StringIO()
diff.show_diff_trees(prev, target, out)
print out.getvalue()

用語の大体の意味(APIではそれぞれモジュールになってる)

  • branch: 参照する(分散)ブランチ(その中にリポジトリがある)
  • repository: リポジトリ管理オブジェクト
  • revision: commitの単位
    • revision_id: repositoryで管理してるrevisionのid
    • revno: branchにおけるローカルなrevisionの整数
  • delta: revisionでの変更(メタ)情報
  • revisiontree: スナップショットデータ

ワーキングコピーの操作

例: リモートからのマージ(pull)

import traceback
from bzrlib.branch import Branch
from bzrlib.workingtree import WorkingTree

repos_dir = "/home/iom/bzr/hello-fixed-errors"
work_dir = "/home/bellbind/bzr/hello"

branch = Branch.open(repos_dir)
work = WorkingTree.open(work_dir)
try:
    work.merge_from_branch(branch)
except:
    traceback.print_exc()

workingtreeは、自分が変更操作するディレクト