miauのブログ

はてなダイアリー「miauの避難所」をはてなブログに移行しました

Subversion で受領ファイルをうまく管理したい

Subversionリポジトリを作るときは、そのルートに received(受領ファイル)みたいなディレクトリを作っておいて、

  • 一時的なやりとりで使ったファイルはとりあえず received/yyyymmdd_hoge 等に放り込む
  • まともに変更をトラッキングできそうなファイルは received/hoge 配下でベンダブランチ風に管理する

というような運用を行っていたのですが、「変更をトラッキングしたいけど受領ファイルもそのまんま管理したい」というケースがたまにあるので、運用方法を考えてみた&補助用スクリプトを書いてみました。

現状のベンダブランチ風の管理

ベンダブランチの管理方法 - miauの避難所 で書いたこの運用方法なんですが。

受領ファイルの管理

/vendorsrc の運用に慣れてくると、ソースコード以外の外部リソースについて似たような管理をしたくなってきたりします。たとえば別会社にデザインを依頼していて、定期的でメールで受け取るような場合にも上記の方法は有効です。

このようなファイルについても trunk/branches/tags とライフサイクルが異なる&マージが必要になるものですので、/received(受領ファイル)のようなディレクトリを作成し、そこで管理するようにしています。今回はデザイン関連のファイルなので /received/design のような形ですね。

この方法では

  • SVN 内の /received/design を管理用のディレクトリとして使う
  • メール等でファイルを受領すると 20110427 のような日付ファイルに格納したうえで svn_load_dirs.pl を呼び出す
  • すると /received/design/current が更新され、/received/design/20110427 というタグも生成される

という感じの運用になります。

ベンダブランチ風管理で困る点

この方法、外部から送られるファイルが完全な状態であれば問題なく運用できるんですけど、実際にメール等で更新ファイルが送付されてくる場合は、変更があったファイルだけ送られてくるケースというのが結構あります。

この場合、/received/design/current を trunk に見立てて手動で更新&自分でタグ付けすればふつうに管理はできるんですが、ディレクトリ構造が変わっていたり、ファイル末尾に更新を示す文字列が付加されていたりすると厄介です。

例えば、/received/infra で管理したいインフラ関連の資料が、初回は完全なディレクトリ構成で

00.はじめに/Readme.txt
01.IPアドレス管理表/IPアドレス管理表.xls
02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
02.ネットワーク構成図/ネットワーク構成図_20090930.ppt

として送られてきたのに、後のタイミングでは

IPアドレス管理表_20091102.xls
ネットワーク構成図_20091102.ppt

のように送られてきてたりします。こうなると、

  • ファイル末尾の _yyyymmdd(場合によっては「_修正版2」みたいな名前だったりする)を削除して格納しなおす必要がある
  • 格納先のパスをいちいち探して更新をかける必要がある

という問題があります。

ついでに、svn_load_dirs.pl を使うと実行時点の全ファイルをコピーしてタグが生成されますが、そうではなく

  • 日付ごとのディレクトリは受領したファイルのみを、受領時のディレクトリ構造&ファイル名で保存したい
    • 電話で急に「○月○日に送った "〜修正版2" のファイル見ていただけます?それの・・・」みたいに言われることがあるので、すぐに参照できるようにしておきたい
  • current は末尾の _yyyymmdd 等を除いた綺麗なディレクトリ構造&ファイル名で保存したい

気がします。

上記の受領ファイルであれば、最終的に

20090930/00.はじめに/Readme.txt
20090930/01.IPアドレス管理表/IPアドレス管理表.xls
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.ppt
20091102/IPアドレス管理表_20091102.xls
20091102/ネットワーク構成図_20091102.ppt
current/00.はじめに/Readme.txt
current/01.IPアドレス管理表/IPアドレス管理表.xls
current/02.ネットワーク構成図/ネットワーク構成図.pdf
current/02.ネットワーク構成図/ネットワーク構成図.ppt

こうなるイメージです。

運用方法

これを実現するための運用方法はこんな感じになると思います。

  • ファイルを受領したら、ディレクトリ構造&ファイル名をきれいに変更したうえで current を更新する
  • current のファイルを yyyymmdd にもとのファイル名にリネームしつつ svn copy

たとえば初回に

00.はじめに/Readme.txt
01.IPアドレス管理表/IPアドレス管理表.xls
02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
02.ネットワーク構成図/ネットワーク構成図_20090930.ppt

として送られたファイルは、まず末尾の _yyyymmdd を取り除いて

current/00.はじめに/Readme.txt
current/01.IPアドレス管理表/IPアドレス管理表.xls
current/02.ネットワーク構成図/ネットワーク構成図.pdf
current/02.ネットワーク構成図/ネットワーク構成図.ppt

として格納します。

そして受領時のファイル情報をそのまま残すために

svn copy current/00.はじめに/Readme.txt \
         20090930/00.はじめに/Readme.txt
svn copy current/01.IPアドレス管理表/IPアドレス管理表.xls \
         20090930/01.IPアドレス管理表/IPアドレス管理表.xls
svn copy current/02.ネットワーク構成図/ネットワーク構成図.pdf \
         20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
svn copy current/02.ネットワーク構成図/ネットワーク構成図.ppt \
         20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.ppt

のように元ファイル名にリネームしなおすと。(中間ディレクトリの生成&svn add は省略しています。)

これでちゃんとトラッキングできそうです。でも毎回この作業を行うのは大変そうですね。

補助用スクリプト

ということで簡単な補助用スクリプトを作ってみました(fetch_third_party_files.rb)。

例によって gist に上げていますので、物好きな方は raw のリンクからダウンロードしてご利用ください。

方針
  • テキストエディタでファイル名一覧を編集して、ファイルのリネームの指定を行います
  • あくまでも補助を行うだけなので、svn add や svn copy は行なっても svn commit は行いません
  • 受領ファイルを取り扱う前提なので、あまり堅牢な処理にはしていません
    • たとえば svn copy 前にバックアップを行わずに元ファイルの削除を行なっています
    • 消されて困るようなファイルを扱う場合は、あらかじめバックアップを取得しておいてください
必要なもの
  • ruby が動作する必要があります(1.8.7 で動作確認しています)
  • svn コマンドに PATH が通っている必要があります
  • 環境変数 EDITOR にテキストエディタのパスを設定しておく必要があります

補助用スクリプトの使い方

1. 起動

受領ファイルをあらかじめ SVN に収めたいフォルダに配置してから、

ruby fetch_third_party_files.rb <受領ファイルの格納ディレクトリ> <最新版の格納ディレクトリ>

のようにして起動します。

たとえば received/infra で管理したい場合、この配下に受領ファイル一式(今回であれば 20090930)を配置してから、

cd received/infra
set EDITOR=C:/Program Files/sakura/sakura.exe
ruby fetch_third_party_files.rb 20090930 current

のようにして起動することになります。

2. ファイル一覧の編集

エディタが起動して、↓のようなテキストが表示されていると思います。

20090930/00.はじめに/Readme.txt
20090930/01.IPアドレス管理表/IPアドレス管理表_20090930.xls
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.ppt
#
# ↓元ファイルの一覧です。この順で格納先のファイル名を記載してください。
#  「#」で始まる行は無視されます。
#
# 20090930/00.はじめに/Readme.txt
# 20090930/01.IPアドレス管理表/IPアドレス管理表_20090930.xls
# 20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
# 20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.ppt
#
# ↓SVN ディレクトリのファイル一覧です。参考にしてください。
#
# current

「#」で始まる行は無視されます(git 風)ので、先頭の部分を格納先の名称に変更します。
今回であれば current 配下に _yyyymmdd を取り除いて格納したいわけなので、

current/00.はじめに/Readme.txt
current/01.IPアドレス管理表/IPアドレス管理表.xls
current/02.ネットワーク構成図/ネットワーク構成図.pdf
current/02.ネットワーク構成図/ネットワーク構成図.ppt

のように編集すればよいです。

3. 変更内容の確認

内容に問題がなければ、

20090930/00.はじめに/Readme.txt
   [Add] current/00.はじめに/Readme.txt
20090930/01.IPアドレス管理表/IPアドレス管理表_20090930.xls
   [Add] current/01.IPアドレス管理表/IPアドレス管理表.xls
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
   [Add] current/02.ネットワーク構成図/ネットワーク構成図.pdf
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.ppt
   [Add] current/02.ネットワーク構成図/ネットワーク構成図.ppt

変更内容に間違いはありませんか?([Add] は新規ファイル、[Edit] は既存ファイル)
[y/n]:

のように確認メッセージが表示されるので、問題なければ y を入力して Enter を押下します。

n を入力した場合や、内容に問題があった場合(行数が変わっている等)は再度エディタが起動します。

4. svn add の実行結果確認&問題なければ svn commit

y を入力すると svn add が走って

20090930/00.はじめに/Readme.txt
A         E:\tmp\svn_temp\work\received\infra
A         E:\tmp\svn_temp\work\received\infra\current
A         E:\tmp\svn_temp\work\received\infra\current\00.はじめに
A         E:\tmp\svn_temp\work\received\infra\current\00.はじめに\Readme.txt
20090930/01.IPアドレス管理表/IPアドレス管理表_20090930.xls
A         E:\tmp\svn_temp\work\received\infra\current\01.IPアドレス管理表
A  (bin)  E:\tmp\svn_temp\work\received\infra\current\01.IPアドレス管理表\IPアドレス管理表.xls
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.pdf
A         E:\tmp\svn_temp\work\received\infra\current\02.ネットワーク構成図
A  (bin)  E:\tmp\svn_temp\work\received\infra\current\02.ネットワーク構成図\ネットワーク構成図.pdf
20090930/02.ネットワーク構成図/ネットワーク構成図_20090930.ppt
A  (bin)  E:\tmp\svn_temp\work\received\infra\current\02.ネットワーク構成図\ネットワーク構成図.ppt
current が更新されました。問題なければ svn commit を実行してください。
svn commit が完了したら Enter を押下してください。引き続き 20090930 の更新が行われます。

のようなログが表示され、入力待ちになるはずです。current 配下を見て、問題がないことを確認します。ちなみに既存ファイルでは

svn: warning: '〜' is already under version control

という警告が出ますが、手抜きでチェック処理を入れていないだけですので、無視して問題ありません。

問題がある場合は

  1. Ctrl+C でスクリプトを強制終了
  2. svn revert current で svn add を取消

して、スクリプトを再実行してください。

問題なければコミットします。(Tortoise SVN で実行してもよいです)

svn commit -m "20090930 に受領したインフラ関連のファイルを格納。"
5. svn copy の実行結果確認&問題なければ svn commit

Enter を押下すると、current から 20090930 へ元ファイル名での svn copy が行われます。

current/00.はじめに/Readme.txt
A         E:\tmp\svn_temp\work\received\infra\20090930
A         E:\tmp\svn_temp\work\received\infra\20090930\00.はじめに
A         20090930\00.はじめに\Readme.txt
current/01.IPアドレス管理表/IPアドレス管理表.xls
A         E:\tmp\svn_temp\work\received\infra\20090930\01.IPアドレス管理表
A         20090930\01.IPアドレス管理表\IPアドレス管理表_20090930.xls
current/02.ネットワーク構成図/ネットワーク構成図.pdf
A         E:\tmp\svn_temp\work\received\infra\20090930\02.ネットワーク構成図
A         20090930\02.ネットワーク構成図\ネットワーク構成図_20090930.pdf
current/02.ネットワーク構成図/ネットワーク構成図.ppt
A         20090930\02.ネットワーク構成図\ネットワーク構成図_20090930.ppt

スクリプトの役目はここまでです。内容に問題がなければコミットして終了です。

svn commit -m "r2286 でコミットしたファイルについて、受領時のファイル名でコピーを格納。"
(参考)二回目の受領ファイルに対する処理

新しいファイルが届いたら、一回目と同様

ruby fetch_third_party_files.rb 20091102 current

としてスクリプトを起動します。するとエディタが

20091102/IPアドレス管理表_20091102.xls
20091102/ネットワーク構成図_20091102.ppt
#
# ↓元ファイルの一覧です。この順で格納先のファイル名を記載してください。
#  「#」で始まる行は無視されます。
#
# 20091102/IPアドレス管理表_20091102.xls
# 20091102/ネットワーク構成図_20091102.ppt
#
# ↓SVN ディレクトリのファイル一覧です。参考にしてください。
#
# current/00.はじめに/Readme.txt
# current/01.IPアドレス管理表/IPアドレス管理表.xls
# current/02.ネットワーク構成図/ネットワーク構成図.pdf
# current/02.ネットワーク構成図/ネットワーク構成図.ppt

のような感じで起動しますので、新規ファイルの追加が無い場合は、一番下の部分からファイル名を抜き出して、一番上のところにコピーするだけでいいはずです。

もしリネームされている&リネーム後のファイル名で格納すべきファイルがある場合は、

  • いったん Ctrl+C で中断
  • svn rename しておく(ついでに svn commit しても OK)
  • 再度スクリプトを実行

という感じで人力で対応してください。

以降の流れは一回目と同じです。

TODO っぽい部分

受領ファイルに current での管理が不要なファイルが入っていることもあるので「空行にしておけば current には入れない」処理を実装するつもりでしたが、まだやってません。まあ次に使う機会があれば手を入れればいいかなと。