カテゴリー別アーカイブ: Subversion

svnで結果をたくさん入れたかった

Ubuntu Serverのアップグレードを行ったんだけど、apacheのconfファイルが色々と変わってて、それに伴って/etc配下をsvnに入れてた分の更新作業を行った。

Ubuntu Serverは12.04から14.04にアップグレードしたんだけれど、一つ前の13.10からapacheのconfのルールなどがちょくちょくかわったみたいで更新作業が結構発生した。

また標準で(?)くっついてくるモジュールが減ったらしく、前のバージョンでは存在したmodsのconfとloadファイルが無くなっていた。

自分は利用するconfファイルをすべてsvn管理下においているんだけど、アップグレードでaptによって削除されてしまったファイルがいくつか。


shell> cd /etc/apache2/
shell> svn st
...(前略)...
? mods-available/authn_core.load
! mods-available/authn_default.load
? mods-available/authn_socache.load
? mods-available/authz_core.load
? mods-available/authz_dbd.load
! mods-available/authz_default.load
? mods-available/buffer.load
? mods-available/cache_disk.conf
? mods-available/cache_disk.load
? mods-available/cache_socache.load
! mods-available/cern_meta.load
? mods-available/data.load
? mods-available/dialup.load
...(後略)....

svn stしてみると出てくるファイルのうち、?は新規に追加されたファイル、!は削除されてしまったファイル。
これらのファイルをsvn del、svn addしてみる。
手動でひとつひとつ追加、削除するのは大変なのでsvn stからcutをつかってxargsにわたしてみる。
svn stの!とか?からファイル名までは空白8文字で、cutに行頭から9文字を削除するオプションがあるらしくてそれをつかう。

shell> svn st | grep ! | cut -c9- | xargs svn del
D authn_default.load
D authz_default.load
D cern_meta.load
D disk_cache.conf
D disk_cache.load
D ident.load
D imagemap.load
D mem_cache.conf
D mem_cache.load
D version.load
shell> svn st | grep \? | cut -c9- | xargs svn add
A cache_disk.load
A cache_socache.load
A data.load
A dialup.load
A echo.load
...(後略)...

</pre>

というわけでたくさんのファイルを一括して処理できました。

addの方ではハテナマークをエスケープするためにバックスラッシュを追加した。またファイル名の途中にハテナやビックリが入っていると引っかかりそうなので、行頭から(-e ‘^!’)を入れた方がいいかも。

Subversionのサーバをsvnからhttpに切り替えた時に作業ディレクトリで起こったエラー

0. サブバージョンを置き換えたらエラー発生

Subversionのサーバをsvnからhttpに切り替えたんだけど、作業ディレクトリ側でエラーが発生した。
当初Subversionはsvnservによって、svnプロトコルでやりとりを行っていた。svn coとかするときにsvn://で始まるURLを使っていた、ということですね。

<br />shell&gt; svn co svn://svn.example.com/hogerepo/<br />

LAN内で利用する分には不満がなかったんだけど、外部のインターネット越しに利用するとなると色々と不便があったのでHTTPで外部からも取得できるように変更した。
svnプロトコル自体を公開すれば良いじゃないか、という意見もあるかもしれないけれど、色々と考えた結果apache経由のhttpのみを公開することに。その辺の移行も大変だったけれど、それはまた別の機会に。

今回svn -> httpにする事で、今までチェックアウトしてきた作業ディレクトリで、svnの操作が行えなくなってしまった。もちろんプロトコルを変えたので当然と言えば当然。今回はこの動かなくなってしまった作業ディレクトリのリポジトリ参照先を変更することに。

1. 発生するエラー

まず現状のエラーを確認。

<br />shell&gt; svn update<br /> Updating '.':<br /> svn: E000061: Unable to connect to a repository at URL '<span style="text-decoration: underline;">svn://svn.example.com/hogerepo</span>'<br /> svn: E000061: Can't connect to host '<span style="text-decoration: underline;">svn.example.com</span>': Connection refused<br />

svn.example.comへ接続できない、と怒られていますね。もちろんこれはsvnservの廃止、httpの移行を行ったのでsvn.example.comへsvnプロトコルではアクセスできない、ということですね。

2. svnの参照リポジトリの変更

svnコマンドには参照リポジトリの変更というものがある。今回はそれを利用する。まず前段階として現在どういったリポジトリを参照しているか、を確認する。

<br />shell&gt; svn info | grep URL<br />URL: <span style="text-decoration: underline;">svn://svn.example.com/hogerepo</span><br />

svn infoで出力される情報の内、URLの項目を調べておく。今回の件ではsvn://svn.example.com/hogerepo が該当する。
今回の svn -> http の移行はプロトコルの変更のみで、svnサーバの名前は従来と同様に svn.example.com で行くこととなった。
(実際にはsvn_test.example.comのように移行時には別のサーバを立て、移行作業が完了した後にsvn.example.comの指すホストを書き換えている)
今回の移行はサーバのリポジトリの配下にあるリポジトリ構造、ディレクトリ構造もそのまま引き継いだので、

svn://svn.example.com/hogerepo
というリポジトリが
http://svn.example.com/hogerepo
になるだけとなった。

ちなみにリポジトリの配下のディレクトリ(ここではhogerepoリポジトリにあるディレクトリ)以下を変更する場合も同様。
さてこのURLを使って、以下のようにsvn switchを発行してやる。

<br /></span><span style="line-height: 1.714285714; font-size: 1rem;">shell&gt; svn switch --relocate </span><span style="text-decoration: underline;">svn://svn.</span><span style="text-decoration: underline;">example.com/hogerepo </span><span style="text-decoration: underline;">http://svn.example.com/hogerepo<br />

これで完了。簡単ですね。

ちなみに今回はサーバの移行をディレクトリを丸ごとコピーしたんだけれど、場合によってはリポジトリをダンプして読ませて、といった他のケースも有り得る。そうなってくるとこの作業ディレクトリの指すリポジトリ変更にはちょっと問題があったりする。具体的にはUUIDと呼ばれるリポジトリを一意に識別するものがあるのですが、これが一致しないとsvn switchの段階で怒られてしまいます。

この件に関しては下記に解決方法の一例があるので参照を。

svn switch –relocate: wrong uuid?

複数人開発の時にデータベースの同期をうまく取る方法

最近「意外に若かったんだね」と言われるようになりました、その言葉の指すところについては考えないようにしています岡田洋一ですコンニチハ。

さて、僕はしばらくチームで開発を行っています。大人数というわけでも無く、2〜3人での小規模プロジェクトチームです。少人数制のチームではありがちで、僕以外のメンバーもプログラム〜インフラ周りも修正することが多く、データベースのテーブル構造を修正することが各自にありえます。

さてそんなときにデータベースの同期を取る方法について考えてみました。

現状はテーブルのCREATE分を出力させ、プロジェクトのwikiに書き込んでいます。

wikiは変更情報を保存しますので、ある程度のバージョン管理ができました。が、いかんせん「出力、編集、保存、確認、伝達、適用」と、修正内容をチーム内で共有するためのステップが多いのです。少人数チームでステップが多いのは良くないですね。素早さこそがウリですから。

次に「テーブルの差分になるALTERのみを書く」ということについて勘案しました。が、こちらも開発を兼ねているため、テーブルの変更となるALTER分はそこそこの数が出てしまい、すべてのALTERを記録して適用することは面倒となりました。素早さがなくなってしまいます。

 

というわけで、現在のテーブル情報を書き出しつつバージョン管理システムで共有、という手段にしました。

現在プロジェクトはSVNで管理されていたので、テーブル情報のみをファイルに書き出してコミット、それを手元へ適用という手段をとりました。ちなみにデータベースはMySQLです。

テーブル情報のみを書き出す為に必要なコードは


shell> mysqldump -h mysqlhost -u user -ppassword --no-data target_schema | sed 's/ AUTO_INCREMENT=[0-9]*//' > tables.sql

shell> svn commit tables.sql -m 'update table sql.'

となりました。mysqlのホスト名、ユーザ名、パスワード、対象スキーマは読み替えて下さい。パスワードはナシにするとプロンプトで聞いてきます。

パイプでsedに渡してAUTO_INCREMENTを消しています。

最後にこの出力をファイルに書き出して、コミットして共有します。

 

これだと差分をうまく見ることができるので便利ですね!

subversion1.7をインストールした環境でphp-svnのコンパイルが通らない

開発用のサーバを立てていて、svnの1.7.1をソースからコンパイルして入れた環境(Ubuntu 11.10)で、phpのモジュール「php-svn」のインストールが出来なかった時のメモ。
当然peclから入れてもエラーで通らない。廃止された関数があるらしい。
しかたなく、1.6系のライブラリをインストール

sudo aptitude install libsvn-dev

aptとかから入れた物は/usr/以下、ソースから入れら/usr/local以下に入るので共存できる。
で、Makefileを編集

/usr/local/include/subversion-1/

/usr/include/subversion-1/

に置換してmakeしてみたら通った。

subversion1.6から1.7に移行する手順

subversionのサーバをFreeBSDに変更したら、portsのsubversionがデフォルトで1.7になってたので、Linux,Macを含めて移行した。

dumpで1.6の旧サーバからバックアップ
旧サーバはUbuntu server 11.04

svnadmin dump /var/svn/レポジトリ名 | gzip > ./レポジトリ名.gz

新サーバのFreeBSDではデフォルトオプションでportsからsubversionをインストール。
svnユーザ,グループを作っておいて、svnルート以下の所有者をsvnにしておく

% sudo -u svn svnadmin create /var/svn/レポジトリ名
% gzip -dc レポジトリ名.gz | sudo -u svn svnadmin load /var/svn/レポジトリ名

んで、クライアント
Ubuntuだとパッケージにはまだ1.6しか無いので、ソースからコンパイル
http://ftp.riken.jp/net/apache/subversion/辺りからソースを落としてきて

% ./configure --enable-shared --without-berkeley-db
% make
% sudo make install

でrehashなりしたら1.7.1が使えるようになった

次にMac OS Lion
macportsにも1.7系はまだ無いので、Ubuntuと同じようにコンパイルした。

使えるようになったところで、1.6で管理されてたディレクトリで

% svn st
svn: E155036: Please see the 'svn upgrade' command
svn: E155036: Working copy '/var/www/storage' is too old (format 10, created by Subversion 1.6)

とかしてみると、起こられる。言われるままに

% svn upgrade

を実行したら終わり

eclipse上でのsvn管理下ファイルのマージ手順(Subclipse使用)

  • trunk/hoge.txt  (rev.1)
  • branch/hoge.txt  (rev.3)

rev.2でtrunkからbranchを作成し、rev.3でbranchのhoge.txtに変更を加えたという状態があったとして、rev.2からrev.3までで加えた変更をtrunkの方にも適用したいとする。

  1. ecpliseのtrunkの方のプロジェクトのhoge.txtを選択し、右クリック → チーム → マージ。
  2. FromのURLにbranchの方のhoge.txtを指定。
  3. rev.2から3までの変更を適用したいので、Fromのリビジョン番号には2を指定し、Toのリビジョン番号には3を指定。(ToのURLは “From”のURLを利用 にチェック)
  4. (ユニファイドdiff で結果を確認後、)マージ を実行。
  5. trunk/hoge.txt に変更点が適用されるのでコミット。

subversionのサーバを移行する手順

svnのサーバを別のマシンにする必要があったので、自分用メモ。
Ubuntu server 9.10 => Debian GNU/Linux 6.0

旧サーバのUbuntu側で
svnadmin dump /var/svn/レポジトリ名 | gzip > ./レポジトリ名.gz
てのをレポジトリ毎にやって
新サーバのDebianで
svnadmin create /var/svn/レポジトリ名
をレポジトリ分やって
gzip -dc レポジトリ名.gz | svnadmin load /var/svn/レポジトリ名
でバックアップを復元する。

後は、参照先を新しいサーバに変更する。
svn switch –relocate –username ユーザ名 svn://古いサーバ/レポジトリ/ svn://新しいサーバ/レポジトリ/

FreeBSDでtracを動かそうとしたときに起きたエラーについて

FreeBSDでtracを動かそうとしたときに起きたエラーについて。

ホームディレクトリが存在しないユーザでpythonを実行するとエラーになる件。pythonのことをよくしらないけど、厳密にはpythonのエラーではなくeggのエラー?になるような気がする。

以下エラーメッセージ


shell> sudo -u www python
Python 2.6.6 (r266:84292, Mar 16 2011, 02:49:37)
[GCC 4.2.1 20070719  [FreeBSD]] on freebsd8
Type "help", "copyright", "credits" or "license" for more information.
>>> import MySQLdb
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/MySQLdb/__init__.py", line 19, in <module>
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/_mysql.py", line 7, in <module>
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/_mysql.py", line 4, in __bootstrap__
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/pkg_resources.py", line 882, in resource_filename
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/pkg_resources.py", line 1351, in get_resource_filename
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/pkg_resources.py", line 1373, in _extract_resource
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/pkg_resources.py", line 962, in get_cache_path
File "build/bdist.freebsd-8.2-RELEASE-amd64/egg/pkg_resources.py", line 928, in extraction_error
pkg_resources.ExtractionError: Can't extract file(s) to egg cache

The following error occurred while trying to extract file(s) to the Python egg
cache:

[Errno 17] File exists: '/nonexistent'

The Python egg cache directory is currently set to:

/nonexistent/.python-eggs

Perhaps your account does not have write access to this directory?  You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.

このエラーは、www, svnといったホームディレクトリを持たないユーザがpythonを使ったスクリプトを実行したときに遭遇する。 たとえばtrac-adminをwwwユーザで実行したとき、またsubversionでコミット時のフック、hooks/post-commitのところでもエラーがでてたりする。 今回はpost-commitのあとtrac-svn-hookを呼び出していたので、ログがtrac/log/svn-hooks-testrep.logにエラーが出ていた。コレに書いてあるだけで他にはwarningとか出ないのでなかなか気づかなかった。


shell> tail svn-hooks-testrep.log

Changeset 4 added
Traceback (most recent call last):
File "/usr/local/lib/python2.6/logging/handlers.py", line 796, in emit
self.socket.send(msg)
error: [Errno 40] Message too long
TracError: Unsupported database type "mysql"
FAILED: see the Trac log

同様にwwwユーザでtrac-adminを走らせてもエラーがでる。


> sudo -u www trac-admin /path/to/trac repository resync testrep
Traceback (most recent call last):
File "/usr/local/lib/python2.6/logging/handlers.py", line 796, in emit
self.socket.send(msg)
error: [Errno 40] Message too long
TracError: Unsupported database type "mysql"

で、解決方法は・・・、一筋縄ではいかない。 それぞれのユーザにホームディレクトリを持たせるのが一番手っ取り早い。でもこれらのユーザをnisで管理してたらそこも一斉に書き換わっちゃう。 いらないところは最小限に、ってことで、該当するホストに/nonexistentフォルダを作ってみる。いいのかな、こんなやりかたで・・・。


shell> sudo mkdir /nonexistent
shell> sudo chmod 777 /nonexistent/

ひとまずこれで動いた。 おしまい。

subversionでcommitが失敗する

tracで色々やろうと試行錯誤中に、subversionでcommitが失敗した。
元々あったsubversionのサーバを、リポジトリをお引っ越しさせてサーバ機能を別ホストに分けようとした。でもそこでコミットができない。
コミットしようとすると下記のようなエラーで怒られてしまう。


shell> svn ci hoge -m 'refs #80'
Sending        hoge
Transmitting file data .svn: Commit failed (details follow):
svn: Can't get exclusive lock on file '/path/to/repositories/testrep/db/txn-current-lock': Operation not supported

排他的ロックが取得できませんよ、とのこと。

実はこの新しいsubversionのサーバ、nfs上にリポジトリを置いてみた。 nfs上にリポジトリがあるのでファイルロックがとれないとのこと。

subversionサーバ上でrpc.lockdとrpc.statdを動かしてロックをとれるようにして、再度コミット。


shell> svn ci hoge -m 'refs #80'
Sending        hoge
Transmitting file data .
Committed revision 2.

うまくいったー。

svnでディレクトリのみを管理したかった

svnでディレクトリのみを管理したかった。

まずデフォルト(freebsdのdevel/subversionでインストールされるsvn)では、ディレクトリに対してaddすると以下すべてのファイルが一緒にaddされる。

%svn add sitemap
A sitemap
A (bin) sitemap/sitemap1.xml.gz
A sitemap/sitemap1.xml
A (bin) sitemap/sitemapindex.xml.gz
A sitemap/sitemapindex.xml
A sitemap/sitemap0.xml
A (bin) sitemap/sitemap2.xml.gz
A sitemap/sitemap2.xml
A (bin) sitemap/sitemap3.xml.gz
A sitemap/sitemap3.xml

でもこのディレクトリの中身が、結構変わるもので、あくまでディレクトリは入れ物っていうだけ、中身のファイルをバージョン管理かにおいてほしくなかった。

まずは今回の問題に先立って、対象となるディレクトリの中身全部を誤ってバージョン管理下に置いてしまったのでそれをもどす。
%svn revert sitemap
deleteがいいのかな、とかちょっと考えたけど、revertだとaddされる前に戻るらしい。revertはちょっと危険なコマンド。必ず引数がいるあたり。
とにかくrevertすればaddを取り消せる。add->commitしてたらdeleteするしかないと思うけど。

次にバージョン管理化から外す方法。
svnではディレクトリごと(ファイルごと?)にpropと呼ばれる、管理情報のフラグ(true or falseだけじゃなくてほかにもあるよ?)みたいなのを持てる。これを設定してやれば管理対象から外すことができる。

今回のケースだと、sitemapっていうディレクトリの中にあるファイルはすべて管理外にしていただきたい。ということで、sitemapがあるディレクトリ直下でpropsetコマンドにてignoreのフラグをつける。

%svn propset svn:ignore “*” ./sitemap
svn: warning: ‘sitemap’ is not under version control

怒られてしまった。
注意すべきは*をダブルクォートとかで囲むこと。これはsitemapっていうディレクトリに対して、svn:ignoreっていう属性を”*”に適応させたいです、っていうのを”svn”に伝えるため。クォートされてないとシェルが展開しようとして、内部的には
%svn propset svn:ignore hoge1.txt ./sitemap
%svn propset svn:ignore hoge2.txt ./sitemap
%svn propset svn:ignore hoge3.txt ./sitemap
%svn propset svn:ignore hoge4.txt ./sitemap

となってしまうためだ。

最後に怒られてしまった原因は、そのまま、バージョン管理下にない、ということ。
デフォルトでaddは以下のディレクトリもaddしてくれる。便利だなぁ、と思ってたけど初めて今回、ディレクトリのみをaddしたくなった。
%svn add –non-recursive sitemap
A sitemap
これでおk。
最後にコミットしておしまい。