Trac 1.0にてSubversionからGitに移行する(未完成)

Debian GNU/Linux Wheezyで Trac 0.12.2Tracのプロジェクトのコピー、そしてDebian GNU/Linux Wheezy上でTrac 0.12 を Trac 1.0にバージョンアップするの流れで設置したTrac 1.0において、リポジトリSubversionからGitに移行する。

環境

リポジトリ内容のSubversionからGitへの移行

以下のとおりにする。

今回は、/var/git 以下にgitリポジトリを置くこととする。当該リポジトリを/var/git/repos.gitとする。

HTTP経由でGitリポジトリにアクセスする

以下のとおりにする。

アクセス制限は、Tracのアクセス制限に使っているDigest認証をそのまま流用する。Debian GNU/Linux Wheezyで Trac 0.12.2では、/var/trac/trac.htdigest に認証ファイルがあるので、/etc/apache2/site-avaiables/default に以下を追記する。これで、TracのユーザとGitリポジトリのユーザを一致させられる。

SetENV GIT_PROJECT_ROOT /var/git
SetENV GIT_HTTP_EXPORT_ALL
ScriptAlias /git "/usr/lib/git-core/git-http-backend"

<Location /git>
 AuthType Digest
 AuthDigestProvider file
 AuthName "Trac"
 AuthUserFile /var/trac/trac.htdigest
 Require valid-user
 Order allow,deny
 Allow from all
</Location>

リポジトリの変更

TracGitによると、Trac 1.0からGitプラグインは既に含まれているため、設定を変更すればGitと連携できる。

私は、複数のプロジェクトを1つのTracで運用しているので(詳しくは、こちら参照。Tracのプロジェクトのコピー)。/var/trac/sites/my_project に移行対象のプロジェクトがあるとする。このとき、/var/trac/sites/my_project/conf/trac.ini を編集する。

% cd /var/trac/sites/my_project/conf/
% cp -p trac.ini trac.ini.for_svn
% vi trac.ini

追記内容は以下のとおり(キャッシュの利用については参考にしているサイトがtrueにしていたのでそれに準じている。TracGittrac.ini(git)Trac1.0.1とgitを連携させる

[components]
tracopt.versioncontrol.git.* = enabled
tracopt.ticket.commit_updater.* = enabled

[git]
cached_repository = true
git_bin = /usr/bin/git
persistent_cache = true

[trac]
repository_type = git
repository_dir = /var/git/repos.git

その後、リポジトリを同期させる。

% sudo trac-admin /var/trac/sites/my_project repository resync "(default)"

Tracの当該プロジェクトにアクセスする。必要に応じて、プロジェクトの管理画面から、Subversionリポジトリをプロジェクトから外す。

Commit Ticket Updaterを使ってgit push時にチケットの状態を更新する(2013/04/16現在うまくいかない)

Git:7.3 Git のカスタマイズ - Git フックを読むと、update というスクリプトが呼び出されるとき、refname, oldrev, newrev という3つの値が標準入力で引き渡されるとのこと。ネット上を探す限り、Commit Ticket Updaterを使って git push時にチケットの状態を更新するスクリプトは全部refname, oldrev, newrevを利用している。

このため、従来のpost-recieveでなく、updateを使ってgit push時にチケットの状態の更新を試みる。/var/git/repos.git/hooks/update として、以下のスクリプトを設置した。このスクリプトは、StackOverflow: How can I allow Git commit messages like “fixes #3” to update Trac tickets?を参考にした。

#!/usr/bin/ruby
# From http://stackoverflow.com/questions/15864592/how-can-i-allow-git-commit-messages-like-fixes-3-to-update-trac-tickets

GIT_PATH = '/usr/bin/git'
REPO_NAME = '(default)'
TRAC_ADMIN_PATH = '/usr/bin/trac-admin'
PROJECT_PATH = '/var/trac/sites/my_project'

refname = ARGV[0]
oldrev = ARGV[1]
newrev = ARGV[2]

if oldrev =~ /^0+$/
   revspec = newrev
else
   revspec = oldrev + '..' + newrev
  end

other_branches = `#{GIT_PATH} for-each-ref --format='%(refname)' refs/heads/ | grep -F -v "#{refname}"`
other_branches = other_branches.chomp.gsub /[\r\n]+/, ' '

commits = `#{GIT_PATH} rev-parse --not #{other_branches} | #{GIT_PATH} rev-list --stdin #{revspec}`

commits.each_line do |commit|
  p "#{TRAC_ADMIN_PATH} #{PROJECT_PATH} changeset added '#{REPO_NAME}' #{commit.chomp}"
  `#{TRAC_ADMIN_PATH} #{PROJECT_PATH} changeset added '#{REPO_NAME}' #{commit.chomp}`
end

実行権限を与える。

% sudo chmod 755 /var/git/repos.git/hooks/update
% sudo chown www-data:www-data /var/git/repos.git/hooks/update

ローカルマシンで更新し、git pushするとターミナルには以下のように表示される。

% git add hogehoge.txt
% git commit -m "fixes #111"
% git push                  
WARNING: gnome-keyring:: couldn't connect to: /tmp/keyring-uKFU2g/pkcs11: No such file or directory
Username for 'http://www.hogehoge.jp': next49
Password for 'http://next49@www.hogehoge.jp': 
remote: "oldrev = 4fadba0da537ada442e8397fc859c73d2f1b829e, newrev = ed5ab0c1e0b212a6eb162b54cddda6c3d4a12942, refname = refs/heads/master"
remote: "/usr/bin/trac-admin /var/trac/sites/my_project changeset added '(default)' ed5ab0c1e0b212a6eb162b54cddda6c3d4a12942"
To http://www.hogehoge.jp/git/repos.git
   4fadba0..ed5ab0c  master -> master

Tracの「タイムライン」ではちゃんと変更およびコミットログが反映されているのだが、#111番のチケットのページにはこの変更は反映されていない。また、#111番のチケットは閉じられていない。

/var/trac/sites/my_project/log/trac.log では以下のようなエラーが表示される。

2013-04-17 00:17:39,553 Trac[env] INFO: -------------------------------- environment startup [Trac 1.0] --------------------------------
2013-04-17 00:17:39,851 Trac[git_fs] INFO: detected GIT version 1.7.10.4
2013-04-17 00:17:39,987 Trac[PyGIT] INFO: read_commit failed for 'None' ('4fadba0da537ada442e8397fc859c73d2f1b829e')
2013-04-17 00:17:39,988 Trac[PyGIT] INFO: read_commit failed for 'None' ('4fadba0da537ada442e8397fc859c73d2f1b829e')

PyGIT.pyのソースの該当部分は、以下の部分である。なので、commit_idが空の様子。

def read_commit(self, commit_id):
        if not commit_id:
            raise GitError("read_commit called with empty commit_id")

        commit_id, commit_id_orig = self.fullrev(commit_id), commit_id

        db = self.get_commits()
        if commit_id not in db:
            self.logger.info("read_commit failed for '%s' ('%s')" %
                             (commit_id, commit_id_orig))
            raise GitErrorSha

一方で、サーバにて、コマンドプロンプトから以下のコマンドを実行すると#111番のチケットのページにはこの変更は反映される。ただし、#111番のチケットは閉じられていない。

% sudo /usr/bin/trac-admin /var/trac/sites/my_project changeset added '(default)' ed5ab0c1e0b212a6eb162b54cddda6c3d4a12942

いろいろ試してみたけど、ここまでが限界なのでとりあえずこれで終わる。